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