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