2 This file is part of GNUnet.
3 (C) 2011 Christian Grothoff (and other contributing authors)
4 GNUnet is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published
6 by the Free Software Foundation; either version 3, or (at your
7 option) any later version.
8 GNUnet is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 General Public License for more details.
12 You should have received a copy of the GNU General Public License
13 along with GNUnet; see the file COPYING. If not, write to the
14 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
15 Boston, MA 02111-1307, USA.
19 * @file mesh/mesh_api.c
20 * @brief mesh api: client implementation of mesh service
21 * @author Bartlomiej Polot
26 * - AUXILIARY FUNCTIONS
29 * - API CALL DEFINITIONS
31 * TODO: add regex to reconnect
34 #include "gnunet_common.h"
35 #include "gnunet_client_lib.h"
36 #include "gnunet_util_lib.h"
37 #include "gnunet_peer_lib.h"
38 #include "gnunet_mesh_service.h"
40 #include "mesh_protocol.h"
42 #define LOG(kind,...) GNUNET_log_from (kind, "mesh-api",__VA_ARGS__)
44 #define DEBUG_ACK GNUNET_YES
46 /******************************************************************************/
47 /************************ DATA STRUCTURES ****************************/
48 /******************************************************************************/
51 * Transmission queue to the service
53 struct GNUNET_MESH_TransmitHandle
59 struct GNUNET_MESH_TransmitHandle *next;
64 struct GNUNET_MESH_TransmitHandle *prev;
67 * Tunnel this message is sent on / for (may be NULL for control messages).
69 struct GNUNET_MESH_Tunnel *tunnel;
72 * Callback to obtain the message to transmit, or NULL if we
73 * got the message in 'data'. Notice that messages built
74 * by 'notify' need to be encapsulated with information about
77 GNUNET_CONNECTION_TransmitReadyNotify notify;
80 * Closure for 'notify'
85 * How long is this message valid. Once the timeout has been
86 * reached, the message must no longer be sent. If this
87 * is a message with a 'notify' callback set, the 'notify'
88 * function should be called with 'buf' NULL and size 0.
90 struct GNUNET_TIME_Absolute timeout;
93 * Task triggering a timeout, can be NO_TASK if the timeout is FOREVER.
95 GNUNET_SCHEDULER_TaskIdentifier timeout_task;
98 * Target of the message, 0 for multicast. This field
99 * is only valid if 'notify' is non-NULL.
101 GNUNET_PEER_Id target;
104 * Size of 'data' -- or the desired size of 'notify' if 'data' is NULL.
111 * Opaque handle to the service.
113 struct GNUNET_MESH_Handle
117 * Handle to the server connection, to send messages later
119 struct GNUNET_CLIENT_Connection *client;
122 * Set of handlers used for processing incoming messages in the tunnels
124 const struct GNUNET_MESH_MessageHandler *message_handlers;
127 * Set of applications that should be claimed to be offered at this node.
128 * Note that this is just informative, the appropiate handlers must be
129 * registered independently and the mapping is up to the developer of the
130 * client application.
132 GNUNET_MESH_ApplicationType *applications;
135 * Double linked list of the tunnels this client is connected to, head.
137 struct GNUNET_MESH_Tunnel *tunnels_head;
140 * Double linked list of the tunnels this client is connected to, tail.
142 struct GNUNET_MESH_Tunnel *tunnels_tail;
145 * Callback for inbound tunnel creation
147 GNUNET_MESH_InboundTunnelNotificationHandler *new_tunnel;
150 * Callback for inbound tunnel disconnection
152 GNUNET_MESH_TunnelEndHandler *cleaner;
155 * Handle to cancel pending transmissions in case of disconnection
157 struct GNUNET_CLIENT_TransmitHandle *th;
160 * Closure for all the handlers given by the client
165 * Messages to send to the service, head.
167 struct GNUNET_MESH_TransmitHandle *th_head;
170 * Messages to send to the service, tail.
172 struct GNUNET_MESH_TransmitHandle *th_tail;
175 * tid of the next tunnel to create (to avoid reusing IDs often)
177 MESH_TunnelNumber next_tid;
180 * Number of handlers in the handlers array.
182 unsigned int n_handlers;
185 * Number of applications in the applications array.
187 unsigned int n_applications;
190 * Have we started the task to receive messages from the service
191 * yet? We do this after we send the 'MESH_LOCAL_CONNECT' message.
196 * Configuration given by the client, in case of reconnection
198 const struct GNUNET_CONFIGURATION_Handle *cfg;
201 * Time to the next reconnect in case one reconnect fails
203 struct GNUNET_TIME_Relative reconnect_time;
206 * Task for trying to reconnect.
208 GNUNET_SCHEDULER_TaskIdentifier reconnect_task;
213 GNUNET_MESH_TunnelsCB tunnels_cb;
216 * Monitor callback closure.
223 GNUNET_MESH_TunnelCB tunnel_cb;
226 * Tunnel callback closure.
231 * All the peer in the tunnel so far.
233 struct GNUNET_PeerIdentity *peers;
236 * How many peers we have in this tunnel so far.
238 unsigned int tunnel_npeers;
241 unsigned int acks_sent;
242 unsigned int acks_recv;
248 * Description of a peer
250 struct GNUNET_MESH_Peer
253 * ID of the peer in short form
258 * Tunnel this peer belongs to
260 struct GNUNET_MESH_Tunnel *t;
263 * Flag indicating whether service has informed about its connection
271 * Opaque handle to a tunnel.
273 struct GNUNET_MESH_Tunnel
279 struct GNUNET_MESH_Tunnel *next;
284 struct GNUNET_MESH_Tunnel *prev;
287 * Callback to execute when peers connect to the tunnel
289 GNUNET_MESH_PeerConnectHandler connect_handler;
292 * Callback to execute when peers disconnect from the tunnel
294 GNUNET_MESH_PeerDisconnectHandler disconnect_handler;
297 * Closure for the connect/disconnect handlers
302 * Handle to the mesh this tunnel belongs to
304 struct GNUNET_MESH_Handle *mesh;
307 * Local ID of the tunnel
309 MESH_TunnelNumber tid;
312 * Owner of the tunnel. 0 if the tunnel is the local client.
314 GNUNET_PEER_Id owner;
317 * All peers added to the tunnel
319 struct GNUNET_MESH_Peer **peers;
322 * List of application types that have been requested for this tunnel
324 GNUNET_MESH_ApplicationType *apps;
327 * Any data the caller wants to put in here
332 * Number of peers added to the tunnel
337 * Size of packet queued in this tunnel
339 unsigned int packet_size;
342 * Number of applications requested this tunnel
347 * Is the tunnel throttled to the slowest peer?
352 * Is the tunnel allowed to buffer?
357 * Next packet ID to send.
359 uint32_t next_send_pid;
362 * Maximum allowed PID to send (ACK recevied).
364 uint32_t max_send_pid;
367 * Last pid received from the service.
369 uint32_t last_recv_pid;
372 * Which ACK value have we last sent to the service?
374 uint32_t max_recv_pid;
378 /******************************************************************************/
379 /*********************** DECLARATIONS *************************/
380 /******************************************************************************/
383 * Function called to send a message to the service.
384 * "buf" will be NULL and "size" zero if the socket was closed for writing in
387 * @param cls closure, the mesh handle
388 * @param size number of bytes available in buf
389 * @param buf where the callee should write the connect message
390 * @return number of bytes written to buf
393 send_callback (void *cls, size_t size, void *buf);
396 /******************************************************************************/
397 /*********************** AUXILIARY FUNCTIONS *************************/
398 /******************************************************************************/
401 * Check if transmission is a payload packet.
403 * @param th Transmission handle.
405 * @return GNUNET_YES if it is a payload packet,
406 * GNUNET_NO if it is a mesh management packet.
409 th_is_payload (struct GNUNET_MESH_TransmitHandle *th)
411 return (th->notify != NULL) ? GNUNET_YES : GNUNET_NO;
416 * Check whether there is any message ready in the queue and find the size.
418 * @param h Mesh handle.
420 * @return The size of the first ready message in the queue,
421 * 0 if there is none.
424 message_ready_size (struct GNUNET_MESH_Handle *h)
426 struct GNUNET_MESH_TransmitHandle *th;
427 struct GNUNET_MESH_Tunnel *t;
429 for (th = h->th_head; NULL != th; th = th->next)
432 if (GNUNET_NO == th_is_payload (th))
434 LOG (GNUNET_ERROR_TYPE_DEBUG, " message internal\n");
437 if (GNUNET_NO == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
439 LOG (GNUNET_ERROR_TYPE_DEBUG, " message payload ok (%u <= %u)\n",
440 t->next_send_pid, t->max_send_pid);
449 * Get the tunnel handler for the tunnel specified by id from the given handle
450 * @param h Mesh handle
451 * @param tid ID of the wanted tunnel
452 * @return handle to the required tunnel or NULL if not found
454 static struct GNUNET_MESH_Tunnel *
455 retrieve_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
457 struct GNUNET_MESH_Tunnel *t;
471 * Create a new tunnel and insert it in the tunnel list of the mesh handle
472 * @param h Mesh handle
473 * @param tid desired tid of the tunnel, 0 to assign one automatically
474 * @return handle to the created tunnel
476 static struct GNUNET_MESH_Tunnel *
477 create_tunnel (struct GNUNET_MESH_Handle *h, MESH_TunnelNumber tid)
479 struct GNUNET_MESH_Tunnel *t;
481 t = GNUNET_malloc (sizeof (struct GNUNET_MESH_Tunnel));
482 GNUNET_CONTAINER_DLL_insert (h->tunnels_head, h->tunnels_tail, t);
486 t->tid = h->next_tid;
487 while (NULL != retrieve_tunnel (h, h->next_tid))
490 h->next_tid &= ~GNUNET_MESH_LOCAL_TUNNEL_ID_SERV;
491 h->next_tid |= GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
498 t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
499 t->last_recv_pid = (uint32_t) -1;
500 t->buffering = GNUNET_YES;
506 * Destroy the specified tunnel.
507 * - Destroys all peers, calling the disconnect callback on each if needed
508 * - Cancels all outgoing traffic for that tunnel, calling respective notifys
509 * - Calls cleaner if tunnel was inbound
510 * - Frees all memory used
512 * @param t Pointer to the tunnel.
513 * @param call_cleaner Whether to call the cleaner handler.
515 * @return Handle to the required tunnel or NULL if not found.
518 destroy_tunnel (struct GNUNET_MESH_Tunnel *t, int call_cleaner)
520 struct GNUNET_MESH_Handle *h;
521 struct GNUNET_PeerIdentity pi;
522 struct GNUNET_MESH_TransmitHandle *th;
523 struct GNUNET_MESH_TransmitHandle *next;
526 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroy_tunnel %X\n", t->tid);
535 /* disconnect all peers */
536 GNUNET_CONTAINER_DLL_remove (h->tunnels_head, h->tunnels_tail, t);
537 for (i = 0; i < t->npeers; i++)
539 if ( (NULL != t->disconnect_handler) && t->peers[i]->connected)
541 GNUNET_PEER_resolve (t->peers[i]->id, &pi);
542 t->disconnect_handler (t->cls, &pi);
544 GNUNET_PEER_change_rc (t->peers[i]->id, -1);
545 GNUNET_free (t->peers[i]);
548 /* signal tunnel destruction */
549 if ( (NULL != h->cleaner) && (0 != t->owner) && (GNUNET_YES == call_cleaner) )
550 h->cleaner (h->cls, t, t->ctx);
552 /* check that clients did not leave messages behind in the queue */
553 for (th = h->th_head; NULL != th; th = next)
558 /* Clients should have aborted their requests already.
559 * Management traffic should be ok, as clients can't cancel that */
560 GNUNET_break (GNUNET_NO == th_is_payload(th));
561 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
563 /* clean up request */
564 if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
565 GNUNET_SCHEDULER_cancel (th->timeout_task);
569 /* if there are no more pending requests with mesh service, cancel active request */
570 /* Note: this should be unnecessary... */
571 if ((0 == message_ready_size (h)) && (NULL != h->th))
573 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
579 GNUNET_free (t->peers);
581 GNUNET_PEER_change_rc (t->owner, -1);
582 if (0 != t->napps && t->apps)
583 GNUNET_free (t->apps);
590 * Get the peer descriptor for the peer with id from the given tunnel
591 * @param t Tunnel handle
592 * @param id Short form ID of the wanted peer
593 * @return handle to the requested peer or NULL if not found
595 static struct GNUNET_MESH_Peer *
596 retrieve_peer (struct GNUNET_MESH_Tunnel *t, GNUNET_PEER_Id id)
600 for (i = 0; i < t->npeers; i++)
601 if (t->peers[i]->id == id)
608 * Add a peer into a tunnel
609 * @param t Tunnel handle
610 * @param pi Full ID of the new peer
611 * @return handle to the newly created peer
613 static struct GNUNET_MESH_Peer *
614 add_peer_to_tunnel (struct GNUNET_MESH_Tunnel *t,
615 const struct GNUNET_PeerIdentity *pi)
617 struct GNUNET_MESH_Peer *p;
625 id = GNUNET_PEER_intern (pi);
627 p = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
630 GNUNET_array_append (t->peers, t->npeers, p);
636 * Remove a peer from a tunnel
637 * @param p Peer handle
640 remove_peer_from_tunnel (struct GNUNET_MESH_Peer *p)
644 for (i = 0; i < p->t->npeers; i++)
646 if (p->t->peers[i] == p)
649 if (i == p->t->npeers)
654 p->t->peers[i] = p->t->peers[p->t->npeers - 1];
655 GNUNET_array_grow (p->t->peers, p->t->npeers, p->t->npeers - 1);
660 * Notify client that the transmission has timed out
663 * @param tc task context
666 timeout_transmission (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
668 struct GNUNET_MESH_TransmitHandle *th = cls;
669 struct GNUNET_MESH_Handle *mesh;
671 mesh = th->tunnel->mesh;
672 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
673 th->tunnel->packet_size = 0;
674 if (GNUNET_YES == th_is_payload (th))
675 th->notify (th->notify_cls, 0, NULL);
677 if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
679 /* nothing ready to transmit, no point in asking for transmission */
680 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
687 * Add a transmit handle to the transmission queue and set the
690 * @param h mesh handle with the queue head and tail
691 * @param th handle to the packet to be transmitted
694 add_to_queue (struct GNUNET_MESH_Handle *h,
695 struct GNUNET_MESH_TransmitHandle *th)
697 GNUNET_CONTAINER_DLL_insert_tail (h->th_head, h->th_tail, th);
698 if (GNUNET_TIME_UNIT_FOREVER_ABS.abs_value == th->timeout.abs_value)
701 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_absolute_get_remaining
702 (th->timeout), &timeout_transmission, th);
707 * Auxiliary function to send an already constructed packet to the service.
708 * Takes care of creating a new queue element, copying the message and
709 * calling the tmt_rdy function if necessary.
711 * @param h mesh handle
712 * @param msg message to transmit
713 * @param tunnel tunnel this send is related to (NULL if N/A)
716 send_packet (struct GNUNET_MESH_Handle *h,
717 const struct GNUNET_MessageHeader *msg,
718 struct GNUNET_MESH_Tunnel *tunnel);
722 * Send an ack on the tunnel to confirm the processing of a message.
724 * @param h Mesh handle.
725 * @param t Tunnel on which to send the ACK.
728 send_ack (struct GNUNET_MESH_Handle *h, struct GNUNET_MESH_Tunnel *t)
730 struct GNUNET_MESH_LocalAck msg;
733 delta = t->max_recv_pid - t->last_recv_pid;
734 if (delta > ACK_THRESHOLD)
736 LOG (GNUNET_ERROR_TYPE_DEBUG,
737 "Not sending ACK on tunnel %X: ACK: %u, PID: %u, buffer %u\n",
738 t->tid, t->max_recv_pid, t->last_recv_pid, delta);
741 if (GNUNET_YES == t->buffering)
742 t->max_recv_pid = t->last_recv_pid + INITIAL_WINDOW_SIZE;
744 t->max_recv_pid = t->last_recv_pid + 1;
745 LOG (GNUNET_ERROR_TYPE_DEBUG,
746 "Sending ACK on tunnel %X: %u\n",
747 t->tid, t->max_recv_pid);
748 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK);
749 msg.header.size = htons (sizeof (msg));
750 msg.tunnel_id = htonl (t->tid);
751 msg.max_pid = htonl (t->max_recv_pid);
754 t->mesh->acks_sent++;
757 send_packet (h, &msg.header, t);
764 * Reconnect callback: tries to reconnect again after a failer previous
766 * @param cls closure (mesh handle)
767 * @param tc task context
770 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
774 * Send a connect packet to the service with the applications and types
775 * requested by the user.
777 * @param h The mesh handle.
781 send_connect (struct GNUNET_MESH_Handle *h)
785 size = sizeof (struct GNUNET_MESH_ClientConnect);
786 size += h->n_applications * sizeof (GNUNET_MESH_ApplicationType);
787 size += h->n_handlers * sizeof (uint16_t);
789 char buf[size] GNUNET_ALIGN;
790 struct GNUNET_MESH_ClientConnect *msg;
791 GNUNET_MESH_ApplicationType *apps;
796 /* build connection packet */
797 msg = (struct GNUNET_MESH_ClientConnect *) buf;
798 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT);
799 msg->header.size = htons (size);
800 apps = (GNUNET_MESH_ApplicationType *) &msg[1];
801 for (napps = 0; napps < h->n_applications; napps++)
803 apps[napps] = htonl (h->applications[napps]);
804 LOG (GNUNET_ERROR_TYPE_DEBUG, " app %u\n",
805 h->applications[napps]);
807 types = (uint16_t *) & apps[napps];
808 for (ntypes = 0; ntypes < h->n_handlers; ntypes++)
810 types[ntypes] = htons (h->message_handlers[ntypes].type);
811 LOG (GNUNET_ERROR_TYPE_DEBUG, " type %u\n",
812 h->message_handlers[ntypes].type);
814 msg->applications = htons (napps);
815 msg->types = htons (ntypes);
816 LOG (GNUNET_ERROR_TYPE_DEBUG,
817 "Sending %lu bytes long message %d types and %d apps\n",
818 ntohs (msg->header.size), ntypes, napps);
819 send_packet (h, &msg->header, NULL);
825 * Reconnect to the service, retransmit all infomation to try to restore the
828 * @param h handle to the mesh
830 * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
833 do_reconnect (struct GNUNET_MESH_Handle *h)
835 struct GNUNET_MESH_Tunnel *t;
838 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
839 LOG (GNUNET_ERROR_TYPE_DEBUG, "******* RECONNECT *******\n");
840 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
841 LOG (GNUNET_ERROR_TYPE_DEBUG, "******** on %p *******\n", h);
842 LOG (GNUNET_ERROR_TYPE_DEBUG, "*****************************\n");
847 GNUNET_CLIENT_notify_transmit_ready_cancel (h->th);
850 if (NULL != h->client)
852 GNUNET_CLIENT_disconnect (h->client);
856 h->client = GNUNET_CLIENT_connect ("mesh", h->cfg);
857 if (h->client == NULL)
859 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
862 GNUNET_TIME_relative_min (GNUNET_TIME_UNIT_SECONDS,
863 GNUNET_TIME_relative_multiply
864 (h->reconnect_time, 2));
865 LOG (GNUNET_ERROR_TYPE_DEBUG,
866 "Next retry in %s\n",
867 GNUNET_STRINGS_relative_time_to_string (h->reconnect_time,
874 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
877 /* Rebuild all tunnels */
878 for (t = h->tunnels_head; NULL != t; t = t->next)
880 struct GNUNET_MESH_TunnelMessage tmsg;
881 struct GNUNET_MESH_PeerControl pmsg;
883 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
885 /* Tunnel was created by service (incoming tunnel) */
886 /* TODO: Notify service of missing tunnel, to request
887 * creator to recreate path (find a path to him via DHT?)
891 t->next_send_pid = 0;
892 t->max_send_pid = INITIAL_WINDOW_SIZE - 1;
893 t->last_recv_pid = (uint32_t) -1;
894 tmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
895 tmsg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
896 tmsg.tunnel_id = htonl (t->tid);
897 send_packet (h, &tmsg.header, t);
899 pmsg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
900 pmsg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
901 pmsg.tunnel_id = htonl (t->tid);
903 /* Reconnect all peers */
904 /* If the tunnel was "by type", dont connect individual peers */
905 for (i = 0; i < t->npeers && 0 == t->napps; i++)
907 GNUNET_PEER_resolve (t->peers[i]->id, &pmsg.peer);
908 if (NULL != t->disconnect_handler && t->peers[i]->connected)
909 t->disconnect_handler (t->cls, &pmsg.peer);
910 send_packet (t->mesh, &pmsg.header, t);
912 /* Reconnect all types, if any */
913 for (i = 0; i < t->napps; i++)
915 struct GNUNET_MESH_ConnectPeerByType msg;
917 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
918 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
919 msg.tunnel_id = htonl (t->tid);
920 msg.type = htonl (t->apps[i]);
921 send_packet (t->mesh, &msg.header, t);
923 if (GNUNET_NO == t->buffering)
924 GNUNET_MESH_tunnel_buffer (t, GNUNET_NO);
925 if (GNUNET_YES == t->speed_min)
926 GNUNET_MESH_tunnel_speed_min (t);
932 * Reconnect callback: tries to reconnect again after a failer previous
934 * @param cls closure (mesh handle)
935 * @param tc task context
938 reconnect_cbk (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
940 struct GNUNET_MESH_Handle *h = cls;
942 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
943 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
950 * Reconnect to the service, retransmit all infomation to try to restore the
953 * @param h handle to the mesh
955 * @return GNUNET_YES in case of sucess, GNUNET_NO otherwise (service down...)
958 reconnect (struct GNUNET_MESH_Handle *h)
960 LOG (GNUNET_ERROR_TYPE_DEBUG, "Requested RECONNECT\n");
961 h->in_receive = GNUNET_NO;
962 if (GNUNET_SCHEDULER_NO_TASK == h->reconnect_task)
963 h->reconnect_task = GNUNET_SCHEDULER_add_delayed (h->reconnect_time,
968 /******************************************************************************/
969 /*********************** RECEIVE HANDLERS ****************************/
970 /******************************************************************************/
973 * Process the new tunnel notification and add it to the tunnels in the handle
975 * @param h The mesh handle
976 * @param msg A message with the details of the new incoming tunnel
979 process_tunnel_created (struct GNUNET_MESH_Handle *h,
980 const struct GNUNET_MESH_TunnelNotification *msg)
982 struct GNUNET_MESH_Tunnel *t;
983 MESH_TunnelNumber tid;
985 tid = ntohl (msg->tunnel_id);
986 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating incoming tunnel %X\n", tid);
987 if (tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
992 if (NULL != h->new_tunnel)
994 struct GNUNET_ATS_Information atsi;
996 t = create_tunnel (h, tid);
997 t->owner = GNUNET_PEER_intern (&msg->peer);
999 t->peers = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer *));
1000 t->peers[0] = GNUNET_malloc (sizeof (struct GNUNET_MESH_Peer));
1002 t->peers[0]->connected = 1;
1003 t->peers[0]->id = t->owner;
1004 GNUNET_PEER_change_rc (t->owner, 1);
1007 if ((msg->opt & MESH_TUNNEL_OPT_NOBUFFER) != 0)
1008 t->buffering = GNUNET_NO;
1010 t->buffering = GNUNET_YES;
1011 if ((msg->opt & MESH_TUNNEL_OPT_SPEED_MIN) != 0)
1012 t->speed_min = GNUNET_YES;
1015 LOG (GNUNET_ERROR_TYPE_DEBUG, " created tunnel %p\n", t);
1016 t->ctx = h->new_tunnel (h->cls, t, &msg->peer, &atsi);
1017 LOG (GNUNET_ERROR_TYPE_DEBUG, "User notified\n");
1021 struct GNUNET_MESH_TunnelMessage d_msg;
1023 LOG (GNUNET_ERROR_TYPE_DEBUG, "No handler for incoming tunnels\n");
1025 d_msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1026 d_msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1027 d_msg.tunnel_id = msg->tunnel_id;
1029 send_packet (h, &d_msg.header, NULL);
1036 * Process the tunnel destroy notification and free associated resources
1038 * @param h The mesh handle
1039 * @param msg A message with the details of the tunnel being destroyed
1042 process_tunnel_destroy (struct GNUNET_MESH_Handle *h,
1043 const struct GNUNET_MESH_TunnelMessage *msg)
1045 struct GNUNET_MESH_Tunnel *t;
1046 MESH_TunnelNumber tid;
1048 tid = ntohl (msg->tunnel_id);
1049 t = retrieve_tunnel (h, tid);
1059 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X destroyed\n", t->tid);
1060 destroy_tunnel (t, GNUNET_YES);
1066 * Process the new peer event and notify the upper level of it
1068 * @param h The mesh handle
1069 * @param msg A message with the details of the peer event
1072 process_peer_event (struct GNUNET_MESH_Handle *h,
1073 const struct GNUNET_MESH_PeerControl *msg)
1075 struct GNUNET_MESH_Tunnel *t;
1076 struct GNUNET_MESH_Peer *p;
1077 struct GNUNET_ATS_Information atsi;
1081 LOG (GNUNET_ERROR_TYPE_DEBUG, "processig peer event\n");
1082 size = ntohs (msg->header.size);
1083 if (size != sizeof (struct GNUNET_MESH_PeerControl))
1088 t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1094 id = GNUNET_PEER_search (&msg->peer);
1095 if ((p = retrieve_peer (t, id)) == NULL)
1096 p = add_peer_to_tunnel (t, &msg->peer);
1097 if (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD == ntohs (msg->header.type))
1099 LOG (GNUNET_ERROR_TYPE_DEBUG, "adding peer\n");
1100 if (NULL != t->connect_handler)
1104 t->connect_handler (t->cls, &msg->peer, &atsi);
1110 LOG (GNUNET_ERROR_TYPE_DEBUG, "removing peer\n");
1111 if (NULL != t->disconnect_handler && p->connected)
1113 t->disconnect_handler (t->cls, &msg->peer);
1115 remove_peer_from_tunnel (p);
1118 LOG (GNUNET_ERROR_TYPE_DEBUG, "processing peer event END\n");
1123 * Process the incoming data packets
1125 * @param h The mesh handle
1126 * @param message A message encapsulating the data
1128 * @return GNUNET_YES if everything went fine
1129 * GNUNET_NO if client closed connection (h no longer valid)
1132 process_incoming_data (struct GNUNET_MESH_Handle *h,
1133 const struct GNUNET_MessageHeader *message)
1135 const struct GNUNET_MessageHeader *payload;
1136 const struct GNUNET_MESH_MessageHandler *handler;
1137 const struct GNUNET_PeerIdentity *peer;
1138 struct GNUNET_MESH_Unicast *ucast;
1139 struct GNUNET_MESH_Multicast *mcast;
1140 struct GNUNET_MESH_ToOrigin *to_orig;
1141 struct GNUNET_MESH_Tunnel *t;
1146 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a data message!\n");
1147 type = ntohs (message->type);
1150 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1151 ucast = (struct GNUNET_MESH_Unicast *) message;
1153 t = retrieve_tunnel (h, ntohl (ucast->tid));
1154 payload = (struct GNUNET_MessageHeader *) &ucast[1];
1156 pid = ntohl (ucast->pid);
1157 LOG (GNUNET_ERROR_TYPE_DEBUG, " ucast on tunnel %s [%X]\n",
1158 GNUNET_i2s (peer), ntohl (ucast->tid));
1160 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1161 mcast = (struct GNUNET_MESH_Multicast *) message;
1162 t = retrieve_tunnel (h, ntohl (mcast->tid));
1163 payload = (struct GNUNET_MessageHeader *) &mcast[1];
1165 pid = ntohl (mcast->pid);
1166 LOG (GNUNET_ERROR_TYPE_DEBUG, " mcast on tunnel %s [%X]\n",
1167 GNUNET_i2s (peer), ntohl (mcast->tid));
1169 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1170 to_orig = (struct GNUNET_MESH_ToOrigin *) message;
1171 t = retrieve_tunnel (h, ntohl (to_orig->tid));
1172 payload = (struct GNUNET_MessageHeader *) &to_orig[1];
1173 peer = &to_orig->sender;
1174 pid = ntohl (to_orig->pid);
1175 LOG (GNUNET_ERROR_TYPE_DEBUG, " torig on tunnel %s [%X]\n",
1176 GNUNET_i2s (peer), ntohl (to_orig->tid));
1182 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", pid);
1185 /* Tunnel was ignored/destroyed, probably service didn't get it yet */
1186 LOG (GNUNET_ERROR_TYPE_DEBUG, " ignored!\n");
1190 GMC_is_pid_bigger(pid, t->max_recv_pid))
1193 LOG (GNUNET_ERROR_TYPE_WARNING,
1194 " unauthorized message! (%u, max %u)\n",
1195 pid, t->max_recv_pid);
1196 // FIXME fc what now? accept? reject?
1199 t->last_recv_pid = pid;
1200 type = ntohs (payload->type);
1202 for (i = 0; i < h->n_handlers; i++)
1204 handler = &h->message_handlers[i];
1205 if (handler->type == type)
1207 struct GNUNET_ATS_Information atsi;
1212 handler->callback (h->cls, t, &t->ctx, peer, payload, &atsi))
1214 LOG (GNUNET_ERROR_TYPE_DEBUG, "callback caused disconnection\n");
1215 GNUNET_MESH_disconnect (h);
1220 LOG (GNUNET_ERROR_TYPE_DEBUG,
1221 "callback completed successfully\n");
1230 * Process a local ACK message, enabling the client to send
1231 * more data to the service.
1233 * @param h Mesh handle.
1234 * @param message Message itself.
1237 process_ack (struct GNUNET_MESH_Handle *h,
1238 const struct GNUNET_MessageHeader *message)
1240 struct GNUNET_MESH_LocalAck *msg;
1241 struct GNUNET_MESH_Tunnel *t;
1244 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK!\n");
1246 msg = (struct GNUNET_MESH_LocalAck *) message;
1248 t = retrieve_tunnel (h, ntohl (msg->tunnel_id));
1252 LOG (GNUNET_ERROR_TYPE_WARNING,
1253 "ACK on unknown tunnel %X\n",
1254 ntohl (msg->tunnel_id));
1257 ack = ntohl (msg->max_pid);
1258 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X, ack %u!\n", t->tid, ack);
1259 if (GNUNET_YES == GMC_is_pid_bigger(ack, t->max_send_pid))
1260 t->max_send_pid = ack;
1263 if (NULL == h->th && 0 < t->packet_size)
1265 LOG (GNUNET_ERROR_TYPE_DEBUG, " tmt rdy was NULL, requesting!\n", t->tid, ack);
1267 GNUNET_CLIENT_notify_transmit_ready (h->client, t->packet_size,
1268 GNUNET_TIME_UNIT_FOREVER_REL,
1269 GNUNET_YES, &send_callback, h);
1275 * Process a local reply about info on all tunnels, pass info to the user.
1277 * @param h Mesh handle.
1278 * @param message Message itself.
1281 process_get_tunnels (struct GNUNET_MESH_Handle *h,
1282 const struct GNUNET_MessageHeader *message)
1284 struct GNUNET_MESH_LocalMonitor *msg;
1287 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Get Tunnels messasge received\n");
1289 if (NULL == h->tunnels_cb)
1291 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1295 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1296 npeers = ntohl (msg->npeers);
1297 if (ntohs (message->size) !=
1298 (sizeof (struct GNUNET_MESH_LocalMonitor) +
1299 npeers * sizeof (struct GNUNET_PeerIdentity)))
1301 GNUNET_break_op (0);
1302 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1303 "Get tunnels message: size %hu - expected %u (%u peers)\n",
1304 ntohs (message->size),
1305 sizeof (struct GNUNET_MESH_LocalMonitor) +
1306 npeers * sizeof (struct GNUNET_PeerIdentity),
1310 h->tunnels_cb (h->tunnels_cls,
1312 ntohl (msg->tunnel_id),
1313 (struct GNUNET_PeerIdentity *) &msg[1],
1320 * Process a local monitor_tunnel reply, pass info to the user.
1322 * @param h Mesh handle.
1323 * @param message Message itself.
1326 process_show_tunnel (struct GNUNET_MESH_Handle *h,
1327 const struct GNUNET_MessageHeader *message)
1329 struct GNUNET_MESH_LocalMonitor *msg;
1330 struct GNUNET_PeerIdentity *new_peers;
1331 uint32_t *new_parents;
1336 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Show Tunnel messasge received\n");
1338 if (NULL == h->tunnel_cb)
1340 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " ignored\n");
1344 /* Verify message sanity */
1345 msg = (struct GNUNET_MESH_LocalMonitor *) message;
1346 npeers = ntohl (msg->npeers);
1347 esize = sizeof (struct GNUNET_MESH_LocalMonitor);
1348 esize += npeers * (sizeof (struct GNUNET_PeerIdentity) + sizeof (uint32_t));
1349 if (ntohs (message->size) != esize)
1351 GNUNET_break_op (0);
1352 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1353 "Show tunnel message: size %hu - expected %u (%u peers)\n",
1354 ntohs (message->size),
1358 h->tunnel_cb (h->tunnel_cls, NULL, NULL);
1359 h->tunnel_cb = NULL;
1360 h->tunnel_cls = NULL;
1361 h->tunnel_npeers = 0;
1362 GNUNET_free_non_null (h->peers);
1368 new_peers = (struct GNUNET_PeerIdentity *) &msg[1];
1369 new_parents = (uint32_t *) &new_peers[npeers];
1371 h->peers = GNUNET_realloc (h->peers, h->tunnel_npeers + npeers);
1372 memcpy (&h->peers[h->tunnel_npeers],
1374 npeers * sizeof (struct GNUNET_PeerIdentity));
1375 h->tunnel_npeers += npeers;
1376 for (i = 0; i < npeers; i++)
1377 h->tunnel_cb (h->tunnel_cls,
1379 &h->peers[new_parents[i]]);
1384 * Function to process all messages received from the service
1386 * @param cls closure
1387 * @param msg message received, NULL on timeout or fatal error
1390 msg_received (void *cls, const struct GNUNET_MessageHeader *msg)
1392 struct GNUNET_MESH_Handle *h = cls;
1396 LOG (GNUNET_ERROR_TYPE_DEBUG,
1397 "Mesh service disconnected, reconnecting\n", h);
1401 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n",
1402 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1403 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a message: %s\n",
1404 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1405 switch (ntohs (msg->type))
1407 /* Notify of a new incoming tunnel */
1408 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE:
1409 process_tunnel_created (h, (struct GNUNET_MESH_TunnelNotification *) msg);
1411 /* Notify of a tunnel disconnection */
1412 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1413 process_tunnel_destroy (h, (struct GNUNET_MESH_TunnelMessage *) msg);
1415 /* Notify of a new peer or a peer disconnect in the tunnel */
1416 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD:
1417 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL:
1418 process_peer_event (h, (struct GNUNET_MESH_PeerControl *) msg);
1420 /* Notify of a new data packet in the tunnel */
1421 case GNUNET_MESSAGE_TYPE_MESH_UNICAST:
1422 case GNUNET_MESSAGE_TYPE_MESH_MULTICAST:
1423 case GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN:
1424 if (GNUNET_NO == process_incoming_data (h, msg))
1427 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_ACK:
1428 process_ack (h, msg);
1430 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1431 process_get_tunnels (h, msg);
1433 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1434 process_show_tunnel (h, msg);
1437 /* We shouldn't get any other packages, log and ignore */
1438 LOG (GNUNET_ERROR_TYPE_WARNING,
1439 "unsolicited message form service (type %s)\n",
1440 GNUNET_MESH_DEBUG_M2S (ntohs (msg->type)));
1442 LOG (GNUNET_ERROR_TYPE_DEBUG, "message processed\n");
1443 if (GNUNET_YES == h->in_receive)
1445 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1446 GNUNET_TIME_UNIT_FOREVER_REL);
1450 LOG (GNUNET_ERROR_TYPE_DEBUG,
1451 "in receive off, not calling CLIENT_receive\n");
1456 /******************************************************************************/
1457 /************************ SEND FUNCTIONS ****************************/
1458 /******************************************************************************/
1461 * Function called to send a message to the service.
1462 * "buf" will be NULL and "size" zero if the socket was closed for writing in
1465 * @param cls closure, the mesh handle
1466 * @param size number of bytes available in buf
1467 * @param buf where the callee should write the connect message
1468 * @return number of bytes written to buf
1471 send_callback (void *cls, size_t size, void *buf)
1473 struct GNUNET_MESH_Handle *h = cls;
1474 struct GNUNET_MESH_TransmitHandle *th;
1475 struct GNUNET_MESH_TransmitHandle *next;
1476 struct GNUNET_MESH_Tunnel *t;
1482 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n");
1483 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() Buffer %u\n", size);
1484 if ((0 == size) || (NULL == buf))
1486 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received NULL send callback on %p\n", h);
1493 nsize = message_ready_size (h);
1494 while ((NULL != (th = next)) && (0 < nsize) && (size >= nsize))
1497 if (GNUNET_YES == th_is_payload (th))
1499 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload\n");
1500 if (GNUNET_YES == GMC_is_pid_bigger(t->next_send_pid, t->max_send_pid))
1502 /* This tunnel is not ready to transmit yet, try next message */
1507 if (t->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1509 /* traffic to origin */
1510 struct GNUNET_MESH_ToOrigin to;
1511 struct GNUNET_MessageHeader *mh;
1513 GNUNET_assert (size >= th->size);
1514 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (to)];
1515 psize = th->notify (th->notify_cls, size - sizeof (to), mh);
1516 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin, type %s\n",
1517 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1520 psize += sizeof (to);
1521 GNUNET_assert (size >= psize);
1522 to.header.size = htons (psize);
1523 to.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TO_ORIGIN);
1524 to.tid = htonl (t->tid);
1525 to.pid = htonl (t->next_send_pid);
1527 memset (&to.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1528 memset (&to.sender, 0, sizeof (struct GNUNET_PeerIdentity));
1529 memcpy (cbuf, &to, sizeof (to));
1532 else if (th->target == 0)
1535 struct GNUNET_MESH_Multicast mc;
1536 struct GNUNET_MessageHeader *mh;
1538 GNUNET_assert (size >= th->size);
1539 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (mc)];
1540 psize = th->notify (th->notify_cls, size - sizeof (mc), mh);
1541 LOG (GNUNET_ERROR_TYPE_DEBUG, " multicast, type %s\n",
1542 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1545 psize += sizeof (mc);
1546 GNUNET_assert (size >= psize);
1547 mc.header.size = htons (psize);
1548 mc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_MULTICAST);
1549 mc.tid = htonl (t->tid);
1550 mc.pid = htonl (t->next_send_pid);
1552 memset (&mc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1553 memcpy (cbuf, &mc, sizeof (mc));
1559 struct GNUNET_MESH_Unicast uc;
1560 struct GNUNET_MessageHeader *mh;
1562 GNUNET_assert (size >= th->size);
1563 mh = (struct GNUNET_MessageHeader *) &cbuf[sizeof (uc)];
1564 psize = th->notify (th->notify_cls, size - sizeof (uc), mh);
1565 LOG (GNUNET_ERROR_TYPE_DEBUG, " unicast, type %s\n",
1566 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1569 psize += sizeof (uc);
1570 GNUNET_assert (size >= psize);
1571 uc.header.size = htons (psize);
1572 uc.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_UNICAST);
1573 uc.tid = htonl (t->tid);
1574 uc.pid = htonl (t->next_send_pid);
1576 memset (&uc.oid, 0, sizeof (struct GNUNET_PeerIdentity));
1577 GNUNET_PEER_resolve (th->target, &uc.destination);
1578 memcpy (cbuf, &uc, sizeof (uc));
1585 struct GNUNET_MessageHeader *mh = (struct GNUNET_MessageHeader *) &th[1];
1587 LOG (GNUNET_ERROR_TYPE_DEBUG, " mesh traffic, type %s\n",
1588 GNUNET_MESH_DEBUG_M2S (ntohs (mh->type)));
1589 memcpy (cbuf, &th[1], th->size);
1592 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
1593 GNUNET_SCHEDULER_cancel (th->timeout_task);
1594 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1597 nsize = message_ready_size (h);
1602 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size: %u\n", tsize);
1604 size = message_ready_size (h);
1607 LOG (GNUNET_ERROR_TYPE_DEBUG, " next size: %u\n", size);
1609 GNUNET_CLIENT_notify_transmit_ready (h->client, size,
1610 GNUNET_TIME_UNIT_FOREVER_REL,
1611 GNUNET_YES, &send_callback, h);
1615 if (NULL != h->th_head)
1616 LOG (GNUNET_ERROR_TYPE_DEBUG, " can't transmit any more\n");
1618 LOG (GNUNET_ERROR_TYPE_DEBUG, " nothing left to transmit\n");
1620 if (GNUNET_NO == h->in_receive)
1622 LOG (GNUNET_ERROR_TYPE_DEBUG, " start receiving from service\n");
1623 h->in_receive = GNUNET_YES;
1624 GNUNET_CLIENT_receive (h->client, &msg_received, h,
1625 GNUNET_TIME_UNIT_FOREVER_REL);
1627 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send packet() END\n");
1633 * Auxiliary function to send an already constructed packet to the service.
1634 * Takes care of creating a new queue element, copying the message and
1635 * calling the tmt_rdy function if necessary.
1637 * @param h mesh handle
1638 * @param msg message to transmit
1639 * @param tunnel tunnel this send is related to (NULL if N/A)
1642 send_packet (struct GNUNET_MESH_Handle *h,
1643 const struct GNUNET_MessageHeader *msg,
1644 struct GNUNET_MESH_Tunnel *tunnel)
1646 struct GNUNET_MESH_TransmitHandle *th;
1649 LOG (GNUNET_ERROR_TYPE_DEBUG, " Sending message to service: %s\n",
1650 GNUNET_MESH_DEBUG_M2S(ntohs(msg->type)));
1651 msize = ntohs (msg->size);
1652 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle) + msize);
1653 th->timeout = GNUNET_TIME_UNIT_FOREVER_ABS;
1655 th->tunnel = tunnel;
1656 memcpy (&th[1], msg, msize);
1657 add_to_queue (h, th);
1658 LOG (GNUNET_ERROR_TYPE_DEBUG, " queued\n");
1661 LOG (GNUNET_ERROR_TYPE_DEBUG, " calling ntfy tmt rdy for %u bytes\n", msize);
1663 GNUNET_CLIENT_notify_transmit_ready (h->client, msize,
1664 GNUNET_TIME_UNIT_FOREVER_REL,
1665 GNUNET_YES, &send_callback, h);
1669 /******************************************************************************/
1670 /********************** API CALL DEFINITIONS *************************/
1671 /******************************************************************************/
1674 * Connect to the mesh service.
1676 * @param cfg configuration to use
1677 * @param cls closure for the various callbacks that follow
1678 * (including handlers in the handlers array)
1679 * @param new_tunnel function called when an *inbound* tunnel is created
1680 * @param cleaner function called when an *inbound* tunnel is destroyed by the
1681 * remote peer, it is *not* called if GNUNET_MESH_tunnel_destroy
1682 * is called on the tunnel
1683 * @param handlers callbacks for messages we care about, NULL-terminated
1684 * note that the mesh is allowed to drop notifications about
1685 * inbound messages if the client does not process them fast
1686 * enough (for this notification type, a bounded queue is used)
1687 * @param stypes list of the applications that this client claims to provide
1688 * @return handle to the mesh service NULL on error
1689 * (in this case, init is never called)
1691 struct GNUNET_MESH_Handle *
1692 GNUNET_MESH_connect (const struct GNUNET_CONFIGURATION_Handle *cfg, void *cls,
1693 GNUNET_MESH_InboundTunnelNotificationHandler new_tunnel,
1694 GNUNET_MESH_TunnelEndHandler cleaner,
1695 const struct GNUNET_MESH_MessageHandler *handlers,
1696 const GNUNET_MESH_ApplicationType *stypes)
1698 struct GNUNET_MESH_Handle *h;
1701 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect()\n");
1702 h = GNUNET_malloc (sizeof (struct GNUNET_MESH_Handle));
1703 LOG (GNUNET_ERROR_TYPE_DEBUG, " addr %p\n", h);
1705 h->new_tunnel = new_tunnel;
1706 h->cleaner = cleaner;
1707 h->client = GNUNET_CLIENT_connect ("mesh", cfg);
1708 if (h->client == NULL)
1715 h->message_handlers = handlers;
1716 h->next_tid = GNUNET_MESH_LOCAL_TUNNEL_ID_CLI;
1717 h->reconnect_time = GNUNET_TIME_UNIT_MILLISECONDS;
1718 h->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1721 for (h->n_applications = 0;
1722 stypes && stypes[h->n_applications];
1723 h->n_applications++) ;
1724 if (0 < h->n_applications)
1726 size = h->n_applications * sizeof (GNUNET_MESH_ApplicationType *);
1727 h->applications = GNUNET_malloc (size);
1728 memcpy (h->applications, stypes, size);
1730 /* count handlers */
1731 for (h->n_handlers = 0;
1732 handlers && handlers[h->n_handlers].type;
1735 LOG (GNUNET_ERROR_TYPE_DEBUG, "GNUNET_MESH_connect() END\n");
1741 * Disconnect from the mesh service. All tunnels will be destroyed. All tunnel
1742 * disconnect callbacks will be called on any still connected peers, notifying
1743 * about their disconnection. The registered inbound tunnel cleaner will be
1744 * called should any inbound tunnels still exist.
1746 * @param handle connection to mesh to disconnect
1749 GNUNET_MESH_disconnect (struct GNUNET_MESH_Handle *handle)
1751 struct GNUNET_MESH_Tunnel *t;
1752 struct GNUNET_MESH_Tunnel *aux;
1753 struct GNUNET_MESH_TransmitHandle *th;
1755 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH DISCONNECT\n");
1758 LOG (GNUNET_ERROR_TYPE_INFO, "Sent %d ACKs\n", handle->acks_sent);
1759 LOG (GNUNET_ERROR_TYPE_INFO, "Recv %d ACKs\n\n", handle->acks_recv);
1762 t = handle->tunnels_head;
1766 if (t->tid < GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
1769 LOG (GNUNET_ERROR_TYPE_DEBUG, "tunnel %X not destroyed\n", t->tid);
1771 destroy_tunnel (t, GNUNET_YES);
1774 while ( (th = handle->th_head) != NULL)
1776 struct GNUNET_MessageHeader *msg;
1778 /* Make sure it is an allowed packet (everything else should have been
1779 * already canceled).
1781 GNUNET_break (GNUNET_NO == th_is_payload (th));
1782 msg = (struct GNUNET_MessageHeader *) &th[1];
1783 switch (ntohs(msg->type))
1785 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_CONNECT:
1786 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY:
1787 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS:
1788 case GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL:
1792 LOG (GNUNET_ERROR_TYPE_ERROR, "unexpected msg %u\n",
1796 GNUNET_CONTAINER_DLL_remove (handle->th_head, handle->th_tail, th);
1800 if (NULL != handle->th)
1802 GNUNET_CLIENT_notify_transmit_ready_cancel (handle->th);
1805 if (NULL != handle->client)
1807 GNUNET_CLIENT_disconnect (handle->client);
1808 handle->client = NULL;
1810 if (GNUNET_SCHEDULER_NO_TASK != handle->reconnect_task)
1812 GNUNET_SCHEDULER_cancel(handle->reconnect_task);
1813 handle->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
1815 GNUNET_free_non_null (handle->applications);
1816 GNUNET_free (handle);
1821 * Announce to ther peer the availability of services described by the regex,
1822 * in order to be reachable to other peers via connect_by_string.
1824 * Note that the first 8 characters are considered to be part of a prefix,
1825 * (for instance 'gnunet://'). If you put a variable part in there (*, +. ()),
1826 * all matching strings will be stored in the DHT.
1828 * @param h Handle to mesh.
1829 * @param regex String with the regular expression describing local services.
1830 * @param compression_characters How many characters can be assigned to one
1831 * edge of the graph. The bigger the variability
1832 * of the data, the smaller this parameter should
1834 * For maximum compression, use strlen (regex)
1835 * or 0 (special value). Use with care!
1838 GNUNET_MESH_announce_regex (struct GNUNET_MESH_Handle *h,
1840 unsigned int compression_characters)
1842 struct GNUNET_MESH_RegexAnnounce *msg;
1847 char buffer[UINT16_MAX];
1849 len = strlen (regex);
1850 payload = UINT16_MAX - sizeof(struct GNUNET_MESH_RegexAnnounce);
1851 msg = (struct GNUNET_MESH_RegexAnnounce *) buffer;
1852 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_ANNOUNCE_REGEX);
1853 msg->compression_characters = htons (compression_characters);
1857 msgsize = (len - offset > payload) ? payload : len - offset;
1858 memcpy (&msg[1], ®ex[offset], msgsize);
1860 msgsize += sizeof(struct GNUNET_MESH_RegexAnnounce);
1862 msg->header.size = htons (msgsize);
1863 msg->last = htons (offset >= len);
1865 send_packet (h, &msg->header, NULL);
1866 } while (len > offset);
1870 * Create a new tunnel (we're initiator and will be allowed to add/remove peers
1871 * and to broadcast).
1873 * @param h mesh handle
1874 * @param tunnel_ctx client's tunnel context to associate with the tunnel
1875 * @param connect_handler function to call when peers are actually connected
1876 * @param disconnect_handler function to call when peers are disconnected
1877 * @param handler_cls closure for connect/disconnect handlers
1879 struct GNUNET_MESH_Tunnel *
1880 GNUNET_MESH_tunnel_create (struct GNUNET_MESH_Handle *h, void *tunnel_ctx,
1881 GNUNET_MESH_PeerConnectHandler connect_handler,
1882 GNUNET_MESH_PeerDisconnectHandler disconnect_handler,
1885 struct GNUNET_MESH_Tunnel *t;
1886 struct GNUNET_MESH_TunnelMessage msg;
1888 LOG (GNUNET_ERROR_TYPE_DEBUG, "Creating new tunnel\n");
1889 t = create_tunnel (h, 0);
1890 LOG (GNUNET_ERROR_TYPE_DEBUG, " at %p\n", t);
1891 LOG (GNUNET_ERROR_TYPE_DEBUG, " number %X\n", t->tid);
1892 t->connect_handler = connect_handler;
1893 t->disconnect_handler = disconnect_handler;
1894 t->cls = handler_cls;
1895 t->ctx = tunnel_ctx;
1896 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_CREATE);
1897 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1898 msg.tunnel_id = htonl (t->tid);
1899 send_packet (h, &msg.header, t);
1905 * Destroy an existing tunnel. The existing callback for the tunnel will NOT
1908 * @param tunnel tunnel handle
1911 GNUNET_MESH_tunnel_destroy (struct GNUNET_MESH_Tunnel *tunnel)
1913 struct GNUNET_MESH_Handle *h;
1914 struct GNUNET_MESH_TunnelMessage msg;
1915 struct GNUNET_MESH_TransmitHandle *th;
1917 LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroying tunnel\n");
1920 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_DESTROY);
1921 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1922 msg.tunnel_id = htonl (tunnel->tid);
1926 struct GNUNET_MESH_TransmitHandle *aux;
1927 if (th->tunnel == tunnel)
1930 /* FIXME call the handler? */
1931 if (GNUNET_YES == th_is_payload (th))
1932 th->notify (th->notify_cls, 0, NULL);
1933 GNUNET_CONTAINER_DLL_remove (h->th_head, h->th_tail, th);
1941 destroy_tunnel (tunnel, GNUNET_NO);
1942 send_packet (h, &msg.header, NULL);
1946 * Request that the tunnel data rate is limited to the speed of the slowest
1949 * @param tunnel Tunnel affected.
1952 GNUNET_MESH_tunnel_speed_min (struct GNUNET_MESH_Tunnel *tunnel)
1954 struct GNUNET_MESH_TunnelMessage msg;
1955 struct GNUNET_MESH_Handle *h;
1958 tunnel->speed_min = GNUNET_YES;
1960 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MIN);
1961 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1962 msg.tunnel_id = htonl (tunnel->tid);
1964 send_packet (h, &msg.header, NULL);
1969 * Request that the tunnel data rate is limited to the speed of the fastest
1970 * receiver. This is the default behavior.
1972 * @param tunnel Tunnel affected.
1975 GNUNET_MESH_tunnel_speed_max (struct GNUNET_MESH_Tunnel *tunnel)
1977 struct GNUNET_MESH_TunnelMessage msg;
1978 struct GNUNET_MESH_Handle *h;
1981 tunnel->speed_min = GNUNET_NO;
1983 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_MAX);
1984 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
1985 msg.tunnel_id = htonl (tunnel->tid);
1987 send_packet (h, &msg.header, NULL);
1991 * Turn on/off the buffering status of the tunnel.
1993 * @param tunnel Tunnel affected.
1994 * @param buffer GNUNET_YES to turn buffering on (default),
1995 * GNUNET_NO otherwise.
1998 GNUNET_MESH_tunnel_buffer (struct GNUNET_MESH_Tunnel *tunnel, int buffer)
2000 struct GNUNET_MESH_TunnelMessage msg;
2001 struct GNUNET_MESH_Handle *h;
2004 tunnel->buffering = buffer;
2005 tunnel->max_send_pid = tunnel->next_send_pid;
2007 if (GNUNET_YES == buffer)
2008 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_BUFFER);
2010 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_TUNNEL_NOBUFFER);
2011 msg.header.size = htons (sizeof (struct GNUNET_MESH_TunnelMessage));
2012 msg.tunnel_id = htonl (tunnel->tid);
2014 send_packet (h, &msg.header, NULL);
2019 * Request that a peer should be added to the tunnel. The existing
2020 * connect handler will be called ONCE with either success or failure.
2021 * This function should NOT be called again with the same peer before the
2022 * connect handler is called.
2023 * FIXME: I think the above documentation is false. I think it should
2024 * read: "The connect handler will be called once the peer was actually
2025 * successfully added to the multicast group. This function should
2026 * not be called twice for the same peer (unless, of course,
2027 * the peer was removed using GNUNET_MESH_peer_Request_connect_del in
2030 * @param tunnel handle to existing tunnel
2031 * @param peer peer to add
2034 GNUNET_MESH_peer_request_connect_add (struct GNUNET_MESH_Tunnel *tunnel,
2035 const struct GNUNET_PeerIdentity *peer)
2037 struct GNUNET_MESH_PeerControl msg;
2038 GNUNET_PEER_Id peer_id;
2041 peer_id = GNUNET_PEER_intern (peer);
2042 for (i = 0; i < tunnel->npeers; i++)
2044 if (tunnel->peers[i]->id == peer_id)
2046 /* Peer already exists in tunnel */
2047 GNUNET_PEER_change_rc (peer_id, -1);
2052 if (NULL == add_peer_to_tunnel (tunnel, peer))
2055 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2056 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD);
2057 msg.tunnel_id = htonl (tunnel->tid);
2059 send_packet (tunnel->mesh, &msg.header, tunnel);
2064 * Request that a peer should be removed from the tunnel. The existing
2065 * disconnect handler will be called ONCE if we were connected.
2067 * @param tunnel handle to existing tunnel
2068 * @param peer peer to remove
2071 GNUNET_MESH_peer_request_connect_del (struct GNUNET_MESH_Tunnel *tunnel,
2072 const struct GNUNET_PeerIdentity *peer)
2074 struct GNUNET_MESH_PeerControl msg;
2075 GNUNET_PEER_Id peer_id;
2078 peer_id = GNUNET_PEER_search (peer);
2084 for (i = 0; i < tunnel->npeers; i++)
2085 if (tunnel->peers[i]->id == peer_id)
2087 if (i == tunnel->npeers)
2092 if (NULL != tunnel->disconnect_handler && tunnel->peers[i]->connected == 1)
2093 tunnel->disconnect_handler (tunnel->cls, peer);
2094 GNUNET_PEER_change_rc (peer_id, -1);
2095 GNUNET_free (tunnel->peers[i]);
2096 tunnel->peers[i] = tunnel->peers[tunnel->npeers - 1];
2097 GNUNET_array_grow (tunnel->peers, tunnel->npeers, tunnel->npeers - 1);
2099 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2100 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_DEL);
2101 msg.tunnel_id = htonl (tunnel->tid);
2102 memcpy (&msg.peer, peer, sizeof (struct GNUNET_PeerIdentity));
2103 send_packet (tunnel->mesh, &msg.header, tunnel);
2108 * Request that the mesh should try to connect to a peer supporting the given
2111 * @param tunnel handle to existing tunnel
2112 * @param app_type application type that must be supported by the peer (MESH
2113 * should discover peer in proximity handling this type)
2116 GNUNET_MESH_peer_request_connect_by_type (struct GNUNET_MESH_Tunnel *tunnel,
2117 GNUNET_MESH_ApplicationType app_type)
2119 struct GNUNET_MESH_ConnectPeerByType msg;
2121 GNUNET_array_append (tunnel->apps, tunnel->napps, app_type);
2123 LOG (GNUNET_ERROR_TYPE_DEBUG, "* CONNECT BY TYPE *\n");
2124 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectPeerByType));
2125 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_TYPE);
2126 msg.tunnel_id = htonl (tunnel->tid);
2127 msg.type = htonl (app_type);
2128 send_packet (tunnel->mesh, &msg.header, tunnel);
2133 * Request that the mesh should try to connect to a peer matching the
2134 * description given in the service string.
2136 * FIXME: allow multiple? how to deal with reconnect?
2138 * @param tunnel handle to existing tunnel
2139 * @param description string describing the destination node requirements
2142 GNUNET_MESH_peer_request_connect_by_string (struct GNUNET_MESH_Tunnel *tunnel,
2143 const char *description)
2145 struct GNUNET_MESH_ConnectPeerByString *m;
2149 len = strlen (description);
2150 msgsize = sizeof(struct GNUNET_MESH_ConnectPeerByString) + len;
2151 GNUNET_assert (UINT16_MAX > msgsize);
2153 char buffer[msgsize];
2155 m = (struct GNUNET_MESH_ConnectPeerByString *) buffer;
2156 m->header.size = htons (msgsize);
2157 m->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_ADD_BY_STRING);
2158 m->tunnel_id = htonl (tunnel->tid);
2159 memcpy(&m[1], description, len);
2161 send_packet (tunnel->mesh, &m->header, tunnel);
2167 * Request that the given peer isn't added to this tunnel in calls to
2168 * connect_by_* calls, (due to misbehaviour, bad performance, ...).
2170 * @param tunnel handle to existing tunnel.
2171 * @param peer peer identity of the peer which should be blacklisted
2175 GNUNET_MESH_peer_blacklist (struct GNUNET_MESH_Tunnel *tunnel,
2176 const struct GNUNET_PeerIdentity *peer)
2178 struct GNUNET_MESH_PeerControl msg;
2180 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2181 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_BLACKLIST);
2182 msg.tunnel_id = htonl (tunnel->tid);
2184 send_packet (tunnel->mesh, &msg.header, tunnel);
2191 * Request that the given peer isn't blacklisted anymore from this tunnel,
2192 * and therefore can be added in future calls to connect_by_*.
2193 * The peer must have been previously blacklisted for this tunnel.
2195 * @param tunnel handle to existing tunnel.
2196 * @param peer peer identity of the peer which shouldn't be blacklisted
2197 * for the tunnel anymore.
2200 GNUNET_MESH_peer_unblacklist (struct GNUNET_MESH_Tunnel *tunnel,
2201 const struct GNUNET_PeerIdentity *peer)
2203 struct GNUNET_MESH_PeerControl msg;
2205 msg.header.size = htons (sizeof (struct GNUNET_MESH_PeerControl));
2206 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_PEER_UNBLACKLIST);
2207 msg.tunnel_id = htonl (tunnel->tid);
2209 send_packet (tunnel->mesh, &msg.header, tunnel);
2216 * Ask the mesh to call "notify" once it is ready to transmit the
2217 * given number of bytes to the specified tunnel or target.
2218 * Only one call can be active at any time, to issue another request,
2219 * wait for the callback or cancel the current request.
2221 * @param tunnel tunnel to use for transmission
2222 * @param cork is corking allowed for this transmission?
2223 * @param maxdelay how long can the message wait?
2224 * @param target destination for the message
2225 * NULL for multicast to all tunnel targets
2226 * @param notify_size how many bytes of buffer space does notify want?
2227 * @param notify function to call when buffer space is available;
2228 * will be called with NULL on timeout or if the overall queue
2229 * for this peer is larger than queue_size and this is currently
2230 * the message with the lowest priority
2231 * @param notify_cls closure for notify
2232 * @return non-NULL if the notify callback was queued,
2233 * NULL if we can not even queue the request (insufficient
2234 * memory); if NULL is returned, "notify" will NOT be called.
2236 struct GNUNET_MESH_TransmitHandle *
2237 GNUNET_MESH_notify_transmit_ready (struct GNUNET_MESH_Tunnel *tunnel, int cork,
2238 struct GNUNET_TIME_Relative maxdelay,
2239 const struct GNUNET_PeerIdentity *target,
2241 GNUNET_CONNECTION_TransmitReadyNotify notify,
2244 struct GNUNET_MESH_TransmitHandle *th;
2247 GNUNET_assert (NULL != tunnel);
2248 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY\n");
2249 LOG (GNUNET_ERROR_TYPE_DEBUG, " on tunnel %X\n", tunnel->tid);
2250 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2251 LOG (GNUNET_ERROR_TYPE_DEBUG, " to origin\n");
2252 else if (NULL != target)
2253 LOG (GNUNET_ERROR_TYPE_DEBUG, " target %s\n", GNUNET_i2s (target));
2255 LOG (GNUNET_ERROR_TYPE_DEBUG, " target multicast\n");
2256 LOG (GNUNET_ERROR_TYPE_DEBUG, " payload size %u\n", notify_size);
2257 GNUNET_assert (NULL != notify);
2258 GNUNET_assert (0 == tunnel->packet_size); // Only one data packet allowed
2259 th = GNUNET_malloc (sizeof (struct GNUNET_MESH_TransmitHandle));
2260 th->tunnel = tunnel;
2261 th->timeout = GNUNET_TIME_relative_to_absolute (maxdelay);
2262 th->target = GNUNET_PEER_intern (target);
2263 if (tunnel->tid >= GNUNET_MESH_LOCAL_TUNNEL_ID_SERV)
2264 overhead = sizeof (struct GNUNET_MESH_ToOrigin);
2265 else if (NULL == target)
2266 overhead = sizeof (struct GNUNET_MESH_Multicast);
2268 overhead = sizeof (struct GNUNET_MESH_Unicast);
2269 tunnel->packet_size = th->size = notify_size + overhead;
2270 LOG (GNUNET_ERROR_TYPE_DEBUG, " total size %u\n", th->size);
2271 th->notify = notify;
2272 th->notify_cls = notify_cls;
2273 add_to_queue (tunnel->mesh, th);
2274 if (NULL != tunnel->mesh->th)
2276 if (GMC_is_pid_bigger(tunnel->next_send_pid, tunnel->max_send_pid))
2278 LOG (GNUNET_ERROR_TYPE_DEBUG, " call notify tmt rdy\n");
2280 GNUNET_CLIENT_notify_transmit_ready (tunnel->mesh->client, th->size,
2281 GNUNET_TIME_UNIT_FOREVER_REL,
2282 GNUNET_YES, &send_callback,
2284 LOG (GNUNET_ERROR_TYPE_DEBUG, "MESH NOTIFY TRANSMIT READY END\n");
2290 * Cancel the specified transmission-ready notification.
2292 * @param th handle that was returned by "notify_transmit_ready".
2295 GNUNET_MESH_notify_transmit_ready_cancel (struct GNUNET_MESH_TransmitHandle *th)
2297 struct GNUNET_MESH_Handle *mesh;
2299 th->tunnel->packet_size = 0;
2300 mesh = th->tunnel->mesh;
2301 if (th->timeout_task != GNUNET_SCHEDULER_NO_TASK)
2302 GNUNET_SCHEDULER_cancel (th->timeout_task);
2303 GNUNET_CONTAINER_DLL_remove (mesh->th_head, mesh->th_tail, th);
2305 if ((0 == message_ready_size (mesh)) && (NULL != mesh->th))
2307 /* queue empty, no point in asking for transmission */
2308 GNUNET_CLIENT_notify_transmit_ready_cancel (mesh->th);
2315 * Request information about the running mesh peer.
2316 * The callback will be called for every tunnel known to the service,
2317 * listing all active peers that blong to the tunnel.
2319 * If called again on the same handle, it will overwrite the previous
2320 * callback and cls. To retrieve the cls, monitor_cancel must be
2323 * WARNING: unstable API, likely to change in the future!
2325 * @param h Handle to the mesh peer.
2326 * @param callback Function to call with the requested data.
2327 * @param callback_cls Closure for @c callback.
2330 GNUNET_MESH_get_tunnels (struct GNUNET_MESH_Handle *h,
2331 GNUNET_MESH_TunnelsCB callback,
2334 struct GNUNET_MessageHeader msg;
2336 msg.size = htons (sizeof (msg));
2337 msg.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNELS);
2338 send_packet (h, &msg, NULL);
2339 h->tunnels_cb = callback;
2340 h->tunnels_cls = callback_cls;
2347 * Cancel a monitor request. The monitor callback will not be called.
2349 * @param h Mesh handle.
2351 * @return Closure given to GNUNET_MESH_monitor, if any.
2354 GNUNET_MESH_get_tunnels_cancel (struct GNUNET_MESH_Handle *h)
2358 cls = h->tunnels_cls;
2359 h->tunnels_cb = NULL;
2360 h->tunnels_cls = NULL;
2366 * Request information about a specific tunnel of the running mesh peer.
2368 * WARNING: unstable API, likely to change in the future!
2370 * @param h Handle to the mesh peer.
2371 * @param initiator ID of the owner of the tunnel.
2372 * @param tunnel_number Tunnel number.
2373 * @param callback Function to call with the requested data.
2374 * @param callback_cls Closure for @c callback.
2377 GNUNET_MESH_show_tunnel (struct GNUNET_MESH_Handle *h,
2378 struct GNUNET_PeerIdentity *initiator,
2379 unsigned int tunnel_number,
2380 GNUNET_MESH_TunnelCB callback,
2383 struct GNUNET_MESH_LocalMonitor msg;
2385 msg.header.size = htons (sizeof (msg));
2386 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_LOCAL_INFO_TUNNEL);
2387 msg.npeers = htonl (0);
2388 msg.owner = *initiator;
2389 msg.tunnel_id = htonl (tunnel_number);
2391 send_packet (h, &msg.header, NULL);
2392 h->tunnel_cb = callback;
2393 h->tunnel_cls = callback_cls;
2400 * Transition API for tunnel ctx management
2403 GNUNET_MESH_tunnel_set_data (struct GNUNET_MESH_Tunnel *tunnel, void *data)
2409 * Transition API for tunnel ctx management
2412 GNUNET_MESH_tunnel_get_data (struct GNUNET_MESH_Tunnel *tunnel)