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);
24 /* Function prototypes */
25 int server (int argc,char *argv[]);
26 int forwarder (int argc,char *argv[]);
27 int client (int argc,char *argv[]);
29 /* **********************************************************************
31 * **********************************************************************/
34 int client(int argc,char *argv[]) {
36 gras_socket_t toserver=NULL; /* peer */
37 gras_socket_t toforwarder=NULL; /* peer */
44 const char *host = "127.0.0.1";
47 /* 1. Init the GRAS's infrastructure */
48 gras_init(&argc, argv);
50 /* 2. Get the server's address. The command line override defaults when specified */
56 INFO2("Launch client (server on %s:%d)",host,port);
58 /* 3. Wait for the server startup */
61 /* 4. Create a socket to speak to the server */
63 toserver=gras_socket_client(host,port);
64 toforwarder=gras_socket_client(argv[3],atoi(argv[4]));
66 RETHROW0("Unable to connect to the server: %s");
68 INFO2("Connected to %s:%d.",host,port);
71 /* 5. Register the messages.
72 See, it doesn't have to be done completely at the beginning,
73 but only before use */
76 /* 6. Keep the user informed of what's going on */
77 INFO2("Connected to server which is on %s:%d ",
78 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
80 /* 7. Prepare and send the ping message to the server */
83 gras_msg_rpccall(toserver, 6000.0,
84 gras_msgtype_by_name("plain ping"), &ping, &pong);
86 gras_socket_close(toserver);
87 RETHROW0("Failed to execute a PING rpc on the server: %s");
90 /* 8. Keep the user informed of what's going on, again */
91 INFO4("The answer to PING(%d) on %s:%d is PONG(%d) ",
93 gras_socket_peer_name(toserver),gras_socket_peer_port(toserver),
96 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
97 INFO0("Call the exception raising RPC");
99 gras_msg_rpccall(toserver, 6000.0,
100 gras_msgtype_by_name("raise exception"), NULL, NULL);
105 THROW0(unknown_error,0,"Didn't got the remote exception!");
107 xbt_assert2(e.category == unknown_error, "Got wrong category: %d (instead of %d)",
108 e.category,unknown_error);
109 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
110 xbt_assert1(!strcmp(e.msg,"Some error we will catch on client side"),
111 "Got wrong message: %s", e.msg);;
112 INFO0("Got the expected exception when calling the exception raising RPC");
116 for (i=0; i<5; i++) {
118 INFO1("Call the exception raising RPC (i=%d)",i);
120 gras_msg_rpccall(toserver, 6000.0,
121 gras_msgtype_by_name("raise exception"), NULL, NULL);
127 THROW0(unknown_error,0,"Didn't got the remote exception!");
132 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
134 INFO1("Call the exception raising RPC on the forwarder (i=%d)",i);
136 gras_msg_rpccall(toforwarder, 6000.0,
137 gras_msgtype_by_name("forward exception"), NULL, NULL);
142 THROW0(unknown_error,0,"Didn't got the remote exception!");
144 xbt_assert1(e.category == unknown_error, "Got wrong category: %d", e.category);
145 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
146 xbt_assert1(!strcmp(e.msg,"Some error we will catch on client side"),
147 "Got wrong message: %s", e.msg);;
148 INFO0("Got the expected exception when calling the exception raising RPC");
152 /* 11. Cleanup the place before leaving */
153 gras_socket_close(toserver);
157 } /* end_of_client */
160 /* **********************************************************************
162 * **********************************************************************/
164 gras_socket_t server;
165 } s_forward_data_t, *forward_data_t;
167 static int server_cb_forward_ex(gras_msg_cb_ctx_t ctx,
168 void *payload_data) {
169 forward_data_t fdata=gras_userdata_get();
171 gras_msg_rpccall(fdata->server, 60, gras_msgtype_by_name("raise exception"),NULL,NULL);
175 int forwarder (int argc,char *argv[]) {
176 gras_socket_t mysock;
178 forward_data_t fdata;
180 gras_init(&argc,argv);
182 xbt_assert(argc == 4);
184 fdata=gras_userdata_new(s_forward_data_t);
187 INFO1("Launch forwarder (port=%d)", port);
188 mysock = gras_socket_server(port);
190 gras_os_sleep(0.1); /* wait for the server to be ready */
191 fdata->server=gras_socket_client(argv[2],atoi(argv[3]));
194 gras_cb_register(gras_msgtype_by_name("forward exception"),&server_cb_forward_ex);
196 gras_msg_handle(600.0); /* deal with the first forwarded request */
197 gras_msg_handle(600.0); /* deal with the second forwarded request */
198 gras_socket_close(mysock);
199 gras_socket_close(fdata->server);
206 /* **********************************************************************
208 * **********************************************************************/
210 static int server_cb_raise_ex(gras_msg_cb_ctx_t ctx,
211 void *payload_data) {
212 THROW0(unknown_error,42,"Some error we will catch on client side");
215 static int server_cb_ping(gras_msg_cb_ctx_t ctx,
216 void *payload_data) {
218 /* 1. Get the payload into the msg variable, and retrieve who called us */
219 int msg=*(int*)payload_data;
220 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
222 /* 2. Log which client connected */
223 INFO3("Got message PING(%d) from %s:%d ",
225 gras_socket_peer_name(expeditor), gras_socket_peer_port(expeditor));
227 /* 4. Change the value of the msg variable */
230 /* 5. Return as result */
231 gras_msg_rpcreturn(6000,ctx,&msg);
232 INFO0("Answered with PONG(4321)");
234 /* 6. Cleanups, if any */
236 /* 7. Tell GRAS that we consummed this message */
238 } /* end_of_server_cb_ping */
241 int server (int argc,char *argv[]) {
242 gras_socket_t mysock;
247 /* 1. Init the GRAS infrastructure */
248 gras_init(&argc,argv);
250 /* 2. Get the port I should listen on from the command line, if specified */
254 INFO1("Launch server (port=%d)", port);
256 /* 3. Create my master socket */
257 mysock = gras_socket_server(port);
259 /* 4. Register the known messages and register my callback */
261 gras_cb_register(gras_msgtype_by_name("plain ping"),&server_cb_ping);
262 gras_cb_register(gras_msgtype_by_name("raise exception"),&server_cb_raise_ex);
264 INFO1("Listening on port %d ", gras_socket_my_port(mysock));
266 /* 5. Wait for the ping incomming messages */
267 gras_msg_handle(600.0);
268 /* 6. Wait for the exception raiser incomming messages */
269 gras_msg_handle(600.0);
272 gras_msg_handle(600.0);
275 /* 7. Wait for the exception forwarder incomming messages (twice, to see if it triggers bugs) */
276 gras_msg_handle(600.0);
277 gras_msg_handle(600.0);
279 /* 8. Free the allocated resources, and shut GRAS down */
280 gras_socket_close(mysock);
285 } /* end_of_server */