2 This file is part of GNUnet.
3 (C) 2013 Christian Grothoff (and other contributing authors)
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.
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.
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.
24 #include "mesh_protocol_enc.h" // GNUNET_MESH_Data is shared
26 #include "gnunet-service-mesh_local.h"
27 #include "gnunet-service-mesh_tunnel.h"
29 /******************************************************************************/
30 /******************************** STRUCTS **********************************/
31 /******************************************************************************/
34 * Struct containing information about a client of the service
36 * TODO: add a list of 'waiting' ports
43 struct MeshClient *next;
48 struct MeshClient *prev;
51 * Tunnels that belong to this client, indexed by local id
53 struct GNUNET_CONTAINER_MultiHashMap32 *own_channels;
56 * Tunnels this client has accepted, indexed by incoming local id
58 struct GNUNET_CONTAINER_MultiHashMap32 *incoming_channels;
61 * Handle to communicate with the client
63 struct GNUNET_SERVER_Client *handle;
66 * Ports that this client has declared interest in.
67 * Indexed by port, contains *Client.
69 struct GNUNET_CONTAINER_MultiHashMap32 *ports;
72 * Whether the client is active or shutting down (don't send confirmations
73 * to a client that is shutting down.
78 * ID of the client, mainly for debug messages
83 /******************************************************************************/
84 /******************************* GLOBALS ***********************************/
85 /******************************************************************************/
88 * Handle to server lib.
90 static struct GNUNET_SERVER_Handle *server_handle;
93 * DLL with all the clients, head.
95 static struct MeshClient *clients_head;
98 * DLL with all the clients, tail.
100 static struct MeshClient *clients_tail;
103 * Next ID to assign to a client.
105 unsigned int next_client_id;
108 * All ports clients of this peer have opened.
110 static struct GNUNET_CONTAINER_MultiHashMap32 *ports;
113 * Notification context, to send messages to local clients.
115 static struct GNUNET_SERVER_NotificationContext *nc;
118 /******************************************************************************/
119 /******************************** STATIC ***********************************/
120 /******************************************************************************/
123 * Remove client's ports from the global hashmap on disconnect.
125 * @param cls Closure (unused).
127 * @param value Client structure.
129 * @return GNUNET_OK, keep iterating.
132 client_release_ports (void *cls,
138 res = GNUNET_CONTAINER_multihashmap32_remove (ports, key, value);
139 if (GNUNET_YES != res)
142 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
143 "Port %u by client %p was not registered.\n",
151 /******************************************************************************/
152 /******************************** HANDLES ***********************************/
153 /******************************************************************************/
157 * Handler for client connection.
159 * @param cls Closure (unused).
160 * @param client Client handler.
163 handle_client_connect (void *cls, struct GNUNET_SERVER_Client *client)
165 struct MeshClient *c;
169 c = GNUNET_malloc (sizeof (struct MeshClient));
171 c->id = next_client_id++; /* overflow not important: just for debug */
172 GNUNET_SERVER_client_keep (client);
173 GNUNET_SERVER_client_set_user_context (client, c);
174 GNUNET_CONTAINER_DLL_insert (clients_head, clients_tail, c);
179 * Handler for client disconnection
182 * @param client identification of the client; NULL
183 * for the last call when the server is destroyed
186 handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
188 struct MeshClient *c;
190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client disconnected: %p\n", client);
193 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (SERVER DOWN)\n");
197 c = client_get (client);
200 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "matching client found (%u, %p)\n",
202 GNUNET_SERVER_client_drop (c->handle);
203 c->shutting_down = GNUNET_YES;
204 if (NULL != c->own_channels)
206 GNUNET_CONTAINER_multihashmap32_iterate (c->own_channels,
207 &channel_destroy_iterator, c);
208 GNUNET_CONTAINER_multihashmap32_destroy (c->own_channels);
211 if (NULL != c->incoming_channels)
213 GNUNET_CONTAINER_multihashmap32_iterate (c->incoming_channels,
214 &channel_destroy_iterator, c);
215 GNUNET_CONTAINER_multihashmap32_destroy (c->incoming_channels);
218 if (NULL != c->ports)
220 GNUNET_CONTAINER_multihashmap32_iterate (c->ports,
221 &client_release_ports, c);
222 GNUNET_CONTAINER_multihashmap32_destroy (c->ports);
224 GNUNET_CONTAINER_DLL_remove (clients_head, clients_tail, c);
225 GNUNET_STATISTICS_update (stats, "# clients", -1, GNUNET_NO);
226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client free (%p)\n", c);
231 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " context NULL!\n");
233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "done!\n");
239 * Handler for new clients
242 * @param client identification of the client
243 * @param message the actual message, which includes messages the client wants
246 handle_new_client (void *cls, struct GNUNET_SERVER_Client *client,
247 const struct GNUNET_MessageHeader *message)
249 struct GNUNET_MESH_ClientConnect *cc_msg;
250 struct MeshClient *c;
255 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client connected %p\n", client);
257 /* Check data sanity */
258 size = ntohs (message->size) - sizeof (struct GNUNET_MESH_ClientConnect);
259 cc_msg = (struct GNUNET_MESH_ClientConnect *) message;
260 if (0 != (size % sizeof (uint32_t)))
263 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
266 size /= sizeof (uint32_t);
268 /* Initialize new client structure */
269 c = GNUNET_SERVER_client_get_user_context (client, struct MeshClient);
270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client id %u\n", c->id);
271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " client has %u ports\n", size);
276 p = (uint32_t *) &cc_msg[1];
277 c->ports = GNUNET_CONTAINER_multihashmap32_create (size);
278 for (i = 0; i < size; i++)
281 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port: %u\n", u32);
283 /* store in client's hashmap */
284 GNUNET_CONTAINER_multihashmap32_put (c->ports, u32, c,
285 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
286 /* store in global hashmap */
287 /* FIXME only allow one client to have the port open,
288 * have a backup hashmap with waiting clients */
289 GNUNET_CONTAINER_multihashmap32_put (ports, u32, c,
290 GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
294 c->own_channels = GNUNET_CONTAINER_multihashmap32_create (32);
295 c->incoming_channels = GNUNET_CONTAINER_multihashmap32_create (32);
296 GNUNET_SERVER_notification_context_add (nc, client);
297 GNUNET_STATISTICS_update (stats, "# clients", 1, GNUNET_NO);
299 GNUNET_SERVER_receive_done (client, GNUNET_OK);
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new client processed\n");
305 * Handler for requests of new tunnels
307 * @param cls Closure.
308 * @param client Identification of the client.
309 * @param message The actual message.
312 handle_channel_create (void *cls, struct GNUNET_SERVER_Client *client,
313 const struct GNUNET_MessageHeader *message)
315 struct GNUNET_MESH_ChannelMessage *msg;
316 struct MeshPeer *peer;
317 struct MeshTunnel2 *t;
318 struct MeshChannel *ch;
319 struct MeshClient *c;
320 MESH_ChannelNumber chid;
322 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "new channel requested\n");
324 /* Sanity check for client registration */
325 if (NULL == (c = client_get (client)))
328 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
333 /* Message size sanity check */
334 if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size))
337 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
341 msg = (struct GNUNET_MESH_ChannelMessage *) message;
342 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " towards %s:%u\n",
343 GNUNET_i2s (&msg->peer), ntohl (msg->port));
344 chid = ntohl (msg->channel_id);
346 /* Sanity check for duplicate channel IDs */
347 if (NULL != channel_get_by_local_id (c, chid))
350 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
354 peer = peer_get (&msg->peer);
355 if (NULL == peer->tunnel)
357 peer->tunnel = tunnel_new ();
358 peer->tunnel->peer = peer;
359 if (peer->id == myid)
361 tunnel_change_state (peer->tunnel, MESH_TUNNEL_READY);
371 ch = channel_new (t, c, chid);
375 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
378 ch->port = ntohl (msg->port);
379 channel_set_options (ch, ntohl (msg->opt));
381 /* In unreliable channels, we'll use the DLL to buffer BCK data */
382 ch->root_rel = GNUNET_new (struct MeshChannelReliability);
383 ch->root_rel->ch = ch;
384 ch->root_rel->expected_delay = MESH_RETRANSMIT_TIME;
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CREATED CHANNEL %s[%x]:%u (%x)\n",
387 peer2s (t->peer), ch->gid, ch->port, ch->lid_root);
389 /* Send create channel */
391 struct GNUNET_MESH_ChannelCreate msgcc;
393 msgcc.header.size = htons (sizeof (msgcc));
394 msgcc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE);
395 msgcc.chid = htonl (ch->gid);
396 msgcc.port = msg->port;
397 msgcc.opt = msg->opt;
399 GMT_queue_data (t, ch, &msgcc.header, GNUNET_YES);
402 GNUNET_SERVER_receive_done (client, GNUNET_OK);
408 * Handler for requests of deleting tunnels
411 * @param client identification of the client
412 * @param message the actual message
415 handle_channel_destroy (void *cls, struct GNUNET_SERVER_Client *client,
416 const struct GNUNET_MessageHeader *message)
418 struct GNUNET_MESH_ChannelMessage *msg;
419 struct MeshClient *c;
420 struct MeshChannel *ch;
421 struct MeshTunnel2 *t;
422 MESH_ChannelNumber chid;
424 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
425 "Got a DESTROY CHANNEL from client!\n");
427 /* Sanity check for client registration */
428 if (NULL == (c = client_get (client)))
431 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
436 /* Message sanity check */
437 if (sizeof (struct GNUNET_MESH_ChannelMessage) != ntohs (message->size))
440 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
444 msg = (struct GNUNET_MESH_ChannelMessage *) message;
446 /* Retrieve tunnel */
447 chid = ntohl (msg->channel_id);
448 ch = channel_get_by_local_id (c, chid);
451 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " channel %X not found\n", chid);
453 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
457 /* Cleanup after the tunnel */
458 client_delete_channel (c, ch);
459 if (c == ch->dest && GNUNET_MESH_LOCAL_CHANNEL_ID_SERV <= chid)
463 else if (c == ch->root && GNUNET_MESH_LOCAL_CHANNEL_ID_SERV > chid)
469 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
470 " channel %X client %p (%p, %p)\n",
471 chid, c, ch->root, ch->dest);
476 channel_destroy (ch);
477 tunnel_destroy_if_empty (t);
479 GNUNET_SERVER_receive_done (client, GNUNET_OK);
485 * Handler for client traffic
488 * @param client identification of the client
489 * @param message the actual message
492 handle_data (void *cls, struct GNUNET_SERVER_Client *client,
493 const struct GNUNET_MessageHeader *message)
495 struct GNUNET_MESH_LocalData *msg;
496 struct MeshClient *c;
497 struct MeshChannel *ch;
498 struct MeshChannelReliability *rel;
499 MESH_ChannelNumber chid;
503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
504 "Got data from a client!\n");
506 /* Sanity check for client registration */
507 if (NULL == (c = client_get (client)))
510 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
515 msg = (struct GNUNET_MESH_LocalData *) message;
517 /* Sanity check for message size */
518 size = ntohs (message->size) - sizeof (struct GNUNET_MESH_LocalData);
519 if (size < sizeof (struct GNUNET_MessageHeader))
522 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
526 /* Channel exists? */
527 chid = ntohl (msg->id);
528 fwd = chid < GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
529 ch = channel_get_by_local_id (c, chid);
533 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
537 /* Is the client in the channel? */
540 ch->root->handle == client)
544 ch->dest->handle == client) ) )
547 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
551 rel = fwd ? ch->root_rel : ch->dest_rel;
552 rel->client_ready = GNUNET_NO;
554 /* Ok, everything is correct, send the message. */
556 struct GNUNET_MESH_Data *payload;
557 uint16_t p2p_size = sizeof(struct GNUNET_MESH_Data) + size;
558 unsigned char cbuf[p2p_size];
560 payload = (struct GNUNET_MESH_Data *) cbuf;
561 payload->mid = htonl (rel->mid_send);
563 memcpy (&payload[1], &msg[1], size);
564 payload->header.size = htons (p2p_size);
565 payload->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_DATA);
566 payload->chid = htonl (ch->gid);
567 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
568 send_prebuilt_message_channel (&payload->header, ch, fwd);
570 if (GNUNET_YES == ch->reliable)
571 channel_save_copy (ch, &payload->header, fwd);
573 if (tunnel_get_buffer (ch->t, fwd) > 0)
574 send_local_ack (ch, fwd);
575 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "receive done OK\n");
576 GNUNET_SERVER_receive_done (client, GNUNET_OK);
583 * Handler for client's ACKs for payload traffic.
585 * @param cls Closure (unused).
586 * @param client Identification of the client.
587 * @param message The actual message.
590 handle_ack (void *cls, struct GNUNET_SERVER_Client *client,
591 const struct GNUNET_MessageHeader *message)
593 struct GNUNET_MESH_LocalAck *msg;
594 struct MeshChannelReliability *rel;
595 struct MeshChannel *ch;
596 struct MeshClient *c;
597 MESH_ChannelNumber chid;
600 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a local ACK\n");
602 /* Sanity check for client registration */
603 if (NULL == (c = client_get (client)))
606 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " by client %u\n", c->id);
611 msg = (struct GNUNET_MESH_LocalAck *) message;
613 /* Channel exists? */
614 chid = ntohl (msg->channel_id);
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on channel %X\n", chid);
616 ch = channel_get_by_local_id (c, chid);
617 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " -- ch %p\n", ch);
621 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Channel %X unknown.\n", chid);
622 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " for client %u.\n", c->id);
623 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
627 /* If client is root, the ACK is going FWD, therefore this is "BCK". */
628 /* If client is dest, the ACK is going BCK, therefore this is "FWD" */
629 fwd = chid >= GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
630 rel = fwd ? ch->dest_rel : ch->root_rel;
632 rel->client_ready = GNUNET_YES;
633 channel_send_client_buffered_data (ch, c, fwd);
634 send_ack (NULL, ch, fwd);
636 GNUNET_SERVER_receive_done (client, GNUNET_OK);
643 * Iterator over all tunnels to send a monitoring client info about each tunnel.
645 * @param cls Closure (client handle).
646 * @param key Key (hashed tunnel ID, unused).
647 * @param value Tunnel info.
649 * @return GNUNET_YES, to keep iterating.
652 // monitor_all_tunnels_iterator (void *cls,
653 // const struct GNUNET_HashCode * key,
656 // struct GNUNET_SERVER_Client *client = cls;
657 // struct MeshChannel *ch = value;
658 // struct GNUNET_MESH_LocalMonitor *msg;
660 // msg = GNUNET_malloc (sizeof(struct GNUNET_MESH_LocalMonitor));
661 // msg->channel_id = htonl (ch->gid);
662 // msg->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
663 // msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
665 // GNUNET_log (GNUNET_ERROR_TYPE_INFO,
666 // "* sending info about tunnel %s\n",
667 // GNUNET_i2s (&msg->owner));
669 // GNUNET_SERVER_notification_context_unicast (nc, client,
670 // &msg->header, GNUNET_NO);
671 // return GNUNET_YES;
676 * Handler for client's MONITOR request.
678 * @param cls Closure (unused).
679 * @param client Identification of the client.
680 * @param message The actual message.
683 handle_get_tunnels (void *cls, struct GNUNET_SERVER_Client *client,
684 const struct GNUNET_MessageHeader *message)
686 struct MeshClient *c;
688 /* Sanity check for client registration */
689 if (NULL == (c = client_get (client)))
692 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
696 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
697 "Received get tunnels request from client %u\n",
699 // GNUNET_CONTAINER_multihashmap_iterate (tunnels,
700 // monitor_all_tunnels_iterator,
702 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
703 "Get tunnels request from client %u completed\n",
705 GNUNET_SERVER_receive_done (client, GNUNET_OK);
710 * Handler for client's MONITOR_TUNNEL request.
712 * @param cls Closure (unused).
713 * @param client Identification of the client.
714 * @param message The actual message.
717 handle_show_tunnel (void *cls, struct GNUNET_SERVER_Client *client,
718 const struct GNUNET_MessageHeader *message)
720 const struct GNUNET_MESH_LocalMonitor *msg;
721 struct GNUNET_MESH_LocalMonitor *resp;
722 struct MeshClient *c;
723 struct MeshChannel *ch;
725 /* Sanity check for client registration */
726 if (NULL == (c = client_get (client)))
729 GNUNET_SERVER_receive_done (client, GNUNET_SYSERR);
733 msg = (struct GNUNET_MESH_LocalMonitor *) message;
734 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
735 "Received tunnel info request from client %u for tunnel %s[%X]\n",
738 ntohl (msg->channel_id));
739 // ch = channel_get (&msg->owner, ntohl (msg->channel_id));
743 /* We don't know the tunnel */
744 struct GNUNET_MESH_LocalMonitor warn;
747 GNUNET_SERVER_notification_context_unicast (nc, client,
750 GNUNET_SERVER_receive_done (client, GNUNET_OK);
754 /* Initialize context */
755 resp = GNUNET_malloc (sizeof (struct GNUNET_MESH_LocalMonitor));
757 resp->header.size = htons (sizeof (struct GNUNET_MESH_LocalMonitor));
758 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
759 &resp->header, GNUNET_NO);
762 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
763 "Monitor tunnel request from client %u completed\n",
765 GNUNET_SERVER_receive_done (client, GNUNET_OK);
770 * Functions to handle messages from clients
772 static struct GNUNET_SERVER_MessageHandler client_handlers[] = {
773 {&handle_new_client, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT, 0},
774 {&handle_channel_create, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE,
775 sizeof (struct GNUNET_MESH_ChannelMessage)},
776 {&handle_channel_destroy, NULL, GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY,
777 sizeof (struct GNUNET_MESH_ChannelMessage)},
778 {&handle_data, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA, 0},
779 {&handle_ack, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK,
780 sizeof (struct GNUNET_MESH_LocalAck)},
781 {&handle_get_tunnels, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS,
782 sizeof (struct GNUNET_MessageHeader)},
783 {&handle_show_tunnel, NULL, GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL,
784 sizeof (struct GNUNET_MESH_LocalMonitor)},
790 /******************************************************************************/
791 /******************************** API ***********************************/
792 /******************************************************************************/
795 * Initialize server subsystem.
797 * @param handle Server handle.
800 GML_init (struct GNUNET_SERVER_Handle *handle)
802 server_handle = handle;
803 GNUNET_SERVER_suspend (server_handle);
804 ports = GNUNET_CONTAINER_multihashmap32_create (32);
809 * Install server (service) handlers and start listening to clients.
814 GNUNET_SERVER_add_handlers (server_handle, client_handlers);
815 GNUNET_SERVER_connect_notify (server_handle, &handle_client_connect, NULL);
816 GNUNET_SERVER_disconnect_notify (server_handle, &handle_client_disconnect,
818 nc = GNUNET_SERVER_notification_context_create (server_handle, 1);
823 GNUNET_SERVER_resume (server_handle);
835 GNUNET_SERVER_notification_context_destroy (nc);
842 * Check if client has registered with the service and has not disconnected
844 * @param client the client to check
846 * @return non-NULL if client exists in the global DLL
849 GML_client_get (struct GNUNET_SERVER_Client *client)
851 return GNUNET_SERVER_client_get_user_context (client, struct MeshClient);
856 * Deletes a tunnel from a client (either owner or destination).
858 * @param c Client whose tunnel to delete.
859 * @param ch Channel which should be deleted.
862 GML_client_delete_channel (struct MeshClient *c, struct MeshChannel *ch)
868 res = GNUNET_CONTAINER_multihashmap32_remove (c->own_channels,
870 if (GNUNET_YES != res)
871 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_delete_channel owner KO\n");
875 res = GNUNET_CONTAINER_multihashmap32_remove (c->incoming_channels,
877 if (GNUNET_YES != res)
878 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "client_delete_tunnel client KO\n");
883 * Build a local ACK message and send it to a local client, if needed.
885 * If the client was already allowed to send data, do nothing.
887 * @param ch Channel on which to send the ACK.
888 * @param c Client to whom send the ACK.
889 * @param fwd Set to GNUNET_YES for FWD ACK (dest->root)
892 GML_send_ack (struct MeshChannel *ch, int fwd)
894 struct GNUNET_MESH_LocalAck msg;
895 struct MeshChannelReliability *rel;
896 struct MeshClient *c;
898 c = fwd ? ch->root : ch->dest;
899 rel = fwd ? ch->root_rel : ch->dest_rel;
901 if (GNUNET_YES == rel->client_ready)
902 return; /* don't send double ACKs to client */
904 rel->client_ready = GNUNET_YES;
906 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
907 "send local %s ack on %s:%X towards %p\n",
908 fwd ? "FWD" : "BCK", peer2s (ch->t->peer), ch->gid, c);
911 || ( fwd && (0 == ch->lid_root || c != ch->root))
912 || (!fwd && (0 == ch->lid_dest || c != ch->dest)) )
917 msg.header.size = htons (sizeof (msg));
918 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
919 msg.channel_id = htonl (fwd ? ch->lid_root : ch->lid_dest);
920 GNUNET_SERVER_notification_context_unicast (nc,
929 * Notify the client that a new incoming channel was created.
931 * @param ch Channel that was created.
934 GML_send_channel_create (struct MeshClient *c,
935 uint32_t id, uint32_t port, uint32_t opt,
936 struct GNUNET_PeerIdentity *peer)
938 struct GNUNET_MESH_ChannelMessage msg;
940 msg.header.size = htons (sizeof (msg));
941 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
942 msg.channel_id = htonl (id);
943 msg.port = htonl (port);
944 msg.opt = htonl (opt);
946 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
947 &msg.header, GNUNET_NO);
952 * Notify a client that a channel is no longer valid.
955 * @param id ID of the channel that is destroyed.
958 GML_send_channel_destroy (struct MeshClient *c, uint32_t id)
960 struct GNUNET_MESH_ChannelMessage msg;
967 msg.header.size = htons (sizeof (msg));
968 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
969 msg.channel_id = htonl (id);
970 msg.port = htonl (0);
971 memset (&msg.peer, 0, sizeof (msg.peer));
973 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
974 &msg.header, GNUNET_NO);
979 * Modify the mesh message ID from global to local and send to client.
981 * @param msg Message to modify and send.
982 * @param c Client to send to.
983 * @param tid Tunnel ID to use (c can be both owner and client).
986 GML_send_data (struct MeshClient *c,
987 const struct GNUNET_MESH_Data *msg,
988 MESH_ChannelNumber id)
990 struct GNUNET_MESH_LocalData *copy;
991 uint16_t size = ntohs (msg->header.size) - sizeof (struct GNUNET_MESH_Data);
992 char cbuf[size + sizeof (struct GNUNET_MESH_LocalData)];
994 if (size < sizeof (struct GNUNET_MessageHeader))
1004 copy = (struct GNUNET_MESH_LocalData *) cbuf;
1005 memcpy (©[1], &msg[1], size);
1006 copy->header.size = htons (sizeof (struct GNUNET_MESH_LocalData) + size);
1007 copy->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_DATA);
1008 copy->id = htonl (id);
1009 GNUNET_SERVER_notification_context_unicast (nc, c->handle,
1010 ©->header, GNUNET_NO);