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