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 */
70 memset(&e,0,sizeof(xbt_ex_t));
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, "plain ping", &ping, &pong);
120 gras_socket_close(toserver);
121 RETHROW0("Failed to execute a PING rpc on the server: %s");
123 exception_catching();
125 /* 8. Keep the user informed of what's going on, again */
126 INFO4("The answer to PING(%d) on %s:%d is PONG(%d) ",
128 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver),
131 /* 9. Call a RPC which raises an exception (to test exception propagation) */
132 INFO0("Call the exception raising RPC");
134 gras_msg_rpccall(toserver, 6000.0, "raise exception", NULL, NULL);
137 xbt_assert2(e.category == unknown_error,
138 "Got wrong category: %d (instead of %d)",
139 e.category,unknown_error);
140 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
141 xbt_assert1(!strncmp(e.msg,"Some error we will catch on client side",
142 strlen("Some error we will catch on client side")),
143 "Got wrong message: %s", e.msg);
144 INFO0("Got the expected exception when calling the exception raising RPC");
149 THROW0(unknown_error,0,"Didn't got the remote exception!");
151 INFO0("Called the exception raising RPC");
152 exception_catching();
155 for (i=0; i<5; i++) {
157 INFO1("Call the exception raising RPC (i=%d)",i);
159 gras_msg_rpccall(toserver, 6000.0, "raise exception", NULL, NULL);
165 THROW0(unknown_error,0,"Didn't got the remote exception!");
170 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
172 INFO1("Call the exception raising RPC on the forwarder (i=%d)",i);
174 gras_msg_rpccall(toforwarder, 6000.0, "forward exception", NULL, NULL);
179 THROW0(unknown_error,0,"Didn't got the remote exception!");
181 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
182 xbt_assert1(!strncmp(e.msg,"Some error we will catch on client side",
183 strlen("Some error we will catch on client side")),
184 "Got wrong message: %s", e.msg);
185 xbt_assert2(e.category == unknown_error,
186 "Got wrong category: %d (instead of %d)",
187 e.category,unknown_error);
188 INFO0("Got the expected exception when calling the exception raising RPC");
190 exception_catching();
193 INFO2("Ask %s:%d to die",gras_socket_peer_name(toforwarder),gras_socket_peer_port(toforwarder));
194 gras_msg_send(toforwarder,"kill",NULL);
195 INFO2("Ask %s:%d to die",gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
196 gras_msg_send(toserver,"kill",NULL);
198 /* 11. Cleanup the place before leaving */
199 gras_socket_close(toserver);
200 gras_socket_close(toforwarder);
204 } /* end_of_client */
207 /* **********************************************************************
209 * **********************************************************************/
211 gras_socket_t server;
213 } s_forward_data_t, *forward_data_t;
215 static int forwarder_cb_kill(gras_msg_cb_ctx_t ctx,
216 void *payload_data) {
217 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
218 INFO2("Asked to die by %s:%d",gras_socket_peer_name(expeditor),gras_socket_peer_port(expeditor));
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 INFO0("Forward a request");
229 gras_msg_rpccall(fdata->server, 60, "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("forward exception", &forwarder_cb_forward_ex);
254 gras_cb_register("kill", &forwarder_cb_kill);
256 while (!fdata->done) {
257 gras_msg_handle(600.0);
260 gras_socket_close(mysock);
261 gras_socket_close(fdata->server);
268 /* **********************************************************************
270 * **********************************************************************/
272 gras_socket_t server;
274 } s_server_data_t, *server_data_t;
276 static int server_cb_kill(gras_msg_cb_ctx_t ctx,
277 void *payload_data) {
278 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
279 INFO2("Asked to die by %s:%d",gras_socket_peer_name(expeditor),gras_socket_peer_port(expeditor));
281 server_data_t sdata=gras_userdata_get();
286 static int server_cb_raise_ex(gras_msg_cb_ctx_t ctx,
287 void *payload_data) {
292 static int server_cb_ping(gras_msg_cb_ctx_t ctx,
293 void *payload_data) {
295 /* 1. Get the payload into the msg variable, and retrieve who called us */
296 int msg=*(int*)payload_data;
297 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
299 /* 2. Log which client connected */
300 INFO3("Got message PING(%d) from %s:%d ",
302 gras_socket_peer_name(expeditor), gras_socket_peer_port(expeditor));
304 /* 4. Change the value of the msg variable */
307 /* 5. Return as result */
308 gras_msg_rpcreturn(6000,ctx,&msg);
309 INFO0("Answered with PONG(4321)");
311 /* 6. Cleanups, if any */
313 /* 7. Tell GRAS that we consummed this message */
315 } /* end_of_server_cb_ping */
318 int server (int argc,char *argv[]) {
319 gras_socket_t mysock;
324 /* 1. Init the GRAS infrastructure */
325 gras_init(&argc,argv);
327 /* 2. Get the port I should listen on from the command line, if specified */
331 sdata=gras_userdata_new(s_server_data_t);
334 INFO1("Launch server (port=%d)", port);
336 /* 3. Create my master socket */
337 mysock = gras_socket_server(port);
339 /* 4. Register the known messages and register my callback */
341 gras_cb_register("plain ping",&server_cb_ping);
342 gras_cb_register("raise exception",&server_cb_raise_ex);
343 gras_cb_register("kill",&server_cb_kill);
345 INFO1("Listening on port %d ", gras_socket_my_port(mysock));
347 /* 5. Wait for the ping incomming messages */
349 /** \bug if the server is gone before the forwarder tries to connect,
350 it dies awfully with the following message. The problem stands somewhere
351 at the interface between the gras_socket_t and the msg mess. There is thus
352 no way for me to dive into this before this interface is rewritten
353 ==15875== Invalid read of size 4
354 ==15875== at 0x408B805: find_port (transport_plugin_sg.c:68)
355 ==15875== by 0x408BD64: gras_trp_sg_socket_client (transport_plugin_sg.c:115)
356 ==15875== by 0x404A38B: gras_socket_client_ext (transport.c:255)
357 ==15875== by 0x404A605: gras_socket_client (transport.c:288)
358 ==15875== by 0x804B49D: forwarder (rpc.c:245)
359 ==15875== by 0x80491FB: launch_forwarder (_rpc_simulator.c:52)
360 ==15875== by 0x406780B: __context_wrapper (context.c:164)
361 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
362 ==15875== by 0x42AA549: clone (clone.S:119)
363 ==15875== Address 0x433B49C is 44 bytes inside a block of size 48 free'd
364 ==15875== at 0x401CF46: free (vg_replace_malloc.c:235)
365 ==15875== by 0x408F1FA: gras_process_exit (sg_process.c:117)
366 ==15875== by 0x4049386: gras_exit (gras.c:64)
367 ==15875== by 0x804B936: server (rpc.c:345)
368 ==15875== by 0x80492B1: launch_server (_rpc_simulator.c:69)
369 ==15875== by 0x406780B: __context_wrapper (context.c:164)
370 ==15875== by 0x41A6CB3: pthread_start_thread (manager.c:310)
371 ==15875== by 0x42AA549: clone (clone.S:119)
373 while (!sdata->done) {
374 gras_msg_handle(600.0);
375 exception_catching();
378 /* 8. Free the allocated resources, and shut GRAS down */
380 gras_socket_close(mysock);
385 } /* end_of_server */