Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
5095e3013d224d5aa3c5fc642bf9494ac767fd5b
[simgrid.git] / examples / gras / ping / ping.c
1 #include "ping.h"
2
3
4 XBT_LOG_NEW_DEFAULT_CATEGORY(Ping,"Messages specific to this example");
5
6 /* Global private data */
7 typedef struct {
8   gras_socket_t sock;
9   int endcondition;
10 } server_data_t;
11
12
13 /* register messages which may be sent (common to client and server) */
14 void ping_register_messages(void) {
15   gras_msgtype_declare("ping", gras_datadesc_by_name("int"));
16   gras_msgtype_declare("pong", gras_datadesc_by_name("int"));
17   INFO0("Messages registered");
18 }
19
20 static int server_cb_ping_handler(gras_msg_cb_ctx_t ctx, void* payload) {
21                              
22   xbt_ex_t e;
23   /* 1. Get the payload into the msg variable, and retrieve my caller */
24   int msg=*(int*)payload;
25   gras_socket_t expeditor = gras_msg_cb_ctx_from(ctx);
26
27   /* 2. Retrieve the server's state (globals) */
28
29   server_data_t *globals=(server_data_t*)gras_userdata_get();
30   globals->endcondition = 0;
31    
32   /* 3. Log which client connected */
33   INFO3(">>>>>>>> Got message PING(%d) from %s:%d <<<<<<<<", 
34         msg, 
35         gras_socket_peer_name(expeditor), gras_socket_peer_port(expeditor));
36   
37   /* 4. Change the value of the msg variable */
38   msg = 4321;
39   /* 5. Send it back as payload of a pong message to the expeditor */
40   TRY {
41     gras_msg_send(expeditor, "pong", &msg);
42
43   /* 6. Deal with errors: add some details to the exception */
44   } CATCH(e) {
45     gras_socket_close(globals->sock);
46     RETHROW0("Unable answer with PONG: %s");
47   }
48
49   INFO0(">>>>>>>> Answered with PONG(4321) <<<<<<<<");
50    
51   /* 7. Set the endcondition boolean to true (and make sure the server stops after receiving it). */
52   globals->endcondition = 1;
53   
54   /* 8. Make sure we don't leak sockets */
55   gras_socket_close(expeditor);
56    
57   /* 9. Tell GRAS that we consummed this message */
58   return 0;
59 } /* end_of_server_cb_ping_handler */
60
61 int server (int argc,char *argv[]) {
62   server_data_t *globals;
63
64   int port = 4000;
65   
66   /* 1. Init the GRAS infrastructure and declare my globals */
67   gras_init(&argc,argv);
68   globals=gras_userdata_new(server_data_t);
69    
70   /* 2. Get the port I should listen on from the command line, if specified */
71   if (argc == 2) {
72     port=atoi(argv[1]);
73   }
74
75   INFO1("Launch server (port=%d)", port);
76
77   /* 3. Create my master socket */
78   globals->sock = gras_socket_server(port);
79
80   /* 4. Register the known messages. This function is called twice here, but it's because
81         this file also acts as regression test, no need to do so yourself of course. */
82   ping_register_messages();
83   ping_register_messages(); /* just to make sure it works ;) */
84    
85   /* 5. Register my callback */
86   gras_cb_register("ping",&server_cb_ping_handler);
87
88   INFO1(">>>>>>>> Listening on port %d <<<<<<<<", gras_socket_my_port(globals->sock));
89   globals->endcondition=0;
90
91   /* 6. Wait up to 10 minutes for an incomming message to handle */
92   gras_msg_handle(60.0);
93    
94   /* 7. Housekeeping */
95   if (!globals->endcondition)
96      WARN0("An error occured, the endcondition was not set by the callback");
97   
98   /* 8. Free the allocated resources, and shut GRAS down */
99   gras_socket_close(globals->sock);
100   free(globals);
101   gras_exit();
102    
103   INFO0("Done.");
104   return 0;
105 } /* end_of_server */
106
107
108 int client(int argc,char *argv[]) {
109   xbt_ex_t e; 
110   gras_socket_t toserver=NULL; /* peer */
111
112   gras_socket_t from;
113   int ping, pong;
114
115   const char *host = "127.0.0.1";
116         int   port = 4000;
117
118   /* 1. Init the GRAS's infrastructure */
119   gras_init(&argc, argv);
120    
121   /* 2. Get the server's address. The command line override defaults when specified */
122   if (argc == 3) {
123     host=argv[1];
124     port=atoi(argv[2]);
125   } 
126
127   INFO2("Launch client (server on %s:%d)",host,port);
128    
129   /* 3. Wait for the server startup */
130   gras_os_sleep(1);
131    
132   /* 4. Create a socket to speak to the server */
133   TRY {
134     toserver=gras_socket_client(host,port);
135   } CATCH(e) {
136     RETHROW0("Unable to connect to the server: %s");
137   }
138   INFO2("Connected to %s:%d.",host,port);    
139
140
141   /* 5. Register the messages. 
142         See, it doesn't have to be done completely at the beginning, only before use */
143   ping_register_messages();
144
145   /* 6. Keep the user informed of what's going on */
146   INFO2(">>>>>>>> Connected to server which is on %s:%d <<<<<<<<", 
147         gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
148
149   /* 7. Prepare and send the ping message to the server */
150   ping = 1234;
151   TRY {
152     gras_msg_send(toserver, "ping", &ping);
153   } CATCH(e) {
154     gras_socket_close(toserver);
155     RETHROW0("Failed to send PING to server: %s");
156   }
157   INFO3(">>>>>>>> Message PING(%d) sent to %s:%d <<<<<<<<",
158         ping,
159         gras_socket_peer_name(toserver),gras_socket_peer_port(toserver));
160
161   /* 8. Wait for the answer from the server, and deal with issues */
162   TRY {
163     gras_msg_wait(6000,"pong", &from,&pong);
164   } CATCH(e) {
165     gras_socket_close(toserver);
166     RETHROW0("Why can't I get my PONG message like everyone else: %s");
167   }
168
169   /* 9. Keep the user informed of what's going on, again */
170   INFO3(">>>>>>>> Got PONG(%d) from %s:%d <<<<<<<<", 
171         pong,
172         gras_socket_peer_name(from),gras_socket_peer_port(from));
173
174   /* 10. Free the allocated resources, and shut GRAS down */
175   gras_socket_close(toserver);
176   gras_exit();
177   INFO0("Done.");
178   return 0;
179 } /* end_of_client */