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