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_assert1(e.category == unknown_error, "Got wrong category: %d", e.category);
108 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
109 xbt_assert1(!strcmp(e.msg,"Some error we will catch on client side"),
110 "Got wrong message: %s", e.msg);;
111 INFO0("Got the expected exception when calling the exception raising RPC");
115 for (i=0; i<5; i++) {
117 INFO0("Call the exception raising RPC");
119 gras_msg_rpccall(toserver, 6000.0,
120 gras_msgtype_by_name("raise exception"), NULL, NULL);
126 THROW0(unknown_error,0,"Didn't got the remote exception!");
131 /* 9. Call a RPC which raises an exception (to test that exception propagation works) */
132 INFO0("Call the exception raising RPC on the forwarder");
135 gras_msg_rpccall(toforwarder, 6000.0,
136 gras_msgtype_by_name("forward exception"), NULL, NULL);
141 THROW0(unknown_error,0,"Didn't got the remote exception!");
143 xbt_assert1(e.category == unknown_error, "Got wrong category: %d", e.category);
144 xbt_assert1(e.value == 42, "Got wrong value: %d (!=42)", e.value);
145 xbt_assert1(!strcmp(e.msg,"Some error we will catch on client side"),
146 "Got wrong message: %s", e.msg);;
147 INFO0("Got the expected exception when calling the exception raising RPC");
151 /* 11. Cleanup the place before leaving */
152 gras_socket_close(toserver);
156 } /* end_of_client */
159 /* **********************************************************************
161 * **********************************************************************/
163 gras_socket_t server;
164 } s_forward_data_t, *forward_data_t;
166 static int server_cb_forward_ex(gras_msg_cb_ctx_t ctx,
167 void *payload_data) {
168 forward_data_t fdata=gras_userdata_get();
170 gras_msg_rpccall(fdata->server, 60, gras_msgtype_by_name("raise exception"),NULL,NULL);
174 int forwarder (int argc,char *argv[]) {
175 gras_socket_t mysock;
177 forward_data_t fdata;
179 gras_init(&argc,argv);
181 xbt_assert(argc == 4);
183 fdata=gras_userdata_new(s_forward_data_t);
186 INFO1("Launch forwarder (port=%d)", port);
187 mysock = gras_socket_server(port);
189 gras_os_sleep(0.1); /* wait for the server to be ready */
190 fdata->server=gras_socket_client(argv[2],atoi(argv[3]));
193 gras_cb_register(gras_msgtype_by_name("forward exception"),&server_cb_forward_ex);
195 gras_msg_handle(600.0); /* deal with the first forwarded request */
196 gras_msg_handle(600.0); /* deal with the second forwarded request */
197 gras_socket_close(mysock);
198 gras_socket_close(fdata->server);
205 /* **********************************************************************
207 * **********************************************************************/
209 static int server_cb_raise_ex(gras_msg_cb_ctx_t ctx,
210 void *payload_data) {
211 THROW0(unknown_error,42,"Some error we will catch on client side");
214 static int server_cb_ping(gras_msg_cb_ctx_t ctx,
215 void *payload_data) {
217 /* 1. Get the payload into the msg variable, and retrieve who called us */
218 int msg=*(int*)payload_data;
219 gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
221 /* 2. Log which client connected */
222 INFO3("Got message PING(%d) from %s:%d ",
224 gras_socket_peer_name(expeditor), gras_socket_peer_port(expeditor));
226 /* 4. Change the value of the msg variable */
229 /* 5. Return as result */
230 gras_msg_rpcreturn(6000,ctx,&msg);
231 INFO0("Answered with PONG(4321)");
233 /* 6. Cleanups, if any */
235 /* 7. Tell GRAS that we consummed this message */
237 } /* end_of_server_cb_ping */
240 int server (int argc,char *argv[]) {
241 gras_socket_t mysock;
246 /* 1. Init the GRAS infrastructure */
247 gras_init(&argc,argv);
249 /* 2. Get the port I should listen on from the command line, if specified */
253 INFO1("Launch server (port=%d)", port);
255 /* 3. Create my master socket */
256 mysock = gras_socket_server(port);
258 /* 4. Register the known messages and register my callback */
260 gras_cb_register(gras_msgtype_by_name("plain ping"),&server_cb_ping);
261 gras_cb_register(gras_msgtype_by_name("raise exception"),&server_cb_raise_ex);
263 INFO1("Listening on port %d ", gras_socket_my_port(mysock));
265 /* 5. Wait for the ping incomming messages */
266 gras_msg_handle(600.0);
267 /* 6. Wait for the exception raiser incomming messages */
268 gras_msg_handle(600.0);
271 gras_msg_handle(600.0);
274 /* 7. Wait for the exception forwarder incomming messages (twice, to see if it triggers bugs) */
275 gras_msg_handle(600.0);
276 gras_msg_handle(600.0);
278 /* 8. Free the allocated resources, and shut GRAS down */
279 gras_socket_close(mysock);
284 } /* end_of_server */