- sync
[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 = GML_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 = GML_channel_get (c, chid);
547   if (NULL == ch)
548   {
549     GNUNET_break (0);
550     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
551     return;
552   }
553
554   rel = fwd ? ch->root_rel : ch->dest_rel;
555   rel->client_ready = GNUNET_NO;
556
557   /* Ok, everything is correct, send the message. */
558   {
559     struct GNUNET_MESH_Data *payload;
560     uint16_t p2p_size = sizeof(struct GNUNET_MESH_Data) + size;
561     unsigned char cbuf[p2p_size];
562
563     payload = (struct GNUNET_MESH_Data *) cbuf;
564     payload->mid = htonl (rel->mid_send);
565     rel->mid_send++;
566     memcpy (&payload[1], &msg[1], size);
567     payload->header.size = htons (p2p_size);
568     payload->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA);
569     payload->chid = htonl (ch->gid);
570     LOG (GNUNET_ERROR_TYPE_DEBUG, "  sending on channel...\n");
571     send_prebuilt_message_channel (&payload->header, ch, fwd);
572
573     if (GNUNET_YES == ch->reliable)
574       channel_save_copy (ch, &payload->header, fwd);
575   }
576   if (tunnel_get_buffer (ch->t, fwd) > 0)
577     send_local_ack (ch, fwd);
578   LOG (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
579   GNUNET_SERVER_receive_done (client, GNUNET_OK);
580
581   return;
582 }
583
584
585 /**
586  * Handler for client's ACKs for payload traffic.
587  *
588  * @param cls Closure (unused).
589  * @param client Identification of the client.
590  * @param message The actual message.
591  */
592 static void
593 handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
594             const struct GNUNET_MessageHeader *message)
595 {
596   struct GNUNET_MESH_LocalAck *msg;
597   struct MeshChannel *ch;
598   struct MeshClient *c;
599   MESH_ChannelNumber chid;
600   int fwd;
601
602   LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
603
604   /* Sanity check for client registration */
605   if (NULL == (c = GML_client_get (client)))
606   {
607     GNUNET_break (0);
608     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
609     return;
610   }
611   LOG (GNUNET_ERROR_TYPE_DEBUG, "  by client %u\n", c->id);
612
613   msg = (struct GNUNET_MESH_LocalAck *) message;
614
615   /* Channel exists? */
616   chid = ntohl (msg->channel_id);
617   LOG (GNUNET_ERROR_TYPE_DEBUG, "  on channel %X\n", chid);
618   ch = GML_channel_get (c, chid);
619   LOG (GNUNET_ERROR_TYPE_DEBUG, "   -- ch %p\n", ch);
620   if (NULL == ch)
621   {
622     GNUNET_break (0);
623     LOG (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid);
624     LOG (GNUNET_ERROR_TYPE_WARNING, "  for client %u.\n", c->id);
625     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
626     return;
627   }
628
629   /* If client is root, the ACK is going FWD, therefore this is "BCK". */
630   /* If client is dest, the ACK is going BCK, therefore this is "FWD" */
631   fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
632
633   GNUNET_SERVER_receive_done (client, GNUNET_OK);
634   GMCH_handle_local_ack (ch, fwd);
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 //   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 static void
681 handle_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 = GML_client_get (client)))
688   {
689     GNUNET_break (0);
690     GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
691     return;
692   }
693
694   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   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 handle_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 = GML_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   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   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   {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
772   {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE,
773    sizeof (struct GNUNET_MESH_ChannelMessage)},
774   {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY,
775    sizeof (struct GNUNET_MESH_ChannelMessage)},
776   {&handle_data, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
777   {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
778    sizeof (struct GNUNET_MESH_LocalAck)},
779   {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
780    sizeof (struct GNUNET_MessageHeader)},
781   {&handle_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 /**
793  * Initialize server subsystem.
794  *
795  * @param handle Server handle.
796  */
797 void
798 GML_init (struct GNUNET_SERVER_Handle *handle)
799 {
800   server_handle = handle;
801   GNUNET_SERVER_suspend (server_handle);
802   ports = GNUNET_CONTAINER_multihashmap32_create (32);
803 }
804
805
806 /**
807  * Install server (service) handlers and start listening to clients.
808  */
809 void
810 GML_start (void)
811 {
812   GNUNET_SERVER_add_handlers (server_handle, client_handlers);
813   GNUNET_SERVER_connect_notify (server_handle,  &handle_client_connect, NULL);
814   GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
815                                    NULL);
816   nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
817
818   clients_head = NULL;
819   clients_tail = NULL;
820   next_client_id = 0;
821   GNUNET_SERVER_resume (server_handle);
822 }
823
824
825 /**
826  * Shutdown server.
827  */
828 void
829 GML_shutdown (void)
830 {
831   if (nc != NULL)
832   {
833     GNUNET_SERVER_notification_context_destroy (nc);
834     nc = NULL;
835   }
836 }
837
838
839 /**
840  * Get a chennel from a client
841  *
842  * @param c the client to check
843  * @param chid Channel ID, must be local (> 0x800...)
844  *
845  * @return non-NULL if channel exists in the clients lists
846  */
847 struct MeshChannel *
848 GML_channel_get (struct MeshClient *c, MESH_ChannelNumber chid)
849 {
850   if (0 == (chid & GNUNET_MESH_LOCAL_CHANNEL_ID_CLI))
851   {
852     GNUNET_break_op (0);
853     LOG (GNUNET_ERROR_TYPE_DEBUG, "CHID %X not a local chid\n", chid);
854     return NULL;
855   }
856   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
857     return GNUNET_CONTAINER_multihashmap32_get (c->incoming_channels, chid);
858   return GNUNET_CONTAINER_multihashmap32_get (c->own_channels, chid);
859 }
860
861
862 /**
863  * Add a channel to a client
864  *
865  * @param client Client.
866  * @param chid Channel ID.
867  * @param ch Channel.
868  */
869 void
870 GML_channel_add (struct MeshClient *client,
871                  uint32_t chid,
872                  struct MeshChannel *ch)
873 {
874   if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV)
875     GNUNET_CONTAINER_multihashmap32_put (client->incoming_channels, chid, ch,
876                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
877   else if (chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_CLI)
878     GNUNET_CONTAINER_multihashmap32_put (client->own_channels, chid, ch,
879                                          GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_ONLY);
880   else
881     GNUNET_break (0);
882 }
883
884
885 /**
886  * Remove a channel from a client
887  *
888  * @param client Client.
889  * @param chid Channel ID.
890  * @param ch Channel.
891  */
892 void
893 GML_channel_remove (struct MeshClient *client,
894                     uint32_t chid,
895                     struct MeshChannel *ch)
896 {
897   if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid)
898     GNUNET_CONTAINER_multihashmap32_remove (client->incoming_channels, chid, ch);
899   else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= chid)
900     GNUNET_CONTAINER_multihashmap32_remove (client->own_channels, chid, ch);
901   else
902     GNUNET_break (0);
903 }
904
905
906 /**
907  * Get the tunnel's next free local channel ID.
908  *
909  * @param c Client.
910  *
911  * @return LID of a channel free to use.
912  */
913 MESH_ChannelNumber
914 GML_get_next_chid (struct MeshClient *c)
915 {
916   MESH_ChannelNumber chid;
917
918   while (NULL != GML_channel_get (c, c->next_chid))
919   {
920     LOG (GNUNET_ERROR_TYPE_DEBUG, "Channel %u exists...\n", c->next_chid);
921     c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
922   }
923   chid = c->next_chid;
924   c->next_chid = (c->next_chid + 1) | GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
925
926   return chid;
927 }
928
929
930 /**
931  * Check if client has registered with the service and has not disconnected
932  *
933  * @param client the client to check
934  *
935  * @return non-NULL if client exists in the global DLL
936  */
937 struct MeshClient *
938 GML_client_get (struct GNUNET_SERVER_Client *client)
939 {
940   return GNUNET_SERVER_client_get_user_context (client, struct MeshClient);
941 }
942
943 /**
944  * Find a client that has opened a port
945  *
946  * @param port Port to check.
947  *
948  * @return non-NULL if a client has the port.
949  */
950 struct MeshClient *
951 GML_client_get_by_port (uint32_t port)
952 {
953   return GNUNET_CONTAINER_multihashmap32_get (ports, port);
954 }
955
956
957 /**
958  * Deletes a tunnel from a client (either owner or destination).
959  *
960  * @param c Client whose tunnel to delete.
961  * @param ch Channel which should be deleted.
962  * @param id Channel ID.
963  */
964 void
965 GML_client_delete_channel (struct MeshClient *c,
966                            struct MeshChannel *ch,
967                            MESH_ChannelNumber id)
968 {
969   int res;
970
971   if (GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= id)
972   {
973     res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
974                                                   id, ch);
975     if (GNUNET_YES != res)
976       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel dest KO\n");
977   }
978   else if (GNUNET_MESH_LOCAL_CHANNEL_ID_CLI <= id)
979   {
980     res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
981                                                   id, ch);
982     if (GNUNET_YES != res)
983       LOG (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel root KO\n");
984   }
985   else
986   {
987     GNUNET_break (0);
988   }
989 }
990
991 /**
992  * Build a local ACK message and send it to a local client, if needed.
993  *
994  * If the client was already allowed to send data, do nothing.
995  *
996  * @param c Client to whom send the ACK.
997  * @param id Channel ID to use
998  */
999 void
1000 GML_send_ack (struct MeshClient *c, MESH_ChannelNumber id)
1001 {
1002   struct GNUNET_MESH_LocalAck msg;
1003
1004   LOG (GNUNET_ERROR_TYPE_DEBUG,
1005               "send local %s ack on %X towards %p\n",
1006               id < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV ? "FWD" : "BCK", id, c);
1007
1008   msg.header.size = htons (sizeof (msg));
1009   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
1010   msg.channel_id = htonl (id);
1011   GNUNET_SERVER_notification_context_unicast (nc,
1012                                               c->handle,
1013                                               &msg.header,
1014                                               GNUNET_NO);
1015
1016 }
1017
1018
1019 /**
1020  * Notify the client that a new incoming channel was created.
1021  *
1022  * @param ch Channel that was created.
1023  */
1024 void
1025 GML_send_channel_create (struct MeshClient *c,
1026                          uint32_t id, uint32_t port, uint32_t opt,
1027                          const struct GNUNET_PeerIdentity *peer)
1028 {
1029   struct GNUNET_MESH_ChannelMessage msg;
1030
1031   msg.header.size = htons (sizeof (msg));
1032   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1033   msg.channel_id = htonl (id);
1034   msg.port = htonl (port);
1035   msg.opt = htonl (opt);
1036   msg.peer = *peer;
1037   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1038                                               &msg.header, GNUNET_NO);
1039 }
1040
1041
1042 /**
1043  * Notify a client that a channel is no longer valid.
1044  *
1045  * @param c Client.
1046  * @param id ID of the channel that is destroyed.
1047  */
1048 void
1049 GML_send_channel_destroy (struct MeshClient *c, uint32_t id)
1050 {
1051   struct GNUNET_MESH_ChannelMessage msg;
1052
1053   if (NULL == c)
1054   {
1055     GNUNET_break (0);
1056     return;
1057   }
1058   msg.header.size = htons (sizeof (msg));
1059   msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1060   msg.channel_id = htonl (id);
1061   msg.port = htonl (0);
1062   memset (&msg.peer, 0, sizeof (msg.peer));
1063   msg.opt = htonl (0);
1064   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1065                                               &msg.header, GNUNET_NO);
1066 }
1067
1068
1069 /**
1070  * Modify the mesh message ID from global to local and send to client.
1071  *
1072  * @param c Client to send to.
1073  * @param msg Message to modify and send.
1074  * @param id Channel ID to use (c can be both owner and client).
1075  */
1076 void
1077 GML_send_data (struct MeshClient *c,
1078                const struct GNUNET_MESH_Data *msg,
1079                MESH_ChannelNumber id)
1080 {
1081   struct GNUNET_MESH_LocalData *copy;
1082   uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_MESH_Data);
1083   char cbuf[size + sizeof (struct GNUNET_MESH_LocalData)];
1084
1085   if (size < sizeof (struct GNUNET_MessageHeader))
1086   {
1087     GNUNET_break_op (0);
1088     return;
1089   }
1090   if (NULL == c)
1091   {
1092     GNUNET_break (0);
1093     return;
1094   }
1095   copy = (struct GNUNET_MESH_LocalData *) cbuf;
1096   memcpy (&copy[1], &msg[1], size);
1097   copy->header.size = htons (sizeof (struct GNUNET_MESH_LocalData) + size);
1098   copy->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA);
1099   copy->id = htonl (id);
1100   GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1101                                               &copy->header, GNUNET_NO);
1102 }
1103
1104
1105 /**
1106  * Get the static string to represent a client.
1107  *
1108  * @param c Client.
1109  *
1110  * @return Static string for the client.
1111  */
1112 const char *
1113 GML_2s (const struct MeshClient *c)
1114 {
1115   static char buf[32];
1116
1117   sprintf (buf, "%u", c->id);
1118   return buf;
1119 }