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