- fix dht
[oweals/gnunet.git] / src / mesh / gnunet-service-mesh_local.c
1 /*
2      This file is part of GNUnet.
3      (C) 2013 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 3, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21
22 #include "platform.h"
23 #include "gnunet_util_lib.h"
24
25 #include "gnunet_statistics_service.h"
26
27 #include "mesh_enc.h"
28 #include "mesh_protocol_enc.h" // GNUNET_MESH_Data is shared
29
30 #include "gnunet-service-mesh_local.h"
31 #include "gnunet-service-mesh_tunnel.h"
32
33 #define LOG(level, ...) GNUNET_log_from(level,"mesh-loc",__VA_ARGS__)
34
35 /******************************************************************************/
36 /********************************   STRUCTS  **********************************/
37 /******************************************************************************/
38
39 /**
40  * Struct containing information about a client of the service
41  *
42  * TODO: add a list of 'waiting' ports
43  */
44 struct MeshClient
45 {
46     /**
47      * Linked list next
48      */
49   struct MeshClient *next;
50
51     /**
52      * Linked list prev
53      */
54   struct MeshClient *prev;
55
56     /**
57      * Tunnels that belong to this client, indexed by local id
58      */
59   struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
60
61     /**
62      * Tunnels this client has accepted, indexed by incoming local id
63      */
64   struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
65
66     /**
67      * Channel ID for the next incoming channel.
68      */
69   MESH_ChannelNumber next_chid;
70
71     /**
72      * Handle to communicate with the client
73      */
74   struct GNUNET_SERVER_Client *handle;
75
76     /**
77      * Ports that this client has declared interest in.
78      * Indexed by port, contains *Client.
79      */
80   struct GNUNET_CONTAINER_MultiHashMap32 *ports;
81
82     /**
83      * Whether the client is active or shutting down (don't send confirmations
84      * to a client that is shutting down.
85      */
86   int shutting_down;
87
88     /**
89      * ID of the client, mainly for debug messages
90      */
91   unsigned int id;
92 };
93
94 /******************************************************************************/
95 /*******************************   GLOBALS  ***********************************/
96 /******************************************************************************/
97
98 /**
99  * Global handle to the statistics service.
100  */
101 extern struct GNUNET_STATISTICS_Handle *stats;
102
103 /**
104  * Handle to server lib.
105  */
106 static struct GNUNET_SERVER_Handle *server_handle;
107
108 /**
109  * DLL with all the clients, head.
110  */
111 static struct MeshClient *clients_head;
112
113 /**
114  * DLL with all the clients, tail.
115  */
116 static struct MeshClient *clients_tail;
117
118 /**
119  * Next ID to assign to a client.
120  */
121 unsigned int next_client_id;
122
123 /**
124  * All ports clients of this peer have opened.
125  */
126 static struct GNUNET_CONTAINER_MultiHashMap32 *ports;
127
128 /**
129  * Notification context, to send messages to local clients.
130  */
131 static struct GNUNET_SERVER_NotificationContext *nc;
132
133
134 /******************************************************************************/
135 /********************************   STATIC  ***********************************/
136 /******************************************************************************/
137
138 /**
139  * Remove client's ports from the global hashmap on disconnect.
140  *
141  * @param cls Closure (unused).
142  * @param key Port.
143  * @param value Client structure.
144  *
145  * @return GNUNET_OK, keep iterating.
146  */
147 static int
148 client_release_ports (void *cls,
149                       uint32_t key,
150                       void *value)
151 {
152   int res;
153
154   res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value);
155   if (GNUNET_YES != res)
156   {
157     GNUNET_break (0);
158     LOG (GNUNET_ERROR_TYPE_WARNING,
159                 "Port %u by client %p was not registered.\n",
160                 key, value);
161   }
162   return GNUNET_OK;
163 }
164
165
166
167 /******************************************************************************/
168 /********************************  HANDLES  ***********************************/
169 /******************************************************************************/
170
171
172 /**
173  * Handler for client connection.
174  *
175  * @param cls Closure (unused).
176  * @param client Client handler.
177  */
178 static void
179 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
180 {
181   struct MeshClient *c;
182
183   if (NULL == client)
184     return;
185   c = GNUNET_new (struct MeshClient);
186   c->handle = client;
187   c->id = next_client_id++; /* overflow not important: just for debug */
188   c->next_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
189   GNUNET_SERVER_client_keep (client);
190   GNUNET_SERVER_client_set_user_context (client, c);
191   GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
192 }
193
194
195 /**
196  * Handler for client disconnection
197  *
198  * @param cls closure
199  * @param client identification of the client; NULL
200  *        for the last call when the server is destroyed
201  */
202 static void
203 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
204 {
205   struct MeshClient *c;
206
207   LOG (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
208   if (client == NULL)
209   {
210     LOG (GNUNET_ERROR_TYPE_DEBUG, "   (SERVER DOWN)\n");
211     return;
212   }
213
214   c = client_get (client);
215   if (NULL != c)
216   {
217     LOG (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n",
218                 c->id, c);
219     GNUNET_SERVER_client_drop (c->handle);
220     c->shutting_down = GNUNET_YES;
221     if (NULL != c->own_channels)
222     {
223       GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
224                                                &channel_destroy_iterator, c);
225       GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
226     }
227
228     if (NULL != c->incoming_channels)
229     {
230       GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
231                                                &channel_destroy_iterator, c);
232       GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
233     }
234
235     if (NULL != c->ports)
236     {
237       GNUNET_CONTAINER_multihashmap32_iterate (c->ports,
238                                                &client_release_ports, c);
239       GNUNET_CONTAINER_multihashmap32_destroy (c->ports);
240     }
241     GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
242     GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
243     LOG (GNUNET_ERROR_TYPE_DEBUG, "  client free (%p)\n", c);
244     GNUNET_free (c);
245   }
246   else
247   {
248     LOG (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n");
249   }
250   LOG (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
251   return;
252 }
253
254
255 /**
256  * Handler for new clients
257  *
258  * @param cls closure
259  * @param client identification of the client
260  * @param message the actual message, which includes messages the client wants
261  */
262 static void
263 handle_new_client (void *cls, struct GNUNET_SERVER_Client *client,
264                    const struct GNUNET_MessageHeader *message)
265 {
266   struct GNUNET_MESH_ClientConnect *cc_msg;
267   struct MeshClient *c;
268   unsigned int size;
269   uint32_t *p;
270   unsigned int i;
271
272   LOG (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
273
274   /* Check data sanity */
275   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
276   cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
277   if (0 != (size % sizeof (uint32_t)))
278   {
279     GNUNET_break (0);
280     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
281     return;
282   }
283   size /= sizeof (uint32_t);
284
285   /* Initialize new client structure */
286   c = GNUNET_SERVER_client_get_user_context (client, struct MeshClient);
287   LOG (GNUNET_ERROR_TYPE_DEBUG, "  client id %u\n", c->id);
288   LOG (GNUNET_ERROR_TYPE_DEBUG, "  client has %u ports\n", size);
289   if (size > 0)
290   {
291     uint32_t u32;
292
293     p = (uint32_t *) &cc_msg[1];
294     c->ports = GNUNET_CONTAINER_multihashmap32_create (size);
295     for (i = 0; i < size; i++)
296     {
297       u32 = ntohl (p[i]);
298       LOG (GNUNET_ERROR_TYPE_DEBUG, "    port: %u\n", u32);
299
300       /* store in client's hashmap */
301       GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c,
302                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
303       /* store in global hashmap */
304       /* FIXME only allow one client to have the port open,
305        *       have a backup hashmap with waiting clients */
306       GNUNET_CONTAINER_multihashmap32_put (ports, u32, c,
307                                            GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
308     }
309   }
310
311   c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
312   c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
313   GNUNET_SERVER_notification_context_add (nc, client);
314   GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
315
316   GNUNET_SERVER_receive_done (client, GNUNET_OK);
317   LOG (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
318 }
319
320
321 /**
322  * Handler for requests of new tunnels
323  *
324  * @param cls Closure.
325  * @param client Identification of the client.
326  * @param message The actual message.
327  */
328 static void
329 handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
330                        const struct GNUNET_MessageHeader *message)
331 {
332   struct GNUNET_MESH_ChannelMessage *msg;
333   struct MeshPeer *peer;
334   struct MeshTunnel2 *t;
335   struct MeshChannel *ch;
336   struct MeshClient *c;
337   MESH_ChannelNumber chid;
338
339   LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
340
341   /* Sanity check for client registration */
342   if (NULL == (c = client_get (client)))
343   {
344     GNUNET_break (0);
345     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
346     return;
347   }
348   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
349
350   /* Message size sanity check */
351   if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size))
352   {
353     GNUNET_break (0);
354     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
355     return;
356   }
357
358   msg = (struct GNUNET_MESH_ChannelMessage *) message;
359   LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s:%u\n",
360               GNUNET_i2s (&msg->peer), ntohl (msg->port));
361   chid = ntohl (msg->channel_id);
362
363   /* Sanity check for duplicate channel IDs */
364   if (NULL != channel_get_by_local_id (c, chid))
365   {
366     GNUNET_break (0);
367     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
368     return;
369   }
370
371   peer = peer_get (&msg->peer);
372   if (NULL == peer->tunnel)
373   {
374     peer->tunnel = tunnel_new ();
375     peer->tunnel->peer = peer;
376     if (peer->id == myid)
377     {
378       tunnel_change_state (peer->tunnel, MESH_TUNNEL_READY);
379     }
380     else
381     {
382       peer_connect (peer);
383     }
384   }
385   t = peer->tunnel;
386
387   /* Create channel */
388   ch = channel_new (t, c, chid);
389   if (NULL == ch)
390   {
391     GNUNET_break (0);
392     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
393     return;
394   }
395   ch->port = ntohl (msg->port);
396   channel_set_options (ch, ntohl (msg->opt));
397
398   /* In unreliable channels, we'll use the DLL to buffer BCK data */
399   ch->root_rel = GNUNET_new (struct MeshChannelReliability);
400   ch->root_rel->ch = ch;
401   ch->root_rel->expected_delay = MESH_RETRANSMIT_TIME;
402
403   LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s[%x]:%u (%x)\n",
404               peer2s (t->peer), ch->gid, ch->port, ch->lid_root);
405
406   /* Send create channel */
407   {
408     struct GNUNET_MESH_ChannelCreate msgcc;
409
410     msgcc.header.size = htons (sizeof (msgcc));
411     msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE);
412     msgcc.chid = htonl (ch->gid);
413     msgcc.port = msg->port;
414     msgcc.opt = msg->opt;
415
416     GMT_queue_data (t, ch, &msgcc.header, GNUNET_YES);
417   }
418
419   GNUNET_SERVER_receive_done (client, GNUNET_OK);
420   return;
421 }
422
423
424 /**
425  * Handler for requests of deleting tunnels
426  *
427  * @param cls closure
428  * @param client identification of the client
429  * @param message the actual message
430  */
431 static void
432 handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
433                         const struct GNUNET_MessageHeader *message)
434 {
435   struct GNUNET_MESH_ChannelMessage *msg;
436   struct MeshClient *c;
437   struct MeshChannel *ch;
438   struct MeshTunnel2 *t;
439   MESH_ChannelNumber chid;
440
441   LOG (GNUNET_ERROR_TYPE_DEBUG,
442               "Got a DESTROY CHANNEL from client!\n");
443
444   /* Sanity check for client registration */
445   if (NULL == (c = client_get (client)))
446   {
447     GNUNET_break (0);
448     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
449     return;
450   }
451   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
452
453   /* Message sanity check */
454   if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size))
455   {
456     GNUNET_break (0);
457     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
458     return;
459   }
460
461   msg = (struct GNUNET_MESH_ChannelMessage *) message;
462
463   /* Retrieve tunnel */
464   chid = ntohl (msg->channel_id);
465   ch = channel_get_by_local_id (c, chid);
466   if (NULL == ch)
467   {
468     LOG (GNUNET_ERROR_TYPE_ERROR, "  channel %X not found\n", chid);
469     GNUNET_break (0);
470     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
471     return;
472   }
473
474   /* Cleanup after the tunnel */
475   client_delete_channel (c, ch);
476   if (c == ch->dest && GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid)
477   {
478     ch->dest = NULL;
479   }
480   else if (c == ch->root && GNUNET_MESH_LOCAL_CHANNEL_ID_SERV > chid)
481   {
482     ch->root = NULL;
483   }
484   else
485   {
486     LOG (GNUNET_ERROR_TYPE_ERROR,
487                 "  channel %X client %p (%p, %p)\n",
488                 chid, c, ch->root, ch->dest);
489     GNUNET_break (0);
490   }
491
492   t = ch->t;
493   channel_destroy (ch);
494   tunnel_destroy_if_empty (t);
495
496   GNUNET_SERVER_receive_done (client, GNUNET_OK);
497   return;
498 }
499
500
501 /**
502  * Handler for client traffic
503  *
504  * @param cls closure
505  * @param client identification of the client
506  * @param message the actual message
507  */
508 static void
509 handle_data (void *cls, struct GNUNET_SERVER_Client *client,
510              const struct GNUNET_MessageHeader *message)
511 {
512   struct GNUNET_MESH_LocalData *msg;
513   struct MeshClient *c;
514   struct MeshChannel *ch;
515   struct MeshChannelReliability *rel;
516   MESH_ChannelNumber chid;
517   size_t size;
518   int fwd;
519
520   LOG (GNUNET_ERROR_TYPE_DEBUG,
521               "Got data from a client!\n");
522
523   /* Sanity check for client registration */
524   if (NULL == (c = client_get (client)))
525   {
526     GNUNET_break (0);
527     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
528     return;
529   }
530   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
531
532   msg = (struct GNUNET_MESH_LocalData *) message;
533
534   /* Sanity check for message size */
535   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_LocalData);
536   if (size < sizeof (struct GNUNET_MessageHeader))
537   {
538     GNUNET_break (0);
539     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
540     return;
541   }
542
543   /* Channel exists? */
544   chid = ntohl (msg->id);
545   fwd = chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
546   ch = channel_get_by_local_id (c, chid);
547   if (NULL == ch)
548   {
549     GNUNET_break (0);
550     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
551     return;
552   }
553
554   /* Is the client in the channel? */
555   if ( !( (fwd &&
556            ch->root &&
557            ch->root->handle == client)
558          ||
559           (!fwd &&
560            ch->dest &&
561            ch->dest->handle == client) ) )
562   {
563     GNUNET_break (0);
564     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
565     return;
566   }
567
568   rel = fwd ? ch->root_rel : ch->dest_rel;
569   rel->client_ready = GNUNET_NO;
570
571   /* Ok, everything is correct, send the message. */
572   {
573     struct GNUNET_MESH_Data *payload;
574     uint16_t p2p_size = sizeof(struct GNUNET_MESH_Data) + size;
575     unsigned char cbuf[p2p_size];
576
577     payload = (struct GNUNET_MESH_Data *) cbuf;
578     payload->mid = htonl (rel->mid_send);
579     rel->mid_send++;
580     memcpy (&payload[1], &msg[1], size);
581     payload->header.size = htons (p2p_size);
582     payload->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA);
583     payload->chid = htonl (ch->gid);
584     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
585     send_prebuilt_message_channel (&payload->header, ch, fwd);
586
587     if (GNUNET_YES == ch->reliable)
588       channel_save_copy (ch, &payload->header, fwd);
589   }
590   if (tunnel_get_buffer (ch->t, fwd) > 0)
591     send_local_ack (ch, fwd);
592   LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
593   GNUNET_SERVER_receive_done (client, GNUNET_OK);
594
595   return;
596 }
597
598
599 /**
600  * Handler for client's ACKs for payload traffic.
601  *
602  * @param cls Closure (unused).
603  * @param client Identification of the client.
604  * @param message The actual message.
605  */
606 static void
607 handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
608             const struct GNUNET_MessageHeader *message)
609 {
610   struct GNUNET_MESH_LocalAck *msg;
611   struct MeshChannelReliability *rel;
612   struct MeshChannel *ch;
613   struct MeshClient *c;
614   MESH_ChannelNumber chid;
615   int fwd;
616
617   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
618
619   /* Sanity check for client registration */
620   if (NULL == (c = client_get (client)))
621   {
622     GNUNET_break (0);
623     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
624     return;
625   }
626   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
627
628   msg = (struct GNUNET_MESH_LocalAck *) message;
629
630   /* Channel exists? */
631   chid = ntohl (msg->channel_id);
632   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
633   ch = channel_get_by_local_id (c, chid);
634   LOG (GNUNET_ERROR_TYPE_DEBUG, "   -- ch %p\n", ch);
635   if (NULL == ch)
636   {
637     GNUNET_break (0);
638     LOG (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid);
639     LOG (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
640     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
641     return;
642   }
643
644   /* If client is root, the ACK is going FWD, therefore this is "BCK". */
645   /* If client is dest, the ACK is going BCK, therefore this is "FWD" */
646   fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
647   rel = fwd ? ch->dest_rel : ch->root_rel;
648
649   rel->client_ready = GNUNET_YES;
650   channel_send_client_buffered_data (ch, c, fwd);
651   send_ack (NULL, ch, fwd);
652
653   GNUNET_SERVER_receive_done (client, GNUNET_OK);
654
655   return;
656 }
657
658
659 /*
660  * Iterator over all tunnels to send a monitoring client info about each tunnel.
661  *
662  * @param cls Closure (client handle).
663  * @param key Key (hashed tunnel ID, unused).
664  * @param value Tunnel info.
665  *
666  * @return GNUNET_YES, to keep iterating.
667  */
668 // static int
669 // monitor_all_tunnels_iterator (void *cls,
670 //                               const struct GNUNET_HashCode * key,
671 //                               void *value)
672 // {
673 //   struct GNUNET_SERVER_Client *client = cls;
674 //   struct MeshChannel *ch = value;
675 //   struct GNUNET_MESH_LocalMonitor *msg;
676 //
677 //   msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
678 //   msg->channel_id = htonl (ch->gid);
679 //   msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
680 //   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
681 //
682 //   LOG (GNUNET_ERROR_TYPE_INFO,
683 //               "*  sending info about tunnel %s\n",
684 //               GNUNET_i2s (&msg->owner));
685 //
686 //   GNUNET_SERVER_notification_context_unicast (nc, client,
687 //                                               &msg->header, GNUNET_NO);
688 //   return GNUNET_YES;
689 // }
690
691
692 /**
693  * Handler for client's MONITOR request.
694  *
695  * @param cls Closure (unused).
696  * @param client Identification of the client.
697  * @param message The actual message.
698  */
699 static void
700 handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
701                     const struct GNUNET_MessageHeader *message)
702 {
703   struct MeshClient *c;
704
705   /* Sanity check for client registration */
706   if (NULL == (c = client_get (client)))
707   {
708     GNUNET_break (0);
709     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
710     return;
711   }
712
713   LOG (GNUNET_ERROR_TYPE_INFO,
714               "Received get tunnels request from client %u\n",
715               c->id);
716 //   GNUNET_CONTAINER_multihashmap_iterate (tunnels,
717 //                                          monitor_all_tunnels_iterator,
718 //                                          client);
719   LOG (GNUNET_ERROR_TYPE_INFO,
720               "Get tunnels request from client %u completed\n",
721               c->id);
722   GNUNET_SERVER_receive_done (client, GNUNET_OK);
723 }
724
725
726 /**
727  * Handler for client's MONITOR_TUNNEL request.
728  *
729  * @param cls Closure (unused).
730  * @param client Identification of the client.
731  * @param message The actual message.
732  */
733 void
734 handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
735                     const struct GNUNET_MessageHeader *message)
736 {
737   const struct GNUNET_MESH_LocalMonitor *msg;
738   struct GNUNET_MESH_LocalMonitor *resp;
739   struct MeshClient *c;
740   struct MeshChannel *ch;
741
742   /* Sanity check for client registration */
743   if (NULL == (c = client_get (client)))
744   {
745     GNUNET_break (0);
746     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
747     return;
748   }
749
750   msg = (struct GNUNET_MESH_LocalMonitor *) message;
751   LOG (GNUNET_ERROR_TYPE_INFO,
752               "Received tunnel info request from client %u for tunnel %s[%X]\n",
753               c->id,
754               &msg->owner,
755               ntohl (msg->channel_id));
756 //   ch = channel_get (&msg->owner, ntohl (msg->channel_id));
757   ch = NULL; // FIXME
758   if (NULL == ch)
759   {
760     /* We don't know the tunnel */
761     struct GNUNET_MESH_LocalMonitor warn;
762
763     warn = *msg;
764     GNUNET_SERVER_notification_context_unicast (nc, client,
765                                                 &warn.header,
766                                                 GNUNET_NO);
767     GNUNET_SERVER_receive_done (client, GNUNET_OK);
768     return;
769   }
770
771   /* Initialize context */
772   resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
773   *resp = *msg;
774   resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
775   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
776                                               &resp->header, GNUNET_NO);
777   GNUNET_free (resp);
778
779   LOG (GNUNET_ERROR_TYPE_INFO,
780               "Monitor tunnel request from client %u completed\n",
781               c->id);
782   GNUNET_SERVER_receive_done (client, GNUNET_OK);
783 }
784
785
786 /**
787  * Functions to handle messages from clients
788  */
789 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
790   {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
791   {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE,
792    sizeof (struct GNUNET_MESH_ChannelMessage)},
793   {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY,
794    sizeof (struct GNUNET_MESH_ChannelMessage)},
795   {&handle_data, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
796   {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
797    sizeof (struct GNUNET_MESH_LocalAck)},
798   {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
799    sizeof (struct GNUNET_MessageHeader)},
800   {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
801    sizeof (struct GNUNET_MESH_LocalMonitor)},
802   {NULL, NULL, 0, 0}
803 };
804
805
806
807 /******************************************************************************/
808 /********************************    API    ***********************************/
809 /******************************************************************************/
810
811 /**
812  * Initialize server subsystem.
813  *
814  * @param handle Server handle.
815  */
816 void
817 GML_init (struct GNUNET_SERVER_Handle *handle)
818 {
819   server_handle = handle;
820   GNUNET_SERVER_suspend (server_handle);
821   ports = GNUNET_CONTAINER_multihashmap32_create (32);
822 }
823
824
825 /**
826  * Install server (service) handlers and start listening to clients.
827  */
828 void
829 GML_start (void)
830 {
831   GNUNET_SERVER_add_handlers (server_handle, client_handlers);
832   GNUNET_SERVER_connect_notify (server_handle,  &handle_client_connect, NULL);
833   GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
834                                    NULL);
835   nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
836
837   clients_head = NULL;
838   clients_tail = NULL;
839   next_client_id = 0;
840   GNUNET_SERVER_resume (server_handle);
841 }
842
843
844 /**
845  * Shutdown server.
846  */
847 void
848 GML_shutdown (void)
849 {
850   if (nc != NULL)
851   {
852     GNUNET_SERVER_notification_context_destroy (nc);
853     nc = NULL;
854   }
855 }
856
857
858 /**
859  * Get a chennel from a client
860  *
861  * @param c the client to check
862  * @param chid Channel ID, must be local (> 0x800...)
863  *
864  * @return non-NULL if channel exists in the clients lists
865  */
866 struct MeshChannel *
867 GML_channel_get (struct MeshClient *c, MESH_ChannelNumber chid)
868 {
869   if (0 == (chid & GNUNET_MESH_LOCAL_CHANNEL_ID_CLI))
870   {
871     GNUNET_break_op (0);
872     LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
873     return NULL;
874   }
875   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
876     return GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels, chid);
877   return GNUNET_CONTAINER_multihashmap32_get (c->own_channels, chid);
878 }
879
880
881 /**
882  * Add a channel to a client
883  *
884  * @param client Client.
885  * @param chid Channel ID.
886  * @param ch Channel.
887  */
888 void
889 GML_channel_add (struct MeshClient *client,
890                  uint32_t chid,
891                  struct MeshChannel *ch)
892 {
893   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
894     GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch,
895                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
896   else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)
897     GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
898                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
899   else
900     GNUNET_break (0);
901 }
902
903
904 /**
905  * Remove a channel from a client
906  *
907  * @param client Client.
908  * @param chid Channel ID.
909  * @param ch Channel.
910  */
911 void
912 GML_channel_remove (struct MeshClient *client,
913                     uint32_t chid,
914                     struct MeshChannel *ch)
915 {
916   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
917     GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels, chid, ch);
918   else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)
919     GNUNET_CONTAINER_multihashmap32_remove (c->own_channels, chid, ch);
920   else
921     GNUNET_break (0);
922 }
923
924
925 /**
926  * Get the tunnel's next free local channel ID.
927  *
928  * @param c Client.
929  *
930  * @return LID of a channel free to use.
931  */
932 MESH_ChannelNumber
933 GML_get_next_chid (struct MeshClient *c)
934 {
935   MESH_ChannelNumber chid;
936
937   while (NULL != GML_channel_get (c, c->next_chid))
938   {
939     LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid);
940     c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
941   }
942   chid = c->next_chid;
943   c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
944
945   return chid;
946 }
947
948
949 /**
950  * Check if client has registered with the service and has not disconnected
951  *
952  * @param client the client to check
953  *
954  * @return non-NULL if client exists in the global DLL
955  */
956 struct MeshClient *
957 GML_client_get (struct GNUNET_SERVER_Client *client)
958 {
959   return GNUNET_SERVER_client_get_user_context (client, struct MeshClient);
960 }
961
962 /**
963  * Find a client that has opened a port
964  *
965  * @param port Port to check.
966  *
967  * @return non-NULL if a client has the port.
968  */
969 struct MeshClient *
970 GML_client_get_by_port (uint32_t port)
971 {
972   return GNUNET_CONTAINER_multihashmap32_get (ports, port);
973 }
974
975
976 /**
977  * Deletes a tunnel from a client (either owner or destination).
978  *
979  * @param c Client whose tunnel to delete.
980  * @param ch Channel which should be deleted.
981  */
982 void
983 GML_client_delete_channel (struct MeshClient *c, struct MeshChannel *ch)
984 {
985   int res;
986
987   if (c == ch->root)
988   {
989     res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
990                                                   ch->lid_root, ch);
991     if (GNUNET_YES != res)
992       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel owner KO\n");
993   }
994   if (c == ch->dest)
995   {
996     res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
997                                                   ch->lid_dest, ch);
998     if (GNUNET_YES != res)
999       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel client KO\n");
1000   }
1001 }
1002
1003 /**
1004  * Build a local ACK message and send it to a local client, if needed.
1005  *
1006  * If the client was already allowed to send data, do nothing.
1007  *
1008  * @param ch Channel on which to send the ACK.
1009  * @param c Client to whom send the ACK.
1010  * @param fwd Set to GNUNET_YES for FWD ACK (dest->root)
1011  */
1012 void
1013 GML_send_ack (struct MeshChannel *ch, int fwd)
1014 {
1015   struct GNUNET_MESH_LocalAck msg;
1016   struct MeshChannelReliability *rel;
1017   struct MeshClient *c;
1018
1019   c   = fwd ? ch->root     : ch->dest;
1020   rel = fwd ? ch->root_rel : ch->dest_rel;
1021
1022   if (GNUNET_YES == rel->client_ready)
1023     return; /* don't send double ACKs to client */
1024
1025   rel->client_ready = GNUNET_YES;
1026
1027   LOG (GNUNET_ERROR_TYPE_DEBUG,
1028               "send local %s ack on %s:%X towards %p\n",
1029               fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid, c);
1030
1031   if (NULL == c
1032       || ( fwd && (0 == ch->lid_root || c != ch->root))
1033       || (!fwd && (0 == ch->lid_dest || c != ch->dest)) )
1034   {
1035     GNUNET_break (0);
1036     return;
1037   }
1038   msg.header.size = htons (sizeof (msg));
1039   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
1040   msg.channel_id = htonl (fwd ? ch->lid_root : ch->lid_dest);
1041   GNUNET_SERVER_notification_context_unicast (nc,
1042                                               c->handle,
1043                                               &msg.header,
1044                                               GNUNET_NO);
1045
1046 }
1047
1048
1049 /**
1050  * Notify the client that a new incoming channel was created.
1051  *
1052  * @param ch Channel that was created.
1053  */
1054 void
1055 GML_send_channel_create (struct MeshClient *c,
1056                          uint32_t id, uint32_t port, uint32_t opt,
1057                          const struct GNUNET_PeerIdentity *peer)
1058 {
1059   struct GNUNET_MESH_ChannelMessage msg;
1060
1061   msg.header.size = htons (sizeof (msg));
1062   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1063   msg.channel_id = htonl (id);
1064   msg.port = htonl (port);
1065   msg.opt = htonl (opt);
1066   msg.peer = *peer;
1067   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1068                                               &msg.header, GNUNET_NO);
1069 }
1070
1071
1072 /**
1073  * Notify a client that a channel is no longer valid.
1074  *
1075  * @param c Client.
1076  * @param id ID of the channel that is destroyed.
1077  */
1078 void
1079 GML_send_channel_destroy (struct MeshClient *c, uint32_t id)
1080 {
1081   struct GNUNET_MESH_ChannelMessage msg;
1082
1083   if (NULL == c)
1084   {
1085     GNUNET_break (0);
1086     return;
1087   }
1088   msg.header.size = htons (sizeof (msg));
1089   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1090   msg.channel_id = htonl (id);
1091   msg.port = htonl (0);
1092   memset (&msg.peer, 0, sizeof (msg.peer));
1093   msg.opt = htonl (0);
1094   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1095                                               &msg.header, GNUNET_NO);
1096 }
1097
1098
1099 /**
1100  * Modify the mesh message ID from global to local and send to client.
1101  *
1102  * @param c Client to send to.
1103  * @param msg Message to modify and send.
1104  * @param id Channel ID to use (c can be both owner and client).
1105  */
1106 void
1107 GML_send_data (struct MeshClient *c,
1108                const struct GNUNET_MESH_Data *msg,
1109                MESH_ChannelNumber id)
1110 {
1111   struct GNUNET_MESH_LocalData *copy;
1112   uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_MESH_Data);
1113   char cbuf[size + sizeof (struct GNUNET_MESH_LocalData)];
1114
1115   if (size < sizeof (struct GNUNET_MessageHeader))
1116   {
1117     GNUNET_break_op (0);
1118     return;
1119   }
1120   if (NULL == c)
1121   {
1122     GNUNET_break (0);
1123     return;
1124   }
1125   copy = (struct GNUNET_MESH_LocalData *) cbuf;
1126   memcpy (&copy[1], &msg[1], size);
1127   copy->header.size = htons (sizeof (struct GNUNET_MESH_LocalData) + size);
1128   copy->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA);
1129   copy->id = htonl (id);
1130   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1131                                               &copy->header, GNUNET_NO);
1132 }
1133
1134
1135 /**
1136  * Get the static string to represent a client.
1137  *
1138  * @param c Client.
1139  *
1140  * @return Static string for the client.
1141  */
1142 const char *
1143 GML_2s (const struct MeshClient *c)
1144 {
1145   static char buf[32];
1146
1147   sprintf (buf, "%u", c->id);
1148   return buf;
1149 }