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