3 /* rpc - demo of the RPC features in GRAS */
5 /* Copyright (c) 2006 Martin Quinson. All rights reserved. */
7 /* This program is free software; you can redistribute it and/or modify it
8 * under the terms of the license (GNU LGPL) which comes with this package. */
12 XBT_LOG_NEW_DEFAULT_CATEGORY(Rpc,"Messages specific to this example");
14 int err=0; /* to make the message of the raised exception more informative and
15 even be able to follow their propagation from server to client*/
17 /* register messages which may be sent (common to client and server) */
18 static void register_messages(void) {
19 gras_msgtype_declare_rpc("plain ping",
20 gras_datadesc_by_name("int"),
21 gras_datadesc_by_name("int"));
23 gras_msgtype_declare_rpc("raise exception", NULL, NULL);
24 gras_msgtype_declare_rpc("forward exception", NULL, NULL);
25 gras_msgtype_declare("kill",NULL);
28 /* Function prototypes */
29 int server (int argc,char *argv[]);
30 int forwarder (int argc,char *argv[]);
31 int client (int argc,char *argv[]);
33 static void exception_raising(void) {
34 THROW1(unknown_error,42,"Some error we will catch on client side %d",err++);
36 static void exception_catching(void) {
48 THROW0(unknown_error,0,"Didn't got the remote exception!");
50 xbt_assert2(e.category == unknown_error, "Got wrong category: %d (instead of %d)",
51 e.category,unknown_error);
52 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
53 xbt_assert1(!strncmp(e.msg,"Some error we will catch on client side",
54 strlen("Some error we will catch on client side")),
55 "Got wrong message: %s", e.msg);
60 /* **********************************************************************
62 * **********************************************************************/
65 int client(int argc,char *argv[]) {
67 gras_socket_t toserver=NULL; /* peer */
68 gras_socket_t toforwarder=NULL; /* peer */
75 const char *host = "127.0.0.1";
78 /* 1. Init the GRAS's infrastructure */
79 gras_init(&argc, argv);
81 /* 2. Get the server's address. The command line override defaults when specified */
86 INFO2("Launch client (server on %s:%d)",host,port);
90 /* 3. Wait for the server & forwarder startup */
93 /* 4. Create a socket to speak to the server */
96 toserver=gras_socket_client(host,port);
97 toforwarder=gras_socket_client(argv[3],atoi(argv[4]));
99 RETHROW0("Unable to connect to the server: %s");
101 INFO2("Connected to %s:%d.",host,port);
104 /* 5. Register the messages.
105 See, it doesn't have to be done completely at the beginning,
106 but only before use */
107 exception_catching();
110 /* 6. Keep the user informed of what's going on */
111 INFO2("Connected to server which is on %s:%d ",
112 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
114 /* 7. Prepare and send the ping message to the server */
117 exception_catching();
118 gras_msg_rpccall(toserver, 6000.0,
119 gras_msgtype_by_name("plain ping"), &ping, &pong);
121 gras_socket_close(toserver);
122 RETHROW0("Failed to execute a PING rpc on the server: %s");
124 exception_catching();
126 /* 8. Keep the user informed of what's going on, again */
127 INFO4("The answer to PING(%d) on %s:%d is PONG(%d) ",
129 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver),
132 /* 9. Call a RPC which raises an exception (to test exception propagation) */
133 INFO0("Call the exception raising RPC");
135 gras_msg_rpccall(toserver, 6000.0,
136 gras_msgtype_by_name("raise exception"), NULL, NULL);
139 xbt_assert2(e.category == unknown_error,
140 "Got wrong category: %d (instead of %d)",
141 e.category,unknown_error);
142 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
143 xbt_assert1(!strncmp(e.msg,"Some error we will catch on client side",
144 strlen("Some error we will catch on client side")),
145 "Got wrong message: %s", e.msg);
146 INFO0("Got the expected exception when calling the exception raising RPC");
151 THROW0(unknown_error,0,"Didn't got the remote exception!");
153 INFO0("Called the exception raising RPC");
154 exception_catching();
157 for (i=0; i<5; i++) {
159 INFO1("Call the exception raising RPC (i=%d)",i);
161 gras_msg_rpccall(toserver, 6000.0,
162 gras_msgtype_by_name("raise exception"), NULL, NULL);
168 THROW0(unknown_error,0,"Didn't got the remote exception!");
173 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
175 INFO1("Call the exception raising RPC on the forwarder (i=%d)",i);
177 gras_msg_rpccall(toforwarder, 6000.0,
178 gras_msgtype_by_name("forward exception"), NULL, NULL);
183 THROW0(unknown_error,0,"Didn't got the remote exception!");
185 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
186 xbt_assert1(!strncmp(e.msg,"Some error we will catch on client side",
187 strlen("Some error we will catch on client side")),
188 "Got wrong message: %s", e.msg);
189 xbt_assert2(e.category == unknown_error,
190 "Got wrong category: %d (instead of %d)",
191 e.category,unknown_error);
192 INFO0("Got the expected exception when calling the exception raising RPC");
194 exception_catching();
197 gras_msg_send(toserver,gras_msgtype_by_name("kill"),NULL);
198 gras_msg_send(toforwarder,gras_msgtype_by_name("kill"),NULL);
200 /* 11. Cleanup the place before leaving */
201 gras_socket_close(toserver);
202 gras_socket_close(toforwarder);
206 } /* end_of_client */
209 /* **********************************************************************
211 * **********************************************************************/
213 gras_socket_t server;
215 } s_forward_data_t, *forward_data_t;
217 static int forwarder_cb_kill(gras_msg_cb_ctx_t ctx,
218 void *payload_data) {
219 forward_data_t fdata=gras_userdata_get();
224 static int forwarder_cb_forward_ex(gras_msg_cb_ctx_t ctx,
225 void *payload_data) {
226 forward_data_t fdata=gras_userdata_get();
228 gras_msg_rpccall(fdata->server, 60,
229 gras_msgtype_by_name("raise exception"),NULL,NULL);
233 int forwarder (int argc,char *argv[]) {
234 gras_socket_t mysock;
236 forward_data_t fdata;
238 gras_init(&argc,argv);
240 xbt_assert(argc == 4);
242 fdata=gras_userdata_new(s_forward_data_t);
246 INFO1("Launch forwarder (port=%d)", port);
247 mysock = gras_socket_server(port);
249 gras_os_sleep(1); /* wait for the server to be ready */
250 fdata->server=gras_socket_client(argv[2],atoi(argv[3]));
253 gras_cb_register(gras_msgtype_by_name("forward exception"),
254 &forwarder_cb_forward_ex);
255 gras_cb_register(gras_msgtype_by_name("kill"),
258 while (!fdata->done) {
259 gras_msg_handle(600.0);
262 gras_socket_close(mysock);
263 gras_socket_close(fdata->server);
270 /* **********************************************************************
272 * **********************************************************************/
274 gras_socket_t server;
276 } s_server_data_t, *server_data_t;
278 static int server_cb_kill(gras_msg_cb_ctx_t ctx,
279 void *payload_data) {
280 server_data_t sdata=gras_userdata_get();
285 static int server_cb_raise_ex(gras_msg_cb_ctx_t ctx,
286 void *payload_data) {
291 static int server_cb_ping(gras_msg_cb_ctx_t ctx,
292 void *payload_data) {
294 /* 1. Get the payload into the msg variable, and retrieve who called us */
295 int msg=*(int*)payload_data;
296 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
298 /* 2. Log which client connected */
299 INFO3("Got message PING(%d) from %s:%d ",
301 gras_socket_peer_name(expeditor), gras_socket_peer_port(expeditor));
303 /* 4. Change the value of the msg variable */
306 /* 5. Return as result */
307 gras_msg_rpcreturn(6000,ctx,&msg);
308 INFO0("Answered with PONG(4321)");
310 /* 6. Cleanups, if any */
312 /* 7. Tell GRAS that we consummed this message */
314 } /* end_of_server_cb_ping */
317 int server (int argc,char *argv[]) {
318 gras_socket_t mysock;
323 /* 1. Init the GRAS infrastructure */
324 gras_init(&argc,argv);
326 /* 2. Get the port I should listen on from the command line, if specified */
330 sdata=gras_userdata_new(s_server_data_t);
333 INFO1("Launch server (port=%d)", port);
335 /* 3. Create my master socket */
336 mysock = gras_socket_server(port);
338 /* 4. Register the known messages and register my callback */
340 gras_cb_register(gras_msgtype_by_name("plain ping"),&server_cb_ping);
341 gras_cb_register(gras_msgtype_by_name("raise exception"),&server_cb_raise_ex);
342 gras_cb_register(gras_msgtype_by_name("kill"),&server_cb_kill);
344 INFO1("Listening on port %d ", gras_socket_my_port(mysock));
346 /* 5. Wait for the ping incomming messages */
348 /* BUG: if the server is gone before the forwarder tries to connect,
349 it dies awfully with :
350 ==15875== Invalid read of size 4
351 ==15875== at 0x408B805: find_port (transport_plugin_sg.c:68)
352 ==15875== by 0x408BD64: gras_trp_sg_socket_client (transport_plugin_sg.c:115)
353 ==15875== by 0x404A38B: gras_socket_client_ext (transport.c:255)
354 ==15875== by 0x404A605: gras_socket_client (transport.c:288)
355 ==15875== by 0x804B49D: forwarder (rpc.c:245)
356 ==15875== by 0x80491FB: launch_forwarder (_rpc_simulator.c:52)
357 ==15875== by 0x406780B: __context_wrapper (context.c:164)
358 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
359 ==15875== by 0x42AA549: clone (clone.S:119)
360 ==15875== Address 0x433B49C is 44 bytes inside a block of size 48 free'd
361 ==15875== at 0x401CF46: free (vg_replace_malloc.c:235)
362 ==15875== by 0x408F1FA: gras_process_exit (sg_process.c:117)
363 ==15875== by 0x4049386: gras_exit (gras.c:64)
364 ==15875== by 0x804B936: server (rpc.c:345)
365 ==15875== by 0x80492B1: launch_server (_rpc_simulator.c:69)
366 ==15875== by 0x406780B: __context_wrapper (context.c:164)
367 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
368 ==15875== by 0x42AA549: clone (clone.S:119)
370 while (!sdata->done) {
371 gras_msg_handle(600.0);
372 exception_catching();
375 /* 8. Free the allocated resources, and shut GRAS down */
377 gras_socket_close(mysock);
382 } /* end_of_server */