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