- migrate handlers to channel.c
[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 GNUNET_MESH_ChannelMessage *msg;
332   struct MeshPeer *peer;
333   struct MeshTunnel2 *t;
334   struct MeshChannel *ch;
335   struct MeshClient *c;
336   MESH_ChannelNumber chid;
337
338   LOG (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
339
340   /* Sanity check for client registration */
341   if (NULL == (c = client_get (client)))
342   {
343     GNUNET_break (0);
344     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
345     return;
346   }
347   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
348
349   /* Message size sanity check */
350   if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size))
351   {
352     GNUNET_break (0);
353     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
354     return;
355   }
356
357   msg = (struct GNUNET_MESH_ChannelMessage *) message;
358   LOG (GNUNET_ERROR_TYPE_DEBUG, "  towards %s:%u\n",
359               GNUNET_i2s (&msg->peer), ntohl (msg->port));
360   chid = ntohl (msg->channel_id);
361
362   /* Sanity check for duplicate channel IDs */
363   if (NULL != channel_get_by_local_id (c, chid))
364   {
365     GNUNET_break (0);
366     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
367     return;
368   }
369
370   peer = peer_get (&msg->peer);
371   if (NULL == peer->tunnel)
372   {
373     peer->tunnel = tunnel_new ();
374     peer->tunnel->peer = peer;
375     if (peer->id == myid)
376     {
377       tunnel_change_state (peer->tunnel, MESH_TUNNEL_READY);
378     }
379     else
380     {
381       peer_connect (peer);
382     }
383   }
384   t = peer->tunnel;
385
386   /* Create channel */
387   ch = channel_new (t, c, chid);
388   if (NULL == ch)
389   {
390     GNUNET_break (0);
391     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
392     return;
393   }
394   ch->port = ntohl (msg->port);
395   channel_set_options (ch, ntohl (msg->opt));
396
397   /* In unreliable channels, we'll use the DLL to buffer BCK data */
398   ch->root_rel = GNUNET_new (struct MeshChannelReliability);
399   ch->root_rel->ch = ch;
400   ch->root_rel->expected_delay = MESH_RETRANSMIT_TIME;
401
402   LOG (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s[%x]:%u (%x)\n",
403               peer2s (t->peer), ch->gid, ch->port, ch->lid_root);
404
405   /* Send create channel */
406   {
407     struct GNUNET_MESH_ChannelCreate msgcc;
408
409     msgcc.header.size = htons (sizeof (msgcc));
410     msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE);
411     msgcc.chid = htonl (ch->gid);
412     msgcc.port = msg->port;
413     msgcc.opt = msg->opt;
414
415     GMT_queue_data (t, ch, &msgcc.header, GNUNET_YES);
416   }
417
418   GNUNET_SERVER_receive_done (client, GNUNET_OK);
419   return;
420 }
421
422
423 /**
424  * Handler for requests of deleting tunnels
425  *
426  * @param cls closure
427  * @param client identification of the client
428  * @param message the actual message
429  */
430 static void
431 handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
432                         const struct GNUNET_MessageHeader *message)
433 {
434   struct GNUNET_MESH_ChannelMessage *msg;
435   struct MeshClient *c;
436   struct MeshChannel *ch;
437   MESH_ChannelNumber chid;
438
439   LOG (GNUNET_ERROR_TYPE_DEBUG,
440               "Got a DESTROY CHANNEL from client!\n");
441
442   /* Sanity check for client registration */
443   if (NULL == (c = GML_client_get (client)))
444   {
445     GNUNET_break (0);
446     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
447     return;
448   }
449   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
450
451   /* Message sanity check */
452   if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size))
453   {
454     GNUNET_break (0);
455     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
456     return;
457   }
458
459   msg = (struct GNUNET_MESH_ChannelMessage *) message;
460
461   /* Retrieve tunnel */
462   chid = ntohl (msg->channel_id);
463   ch = GML_channel_get (c, chid);
464   if (NULL == ch)
465   {
466     LOG (GNUNET_ERROR_TYPE_ERROR, "  channel %X not found\n", chid);
467     GNUNET_break (0);
468     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
469     return;
470   }
471
472   GMCH_handle_local_destroy (ch, c, chid);
473
474   GNUNET_SERVER_receive_done (client, GNUNET_OK);
475   return;
476 }
477
478
479 /**
480  * Handler for client traffic
481  *
482  * @param cls closure
483  * @param client identification of the client
484  * @param message the actual message
485  */
486 static void
487 handle_data (void *cls, struct GNUNET_SERVER_Client *client,
488              const struct GNUNET_MessageHeader *message)
489 {
490   struct GNUNET_MESH_LocalData *msg;
491   struct MeshClient *c;
492   struct MeshChannel *ch;
493   MESH_ChannelNumber chid;
494   size_t size;
495   int fwd;
496
497   LOG (GNUNET_ERROR_TYPE_DEBUG,
498               "Got data from a client!\n");
499
500   /* Sanity check for client registration */
501   if (NULL == (c = GML_client_get (client)))
502   {
503     GNUNET_break (0);
504     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
505     return;
506   }
507   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
508
509   msg = (struct GNUNET_MESH_LocalData *) message;
510
511   /* Sanity check for message size */
512   size = ntohs (message->size) - sizeof (struct GNUNET_MESH_LocalData);
513   if (size < sizeof (struct GNUNET_MessageHeader))
514   {
515     GNUNET_break (0);
516     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
517     return;
518   }
519
520   /* Channel exists? */
521   chid = ntohl (msg->id);
522   fwd = chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
523   ch = GML_channel_get (c, chid);
524   if (NULL == ch)
525   {
526     GNUNET_break (0);
527     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
528     return;
529   }
530
531   if (GNUNET_OK !=
532       GMCH_handle_local_data (ch, c,
533                               (struct GNUNET_MessageHeader *)&msg[1], fwd))
534   {
535     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
536     return;
537   }
538
539   LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
540   GNUNET_SERVER_receive_done (client, GNUNET_OK);
541
542   return;
543 }
544
545
546 /**
547  * Handler for client's ACKs for payload traffic.
548  *
549  * @param cls Closure (unused).
550  * @param client Identification of the client.
551  * @param message The actual message.
552  */
553 static void
554 handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
555             const struct GNUNET_MessageHeader *message)
556 {
557   struct GNUNET_MESH_LocalAck *msg;
558   struct MeshChannel *ch;
559   struct MeshClient *c;
560   MESH_ChannelNumber chid;
561   int fwd;
562
563   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
564
565   /* Sanity check for client registration */
566   if (NULL == (c = GML_client_get (client)))
567   {
568     GNUNET_break (0);
569     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
570     return;
571   }
572   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
573
574   msg = (struct GNUNET_MESH_LocalAck *) message;
575
576   /* Channel exists? */
577   chid = ntohl (msg->channel_id);
578   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
579   ch = GML_channel_get (c, chid);
580   LOG (GNUNET_ERROR_TYPE_DEBUG, "   -- ch %p\n", ch);
581   if (NULL == ch)
582   {
583     GNUNET_break (0);
584     LOG (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid);
585     LOG (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
586     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
587     return;
588   }
589
590   /* If client is root, the ACK is going FWD, therefore this is "BCK". */
591   /* If client is dest, the ACK is going BCK, therefore this is "FWD" */
592   fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
593
594   GMCH_handle_local_ack (ch, fwd);
595   GNUNET_SERVER_receive_done (client, GNUNET_OK);
596
597   return;
598 }
599
600
601 /*
602  * Iterator over all tunnels to send a monitoring client info about each tunnel.
603  *
604  * @param cls Closure (client handle).
605  * @param key Key (hashed tunnel ID, unused).
606  * @param value Tunnel info.
607  *
608  * @return GNUNET_YES, to keep iterating.
609  */
610 // static int
611 // monitor_all_tunnels_iterator (void *cls,
612 //                               const struct GNUNET_HashCode * key,
613 //                               void *value)
614 // {
615 //   struct GNUNET_SERVER_Client *client = cls;
616 //   struct MeshChannel *ch = value;
617 //   struct GNUNET_MESH_LocalMonitor *msg;
618 //
619 //   msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
620 //   msg->channel_id = htonl (ch->gid);
621 //   msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
622 //   msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
623 //
624 //   LOG (GNUNET_ERROR_TYPE_INFO,
625 //               "*  sending info about tunnel %s\n",
626 //               GNUNET_i2s (&msg->owner));
627 //
628 //   GNUNET_SERVER_notification_context_unicast (nc, client,
629 //                                               &msg->header, GNUNET_NO);
630 //   return GNUNET_YES;
631 // }
632
633
634 /**
635  * Handler for client's MONITOR request.
636  *
637  * @param cls Closure (unused).
638  * @param client Identification of the client.
639  * @param message The actual message.
640  */
641 static void
642 handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
643                     const struct GNUNET_MessageHeader *message)
644 {
645   struct MeshClient *c;
646
647   /* Sanity check for client registration */
648   if (NULL == (c = GML_client_get (client)))
649   {
650     GNUNET_break (0);
651     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
652     return;
653   }
654
655   LOG (GNUNET_ERROR_TYPE_INFO,
656               "Received get tunnels request from client %u\n",
657               c->id);
658 //   GNUNET_CONTAINER_multihashmap_iterate (tunnels,
659 //                                          monitor_all_tunnels_iterator,
660 //                                          client);
661   LOG (GNUNET_ERROR_TYPE_INFO,
662               "Get tunnels request from client %u completed\n",
663               c->id);
664   GNUNET_SERVER_receive_done (client, GNUNET_OK);
665 }
666
667
668 /**
669  * Handler for client's MONITOR_TUNNEL request.
670  *
671  * @param cls Closure (unused).
672  * @param client Identification of the client.
673  * @param message The actual message.
674  */
675 void
676 handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
677                     const struct GNUNET_MessageHeader *message)
678 {
679   const struct GNUNET_MESH_LocalMonitor *msg;
680   struct GNUNET_MESH_LocalMonitor *resp;
681   struct MeshClient *c;
682   struct MeshChannel *ch;
683
684   /* Sanity check for client registration */
685   if (NULL == (c = GML_client_get (client)))
686   {
687     GNUNET_break (0);
688     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
689     return;
690   }
691
692   msg = (struct GNUNET_MESH_LocalMonitor *) message;
693   LOG (GNUNET_ERROR_TYPE_INFO,
694               "Received tunnel info request from client %u for tunnel %s[%X]\n",
695               c->id,
696               &msg->owner,
697               ntohl (msg->channel_id));
698 //   ch = channel_get (&msg->owner, ntohl (msg->channel_id));
699   ch = NULL; // FIXME
700   if (NULL == ch)
701   {
702     /* We don't know the tunnel */
703     struct GNUNET_MESH_LocalMonitor warn;
704
705     warn = *msg;
706     GNUNET_SERVER_notification_context_unicast (nc, client,
707                                                 &warn.header,
708                                                 GNUNET_NO);
709     GNUNET_SERVER_receive_done (client, GNUNET_OK);
710     return;
711   }
712
713   /* Initialize context */
714   resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
715   *resp = *msg;
716   resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
717   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
718                                               &resp->header, GNUNET_NO);
719   GNUNET_free (resp);
720
721   LOG (GNUNET_ERROR_TYPE_INFO,
722               "Monitor tunnel request from client %u completed\n",
723               c->id);
724   GNUNET_SERVER_receive_done (client, GNUNET_OK);
725 }
726
727
728 /**
729  * Functions to handle messages from clients
730  */
731 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
732   {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
733   {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE,
734    sizeof (struct GNUNET_MESH_ChannelMessage)},
735   {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY,
736    sizeof (struct GNUNET_MESH_ChannelMessage)},
737   {&handle_data, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
738   {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
739    sizeof (struct GNUNET_MESH_LocalAck)},
740   {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
741    sizeof (struct GNUNET_MessageHeader)},
742   {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
743    sizeof (struct GNUNET_MESH_LocalMonitor)},
744   {NULL, NULL, 0, 0}
745 };
746
747
748
749 /******************************************************************************/
750 /********************************    API    ***********************************/
751 /******************************************************************************/
752
753 /**
754  * Initialize server subsystem.
755  *
756  * @param handle Server handle.
757  */
758 void
759 GML_init (struct GNUNET_SERVER_Handle *handle)
760 {
761   server_handle = handle;
762   GNUNET_SERVER_suspend (server_handle);
763   ports = GNUNET_CONTAINER_multihashmap32_create (32);
764 }
765
766
767 /**
768  * Install server (service) handlers and start listening to clients.
769  */
770 void
771 GML_start (void)
772 {
773   GNUNET_SERVER_add_handlers (server_handle, client_handlers);
774   GNUNET_SERVER_connect_notify (server_handle,  &handle_client_connect, NULL);
775   GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
776                                    NULL);
777   nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
778
779   clients_head = NULL;
780   clients_tail = NULL;
781   next_client_id = 0;
782   GNUNET_SERVER_resume (server_handle);
783 }
784
785
786 /**
787  * Shutdown server.
788  */
789 void
790 GML_shutdown (void)
791 {
792   if (nc != NULL)
793   {
794     GNUNET_SERVER_notification_context_destroy (nc);
795     nc = NULL;
796   }
797 }
798
799
800 /**
801  * Get a chennel from a client
802  *
803  * @param c the client to check
804  * @param chid Channel ID, must be local (> 0x800...)
805  *
806  * @return non-NULL if channel exists in the clients lists
807  */
808 struct MeshChannel *
809 GML_channel_get (struct MeshClient *c, MESH_ChannelNumber chid)
810 {
811   if (0 == (chid & GNUNET_MESH_LOCAL_CHANNEL_ID_CLI))
812   {
813     GNUNET_break_op (0);
814     LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
815     return NULL;
816   }
817   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
818     return GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels, chid);
819   return GNUNET_CONTAINER_multihashmap32_get (c->own_channels, chid);
820 }
821
822
823 /**
824  * Add a channel to a client
825  *
826  * @param client Client.
827  * @param chid Channel ID.
828  * @param ch Channel.
829  */
830 void
831 GML_channel_add (struct MeshClient *client,
832                  uint32_t chid,
833                  struct MeshChannel *ch)
834 {
835   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
836     GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch,
837                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
838   else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)
839     GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
840                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
841   else
842     GNUNET_break (0);
843 }
844
845
846 /**
847  * Remove a channel from a client
848  *
849  * @param client Client.
850  * @param chid Channel ID.
851  * @param ch Channel.
852  */
853 void
854 GML_channel_remove (struct MeshClient *client,
855                     uint32_t chid,
856                     struct MeshChannel *ch)
857 {
858   if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid)
859     GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, chid, ch);
860   else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= chid)
861     GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, chid, ch);
862   else
863     GNUNET_break (0);
864 }
865
866
867 /**
868  * Get the tunnel's next free local channel ID.
869  *
870  * @param c Client.
871  *
872  * @return LID of a channel free to use.
873  */
874 MESH_ChannelNumber
875 GML_get_next_chid (struct MeshClient *c)
876 {
877   MESH_ChannelNumber chid;
878
879   while (NULL != GML_channel_get (c, c->next_chid))
880   {
881     LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid);
882     c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
883   }
884   chid = c->next_chid;
885   c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
886
887   return chid;
888 }
889
890
891 /**
892  * Check if client has registered with the service and has not disconnected
893  *
894  * @param client the client to check
895  *
896  * @return non-NULL if client exists in the global DLL
897  */
898 struct MeshClient *
899 GML_client_get (struct GNUNET_SERVER_Client *client)
900 {
901   return GNUNET_SERVER_client_get_user_context (client, struct MeshClient);
902 }
903
904 /**
905  * Find a client that has opened a port
906  *
907  * @param port Port to check.
908  *
909  * @return non-NULL if a client has the port.
910  */
911 struct MeshClient *
912 GML_client_get_by_port (uint32_t port)
913 {
914   return GNUNET_CONTAINER_multihashmap32_get (ports, port);
915 }
916
917
918 /**
919  * Deletes a channel from a client (either owner or destination).
920  *
921  * @param c Client whose tunnel to delete.
922  * @param ch Channel which should be deleted.
923  * @param id Channel ID.
924  */
925 void
926 GML_client_delete_channel (struct MeshClient *c,
927                            struct MeshChannel *ch,
928                            MESH_ChannelNumber id)
929 {
930   int res;
931
932   if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= id)
933   {
934     res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
935                                                   id, ch);
936     if (GNUNET_YES != res)
937       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
938   }
939   else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= id)
940   {
941     res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
942                                                   id, ch);
943     if (GNUNET_YES != res)
944       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
945   }
946   else
947   {
948     GNUNET_break (0);
949   }
950 }
951
952 /**
953  * Build a local ACK message and send it to a local client, if needed.
954  *
955  * If the client was already allowed to send data, do nothing.
956  *
957  * @param c Client to whom send the ACK.
958  * @param id Channel ID to use
959  */
960 void
961 GML_send_ack (struct MeshClient *c, MESH_ChannelNumber id)
962 {
963   struct GNUNET_MESH_LocalAck msg;
964
965   LOG (GNUNET_ERROR_TYPE_DEBUG,
966               "send local %s ack on %X towards %p\n",
967               id < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c);
968
969   msg.header.size = htons (sizeof (msg));
970   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
971   msg.channel_id = htonl (id);
972   GNUNET_SERVER_notification_context_unicast (nc,
973                                               c->handle,
974                                               &msg.header,
975                                               GNUNET_NO);
976
977 }
978
979
980 /**
981  * Notify the client that a new incoming channel was created.
982  *
983  * @param ch Channel that was created.
984  */
985 void
986 GML_send_channel_create (struct MeshClient *c,
987                          uint32_t id, uint32_t port, uint32_t opt,
988                          const struct GNUNET_PeerIdentity *peer)
989 {
990   struct GNUNET_MESH_ChannelMessage msg;
991
992   msg.header.size = htons (sizeof (msg));
993   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
994   msg.channel_id = htonl (id);
995   msg.port = htonl (port);
996   msg.opt = htonl (opt);
997   msg.peer = *peer;
998   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
999                                               &msg.header, GNUNET_NO);
1000 }
1001
1002
1003 /**
1004  * Notify a client that a channel is no longer valid.
1005  *
1006  * @param c Client.
1007  * @param id ID of the channel that is destroyed.
1008  */
1009 void
1010 GML_send_channel_destroy (struct MeshClient *c, uint32_t id)
1011 {
1012   struct GNUNET_MESH_ChannelMessage msg;
1013
1014   if (NULL == c)
1015   {
1016     GNUNET_break (0);
1017     return;
1018   }
1019   msg.header.size = htons (sizeof (msg));
1020   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1021   msg.channel_id = htonl (id);
1022   msg.port = htonl (0);
1023   memset (&msg.peer, 0, sizeof (msg.peer));
1024   msg.opt = htonl (0);
1025   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1026                                               &msg.header, GNUNET_NO);
1027 }
1028
1029
1030 /**
1031  * Modify the mesh message ID from global to local and send to client.
1032  *
1033  * @param c Client to send to.
1034  * @param msg Message to modify and send.
1035  * @param id Channel ID to use (c can be both owner and client).
1036  */
1037 void
1038 GML_send_data (struct MeshClient *c,
1039                const struct GNUNET_MESH_Data *msg,
1040                MESH_ChannelNumber id)
1041 {
1042   struct GNUNET_MESH_LocalData *copy;
1043   uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_MESH_Data);
1044   char cbuf[size + sizeof (struct GNUNET_MESH_LocalData)];
1045
1046   if (size < sizeof (struct GNUNET_MessageHeader))
1047   {
1048     GNUNET_break_op (0);
1049     return;
1050   }
1051   if (NULL == c)
1052   {
1053     GNUNET_break (0);
1054     return;
1055   }
1056   copy = (struct GNUNET_MESH_LocalData *) cbuf;
1057   memcpy (&copy[1], &msg[1], size);
1058   copy->header.size = htons (sizeof (struct GNUNET_MESH_LocalData) + size);
1059   copy->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA);
1060   copy->id = htonl (id);
1061   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1062                                               &copy->header, GNUNET_NO);
1063 }
1064
1065
1066 /**
1067  * Get the static string to represent a client.
1068  *
1069  * @param c Client.
1070  *
1071  * @return Static string for the client.
1072  */
1073 const char *
1074 GML_2s (const struct MeshClient *c)
1075 {
1076   static char buf[32];
1077
1078   sprintf (buf, "%u", c->id);
1079   return buf;
1080 }