2 This file is part of GNUnet.
3 (C) 2001-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.
22 * @file mesh/gnunet-service-mesh_connection.c
23 * @brief GNUnet MESH service connection handling
24 * @author Bartlomiej Polot
28 #include "gnunet_util_lib.h"
30 #include "gnunet_statistics_service.h"
32 #include "gnunet-service-mesh_connection.h"
33 #include "gnunet-service-mesh_peer.h"
34 #include "gnunet-service-mesh_tunnel.h"
35 #include "gnunet-service-mesh_channel.h"
36 #include "mesh_protocol_enc.h"
37 #include "mesh_path.h"
40 #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
41 GNUNET_TIME_UNIT_MINUTES,\
43 #define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS
44 #define MESH_RETRANSMIT_MARGIN 4
46 #define LOG(level, ...) GNUNET_log_from (level,"mesh-con",__VA_ARGS__)
49 /******************************************************************************/
50 /******************************** STRUCTS **********************************/
51 /******************************************************************************/
54 * Struct containing info about a queued transmission to this peer
61 struct MeshPeerQueue *next;
66 struct MeshPeerQueue *prev;
69 * Peer this transmission is directed to.
71 struct MeshPeer *peer;
74 * Connection this message belongs to.
76 struct MeshConnection *c;
84 * Channel this message belongs to, if known.
86 struct MeshChannel *ch;
89 * Pointer to info stucture used as cls.
106 * Struct to encapsulate all the Flow Control information to a peer to which
107 * we are directly connected (on a core level).
109 struct MeshFlowControl
112 * Connection this controls.
114 struct MeshConnection *c;
117 * How many messages are in the queue on this connection.
119 unsigned int queue_n;
122 * How many messages do we accept in the queue.
124 unsigned int queue_max;
132 * ID of the last packet sent towards the peer.
134 uint32_t last_pid_sent;
137 * ID of the last packet received from the peer.
139 uint32_t last_pid_recv;
142 * Last ACK sent to the peer (peer can't send more than this PID).
144 uint32_t last_ack_sent;
147 * Last ACK sent towards the origin (for traffic towards leaf node).
149 uint32_t last_ack_recv;
152 * Task to poll the peer in case of a lost ACK causes stall.
154 GNUNET_SCHEDULER_TaskIdentifier poll_task;
157 * How frequently to poll for ACKs.
159 struct GNUNET_TIME_Relative poll_time;
164 * Struct containing all information regarding a connection to a peer.
166 struct MeshConnection
169 * Tunnel this connection is part of.
171 struct MeshTunnel3 *t;
174 * Flow control information for traffic fwd.
176 struct MeshFlowControl fwd_fc;
179 * Flow control information for traffic bck.
181 struct MeshFlowControl bck_fc;
184 * ID of the connection.
186 struct GNUNET_HashCode id;
189 * State of the connection.
191 enum MeshConnectionState state;
194 * Path being used for the tunnel.
196 struct MeshPeerPath *path;
199 * Position of the local peer in the path.
201 unsigned int own_pos;
204 * Task to keep the used paths alive at the owner,
205 * time tunnel out on all the other peers.
207 GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
210 * Task to keep the used paths alive at the destination,
211 * time tunnel out on all the other peers.
213 GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
216 * Pending message count.
218 int pending_messages;
221 * Destroy flag: if true, destroy on last message.
226 /******************************************************************************/
227 /******************************* GLOBALS ***********************************/
228 /******************************************************************************/
231 * Global handle to the statistics service.
233 extern struct GNUNET_STATISTICS_Handle *stats;
236 * Connections known, indexed by cid (MeshConnection).
238 static struct GNUNET_CONTAINER_MultiHashMap *connections;
241 * How many connections are we willing to maintain.
242 * Local connections are always allowed, even if there are more connections than max.
244 static unsigned long long max_connections;
247 * How many messages *in total* are we willing to queue, divide by number of
248 * connections to get connection queue size.
250 static unsigned long long max_msgs_queue;
253 * How often to send path keepalives. Paths timeout after 4 missed.
255 static struct GNUNET_TIME_Relative refresh_connection_time;
258 /******************************************************************************/
259 /******************************** STATIC ***********************************/
260 /******************************************************************************/
262 #if 0 // avoid compiler warning for unused static function
264 fc_debug (struct MeshFlowControl *fc)
266 LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
267 fc->last_pid_recv, fc->last_ack_sent);
268 LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
269 fc->last_pid_sent, fc->last_ack_recv);
270 LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
271 fc->queue_n, fc->queue_max);
275 connection_debug (struct MeshConnection *c)
279 LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
282 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
283 peer2s (c->t->peer), GNUNET_h2s (&c->id));
284 LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
285 c->state, c->pending_messages);
286 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
287 fc_debug (&c->fwd_fc);
288 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
289 fc_debug (&c->bck_fc);
294 * Get string description for tunnel state.
296 * @param s Tunnel state.
298 * @return String representation.
301 GMC_state2s (enum MeshConnectionState s)
305 case MESH_CONNECTION_NEW:
306 return "MESH_CONNECTION_NEW";
307 case MESH_CONNECTION_SENT:
308 return "MESH_CONNECTION_SENT";
309 case MESH_CONNECTION_ACK:
310 return "MESH_CONNECTION_ACK";
311 case MESH_CONNECTION_READY:
312 return "MESH_CONNECTION_READY";
314 return "MESH_CONNECTION_STATE_ERROR";
320 * Initialize a Flow Control structure to the initial state.
322 * @param fc Flow Control structure to initialize.
325 fc_init (struct MeshFlowControl *fc)
328 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
329 fc->last_pid_recv = (uint32_t) -1;
330 fc->last_ack_sent = (uint32_t) 0;
331 fc->last_ack_recv = (uint32_t) 0;
332 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
333 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
335 fc->queue_max = (max_msgs_queue / max_connections) + 1;
342 * @param cid Connection ID.
344 static struct MeshConnection *
345 connection_get (const struct GNUNET_HashCode *cid)
347 return GNUNET_CONTAINER_multihashmap_get (connections, cid);
352 * Send an ACK informing the predecessor about the available buffer space.
354 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
355 * the ACK itself goes "back" (dest->root).
357 * @param c Connection on which to send the ACK.
358 * @param buffer How much space free to advertise?
359 * @param fwd Is this FWD ACK? (Going dest->owner)
362 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
364 struct MeshFlowControl *next_fc;
365 struct MeshFlowControl *prev_fc;
366 struct GNUNET_MESH_ACK msg;
370 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
371 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
373 LOG (GNUNET_ERROR_TYPE_DEBUG,
374 "connection send %s ack on %s\n",
375 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
377 /* Check if we need to transmit the ACK */
378 if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
380 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
381 LOG (GNUNET_ERROR_TYPE_DEBUG,
382 " last pid recv: %u, last ack sent: %u\n",
383 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
387 /* Ok, ACK might be necessary, what PID to ACK? */
388 delta = next_fc->queue_max - next_fc->queue_n;
389 ack = prev_fc->last_pid_recv + delta;
390 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
391 LOG (GNUNET_ERROR_TYPE_DEBUG,
392 " last pid %u, last ack %u, qmax %u, q %u\n",
393 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
394 next_fc->queue_max, next_fc->queue_n);
395 if (ack == prev_fc->last_ack_sent)
397 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
401 prev_fc->last_ack_sent = ack;
403 /* Build ACK message and send on connection */
404 msg.header.size = htons (sizeof (msg));
405 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
406 msg.ack = htonl (ack);
409 send_prebuilt_message_connection (&msg.header, c, NULL, !fwd);
414 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
417 * @param connection Connection to confirm.
418 * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
421 send_connection_ack (struct MeshConnection *connection, int fwd)
423 struct MeshTunnel3 *t;
426 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
428 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
429 sizeof (struct GNUNET_MESH_ConnectionACK),
433 if (MESH_TUNNEL_NEW == t->state)
434 tunnel_change_state (t, MESH_TUNNEL_WAITING);
435 if (MESH_CONNECTION_READY != connection->state)
436 connection_change_state (connection, MESH_CONNECTION_SENT);
441 * Sends a CREATE CONNECTION message for a path to a peer.
442 * Changes the connection and tunnel states if necessary.
444 * @param connection Connection to create.
447 send_connection_create (struct MeshConnection *connection)
449 struct MeshTunnel3 *t;
452 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
454 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
455 sizeof (struct GNUNET_MESH_ConnectionCreate) +
456 (connection->path->length *
457 sizeof (struct GNUNET_PeerIdentity)),
462 (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
463 tunnel_change_state (t, MESH_TUNNEL_WAITING);
464 if (MESH_CONNECTION_NEW == connection->state)
465 connection_change_state (connection, MESH_CONNECTION_SENT);
470 connection_change_state (struct MeshConnection* c,
471 enum MeshConnectionState state)
473 LOG (GNUNET_ERROR_TYPE_DEBUG,
474 "Connection %s state was %s\n",
475 GNUNET_h2s (&c->id), GMC_state2s (c->state));
476 LOG (GNUNET_ERROR_TYPE_DEBUG,
477 "Connection %s state is now %s\n",
478 GNUNET_h2s (&c->id), GMC_state2s (state));
485 * Send keepalive packets for a connection.
487 * @param c Connection to keep alive..
488 * @param fwd Is this a FWD keepalive? (owner -> dest).
491 connection_keepalive (struct MeshConnection *c, int fwd)
493 struct GNUNET_MESH_ConnectionKeepAlive *msg;
494 size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
498 type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
499 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
501 LOG (GNUNET_ERROR_TYPE_DEBUG,
502 "sending %s keepalive for connection %s[%d]\n",
507 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
508 msg->header.size = htons (size);
509 msg->header.type = htons (type);
512 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
517 * Send CONNECTION_{CREATE/ACK} packets for a connection.
519 * @param c Connection for which to send the message.
520 * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
523 connection_recreate (struct MeshConnection *c, int fwd)
525 LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
527 send_connection_create (c);
529 send_connection_ack (c, GNUNET_NO);
534 * Generic connection timer management.
535 * Depending on the role of the peer in the connection will send the
536 * appropriate message (build or keepalive)
538 * @param c Conncetion to maintain.
542 connection_maintain (struct MeshConnection *c, int fwd)
544 if (MESH_TUNNEL_SEARCHING == c->t->state)
546 /* TODO DHT GET with RO_BART */
551 case MESH_CONNECTION_NEW:
553 case MESH_CONNECTION_SENT:
554 connection_recreate (c, fwd);
556 case MESH_CONNECTION_READY:
557 connection_keepalive (c, fwd);
566 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
568 struct MeshConnection *c = cls;
570 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
571 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
574 connection_maintain (c, GNUNET_YES);
575 c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
576 &connection_fwd_keepalive,
582 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
584 struct MeshConnection *c = cls;
586 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
587 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
590 connection_maintain (c, GNUNET_NO);
591 c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
592 &connection_bck_keepalive,
599 * Get the first transmittable message for a connection.
601 * @param c Connection.
602 * @param fwd Is this FWD?
604 * @return First transmittable message.
606 static struct MeshPeerQueue *
607 connection_get_first_message (struct MeshConnection *c, int fwd)
609 struct MeshPeerQueue *q;
612 p = connection_get_hop (c, fwd);
614 for (q = p->queue_head; NULL != q; q = q->next)
618 if (queue_is_sendable (q))
627 * @brief Re-initiate traffic on this connection if necessary.
629 * Check if there is traffic queued towards this peer
630 * and the core transmit handle is NULL (traffic was stalled).
631 * If so, call core tmt rdy.
633 * @param c Connection on which initiate traffic.
634 * @param fwd Is this about fwd traffic?
637 connection_unlock_queue (struct MeshConnection *c, int fwd)
639 struct MeshPeer *peer;
640 struct MeshPeerQueue *q;
643 LOG (GNUNET_ERROR_TYPE_DEBUG,
644 "connection_unlock_queue %s on %s\n",
645 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
647 if (GMC_is_terminal (c, fwd))
649 LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
653 peer = connection_get_hop (c, fwd);
655 if (NULL != peer->core_transmit)
657 LOG (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n");
658 return; /* Already unlocked */
661 q = connection_get_first_message (c, fwd);
664 LOG (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n");
665 return; /* Nothing to transmit */
669 peer->core_transmit =
670 GNUNET_CORE_notify_transmit_ready (core_handle,
673 GNUNET_TIME_UNIT_FOREVER_REL,
674 GNUNET_PEER_resolve2 (peer->id),
682 * Cancel all transmissions that belong to a certain connection.
684 * @param c Connection which to cancel.
685 * @param fwd Cancel fwd traffic?
688 connection_cancel_queues (struct MeshConnection *c, int fwd)
690 struct MeshPeerQueue *q;
691 struct MeshPeerQueue *next;
692 struct MeshFlowControl *fc;
693 struct MeshPeer *peer;
700 fc = fwd ? &c->fwd_fc : &c->bck_fc;
701 peer = connection_get_hop (c, fwd);
703 for (q = peer->queue_head; NULL != q; q = next)
708 LOG (GNUNET_ERROR_TYPE_DEBUG,
709 "connection_cancel_queue %s\n",
710 GNUNET_MESH_DEBUG_M2S (q->type));
711 queue_destroy (q, GNUNET_YES);
714 if (NULL == peer->queue_head)
716 if (NULL != peer->core_transmit)
718 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
719 peer->core_transmit = NULL;
721 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
723 GNUNET_SCHEDULER_cancel (fc->poll_task);
724 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
731 * Function called if a connection has been stalled for a while,
732 * possibly due to a missed ACK. Poll the neighbor about its ACK status.
734 * @param cls Closure (poll ctx).
735 * @param tc TaskContext.
738 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
740 struct MeshFlowControl *fc = cls;
741 struct GNUNET_MESH_Poll msg;
742 struct MeshConnection *c;
744 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
745 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
751 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
752 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
753 GNUNET_h2s (&c->id));
754 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n",
755 fc == &c->fwd_fc ? "FWD" : "BCK");
757 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
758 msg.header.size = htons (sizeof (msg));
759 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
760 send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
761 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
762 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
763 &connection_poll, fc);
770 * Get the previous hop in a connection
772 * @param c Connection.
774 * @return Previous peer in the connection.
776 static struct MeshPeer *
777 connection_get_prev_hop (struct MeshConnection *c)
781 if (0 == c->own_pos || c->path->length < 2)
782 id = c->path->peers[0];
784 id = c->path->peers[c->own_pos - 1];
786 return peer_get_short (id);
791 * Get the next hop in a connection
793 * @param c Connection.
795 * @return Next peer in the connection.
797 static struct MeshPeer *
798 connection_get_next_hop (struct MeshConnection *c)
802 if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
803 id = c->path->peers[c->path->length - 1];
805 id = c->path->peers[c->own_pos + 1];
807 return peer_get_short (id);
812 * Get the hop in a connection.
814 * @param c Connection.
815 * @param fwd Next hop?
817 * @return Next peer in the connection.
819 static struct MeshPeer *
820 connection_get_hop (struct MeshConnection *c, int fwd)
823 return connection_get_next_hop (c);
824 return connection_get_prev_hop (c);
831 * Timeout function due to lack of keepalive/traffic from the owner.
832 * Destroys connection if called.
834 * @param cls Closure (connection to destroy).
835 * @param tc TaskContext.
838 connection_fwd_timeout (void *cls,
839 const struct GNUNET_SCHEDULER_TaskContext *tc)
841 struct MeshConnection *c = cls;
843 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
844 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
846 LOG (GNUNET_ERROR_TYPE_DEBUG,
847 "Connection %s[%X] FWD timed out. Destroying.\n",
851 if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
859 * Timeout function due to lack of keepalive/traffic from the destination.
860 * Destroys connection if called.
862 * @param cls Closure (connection to destroy).
863 * @param tc TaskContext
866 connection_bck_timeout (void *cls,
867 const struct GNUNET_SCHEDULER_TaskContext *tc)
869 struct MeshConnection *c = cls;
871 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
872 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
875 LOG (GNUNET_ERROR_TYPE_DEBUG,
876 "Connection %s[%X] FWD timed out. Destroying.\n",
880 if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
888 * Resets the connection timeout task, some other message has done the
890 * - For the first peer on the direction this means to send
891 * a keepalive or a path confirmation message (either create or ACK).
892 * - For all other peers, this means to destroy the connection,
893 * due to lack of activity.
894 * Starts the tiemout if no timeout was running (connection just created).
896 * @param c Connection whose timeout to reset.
897 * @param fwd Is this forward?
899 * TODO use heap to improve efficiency of scheduler.
902 connection_reset_timeout (struct MeshConnection *c, int fwd)
904 GNUNET_SCHEDULER_TaskIdentifier *ti;
905 GNUNET_SCHEDULER_Task f;
907 ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
909 if (GNUNET_SCHEDULER_NO_TASK != *ti)
910 GNUNET_SCHEDULER_cancel (*ti);
912 if (GMC_is_origin (c, fwd)) /* Endpoint */
914 f = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
915 *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
919 struct GNUNET_TIME_Relative delay;
921 delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
922 f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
923 *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
932 register_neighbors (struct MeshConnection *c)
934 struct MeshPeer *peer;
936 peer = connection_get_next_hop (c);
937 if (GNUNET_NO == GMP_is_neighbor (peer))
942 GMP_add_connection (peer, c);
943 peer = connection_get_prev_hop (c);
944 if (GNUNET_NO == GMP_is_neighbor (peer))
949 GMP_add_connection (peer, c);
957 unregister_neighbors (struct MeshConnection *c)
959 struct MeshPeer *peer;
961 peer = connection_get_next_hop (c);
962 GMP_remove_connection (peer, c);
964 peer = connection_get_prev_hop (c);
965 GMP_remove_connection (peer, c);
970 /******************************************************************************/
971 /******************************** API ***********************************/
972 /******************************************************************************/
975 * Core handler for connection creation.
977 * @param cls Closure (unused).
978 * @param peer Sender (neighbor).
979 * @param message Message.
981 * @return GNUNET_OK to keep the connection open,
982 * GNUNET_SYSERR to close it (signal serious error)
985 GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
986 const struct GNUNET_MessageHeader *message)
988 struct GNUNET_MESH_ConnectionCreate *msg;
989 struct GNUNET_PeerIdentity *id;
990 struct GNUNET_HashCode *cid;
991 struct MeshPeerPath *path;
992 struct MeshPeer *dest_peer;
993 struct MeshPeer *orig_peer;
994 struct MeshConnection *c;
995 unsigned int own_pos;
999 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1000 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1003 size = ntohs (message->size);
1004 if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1006 GNUNET_break_op (0);
1010 /* Calculate hops */
1011 size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1012 if (size % sizeof (struct GNUNET_PeerIdentity))
1014 GNUNET_break_op (0);
1017 size /= sizeof (struct GNUNET_PeerIdentity);
1020 GNUNET_break_op (0);
1023 LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
1025 /* Get parameters */
1026 msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1028 id = (struct GNUNET_PeerIdentity *) &msg[1];
1029 LOG (GNUNET_ERROR_TYPE_DEBUG,
1030 " connection %s (%s).\n",
1031 GNUNET_h2s (cid), GNUNET_i2s (id));
1033 /* Create connection */
1034 c = connection_get (cid);
1037 LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
1038 c = connection_new (cid);
1041 connection_reset_timeout (c, GNUNET_YES);
1044 LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
1045 path = path_new (size);
1047 for (i = 0; i < size; i++)
1049 LOG (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
1050 GNUNET_i2s (&id[i]));
1051 path->peers[i] = GNUNET_PEER_intern (&id[i]);
1052 if (path->peers[i] == my_short_id)
1055 if (own_pos == 0 && path->peers[own_pos] != myid)
1057 /* create path: self not found in path through self */
1058 GNUNET_break_op (0);
1059 path_destroy (path);
1063 LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
1064 path_add_to_peers (path, GNUNET_NO);
1065 c->path = path_duplicate (path);
1066 c->own_pos = own_pos;
1072 if (MESH_CONNECTION_NEW == c->state)
1073 connection_change_state (c, MESH_CONNECTION_SENT);
1075 /* Remember peers */
1076 dest_peer = peer_get (&id[size - 1]);
1077 orig_peer = peer_get (&id[0]);
1079 /* Is it a connection to us? */
1080 if (c->own_pos == size - 1)
1082 LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
1083 peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1085 if (NULL == orig_peer->tunnel)
1087 orig_peer->tunnel = tunnel_new ();
1088 orig_peer->tunnel->peer = orig_peer;
1090 GMT_add_connection (orig_peer->tunnel, c);
1091 if (MESH_TUNNEL_NEW == GMT_get_state (c->t))
1092 GMT_change_state (c->t, MESH_TUNNEL_WAITING);
1094 send_connection_ack (c, GNUNET_NO);
1095 if (MESH_CONNECTION_SENT == c->state)
1096 connection_change_state (c, MESH_CONNECTION_ACK);
1098 /* Keep tunnel alive in direction dest->owner*/
1099 connection_reset_timeout (c, GNUNET_NO);
1103 /* It's for somebody else! Retransmit. */
1104 LOG (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
1105 peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1106 peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1107 send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
1114 * Core handler for path confirmations.
1116 * @param cls closure
1117 * @param message message
1118 * @param peer peer identity this notification is about
1120 * @return GNUNET_OK to keep the connection open,
1121 * GNUNET_SYSERR to close it (signal serious error)
1124 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1125 const struct GNUNET_MessageHeader *message)
1127 struct GNUNET_MESH_ConnectionACK *msg;
1128 struct MeshConnection *c;
1129 struct MeshPeerPath *p;
1130 struct MeshPeer *pi;
1133 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1134 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1135 msg = (struct GNUNET_MESH_ConnectionACK *) message;
1136 LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n",
1137 GNUNET_h2s (&msg->cid));
1138 c = connection_get (&msg->cid);
1141 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1143 LOG (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n");
1148 LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
1150 pi = peer_get (peer);
1151 if (connection_get_next_hop (c) == pi)
1153 LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
1155 if (MESH_CONNECTION_SENT == c->state)
1156 connection_change_state (c, MESH_CONNECTION_ACK);
1158 else if (connection_get_prev_hop (c) == pi)
1160 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK\n");
1162 connection_change_state (c, MESH_CONNECTION_READY);
1166 GNUNET_break_op (0);
1169 connection_reset_timeout (c, fwd);
1171 /* Add path to peers? */
1175 path_add_to_peers (p, GNUNET_YES);
1182 /* Message for us as creator? */
1183 if (connection_is_origin (c, GNUNET_YES))
1185 LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
1186 connection_change_state (c, MESH_CONNECTION_READY);
1187 if (MESH_TUNNEL_READY != c->t->state)
1188 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1189 send_connection_ack (c, GNUNET_YES);
1190 tunnel_send_queued_data (c->t, GNUNET_YES);
1191 if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
1193 GNUNET_DHT_get_stop (c->t->peer->dhtget);
1194 c->t->peer->dhtget = NULL;
1199 /* Message for us as destination? */
1200 if (GMC_is_terminal (c, GNUNET_YES))
1202 LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
1203 GMC_change_state (c, MESH_CONNECTION_READY);
1204 GMT_change_state (c->t, MESH_TUNNEL_READY);
1205 GMT_send_queued_data (c->t, GNUNET_NO);
1209 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1210 GMC_send_prebuilt_message (message, c, NULL, fwd);
1216 * Core handler for notifications of broken paths
1218 * @param cls Closure (unused).
1219 * @param peer Peer identity of sending neighbor.
1220 * @param message Message.
1222 * @return GNUNET_OK to keep the connection open,
1223 * GNUNET_SYSERR to close it (signal serious error)
1226 GMC_handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1227 const struct GNUNET_MessageHeader *message)
1229 struct GNUNET_MESH_ConnectionBroken *msg;
1230 struct MeshConnection *c;
1232 LOG (GNUNET_ERROR_TYPE_DEBUG,
1233 "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1234 msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1235 LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1236 GNUNET_i2s (&msg->peer1));
1237 LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1238 GNUNET_i2s (&msg->peer2));
1239 c = connection_get (&msg->cid);
1242 GNUNET_break_op (0);
1245 tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1246 GNUNET_PEER_search (&msg->peer2));
1253 * Core handler for tunnel destruction
1255 * @param cls Closure (unused).
1256 * @param peer Peer identity of sending neighbor.
1257 * @param message Message.
1259 * @return GNUNET_OK to keep the connection open,
1260 * GNUNET_SYSERR to close it (signal serious error)
1263 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1264 const struct GNUNET_MessageHeader *message)
1266 struct GNUNET_MESH_ConnectionDestroy *msg;
1267 struct MeshConnection *c;
1271 msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1272 LOG (GNUNET_ERROR_TYPE_DEBUG,
1273 "Got a CONNECTION DESTROY message from %s\n",
1275 LOG (GNUNET_ERROR_TYPE_DEBUG,
1276 " for connection %s\n",
1277 GNUNET_h2s (&msg->cid));
1278 c = connection_get (&msg->cid);
1281 /* Probably already got the message from another path,
1282 * destroyed the tunnel and retransmitted to children.
1285 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1289 id = GNUNET_PEER_search (peer);
1290 if (id == GMP_get_short_id (connection_get_prev_hop (c)))
1292 else if (id == GMP_get_short_id (connection_get_next_hop (c)))
1296 GNUNET_break_op (0);
1299 GMC_send_prebuilt_message (message, c, NULL, fwd);
1300 c->destroy = GNUNET_YES;
1306 * Generic handler for mesh network encrypted traffic.
1308 * @param peer Peer identity this notification is about.
1309 * @param message Encrypted message.
1310 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1312 * @return GNUNET_OK to keep the connection open,
1313 * GNUNET_SYSERR to close it (signal serious error)
1316 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1317 const struct GNUNET_MESH_Encrypted *msg,
1320 struct MeshConnection *c;
1321 struct MeshTunnel3 *t;
1322 struct MeshPeer *neighbor;
1323 struct MeshFlowControl *fc;
1330 size = ntohs (msg->header.size);
1332 sizeof (struct GNUNET_MESH_Encrypted) +
1333 sizeof (struct GNUNET_MessageHeader))
1335 GNUNET_break_op (0);
1338 type = ntohs (msg->header.type);
1339 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1340 LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1341 GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1343 /* Check connection */
1344 c = connection_get (&msg->cid);
1347 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1348 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1352 fc = fwd ? &c->bck_fc : &c->fwd_fc;
1354 /* Check if origin is as expected */
1355 neighbor = connection_get_hop (c, !fwd);
1356 if (GNUNET_PEER_search (peer) != GMP_get_short_id (neighbor))
1358 GNUNET_break_op (0);
1363 pid = ntohl (msg->pid);
1364 if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1366 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1367 LOG (GNUNET_ERROR_TYPE_DEBUG,
1368 "WARNING Received PID %u, (prev %u), ACK %u\n",
1369 pid, fc->last_pid_recv, fc->last_ack_sent);
1372 if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1374 GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1375 LOG (GNUNET_ERROR_TYPE_DEBUG,
1376 " Pid %u not expected (%u+), dropping!\n",
1377 pid, fc->last_pid_recv + 1);
1380 if (MESH_CONNECTION_SENT == c->state)
1381 connection_change_state (c, MESH_CONNECTION_READY);
1382 connection_reset_timeout (c, fwd);
1383 fc->last_pid_recv = pid;
1385 /* Is this message for us? */
1386 if (GMC_is_terminal (c, fwd))
1388 size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1390 struct GNUNET_MessageHeader *msgh;
1393 /* TODO signature verification */
1394 LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
1395 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1397 fc->last_pid_recv = pid;
1398 tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1402 msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1403 handle_decrypted (t, msgh, fwd);
1404 off += ntohs (msgh->size);
1406 send_ack (c, NULL, fwd);
1410 /* Message not for us: forward to next hop */
1411 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1412 ttl = ntohl (msg->ttl);
1413 LOG (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
1416 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1417 LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1418 send_ack (c, NULL, fwd);
1421 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1423 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1430 * Core handler for mesh network traffic going orig->dest.
1432 * @param cls Closure (unused).
1433 * @param message Message received.
1434 * @param peer Peer who sent the message.
1436 * @return GNUNET_OK to keep the connection open,
1437 * GNUNET_SYSERR to close it (signal serious error)
1440 GMC_handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1441 const struct GNUNET_MessageHeader *message)
1443 return handle_mesh_encrypted (peer,
1444 (struct GNUNET_MESH_Encrypted *)message,
1449 * Core handler for mesh network traffic going dest->orig.
1451 * @param cls Closure (unused).
1452 * @param message Message received.
1453 * @param peer Peer who sent the message.
1455 * @return GNUNET_OK to keep the connection open,
1456 * GNUNET_SYSERR to close it (signal serious error)
1459 GMC_handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1460 const struct GNUNET_MessageHeader *message)
1462 return handle_mesh_encrypted (peer,
1463 (struct GNUNET_MESH_Encrypted *)message,
1469 * Core handler for mesh network traffic point-to-point acks.
1471 * @param cls closure
1472 * @param message message
1473 * @param peer peer identity this notification is about
1475 * @return GNUNET_OK to keep the connection open,
1476 * GNUNET_SYSERR to close it (signal serious error)
1479 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1480 const struct GNUNET_MessageHeader *message)
1482 struct GNUNET_MESH_ACK *msg;
1483 struct MeshConnection *c;
1484 struct MeshFlowControl *fc;
1489 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1490 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1492 msg = (struct GNUNET_MESH_ACK *) message;
1494 c = connection_get (&msg->cid);
1498 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1503 /* Is this a forward or backward ACK? */
1504 id = GNUNET_PEER_search (peer);
1505 if (GMP_get_short_id (connection_get_next_hop (c)) == id)
1507 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1511 else if (GMP_get_short_id (connection_get_prev_hop (c)) == id)
1513 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1519 GNUNET_break_op (0);
1523 ack = ntohl (msg->ack);
1524 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n",
1525 ack, fc->last_ack_recv);
1526 if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1527 fc->last_ack_recv = ack;
1529 /* Cancel polling if the ACK is big enough. */
1530 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1531 GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1533 LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
1534 GNUNET_SCHEDULER_cancel (fc->poll_task);
1535 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1536 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1539 connection_unlock_queue (c, fwd);
1546 * Core handler for mesh network traffic point-to-point ack polls.
1548 * @param cls closure
1549 * @param message message
1550 * @param peer peer identity this notification is about
1552 * @return GNUNET_OK to keep the connection open,
1553 * GNUNET_SYSERR to close it (signal serious error)
1556 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1557 const struct GNUNET_MessageHeader *message)
1559 struct GNUNET_MESH_Poll *msg;
1560 struct MeshConnection *c;
1561 struct MeshFlowControl *fc;
1566 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1567 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1570 msg = (struct GNUNET_MESH_Poll *) message;
1572 c = connection_get (&msg->cid);
1576 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1578 GNUNET_break_op (0);
1582 /* Is this a forward or backward ACK?
1583 * Note: a poll should never be needed in a loopback case,
1584 * since there is no possiblility of packet loss there, so
1585 * this way of discerining FWD/BCK should not be a problem.
1587 id = GNUNET_PEER_search (peer);
1588 if (GMP_get_short_id (connection_get_next_hop (c)) == id)
1590 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1593 else if (GMP_get_short_id (connection_get_prev_hop (c)) == id)
1595 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1600 GNUNET_break_op (0);
1604 pid = ntohl (msg->pid);
1605 LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n",
1606 pid, fc->last_pid_recv);
1607 fc->last_pid_recv = pid;
1608 fwd = fc == &c->fwd_fc;
1609 send_ack (c, NULL, fwd);
1616 * Core handler for mesh keepalives.
1618 * @param cls closure
1619 * @param message message
1620 * @param peer peer identity this notification is about
1621 * @return GNUNET_OK to keep the connection open,
1622 * GNUNET_SYSERR to close it (signal serious error)
1624 * TODO: Check who we got this from, to validate route.
1627 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1628 const struct GNUNET_MessageHeader *message)
1630 struct GNUNET_MESH_ConnectionKeepAlive *msg;
1631 struct MeshConnection *c;
1632 struct MeshPeer *neighbor;
1635 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1636 LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1639 c = connection_get (&msg->cid);
1642 GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1647 fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1648 GNUNET_YES : GNUNET_NO;
1650 /* Check if origin is as expected */
1651 neighbor = connection_get_hop (c, fwd);
1652 if (GNUNET_PEER_search (peer) != GMP_get_short_id (neighbor))
1654 GNUNET_break_op (0);
1658 connection_change_state (c, MESH_CONNECTION_READY);
1659 connection_reset_timeout (c, fwd);
1661 if (GMC_is_terminal (c, fwd))
1664 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1665 GMC_send_prebuilt_message (message, c, NULL, fwd);
1672 * Send an ACK on the appropriate connection/channel, depending on
1673 * the direction and the position of the peer.
1675 * @param c Which connection to send the hop-by-hop ACK.
1676 * @param ch Channel, if any.
1677 * @param fwd Is this a fwd ACK? (will go dest->root)
1680 GMC_send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1682 unsigned int buffer;
1684 LOG (GNUNET_ERROR_TYPE_DEBUG,
1685 "send ack %s on %p %p\n",
1686 fwd ? "FWD" : "BCK", c, ch);
1687 if (NULL == c || GMC_is_terminal (c, fwd))
1689 struct MeshTunnel3 *t;
1690 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n");
1691 t = (NULL == c) ? GMCH_get_tunnel (ch) : GMC_get_tunnel (c);
1692 buffer = GMT_get_buffer (t, fwd);
1696 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
1697 buffer = GMC_get_buffer (c, fwd);
1699 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1701 if ( (NULL != ch && GMCH_is_origin (ch, fwd)) ||
1702 (NULL != c && GMC_is_origin (c, fwd)) )
1704 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1707 GNUNET_assert (NULL != ch);
1708 LOG (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1709 send_local_ack (ch, fwd);
1714 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1715 GNUNET_assert (NULL != ch);
1716 channel_send_connections_ack (ch, buffer, fwd);
1720 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
1721 connection_send_ack (c, buffer, fwd);
1727 * Initialize the connections subsystem
1729 * @param c Configuration handle.
1732 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
1735 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
1738 LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1739 "MESH", "MAX_MSGS_QUEUE", "MISSING");
1740 GNUNET_SCHEDULER_shutdown ();
1745 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
1748 LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1749 "MESH", "MAX_CONNECTIONS", "MISSING");
1750 GNUNET_SCHEDULER_shutdown ();
1755 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
1756 &refresh_connection_time))
1758 LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1759 "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
1760 GNUNET_SCHEDULER_shutdown ();
1763 connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1767 * Shut down the connections subsystem.
1775 struct MeshConnection *
1776 GMC_new (const struct GNUNET_HashCode *cid,
1777 struct MeshTunnel3 *t,
1778 struct MeshPeerPath *p,
1779 unsigned int own_pos)
1781 struct MeshConnection *c;
1783 c = GNUNET_new (struct MeshConnection);
1785 GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
1786 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1787 fc_init (&c->fwd_fc);
1788 fc_init (&c->bck_fc);
1793 if (own_pos > p->length - 1)
1799 c->own_pos = own_pos;
1804 c->fwd_maintenance_task =
1805 GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1806 &connection_fwd_keepalive, c);
1808 register_neighbors (c);
1814 GMC_destroy (struct MeshConnection *c)
1816 struct MeshPeer *peer;
1821 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s\n",
1822 GNUNET_h2s (&c->id));
1824 /* Cancel all traffic */
1825 connection_cancel_queues (c, GNUNET_YES);
1826 connection_cancel_queues (c, GNUNET_NO);
1828 /* Cancel maintainance task (keepalive/timeout) */
1829 if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
1830 GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
1831 if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
1832 GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
1834 /* Unregister from neighbors */
1835 unregister_neighbors (c);
1838 GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
1839 GMT_remove_connection (c->t, c);
1844 * Get the connection ID.
1846 * @param c Connection to get the ID from.
1848 * @return ID of the connection.
1850 const struct GNUNET_HashCode *
1851 GMC_get_id (const struct MeshConnection *c)
1858 * Get the connection state.
1860 * @param c Connection to get the state from.
1862 * @return state of the connection.
1864 enum MeshConnectionState
1865 GMC_get_state (const struct MeshConnection *c)
1871 * Get the connection tunnel.
1873 * @param c Connection to get the tunnel from.
1875 * @return tunnel of the connection.
1877 struct MeshTunnel3 *
1878 GMC_get_tunnel (const struct MeshConnection *c)
1885 * Get free buffer space in a connection.
1887 * @param c Connection.
1888 * @param fwd Is query about FWD traffic?
1890 * @return Free buffer space [0 - max_msgs_queue/max_connections]
1893 GMC_get_buffer (struct MeshConnection *c, int fwd)
1895 struct MeshFlowControl *fc;
1897 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1899 return (fc->queue_max - fc->queue_n);
1903 * Get messages queued in a connection.
1905 * @param c Connection.
1906 * @param fwd Is query about FWD traffic?
1908 * @return Number of messages queued.
1911 GMC_get_qn (struct MeshConnection *c, int fwd)
1913 struct MeshFlowControl *fc;
1915 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1922 * Notify other peers on a connection of a broken link. Mark connections
1923 * to destroy after all traffic has been sent.
1925 * @param c Connection on which there has been a disconnection.
1926 * @param peer Peer that disconnected.
1927 * @param my_full_id My ID (to send to other peers).
1930 GMC_notify_broken (struct MeshConnection *c,
1931 struct MeshPeer *peer,
1932 struct GNUNET_PeerIdentity *my_full_id)
1934 struct GNUNET_MESH_ConnectionBroken msg;
1937 fwd = peer == connection_get_prev_hop (c);
1939 connection_cancel_queues (c, !fwd);
1940 if (GMC_is_terminal (c, fwd))
1942 /* Local shutdown, no one to notify about this. */
1947 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
1948 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
1950 msg.peer1 = *my_full_id;
1951 msg.peer2 = *GMP_get_id (peer);
1952 GMC_send_prebuilt_message (&msg.header, c, NULL, fwd);
1953 c->destroy = GNUNET_YES;
1960 * Is this peer the first one on the connection?
1962 * @param c Connection.
1963 * @param fwd Is this about fwd traffic?
1965 * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
1968 GMC_is_origin (struct MeshConnection *c, int fwd)
1970 if (!fwd && c->path->length - 1 == c->own_pos )
1972 if (fwd && 0 == c->own_pos)
1979 * Is this peer the last one on the connection?
1981 * @param c Connection.
1982 * @param fwd Is this about fwd traffic?
1983 * Note that the ROOT is the terminal for BCK traffic!
1985 * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
1988 GMC_is_terminal (struct MeshConnection *c, int fwd)
1990 return GMC_is_origin (c, !fwd);
1995 * Sends an already built message on a connection, properly registering
1996 * all used resources.
1998 * @param message Message to send. Function makes a copy of it.
1999 * If message is not hop-by-hop, decrements TTL of copy.
2000 * @param c Connection on which this message is transmitted.
2001 * @param ch Channel on which this message is transmitted, or NULL.
2002 * @param fwd Is this a fwd message?
2005 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
2006 struct MeshConnection *c,
2007 struct MeshChannel *ch,
2014 size = ntohs (message->size);
2015 data = GNUNET_malloc (size);
2016 memcpy (data, message, size);
2017 type = ntohs (message->type);
2018 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
2019 GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
2023 struct GNUNET_MESH_Encrypted *emsg;
2024 struct GNUNET_MESH_ACK *amsg;
2025 struct GNUNET_MESH_Poll *pmsg;
2026 struct GNUNET_MESH_ConnectionDestroy *dmsg;
2027 struct GNUNET_MESH_ConnectionBroken *bmsg;
2030 case GNUNET_MESSAGE_TYPE_MESH_FWD:
2031 case GNUNET_MESSAGE_TYPE_MESH_BCK:
2032 emsg = (struct GNUNET_MESH_Encrypted *) data;
2033 ttl = ntohl (emsg->ttl);
2036 GNUNET_break_op (0);
2040 emsg->ttl = htonl (ttl - 1);
2041 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2042 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
2045 case GNUNET_MESSAGE_TYPE_MESH_ACK:
2046 amsg = (struct GNUNET_MESH_ACK *) data;
2048 LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2051 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2052 pmsg = (struct GNUNET_MESH_Poll *) data;
2054 pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
2055 LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2058 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2059 dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2064 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2065 bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2070 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2071 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2078 GMP_queue_add (data,
2088 * Send a message to all peers in this connection that the connection
2089 * is no longer valid.
2091 * If some peer should not receive the message, it should be zero'ed out
2092 * before calling this function.
2094 * @param c The connection whose peers to notify.
2097 GMC_send_destroy (struct MeshConnection *c)
2099 struct GNUNET_MESH_ConnectionDestroy msg;
2101 if (GNUNET_YES == c->destroy)
2104 msg.header.size = htons (sizeof (msg));
2105 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
2107 LOG (GNUNET_ERROR_TYPE_DEBUG,
2108 " sending connection destroy for connection %s\n",
2109 GNUNET_h2s (&c->id));
2111 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
2112 GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_YES);
2113 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
2114 GMC_send_prebuilt_message (&msg.header, c, NULL, GNUNET_NO);
2115 c->destroy = GNUNET_YES;