1 /*////////////////////////////////////////////////////*/
2 // Peer-To-Peer CAN simulator 050406 by Dytto ESIAL //
3 //////////////////////////////////////////////////////
6 #include "xbt/sysdep.h"
10 //#include "types.h" // header alone containing the typedef struct of a node // include can_tests.c must be OFF.
12 //XBT_LOG_NEW_DEFAULT_CATEGORY(can,"Messages specific to this example"); // include can_tests.c must be OFF.
14 //extern char *_gras_this_type_symbol_does_not_exist__s_nuke;
15 int node_nuke_handler(gras_msg_cb_ctx_t ctx,void *payload_data);
17 // struct of a "get_successor" message, when a node look after the area in which he want to be.
18 GRAS_DEFINE_TYPE(s_get_suc,
26 typedef struct s_get_suc get_suc_t;
28 // struct of a "response_successor" message, hen a node receive the information of his new area.
29 GRAS_DEFINE_TYPE(s_rep_suc,
36 char north_host[1024];
38 char south_host[1024];
46 typedef struct s_rep_suc rep_suc_t;
48 int node(int argc,char **argv);
50 // registering messages types
51 static void register_messages(){
52 gras_msgtype_declare("can_get_suc",gras_datadesc_by_symbol(s_get_suc));
53 gras_msgtype_declare("can_rep_suc",gras_datadesc_by_symbol(s_rep_suc));
54 gras_msgtype_declare("can_nuke",gras_datadesc_by_symbol(s_nuke));// can_test.c message // include can_tests.c must be ON.
58 // a forwarding function for a "get_suc" message.
59 static void forward_get_suc(get_suc_t msg, char host[1024], int port){
60 gras_socket_t temp_sock=NULL;
61 xbt_ex_t e; // the error variable used in TRY.. CATCH tokens.
62 //INFO2("Transmiting message to %s:%d",host,port);
64 temp_sock=gras_socket_client(host,port);
66 RETHROW0("Unable to connect!: %s");
69 gras_msg_send(temp_sock,gras_msgtype_by_name("can_get_suc"),&msg);
71 RETHROW0("Unable to send!: %s");
73 INFO3("Forwarding a get_successor message to %s for (%d;%d)",host,msg.xId,msg.yId);
74 gras_socket_close(temp_sock);
77 // the handling function of a "get_suc" message (what do a node when he receive a "get_suc" message.
78 static int node_get_suc_handler(gras_msg_cb_ctx_t ctx,void *payload_data){
79 gras_socket_t expeditor=gras_msg_cb_ctx_from(ctx);
80 get_suc_t *incoming=(get_suc_t*)payload_data;
81 xbt_ex_t e; // the error variable used in TRY.. CATCH tokens.
82 node_data_t *globals=(node_data_t*)gras_userdata_get();
84 INFO3("Received a get_successor message from %s for (%d;%d)",gras_socket_peer_name(expeditor),incoming->xId,incoming->yId);
85 //INFO4("My area is [%d;%d;%d;%d]",globals->x1,globals->x2,globals->y1,globals->y2);
86 if(incoming->xId<globals->x1) // test if the message must be forwarded to a neighbour.
87 forward_get_suc(*incoming, globals->west_host, globals->west_port);
88 else if(incoming->xId>globals->x2)
89 forward_get_suc(*incoming, globals->east_host, globals->east_port);
90 else if(incoming->yId<globals->y1)
91 forward_get_suc(*incoming, globals->south_host, globals->south_port);
92 else if(incoming->yId>globals->y2)
93 forward_get_suc(*incoming, globals->north_host, globals->north_port);
94 else{ // if the message must not be forwarded, then the area is splitted in half and one half is assignated to the new node.
97 INFO4("Spliting my area between me (%d;%d) and the inserting node (%d;%d)!",
98 globals->xId,globals->yId,incoming->xId,incoming->yId);
99 if((globals->x2-globals->x1)>(globals->y2-globals->y1)){ // the height of the area is smaller than its width.
100 if(incoming->xId<globals->xId){ // the new node is west from the actual node.
101 outgoing.x1=globals->x1;
102 outgoing.x2=(incoming->xId+globals->xId)/2;
103 outgoing.y1=globals->y1;
104 outgoing.y2=globals->y2;
105 strcpy(outgoing.north_host,globals->north_host);
106 outgoing.north_port=globals->north_port;
107 strcpy(outgoing.south_host,globals->south_host);
108 outgoing.south_port=globals->south_port;
109 strcpy(outgoing.east_host,globals->host);
110 outgoing.east_port=globals->port;
111 strcpy(outgoing.west_host,globals->west_host);
112 outgoing.west_port=globals->west_port;
114 globals->x1=(incoming->xId+globals->xId)/2;
115 strcpy(globals->west_host,incoming->host);
116 globals->west_port=incoming->port;
119 else if(incoming->xId>globals->xId){ // the new node is east from the actual node.
120 outgoing.x1=(incoming->xId+globals->xId)/2;
121 outgoing.x2=globals->x2;
122 outgoing.y1=globals->y1;
123 outgoing.y2=globals->y2;
124 strcpy(outgoing.north_host,globals->north_host);
125 outgoing.north_port=globals->north_port;
126 strcpy(outgoing.south_host,globals->south_host);
127 outgoing.south_port=globals->south_port;
128 strcpy(outgoing.east_host,globals->east_host);
129 outgoing.east_port=globals->east_port;
130 strcpy(outgoing.west_host,globals->host);
131 outgoing.west_port=globals->port;
133 globals->x2=(incoming->xId+globals->xId)/2;
134 strcpy(globals->east_host,incoming->host);
135 globals->east_port=incoming->port;
140 if(incoming->yId<globals->yId){ // the new node is south from the actual node.
141 outgoing.y1=globals->y1;
142 outgoing.y2=(incoming->yId+globals->yId)/2;
143 outgoing.y1=globals->y1;
144 outgoing.x2=globals->x2;
145 strcpy(outgoing.east_host,globals->east_host);
146 outgoing.east_port=globals->east_port;
147 strcpy(outgoing.west_host,globals->west_host);
148 outgoing.west_port=globals->west_port;
149 strcpy(outgoing.north_host,globals->host);
150 outgoing.north_port=globals->port;
151 strcpy(outgoing.south_host,globals->south_host);
152 outgoing.south_port=globals->south_port;
154 globals->y1=(incoming->yId+globals->yId)/2;
155 strcpy(globals->south_host,incoming->host);
156 globals->south_port=incoming->port;
159 else if(incoming->yId>globals->yId){ // the new node is north from the actual node.
160 outgoing.y1=(incoming->yId+globals->yId)/2;
161 outgoing.y2=globals->y2;
162 outgoing.x1=globals->x1;
163 outgoing.x2=globals->x2;
164 strcpy(outgoing.east_host,globals->east_host);
165 outgoing.east_port=globals->east_port;
166 strcpy(outgoing.west_host,globals->west_host);
167 outgoing.west_port=globals->west_port;
168 strcpy(outgoing.north_host,globals->north_host);
169 outgoing.north_port=globals->north_port;
170 strcpy(outgoing.south_host,globals->host);
171 outgoing.south_port=globals->port;
173 globals->y2=(incoming->yId+globals->yId)/2;
174 strcpy(globals->north_host,incoming->host);
175 globals->north_port=incoming->port;
179 if(validate==1){ // the area for the new node has been defined, then send theses informations to the new node.
180 INFO2("Sending environment informations to node %s:%d",incoming->host,incoming->port);
181 gras_socket_t temp_sock=NULL;
183 temp_sock=gras_socket_client(incoming->host,incoming->port);
185 RETHROW0("Unable to connect to the node wich has requested for an area!: %s");
188 gras_msg_send(temp_sock,gras_msgtype_by_name("can_rep_suc"),&outgoing);
189 INFO0("Environment informations sent!");
191 RETHROW2("%s:Timeout sending environment informations to %s: %s",globals->host,gras_socket_peer_name(expeditor));
193 gras_socket_close(temp_sock);
195 else // we have a problem!
196 INFO0("An error occurded!!!!!!!!!!!!!");
199 gras_socket_close(expeditor); // spare
201 gras_msg_handle(10000.0); // wait a bit in case of someone want to ask me for something.
203 INFO4("My area is [%d;%d;%d;%d]",globals->x1,globals->x2,globals->y1,globals->y2);
204 //INFO0("Closing node, all has been done!");
213 int node(int argc,char **argv){
214 node_data_t *globals=NULL;
215 xbt_ex_t e; // the error variable used in TRY.. CATCH tokens.
219 /* 1. Init the GRAS infrastructure and declare my globals */
220 gras_init(&argc,argv);
221 gras_os_sleep((15-gras_os_getpid())*20); // wait a bit.
223 globals=gras_userdata_new(node_data_t);
225 globals->xId=atoi(argv[1]); // x coordinate of the node.
226 globals->yId=atoi(argv[2]); // y coordinate of the node.
227 globals->port=atoi(argv[3]); // node port
228 globals->sock=gras_socket_server(globals->port); // node socket.
229 snprintf(globals->host,1024,gras_os_myname()); // node name.
230 globals->version=0; // node version (used for fun)
232 /* 2. Inserting the Node */
233 INFO2("Inserting node %s:%d",globals->host,globals->port);
234 if(argc==4){ // the node is a server, then he has the whole area.
239 }else{ // asking for an area.
240 INFO1("Contacting %s so as to request for an area",argv[4]);
241 gras_socket_t temp_sock=NULL;
243 temp_sock=gras_socket_client(argv[4],atoi(argv[5]));
245 RETHROW0("Unable to connect known host to request for an area!: %s");
248 get_suc_t get_suc_msg; // building the "get_suc" message.
249 get_suc_msg.xId=globals->xId;
250 get_suc_msg.yId=globals->yId;
251 strcpy(get_suc_msg.host,globals->host);
252 get_suc_msg.port=globals->port;
254 gras_msg_send(temp_sock,gras_msgtype_by_name("can_get_suc"),&get_suc_msg);
256 gras_socket_close(temp_sock);
257 RETHROW0("Unable to contact known host to get an area!: %s");
259 gras_socket_close(temp_sock);
261 rep_suc_t rep_suc_msg;
262 gras_socket_t temp_sock2=NULL;
263 TRY{ // waiting for a reply.
264 INFO0("Waiting for reply!");
265 gras_msg_wait(6000,gras_msgtype_by_name("can_rep_suc"),&temp_sock2,&rep_suc_msg);
267 RETHROW1("%s: Error waiting for an area:%s",globals->host);
270 // retreiving the data of the response.
271 globals->x1=rep_suc_msg.x1;
272 globals->x2=rep_suc_msg.x2;
273 globals->y1=rep_suc_msg.y1;
274 globals->y2=rep_suc_msg.y2;
275 strcpy(globals->north_host,rep_suc_msg.north_host);
276 globals->north_port=rep_suc_msg.north_port;
277 strcpy(globals->south_host,rep_suc_msg.south_host);
278 globals->south_port=rep_suc_msg.south_port;
279 strcpy(globals->east_host,rep_suc_msg.east_host);
280 globals->east_port=rep_suc_msg.east_port;
281 strcpy(globals->west_host,rep_suc_msg.west_host);
282 globals->west_port=rep_suc_msg.west_port;
284 gras_socket_close(temp_sock); // spare
286 INFO2("Node %s:%d inserted",globals->host,globals->port);
288 // associating messages to handlers.
290 gras_cb_register(gras_msgtype_by_name("can_get_suc"),&node_get_suc_handler);
291 gras_cb_register(gras_msgtype_by_name("can_nuke"),&node_nuke_handler);// can_test.c handler // include can_tests.c must be ON.
294 gras_msg_handle(10000.0); // waiting.. in case of someone has something to say.
296 INFO4("My area is [%d;%d;%d;%d]",globals->x1,globals->x2,globals->y1,globals->y2);
297 //INFO0("Closing node, all has been done!");
300 gras_socket_close(globals->sock); // spare.
301 free(globals); // spare.