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 /* register messages which may be sent (common to client and server) */
15 static void register_messages(void) {
16 gras_msgtype_declare_rpc("plain ping",
17 gras_datadesc_by_name("int"),
18 gras_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() THROW0(unknown_error,42,exception_msg)
33 static void exception_catching(void) {
45 THROW0(unknown_error,0,"Didn't got the remote exception!");
47 xbt_assert2(e.category == unknown_error, "Got wrong category: %d (instead of %d)",
48 e.category,unknown_error);
49 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
50 xbt_assert1(!strncmp(e.msg,exception_msg, strlen(exception_msg)),
51 "Got wrong message: %s", e.msg);
56 /* **********************************************************************
58 * **********************************************************************/
61 int client(int argc,char *argv[]) {
63 gras_socket_t toserver=NULL; /* peer */
64 gras_socket_t toforwarder=NULL; /* peer */
70 const char *host = "127.0.0.1";
73 memset(&e,0,sizeof(xbt_ex_t));
75 /* 1. Init the GRAS's infrastructure */
76 gras_init(&argc, argv);
78 /* 2. Get the server's address. The command line override defaults when specified */
83 INFO2("Launch client (server on %s:%d)",host,port);
87 /* 3. Wait for the server & forwarder startup */
90 /* 4. Create a socket to speak to the server */
93 toserver=gras_socket_client(host,port);
94 toforwarder=gras_socket_client(argv[3],atoi(argv[4]));
96 RETHROW0("Unable to connect to the server: %s");
98 INFO2("Connected to %s:%d.",host,port);
101 /* 5. Register the messages.
102 See, it doesn't have to be done completely at the beginning,
103 but only before use */
104 exception_catching();
107 /* 6. Keep the user informed of what's going on */
108 INFO2("Connected to server which is on %s:%d",
109 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
111 /* 7. Prepare and send the ping message to the server */
114 exception_catching();
115 gras_msg_rpccall(toserver, 6000.0, "plain ping", &ping, &pong);
117 gras_socket_close(toserver);
118 RETHROW0("Failed to execute a PING rpc on the server: %s");
120 exception_catching();
122 /* 8. Keep the user informed of what's going on, again */
123 INFO4("The answer to PING(%d) on %s:%d is PONG(%d)",
125 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver),
128 /* 9. Call a RPC which raises an exception (to test exception propagation) */
129 INFO0("Call the exception raising RPC");
131 gras_msg_rpccall(toserver, 6000.0, "raise exception", NULL, NULL);
134 xbt_assert2(e.category == unknown_error,
135 "Got wrong category: %d (instead of %d)",
136 e.category,unknown_error);
137 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
138 xbt_assert1(!strncmp(e.msg,exception_msg,strlen(exception_msg)),
139 "Got wrong message: %s", e.msg);
140 INFO0("Got the expected exception when calling the exception raising RPC");
145 THROW0(unknown_error,0,"Didn't got the remote exception!");
147 INFO0("Called the exception raising RPC");
148 exception_catching();
151 for (i=0; i<5; i++) {
153 INFO1("Call the exception raising RPC (i=%d)",i);
155 gras_msg_rpccall(toserver, 6000.0, "raise exception", NULL, NULL);
161 THROW0(unknown_error,0,"Didn't got the remote exception!");
166 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
168 INFO1("Call the exception raising RPC on the forwarder (i=%d)",i);
170 gras_msg_rpccall(toforwarder, 6000.0, "forward exception", NULL, NULL);
175 THROW0(unknown_error,0,"Didn't got the remote exception!");
177 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
178 xbt_assert1(!strncmp(e.msg,exception_msg,strlen(exception_msg)),
179 "Got wrong message: %s", e.msg);
180 xbt_assert2(e.category == unknown_error,
181 "Got wrong category: %d (instead of %d)",
182 e.category,unknown_error);
183 INFO0("Got the expected exception when calling the exception raising RPC");
185 exception_catching();
188 INFO2("Ask %s:%d to die",gras_socket_peer_name(toforwarder),gras_socket_peer_port(toforwarder));
189 gras_msg_send(toforwarder,"kill",NULL);
190 INFO2("Ask %s:%d to die",gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
191 gras_msg_send(toserver,"kill",NULL);
193 /* 11. Cleanup the place before leaving */
194 gras_socket_close(toserver);
195 gras_socket_close(toforwarder);
199 } /* end_of_client */
202 /* **********************************************************************
204 * **********************************************************************/
206 gras_socket_t server;
208 } s_forward_data_t, *forward_data_t;
210 static int forwarder_cb_kill(gras_msg_cb_ctx_t ctx,
211 void *payload_data) {
212 forward_data_t fdata;
213 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
214 INFO2("Asked to die by %s:%d",gras_socket_peer_name(expeditor),gras_socket_peer_port(expeditor));
215 fdata=gras_userdata_get();
220 static int forwarder_cb_forward_ex(gras_msg_cb_ctx_t ctx,
221 void *payload_data) {
222 forward_data_t fdata=gras_userdata_get();
224 INFO0("Forward a request");
225 gras_msg_rpccall(fdata->server, 60, "raise exception",NULL,NULL);
229 int forwarder (int argc,char *argv[]) {
230 gras_socket_t mysock;
232 forward_data_t fdata;
234 gras_init(&argc,argv);
236 xbt_assert(argc == 4);
238 fdata=gras_userdata_new(s_forward_data_t);
242 INFO1("Launch forwarder (port=%d)", port);
243 mysock = gras_socket_server(port);
245 gras_os_sleep(1); /* wait for the server to be ready */
246 fdata->server=gras_socket_client(argv[2],atoi(argv[3]));
249 gras_cb_register("forward exception", &forwarder_cb_forward_ex);
250 gras_cb_register("kill", &forwarder_cb_kill);
252 while (!fdata->done) {
253 gras_msg_handle(600.0);
256 gras_socket_close(mysock);
257 gras_socket_close(fdata->server);
264 /* **********************************************************************
266 * **********************************************************************/
268 gras_socket_t server;
270 } s_server_data_t, *server_data_t;
272 static int server_cb_kill(gras_msg_cb_ctx_t ctx,
273 void *payload_data) {
274 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
277 INFO2("Asked to die by %s:%d",gras_socket_peer_name(expeditor),gras_socket_peer_port(expeditor));
279 sdata=gras_userdata_get();
284 static int server_cb_raise_ex(gras_msg_cb_ctx_t ctx,
285 void *payload_data) {
290 static int server_cb_ping(gras_msg_cb_ctx_t ctx,
291 void *payload_data) {
293 /* 1. Get the payload into the msg variable, and retrieve who called us */
294 int msg=*(int*)payload_data;
295 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
297 /* 2. Log which client connected */
298 INFO3("Got message PING(%d) from %s:%d",
300 gras_socket_peer_name(expeditor), gras_socket_peer_port(expeditor));
302 /* 4. Change the value of the msg variable */
305 /* 5. Return as result */
306 gras_msg_rpcreturn(6000,ctx,&msg);
307 INFO0("Answered with PONG(4321)");
309 /* 6. Cleanups, if any */
311 /* 7. Tell GRAS that we consummed this message */
313 } /* end_of_server_cb_ping */
316 int server (int argc,char *argv[]) {
317 gras_socket_t mysock;
322 /* 1. Init the GRAS infrastructure */
323 gras_init(&argc,argv);
325 /* 2. Get the port I should listen on from the command line, if specified */
329 sdata=gras_userdata_new(s_server_data_t);
332 INFO1("Launch server (port=%d)", port);
334 /* 3. Create my master socket */
335 mysock = gras_socket_server(port);
337 /* 4. Register the known messages and register my callback */
339 gras_cb_register("plain ping",&server_cb_ping);
340 gras_cb_register("raise exception",&server_cb_raise_ex);
341 gras_cb_register("kill",&server_cb_kill);
343 INFO1("Listening on port %d", gras_socket_my_port(mysock));
345 /* 5. Wait for the ping incomming messages */
347 /** \bug if the server is gone before the forwarder tries to connect,
348 it dies awfully with the following message. The problem stands somewhere
349 at the interface between the gras_socket_t and the msg mess. There is thus
350 no way for me to dive into this before this interface is rewritten
351 ==15875== Invalid read of size 4
352 ==15875== at 0x408B805: find_port (transport_plugin_sg.c:68)
353 ==15875== by 0x408BD64: gras_trp_sg_socket_client (transport_plugin_sg.c:115)
354 ==15875== by 0x404A38B: gras_socket_client_ext (transport.c:255)
355 ==15875== by 0x404A605: gras_socket_client (transport.c:288)
356 ==15875== by 0x804B49D: forwarder (rpc.c:245)
357 ==15875== by 0x80491FB: launch_forwarder (_rpc_simulator.c:52)
358 ==15875== by 0x406780B: __context_wrapper (context.c:164)
359 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
360 ==15875== by 0x42AA549: clone (clone.S:119)
361 ==15875== Address 0x433B49C is 44 bytes inside a block of size 48 free'd
362 ==15875== at 0x401CF46: free (vg_replace_malloc.c:235)
363 ==15875== by 0x408F1FA: gras_process_exit (sg_process.c:117)
364 ==15875== by 0x4049386: gras_exit (gras.c:64)
365 ==15875== by 0x804B936: server (rpc.c:345)
366 ==15875== by 0x80492B1: launch_server (_rpc_simulator.c:69)
367 ==15875== by 0x406780B: __context_wrapper (context.c:164)
368 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
369 ==15875== by 0x42AA549: clone (clone.S:119)
371 while (!sdata->done) {
372 gras_msg_handle(600.0);
373 exception_catching();
376 /* 8. Free the allocated resources, and shut GRAS down */
378 gras_socket_close(mysock);
383 } /* end_of_server */