1 /* rpc - demo of the RPC features in GRAS */
3 /* Copyright (c) 2006, 2007, 2009, 2010. The SimGrid Team.
4 * All rights reserved. */
6 /* This program is free software; you can redistribute it and/or modify it
7 * under the terms of the license (GNU LGPL) which comes with this package. */
11 XBT_LOG_NEW_DEFAULT_CATEGORY(Rpc, "Messages specific to this example");
13 /* register messages which may be sent (common to client and server) */
14 static void register_messages(void)
16 gras_msgtype_declare_rpc("plain ping",
17 xbt_datadesc_by_name("int"),
18 xbt_datadesc_by_name("int"));
20 gras_msgtype_declare_rpc("raise exception", NULL, NULL);
21 gras_msgtype_declare_rpc("forward exception", NULL, NULL);
22 gras_msgtype_declare("kill", NULL);
25 /* Function prototypes */
26 int server(int argc, char *argv[]);
27 int forwarder(int argc, char *argv[]);
28 int client(int argc, char *argv[]);
30 #define exception_msg "Error for the client"
31 #define exception_raising() THROWF(unknown_error,42,exception_msg)
33 static void exception_catching(void)
38 for (i = 0; i < 5; i++) {
45 xbt_assert(e.category == unknown_error,
46 "Got wrong category: %d (instead of %d)", e.category,
48 xbt_assert(e.value == 42, "Got wrong value: %d (!=42)", e.value);
49 xbt_assert(!strncmp(e.msg, exception_msg, strlen(exception_msg)),
50 "Got wrong message: %s", e.msg);
54 THROWF(unknown_error, 0, "Didn't got the remote exception!");
59 /* **********************************************************************
61 * **********************************************************************/
63 static void client_create_sockets(xbt_socket_t *toserver,
64 xbt_socket_t *toforwarder,
65 const char *srv_host, int srv_port,
66 const char *fwd_host, int fwd_port)
70 *toserver = gras_socket_client(srv_host, srv_port);
71 *toforwarder = gras_socket_client(fwd_host, fwd_port);
74 RETHROWF("Unable to connect to the server: %s");
78 int client(int argc, char *argv[])
81 xbt_socket_t toserver = NULL; /* peer */
82 xbt_socket_t toforwarder = NULL; /* peer */
85 volatile int gotit = 0;
88 const char *host = "127.0.0.1";
91 memset(&e, 0, sizeof(xbt_ex_t));
93 /* 1. Init the GRAS's infrastructure */
94 gras_init(&argc, argv);
96 /* 2. Get the server's address. The command line override defaults when specified */
101 XBT_INFO("Launch client (server on %s:%d)", host, port);
103 exception_catching();
105 /* 3. Wait for the server & forwarder startup */
108 /* 4. Create a socket to speak to the server */
109 client_create_sockets(&toserver, &toforwarder,
110 host, port, argv[3], atoi(argv[4]));
111 XBT_INFO("Connected to %s:%d.", host, port);
114 /* 5. Register the messages.
115 See, it doesn't have to be done completely at the beginning,
116 but only before use */
117 exception_catching();
120 /* 6. Keep the user informed of what's going on */
121 XBT_INFO("Connected to server which is on %s:%d",
122 xbt_socket_peer_name(toserver), xbt_socket_peer_port(toserver));
124 /* 7. Prepare and send the ping message to the server */
127 exception_catching();
128 gras_msg_rpccall(toserver, 6000.0, "plain ping", &ping, &pong);
131 gras_socket_close(toserver);
132 RETHROWF("Failed to execute a PING rpc on the server: %s");
134 exception_catching();
136 /* 8. Keep the user informed of what's going on, again */
137 XBT_INFO("The answer to PING(%d) on %s:%d is PONG(%d)",
139 xbt_socket_peer_name(toserver), xbt_socket_peer_port(toserver),
142 /* 9. Call a RPC which raises an exception (to test exception propagation) */
143 XBT_INFO("Call the exception raising RPC");
145 gras_msg_rpccall(toserver, 6000.0, "raise exception", NULL, NULL);
149 xbt_assert(e.category == unknown_error,
150 "Got wrong category: %d (instead of %d)",
151 e.category, unknown_error);
152 xbt_assert(e.value == 42, "Got wrong value: %d (!=42)", e.value);
153 xbt_assert(!strncmp(e.msg, exception_msg, strlen(exception_msg)),
154 "Got wrong message: %s", e.msg);
156 ("Got the expected exception when calling the exception raising RPC");
161 THROWF(unknown_error, 0, "Didn't got the remote exception!");
163 XBT_INFO("Called the exception raising RPC");
164 exception_catching();
167 for (i = 0; i < 5; i++) {
169 XBT_INFO("Call the exception raising RPC (i=%d)", i);
171 gras_msg_rpccall(toserver, 6000.0, "raise exception", NULL, NULL);
178 THROWF(unknown_error, 0, "Didn't got the remote exception!");
183 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
184 for (i = 0; i < 5; i++) {
185 XBT_INFO("Call the exception raising RPC on the forwarder (i=%d)", i);
187 gras_msg_rpccall(toforwarder, 6000.0, "forward exception", NULL,
192 xbt_assert(e.value == 42, "Got wrong value: %d (!=42)", e.value);
193 xbt_assert(!strncmp(e.msg, exception_msg, strlen(exception_msg)),
194 "Got wrong message: %s", e.msg);
195 xbt_assert(e.category == unknown_error,
196 "Got wrong category: %d (instead of %d)",
197 e.category, unknown_error);
199 ("Got the expected exception when calling the exception raising RPC");
203 THROWF(unknown_error, 0, "Didn't got the remote exception!");
205 exception_catching();
208 XBT_INFO("Ask %s:%d to die", xbt_socket_peer_name(toforwarder),
209 xbt_socket_peer_port(toforwarder));
210 gras_msg_send(toforwarder, "kill", NULL);
211 XBT_INFO("Ask %s:%d to die", xbt_socket_peer_name(toserver),
212 xbt_socket_peer_port(toserver));
213 gras_msg_send(toserver, "kill", NULL);
215 /* 11. Cleanup the place before leaving */
216 gras_socket_close(toserver);
217 gras_socket_close(toforwarder);
221 } /* end_of_client */
224 /* **********************************************************************
226 * **********************************************************************/
230 } s_forward_data_t, *forward_data_t;
232 static int forwarder_cb_kill(gras_msg_cb_ctx_t ctx, void *payload_data)
234 forward_data_t fdata;
235 xbt_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
236 XBT_INFO("Asked to die by %s:%d", xbt_socket_peer_name(expeditor),
237 xbt_socket_peer_port(expeditor));
238 fdata = gras_userdata_get();
243 static int forwarder_cb_forward_ex(gras_msg_cb_ctx_t ctx,
246 forward_data_t fdata = gras_userdata_get();
248 XBT_INFO("Forward a request");
249 gras_msg_rpccall(fdata->server, 60, "raise exception", NULL, NULL);
253 int forwarder(int argc, char *argv[])
257 forward_data_t fdata;
259 gras_init(&argc, argv);
261 xbt_assert(argc == 4);
263 fdata = gras_userdata_new(s_forward_data_t);
265 port = atoi(argv[1]);
267 XBT_INFO("Launch forwarder (port=%d)", port);
268 mysock = gras_socket_server(port);
270 gras_os_sleep(1); /* wait for the server to be ready */
271 fdata->server = gras_socket_client(argv[2], atoi(argv[3]));
274 gras_cb_register("forward exception", &forwarder_cb_forward_ex);
275 gras_cb_register("kill", &forwarder_cb_kill);
277 while (!fdata->done) {
278 gras_msg_handle(600.0);
281 gras_socket_close(mysock);
282 gras_socket_close(fdata->server);
289 /* **********************************************************************
291 * **********************************************************************/
295 } s_server_data_t, *server_data_t;
297 static int server_cb_kill(gras_msg_cb_ctx_t ctx, void *payload_data)
299 xbt_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
302 XBT_INFO("Asked to die by %s:%d", xbt_socket_peer_name(expeditor),
303 xbt_socket_peer_port(expeditor));
305 sdata = gras_userdata_get();
310 static int server_cb_raise_ex(gras_msg_cb_ctx_t ctx, void *payload_data)
316 static int server_cb_ping(gras_msg_cb_ctx_t ctx, void *payload_data)
319 /* 1. Get the payload into the msg variable, and retrieve who called us */
320 int msg = *(int *) payload_data;
321 xbt_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
323 /* 2. Log which client connected */
324 XBT_INFO("Got message PING(%d) from %s:%d",
326 xbt_socket_peer_name(expeditor),
327 xbt_socket_peer_port(expeditor));
329 /* 4. Change the value of the msg variable */
332 /* 5. Return as result */
333 gras_msg_rpcreturn(6000, ctx, &msg);
334 XBT_INFO("Answered with PONG(4321)");
336 /* 6. Cleanups, if any */
338 /* 7. Tell GRAS that we consummed this message */
340 } /* end_of_server_cb_ping */
343 int server(int argc, char *argv[])
350 /* 1. Init the GRAS infrastructure */
351 gras_init(&argc, argv);
353 /* 2. Get the port I should listen on from the command line, if specified */
355 port = atoi(argv[1]);
357 sdata = gras_userdata_new(s_server_data_t);
360 XBT_INFO("Launch server (port=%d)", port);
362 /* 3. Create my master socket */
363 mysock = gras_socket_server(port);
365 /* 4. Register the known messages and register my callback */
367 gras_cb_register("plain ping", &server_cb_ping);
368 gras_cb_register("raise exception", &server_cb_raise_ex);
369 gras_cb_register("kill", &server_cb_kill);
371 XBT_INFO("Listening on port %d", xbt_socket_my_port(mysock));
373 /* 5. Wait for the ping incoming messages */
375 /** \bug if the server is gone before the forwarder tries to connect,
376 it dies awfully with the following message. The problem stands somewhere
377 at the interface between the xbt_socket_t and the msg mess. There is thus
378 no way for me to dive into this before this interface is rewritten
379 ==15875== Invalid read of size 4
380 ==15875== at 0x408B805: find_port (transport_plugin_sg.c:68)
381 ==15875== by 0x408BD64: gras_trp_sg_socket_client (transport_plugin_sg.c:115)
382 ==15875== by 0x404A38B: gras_socket_client_ext (transport.c:255)
383 ==15875== by 0x404A605: gras_socket_client (transport.c:288)
384 ==15875== by 0x804B49D: forwarder (rpc.c:245)
385 ==15875== by 0x80491FB: launch_forwarder (_rpc_simulator.c:52)
386 ==15875== by 0x406780B: __context_wrapper (context.c:164)
387 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
388 ==15875== by 0x42AA549: clone (clone.S:119)
389 ==15875== Address 0x433B49C is 44 bytes inside a block of size 48 free'd
390 ==15875== at 0x401CF46: free (vg_replace_malloc.c:235)
391 ==15875== by 0x408F1FA: gras_process_exit (sg_process.c:117)
392 ==15875== by 0x4049386: gras_exit (gras.c:64)
393 ==15875== by 0x804B936: server (rpc.c:345)
394 ==15875== by 0x80492B1: launch_server (_rpc_simulator.c:69)
395 ==15875== by 0x406780B: __context_wrapper (context.c:164)
396 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
397 ==15875== by 0x42AA549: clone (clone.S:119)
399 while (!sdata->done) {
400 gras_msg_handle(600.0);
401 exception_catching();
404 /* 8. Free the allocated resources, and shut GRAS down */
406 gras_socket_close(mysock);
411 } /* end_of_server */