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 "mesh_protocol_enc.h"
35 #include "mesh_path.h"
38 #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
39 GNUNET_TIME_UNIT_MINUTES,\
41 #define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS
42 #define MESH_RETRANSMIT_MARGIN 4
44 #define LOG(level, ...) GNUNET_log_from (level,"mesh-con",__VA_ARGS__)
47 * All the states a connection can be in.
49 enum MeshConnectionState
52 * Uninitialized status, should never appear in operation.
57 * Connection create message sent, waiting for ACK.
62 * Connection ACK sent, waiting for ACK.
67 * Connection confirmed, ready to carry traffic.
69 MESH_CONNECTION_READY,
73 /******************************************************************************/
74 /******************************** STRUCTS **********************************/
75 /******************************************************************************/
78 * Struct containing info about a queued transmission to this peer
85 struct MeshPeerQueue *next;
90 struct MeshPeerQueue *prev;
93 * Peer this transmission is directed to.
95 struct MeshPeer *peer;
98 * Connection this message belongs to.
100 struct MeshConnection *c;
108 * Channel this message belongs to, if known.
110 struct MeshChannel *ch;
113 * Pointer to info stucture used as cls.
123 * Size of the message
130 * Struct to encapsulate all the Flow Control information to a peer to which
131 * we are directly connected (on a core level).
133 struct MeshFlowControl
136 * Connection this controls.
138 struct MeshConnection *c;
141 * How many messages are in the queue on this connection.
143 unsigned int queue_n;
146 * How many messages do we accept in the queue.
148 unsigned int queue_max;
156 * ID of the last packet sent towards the peer.
158 uint32_t last_pid_sent;
161 * ID of the last packet received from the peer.
163 uint32_t last_pid_recv;
166 * Last ACK sent to the peer (peer can't send more than this PID).
168 uint32_t last_ack_sent;
171 * Last ACK sent towards the origin (for traffic towards leaf node).
173 uint32_t last_ack_recv;
176 * Task to poll the peer in case of a lost ACK causes stall.
178 GNUNET_SCHEDULER_TaskIdentifier poll_task;
181 * How frequently to poll for ACKs.
183 struct GNUNET_TIME_Relative poll_time;
188 * Struct containing all information regarding a connection to a peer.
190 struct MeshConnection
195 struct MeshConnection *next;
196 struct MeshConnection *prev;
199 * Tunnel this connection is part of.
201 struct MeshTunnel2 *t;
204 * Flow control information for traffic fwd.
206 struct MeshFlowControl fwd_fc;
209 * Flow control information for traffic bck.
211 struct MeshFlowControl bck_fc;
214 * ID of the connection.
216 struct GNUNET_HashCode id;
219 * State of the connection.
221 enum MeshConnectionState state;
224 * Path being used for the tunnel.
226 struct MeshPeerPath *path;
229 * Position of the local peer in the path.
231 unsigned int own_pos;
234 * Task to keep the used paths alive at the owner,
235 * time tunnel out on all the other peers.
237 GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
240 * Task to keep the used paths alive at the destination,
241 * time tunnel out on all the other peers.
243 GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
246 * Pending message count.
248 int pending_messages;
251 * Destroy flag: if true, destroy on last message.
256 /******************************************************************************/
257 /******************************* GLOBALS ***********************************/
258 /******************************************************************************/
261 * Global handle to the statistics service.
263 extern struct GNUNET_STATISTICS_Handle *stats;
266 * Connections known, indexed by cid (MeshConnection).
268 static struct GNUNET_CONTAINER_MultiHashMap *connections;
271 * How many connections are we willing to maintain.
272 * Local connections are always allowed, even if there are more connections than max.
274 static unsigned long long max_connections;
277 * How many messages *in total* are we willing to queue, divide by number of
278 * connections to get connection queue size.
280 static unsigned long long max_msgs_queue;
283 * How often to send path keepalives. Paths timeout after 4 missed.
285 static struct GNUNET_TIME_Relative refresh_connection_time;
288 /******************************************************************************/
289 /******************************** STATIC ***********************************/
290 /******************************************************************************/
292 #if 0 // avoid compiler warning for unused static function
294 fc_debug (struct MeshFlowControl *fc)
296 LOG (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
297 fc->last_pid_recv, fc->last_ack_sent);
298 LOG (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
299 fc->last_pid_sent, fc->last_ack_recv);
300 LOG (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
301 fc->queue_n, fc->queue_max);
305 connection_debug (struct MeshConnection *c)
309 LOG (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
312 LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
313 peer2s (c->t->peer), GNUNET_h2s (&c->id));
314 LOG (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
315 c->state, c->pending_messages);
316 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
317 fc_debug (&c->fwd_fc);
318 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
319 fc_debug (&c->bck_fc);
324 * Get string description for tunnel state.
326 * @param s Tunnel state.
328 * @return String representation.
331 GMC_DEBUG_state2s (enum MeshTunnelState s)
335 case MESH_CONNECTION_NEW:
336 return "MESH_CONNECTION_NEW";
337 case MESH_CONNECTION_SENT:
338 return "MESH_CONNECTION_SENT";
339 case MESH_CONNECTION_ACK:
340 return "MESH_CONNECTION_ACK";
341 case MESH_CONNECTION_READY:
342 return "MESH_CONNECTION_READY";
344 return "MESH_CONNECTION_STATE_ERROR";
351 * Initialize a Flow Control structure to the initial state.
353 * @param fc Flow Control structure to initialize.
356 fc_init (struct MeshFlowControl *fc)
359 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
360 fc->last_pid_recv = (uint32_t) -1;
361 fc->last_ack_sent = (uint32_t) 0;
362 fc->last_ack_recv = (uint32_t) 0;
363 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
364 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
366 fc->queue_max = (max_msgs_queue / max_connections) + 1;
373 * @param cid Connection ID.
375 static struct MeshConnection *
376 connection_get (const struct GNUNET_HashCode *cid)
378 return GNUNET_CONTAINER_multihashmap_get (connections, cid);
383 * Send an ACK informing the predecessor about the available buffer space.
385 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
386 * the ACK itself goes "back" (dest->root).
388 * @param c Connection on which to send the ACK.
389 * @param buffer How much space free to advertise?
390 * @param fwd Is this FWD ACK? (Going dest->owner)
393 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
395 struct MeshFlowControl *next_fc;
396 struct MeshFlowControl *prev_fc;
397 struct GNUNET_MESH_ACK msg;
401 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
402 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
404 LOG (GNUNET_ERROR_TYPE_DEBUG,
405 "connection send %s ack on %s\n",
406 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
408 /* Check if we need to transmit the ACK */
409 if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
411 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
412 LOG (GNUNET_ERROR_TYPE_DEBUG,
413 " last pid recv: %u, last ack sent: %u\n",
414 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
418 /* Ok, ACK might be necessary, what PID to ACK? */
419 delta = next_fc->queue_max - next_fc->queue_n;
420 ack = prev_fc->last_pid_recv + delta;
421 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
422 LOG (GNUNET_ERROR_TYPE_DEBUG,
423 " last pid %u, last ack %u, qmax %u, q %u\n",
424 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
425 next_fc->queue_max, next_fc->queue_n);
426 if (ack == prev_fc->last_ack_sent)
428 LOG (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
432 prev_fc->last_ack_sent = ack;
434 /* Build ACK message and send on connection */
435 msg.header.size = htons (sizeof (msg));
436 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
437 msg.ack = htonl (ack);
440 send_prebuilt_message_connection (&msg.header, c, NULL, !fwd);
445 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
448 * @param connection Connection to confirm.
449 * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
452 send_connection_ack (struct MeshConnection *connection, int fwd)
454 struct MeshTunnel2 *t;
457 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
459 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
460 sizeof (struct GNUNET_MESH_ConnectionACK),
464 if (MESH_TUNNEL_NEW == t->state)
465 tunnel_change_state (t, MESH_TUNNEL_WAITING);
466 if (MESH_CONNECTION_READY != connection->state)
467 connection_change_state (connection, MESH_CONNECTION_SENT);
472 * Sends a CREATE CONNECTION message for a path to a peer.
473 * Changes the connection and tunnel states if necessary.
475 * @param connection Connection to create.
478 send_connection_create (struct MeshConnection *connection)
480 struct MeshTunnel2 *t;
483 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
485 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
486 sizeof (struct GNUNET_MESH_ConnectionCreate) +
487 (connection->path->length *
488 sizeof (struct GNUNET_PeerIdentity)),
493 (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
494 tunnel_change_state (t, MESH_TUNNEL_WAITING);
495 if (MESH_CONNECTION_NEW == connection->state)
496 connection_change_state (connection, MESH_CONNECTION_SENT);
501 connection_change_state (struct MeshConnection* c,
502 enum MeshConnectionState state)
504 LOG (GNUNET_ERROR_TYPE_DEBUG,
505 "Connection %s state was %s\n",
506 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (c->state));
507 LOG (GNUNET_ERROR_TYPE_DEBUG,
508 "Connection %s state is now %s\n",
509 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (state));
516 * Send keepalive packets for a connection.
518 * @param c Connection to keep alive..
519 * @param fwd Is this a FWD keepalive? (owner -> dest).
522 connection_keepalive (struct MeshConnection *c, int fwd)
524 struct GNUNET_MESH_ConnectionKeepAlive *msg;
525 size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
529 type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
530 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
532 LOG (GNUNET_ERROR_TYPE_DEBUG,
533 "sending %s keepalive for connection %s[%d]\n",
538 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
539 msg->header.size = htons (size);
540 msg->header.type = htons (type);
543 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
548 * Send CONNECTION_{CREATE/ACK} packets for a connection.
550 * @param c Connection for which to send the message.
551 * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
554 connection_recreate (struct MeshConnection *c, int fwd)
556 LOG (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
558 send_connection_create (c);
560 send_connection_ack (c, GNUNET_NO);
565 * Generic connection timer management.
566 * Depending on the role of the peer in the connection will send the
567 * appropriate message (build or keepalive)
569 * @param c Conncetion to maintain.
573 connection_maintain (struct MeshConnection *c, int fwd)
575 if (MESH_TUNNEL_SEARCHING == c->t->state)
577 /* TODO DHT GET with RO_BART */
582 case MESH_CONNECTION_NEW:
584 case MESH_CONNECTION_SENT:
585 connection_recreate (c, fwd);
587 case MESH_CONNECTION_READY:
588 connection_keepalive (c, fwd);
597 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
599 struct MeshConnection *c = cls;
601 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
602 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
605 connection_maintain (c, GNUNET_YES);
606 c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
607 &connection_fwd_keepalive,
613 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
615 struct MeshConnection *c = cls;
617 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
618 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
621 connection_maintain (c, GNUNET_NO);
622 c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
623 &connection_bck_keepalive,
629 * Send a message to all peers in this connection that the connection
630 * is no longer valid.
632 * If some peer should not receive the message, it should be zero'ed out
633 * before calling this function.
635 * @param c The connection whose peers to notify.
638 connection_send_destroy (struct MeshConnection *c)
640 struct GNUNET_MESH_ConnectionDestroy msg;
642 msg.header.size = htons (sizeof (msg));
643 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
645 LOG (GNUNET_ERROR_TYPE_DEBUG,
646 " sending connection destroy for connection %s[%X]\n",
650 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
651 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_YES);
652 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
653 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_NO);
654 c->destroy = GNUNET_YES;
659 * Get free buffer space in a connection.
661 * @param c Connection.
662 * @param fwd Is query about FWD traffic?
664 * @return Free buffer space [0 - max_msgs_queue/max_connections]
667 connection_get_buffer (struct MeshConnection *c, int fwd)
669 struct MeshFlowControl *fc;
671 fc = fwd ? &c->fwd_fc : &c->bck_fc;
673 return (fc->queue_max - fc->queue_n);
678 * Get the first transmittable message for a connection.
680 * @param c Connection.
681 * @param fwd Is this FWD?
683 * @return First transmittable message.
685 static struct MeshPeerQueue *
686 connection_get_first_message (struct MeshConnection *c, int fwd)
688 struct MeshPeerQueue *q;
691 p = connection_get_hop (c, fwd);
693 for (q = p->queue_head; NULL != q; q = q->next)
697 if (queue_is_sendable (q))
706 * @brief Re-initiate traffic on this connection if necessary.
708 * Check if there is traffic queued towards this peer
709 * and the core transmit handle is NULL (traffic was stalled).
710 * If so, call core tmt rdy.
712 * @param c Connection on which initiate traffic.
713 * @param fwd Is this about fwd traffic?
716 connection_unlock_queue (struct MeshConnection *c, int fwd)
718 struct MeshPeer *peer;
719 struct MeshPeerQueue *q;
722 LOG (GNUNET_ERROR_TYPE_DEBUG,
723 "connection_unlock_queue %s on %s\n",
724 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
726 if (GMC_is_terminal (c, fwd))
728 LOG (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
732 peer = connection_get_hop (c, fwd);
734 if (NULL != peer->core_transmit)
736 LOG (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n");
737 return; /* Already unlocked */
740 q = connection_get_first_message (c, fwd);
743 LOG (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n");
744 return; /* Nothing to transmit */
748 peer->core_transmit =
749 GNUNET_CORE_notify_transmit_ready (core_handle,
752 GNUNET_TIME_UNIT_FOREVER_REL,
753 GNUNET_PEER_resolve2 (peer->id),
761 * Cancel all transmissions that belong to a certain connection.
763 * @param c Connection which to cancel.
764 * @param fwd Cancel fwd traffic?
767 connection_cancel_queues (struct MeshConnection *c, int fwd)
769 struct MeshPeerQueue *q;
770 struct MeshPeerQueue *next;
771 struct MeshFlowControl *fc;
772 struct MeshPeer *peer;
779 fc = fwd ? &c->fwd_fc : &c->bck_fc;
780 peer = connection_get_hop (c, fwd);
782 for (q = peer->queue_head; NULL != q; q = next)
787 LOG (GNUNET_ERROR_TYPE_DEBUG,
788 "connection_cancel_queue %s\n",
789 GNUNET_MESH_DEBUG_M2S (q->type));
790 queue_destroy (q, GNUNET_YES);
793 if (NULL == peer->queue_head)
795 if (NULL != peer->core_transmit)
797 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
798 peer->core_transmit = NULL;
800 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
802 GNUNET_SCHEDULER_cancel (fc->poll_task);
803 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
812 * Function called if a connection has been stalled for a while,
813 * possibly due to a missed ACK. Poll the neighbor about its ACK status.
815 * @param cls Closure (poll ctx).
816 * @param tc TaskContext.
819 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
821 struct MeshFlowControl *fc = cls;
822 struct GNUNET_MESH_Poll msg;
823 struct MeshConnection *c;
825 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
826 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
832 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
833 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
834 GNUNET_h2s (&c->id));
835 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n",
836 fc == &c->fwd_fc ? "FWD" : "BCK");
838 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
839 msg.header.size = htons (sizeof (msg));
840 LOG (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
841 send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
842 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
843 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
844 &connection_poll, fc);
851 * Get the previous hop in a connection
853 * @param c Connection.
855 * @return Previous peer in the connection.
857 static struct MeshPeer *
858 connection_get_prev_hop (struct MeshConnection *c)
862 if (0 == c->own_pos || c->path->length < 2)
863 id = c->path->peers[0];
865 id = c->path->peers[c->own_pos - 1];
867 return peer_get_short (id);
872 * Get the next hop in a connection
874 * @param c Connection.
876 * @return Next peer in the connection.
878 static struct MeshPeer *
879 connection_get_next_hop (struct MeshConnection *c)
883 if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
884 id = c->path->peers[c->path->length - 1];
886 id = c->path->peers[c->own_pos + 1];
888 return peer_get_short (id);
893 * Get the hop in a connection.
895 * @param c Connection.
896 * @param fwd Next hop?
898 * @return Next peer in the connection.
900 static struct MeshPeer *
901 connection_get_hop (struct MeshConnection *c, int fwd)
904 return connection_get_next_hop (c);
905 return connection_get_prev_hop (c);
912 * Timeout function due to lack of keepalive/traffic from the owner.
913 * Destroys connection if called.
915 * @param cls Closure (connection to destroy).
916 * @param tc TaskContext.
919 connection_fwd_timeout (void *cls,
920 const struct GNUNET_SCHEDULER_TaskContext *tc)
922 struct MeshConnection *c = cls;
924 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
925 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
927 LOG (GNUNET_ERROR_TYPE_DEBUG,
928 "Connection %s[%X] FWD timed out. Destroying.\n",
932 if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
940 * Timeout function due to lack of keepalive/traffic from the destination.
941 * Destroys connection if called.
943 * @param cls Closure (connection to destroy).
944 * @param tc TaskContext
947 connection_bck_timeout (void *cls,
948 const struct GNUNET_SCHEDULER_TaskContext *tc)
950 struct MeshConnection *c = cls;
952 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
953 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
956 LOG (GNUNET_ERROR_TYPE_DEBUG,
957 "Connection %s[%X] FWD timed out. Destroying.\n",
961 if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
969 * Resets the connection timeout task, some other message has done the
971 * - For the first peer on the direction this means to send
972 * a keepalive or a path confirmation message (either create or ACK).
973 * - For all other peers, this means to destroy the connection,
974 * due to lack of activity.
975 * Starts the tiemout if no timeout was running (connection just created).
977 * @param c Connection whose timeout to reset.
978 * @param fwd Is this forward?
980 * TODO use heap to improve efficiency of scheduler.
983 connection_reset_timeout (struct MeshConnection *c, int fwd)
985 GNUNET_SCHEDULER_TaskIdentifier *ti;
986 GNUNET_SCHEDULER_Task f;
988 ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
990 if (GNUNET_SCHEDULER_NO_TASK != *ti)
991 GNUNET_SCHEDULER_cancel (*ti);
993 if (GMC_is_origin (c, fwd)) /* Endpoint */
995 f = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
996 *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
1000 struct GNUNET_TIME_Relative delay;
1002 delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
1003 f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
1004 *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
1013 register_neighbors (struct MeshConnection *c)
1015 struct MeshPeer *peer;
1017 peer = connection_get_next_hop (c);
1018 if (GNUNET_NO == GMP_is_neighbor (peer))
1023 GMP_add_connection (peer, c);
1024 peer = connection_get_prev_hop (c);
1025 if (GNUNET_NO == GMP_is_neighbor (peer))
1030 GMP_add_connection (peer, c);
1034 /******************************************************************************/
1035 /******************************** API ***********************************/
1036 /******************************************************************************/
1039 * Core handler for connection creation.
1041 * @param cls Closure (unused).
1042 * @param peer Sender (neighbor).
1043 * @param message Message.
1045 * @return GNUNET_OK to keep the connection open,
1046 * GNUNET_SYSERR to close it (signal serious error)
1049 GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1050 const struct GNUNET_MessageHeader *message)
1052 struct GNUNET_MESH_ConnectionCreate *msg;
1053 struct GNUNET_PeerIdentity *id;
1054 struct GNUNET_HashCode *cid;
1055 struct MeshPeerPath *path;
1056 struct MeshPeer *dest_peer;
1057 struct MeshPeer *orig_peer;
1058 struct MeshConnection *c;
1059 unsigned int own_pos;
1063 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1064 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1067 size = ntohs (message->size);
1068 if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1070 GNUNET_break_op (0);
1074 /* Calculate hops */
1075 size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1076 if (size % sizeof (struct GNUNET_PeerIdentity))
1078 GNUNET_break_op (0);
1081 size /= sizeof (struct GNUNET_PeerIdentity);
1084 GNUNET_break_op (0);
1087 LOG (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
1089 /* Get parameters */
1090 msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1092 id = (struct GNUNET_PeerIdentity *) &msg[1];
1093 LOG (GNUNET_ERROR_TYPE_DEBUG,
1094 " connection %s (%s).\n",
1095 GNUNET_h2s (cid), GNUNET_i2s (id));
1097 /* Create connection */
1098 c = connection_get (cid);
1101 LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
1102 c = connection_new (cid);
1105 connection_reset_timeout (c, GNUNET_YES);
1108 LOG (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
1109 path = path_new (size);
1111 for (i = 0; i < size; i++)
1113 LOG (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
1114 GNUNET_i2s (&id[i]));
1115 path->peers[i] = GNUNET_PEER_intern (&id[i]);
1116 if (path->peers[i] == myid)
1119 if (own_pos == 0 && path->peers[own_pos] != myid)
1121 /* create path: self not found in path through self */
1122 GNUNET_break_op (0);
1123 path_destroy (path);
1124 connection_destroy (c);
1127 LOG (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
1128 path_add_to_peers (path, GNUNET_NO);
1129 c->path = path_duplicate (path);
1130 c->own_pos = own_pos;
1136 if (MESH_CONNECTION_NEW == c->state)
1137 connection_change_state (c, MESH_CONNECTION_SENT);
1139 /* Remember peers */
1140 dest_peer = peer_get (&id[size - 1]);
1141 orig_peer = peer_get (&id[0]);
1143 /* Is it a connection to us? */
1144 if (c->own_pos == size - 1)
1146 LOG (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
1147 peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1149 if (NULL == orig_peer->tunnel)
1151 orig_peer->tunnel = tunnel_new ();
1152 orig_peer->tunnel->peer = orig_peer;
1154 tunnel_add_connection (orig_peer->tunnel, c);
1155 if (MESH_TUNNEL_NEW == c->t->state)
1156 tunnel_change_state (c->t, MESH_TUNNEL_WAITING);
1158 send_connection_ack (c, GNUNET_NO);
1159 if (MESH_CONNECTION_SENT == c->state)
1160 connection_change_state (c, MESH_CONNECTION_ACK);
1162 /* Keep tunnel alive in direction dest->owner*/
1163 connection_reset_timeout (c, GNUNET_NO);
1167 /* It's for somebody else! Retransmit. */
1168 LOG (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
1169 peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1170 peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1171 send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
1178 * Core handler for path confirmations.
1180 * @param cls closure
1181 * @param message message
1182 * @param peer peer identity this notification is about
1184 * @return GNUNET_OK to keep the connection open,
1185 * GNUNET_SYSERR to close it (signal serious error)
1188 GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1189 const struct GNUNET_MessageHeader *message)
1191 struct GNUNET_MESH_ConnectionACK *msg;
1192 struct MeshConnection *c;
1193 struct MeshPeerPath *p;
1194 struct MeshPeer *pi;
1197 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1198 LOG (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1199 msg = (struct GNUNET_MESH_ConnectionACK *) message;
1200 LOG (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n",
1201 GNUNET_h2s (&msg->cid));
1202 c = connection_get (&msg->cid);
1205 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1207 LOG (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n");
1212 LOG (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
1214 pi = peer_get (peer);
1215 if (connection_get_next_hop (c) == pi)
1217 LOG (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
1219 if (MESH_CONNECTION_SENT == c->state)
1220 connection_change_state (c, MESH_CONNECTION_ACK);
1222 else if (connection_get_prev_hop (c) == pi)
1224 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK\n");
1226 connection_change_state (c, MESH_CONNECTION_READY);
1230 GNUNET_break_op (0);
1233 connection_reset_timeout (c, fwd);
1235 /* Add path to peers? */
1239 path_add_to_peers (p, GNUNET_YES);
1246 /* Message for us as creator? */
1247 if (connection_is_origin (c, GNUNET_YES))
1249 LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
1250 connection_change_state (c, MESH_CONNECTION_READY);
1251 if (MESH_TUNNEL_READY != c->t->state)
1252 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1253 send_connection_ack (c, GNUNET_YES);
1254 tunnel_send_queued_data (c->t, GNUNET_YES);
1255 if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
1257 GNUNET_DHT_get_stop (c->t->peer->dhtget);
1258 c->t->peer->dhtget = NULL;
1263 /* Message for us as destination? */
1264 if (GMC_is_terminal (c, GNUNET_YES))
1266 LOG (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
1267 if (MESH_TUNNEL_READY != c->t->state)
1268 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1269 connection_change_state (c, MESH_CONNECTION_READY);
1270 tunnel_send_queued_data (c->t, GNUNET_NO);
1274 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1275 send_prebuilt_message_connection (message, c, NULL, fwd);
1281 * Core handler for notifications of broken paths
1283 * @param cls Closure (unused).
1284 * @param peer Peer identity of sending neighbor.
1285 * @param message Message.
1287 * @return GNUNET_OK to keep the connection open,
1288 * GNUNET_SYSERR to close it (signal serious error)
1291 GMC_handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1292 const struct GNUNET_MessageHeader *message)
1294 struct GNUNET_MESH_ConnectionBroken *msg;
1295 struct MeshConnection *c;
1297 LOG (GNUNET_ERROR_TYPE_DEBUG,
1298 "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1299 msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1300 LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1301 GNUNET_i2s (&msg->peer1));
1302 LOG (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1303 GNUNET_i2s (&msg->peer2));
1304 c = connection_get (&msg->cid);
1307 GNUNET_break_op (0);
1310 tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1311 GNUNET_PEER_search (&msg->peer2));
1318 * Core handler for tunnel destruction
1320 * @param cls Closure (unused).
1321 * @param peer Peer identity of sending neighbor.
1322 * @param message Message.
1324 * @return GNUNET_OK to keep the connection open,
1325 * GNUNET_SYSERR to close it (signal serious error)
1328 GMC_handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1329 const struct GNUNET_MessageHeader *message)
1331 struct GNUNET_MESH_ConnectionDestroy *msg;
1332 struct MeshConnection *c;
1336 msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1337 LOG (GNUNET_ERROR_TYPE_DEBUG,
1338 "Got a CONNECTION DESTROY message from %s\n",
1340 LOG (GNUNET_ERROR_TYPE_DEBUG,
1341 " for connection %s\n",
1342 GNUNET_h2s (&msg->cid));
1343 c = connection_get (&msg->cid);
1346 /* Probably already got the message from another path,
1347 * destroyed the tunnel and retransmitted to children.
1350 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1354 id = GNUNET_PEER_search (peer);
1355 if (id == connection_get_prev_hop (c)->id)
1357 else if (id == connection_get_next_hop (c)->id)
1361 GNUNET_break_op (0);
1364 send_prebuilt_message_connection (message, c, NULL, fwd);
1365 c->destroy = GNUNET_YES;
1371 * Generic handler for mesh network encrypted traffic.
1373 * @param peer Peer identity this notification is about.
1374 * @param message Encrypted message.
1375 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1377 * @return GNUNET_OK to keep the connection open,
1378 * GNUNET_SYSERR to close it (signal serious error)
1381 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1382 const struct GNUNET_MESH_Encrypted *msg,
1385 struct MeshConnection *c;
1386 struct MeshTunnel2 *t;
1387 struct MeshPeer *neighbor;
1388 struct MeshFlowControl *fc;
1395 size = ntohs (msg->header.size);
1397 sizeof (struct GNUNET_MESH_Encrypted) +
1398 sizeof (struct GNUNET_MessageHeader))
1400 GNUNET_break_op (0);
1403 type = ntohs (msg->header.type);
1404 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1405 LOG (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1406 GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1408 /* Check connection */
1409 c = connection_get (&msg->cid);
1412 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1413 LOG (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1417 fc = fwd ? &c->bck_fc : &c->fwd_fc;
1419 /* Check if origin is as expected */
1420 neighbor = connection_get_hop (c, !fwd);
1421 if (peer_get (peer)->id != neighbor->id)
1423 GNUNET_break_op (0);
1428 pid = ntohl (msg->pid);
1429 if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1431 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1432 LOG (GNUNET_ERROR_TYPE_DEBUG,
1433 "WARNING Received PID %u, (prev %u), ACK %u\n",
1434 pid, fc->last_pid_recv, fc->last_ack_sent);
1437 if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1439 GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1440 LOG (GNUNET_ERROR_TYPE_DEBUG,
1441 " Pid %u not expected (%u+), dropping!\n",
1442 pid, fc->last_pid_recv + 1);
1445 if (MESH_CONNECTION_SENT == c->state)
1446 connection_change_state (c, MESH_CONNECTION_READY);
1447 connection_reset_timeout (c, fwd);
1448 fc->last_pid_recv = pid;
1450 /* Is this message for us? */
1451 if (GMC_is_terminal (c, fwd))
1453 size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1455 struct GNUNET_MessageHeader *msgh;
1458 /* TODO signature verification */
1459 LOG (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
1460 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1462 fc->last_pid_recv = pid;
1463 tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1467 msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1468 handle_decrypted (t, msgh, fwd);
1469 off += ntohs (msgh->size);
1471 send_ack (c, NULL, fwd);
1475 /* Message not for us: forward to next hop */
1476 LOG (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1477 ttl = ntohl (msg->ttl);
1478 LOG (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
1481 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1482 LOG (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1483 send_ack (c, NULL, fwd);
1486 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1488 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1495 * Core handler for mesh network traffic going orig->dest.
1497 * @param cls Closure (unused).
1498 * @param message Message received.
1499 * @param peer Peer who sent the message.
1501 * @return GNUNET_OK to keep the connection open,
1502 * GNUNET_SYSERR to close it (signal serious error)
1505 GMC_handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1506 const struct GNUNET_MessageHeader *message)
1508 return handle_mesh_encrypted (peer,
1509 (struct GNUNET_MESH_Encrypted *)message,
1514 * Core handler for mesh network traffic going dest->orig.
1516 * @param cls Closure (unused).
1517 * @param message Message received.
1518 * @param peer Peer who sent the message.
1520 * @return GNUNET_OK to keep the connection open,
1521 * GNUNET_SYSERR to close it (signal serious error)
1524 GMC_handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1525 const struct GNUNET_MessageHeader *message)
1527 return handle_mesh_encrypted (peer,
1528 (struct GNUNET_MESH_Encrypted *)message,
1534 * Core handler for mesh network traffic point-to-point acks.
1536 * @param cls closure
1537 * @param message message
1538 * @param peer peer identity this notification is about
1540 * @return GNUNET_OK to keep the connection open,
1541 * GNUNET_SYSERR to close it (signal serious error)
1544 GMC_handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1545 const struct GNUNET_MessageHeader *message)
1547 struct GNUNET_MESH_ACK *msg;
1548 struct MeshConnection *c;
1549 struct MeshFlowControl *fc;
1554 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1555 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1557 msg = (struct GNUNET_MESH_ACK *) message;
1559 c = connection_get (&msg->cid);
1563 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1568 /* Is this a forward or backward ACK? */
1569 id = GNUNET_PEER_search (peer);
1570 if (connection_get_next_hop (c)->id == id)
1572 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1576 else if (connection_get_prev_hop (c)->id == id)
1578 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1584 GNUNET_break_op (0);
1588 ack = ntohl (msg->ack);
1589 LOG (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n",
1590 ack, fc->last_ack_recv);
1591 if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1592 fc->last_ack_recv = ack;
1594 /* Cancel polling if the ACK is big enough. */
1595 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1596 GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1598 LOG (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
1599 GNUNET_SCHEDULER_cancel (fc->poll_task);
1600 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1601 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1604 connection_unlock_queue (c, fwd);
1611 * Core handler for mesh network traffic point-to-point ack polls.
1613 * @param cls closure
1614 * @param message message
1615 * @param peer peer identity this notification is about
1617 * @return GNUNET_OK to keep the connection open,
1618 * GNUNET_SYSERR to close it (signal serious error)
1621 GMC_handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1622 const struct GNUNET_MessageHeader *message)
1624 struct GNUNET_MESH_Poll *msg;
1625 struct MeshConnection *c;
1626 struct MeshFlowControl *fc;
1631 LOG (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1632 LOG (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1635 msg = (struct GNUNET_MESH_Poll *) message;
1637 c = connection_get (&msg->cid);
1641 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1643 GNUNET_break_op (0);
1647 /* Is this a forward or backward ACK?
1648 * Note: a poll should never be needed in a loopback case,
1649 * since there is no possiblility of packet loss there, so
1650 * this way of discerining FWD/BCK should not be a problem.
1652 id = GNUNET_PEER_search (peer);
1653 if (connection_get_next_hop (c)->id == id)
1655 LOG (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1658 else if (connection_get_prev_hop (c)->id == id)
1660 LOG (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1665 GNUNET_break_op (0);
1669 pid = ntohl (msg->pid);
1670 LOG (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n",
1671 pid, fc->last_pid_recv);
1672 fc->last_pid_recv = pid;
1673 fwd = fc == &c->fwd_fc;
1674 send_ack (c, NULL, fwd);
1681 * Core handler for mesh keepalives.
1683 * @param cls closure
1684 * @param message message
1685 * @param peer peer identity this notification is about
1686 * @return GNUNET_OK to keep the connection open,
1687 * GNUNET_SYSERR to close it (signal serious error)
1689 * TODO: Check who we got this from, to validate route.
1692 GMC_handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1693 const struct GNUNET_MessageHeader *message)
1695 struct GNUNET_MESH_ConnectionKeepAlive *msg;
1696 struct MeshConnection *c;
1697 struct MeshPeer *neighbor;
1700 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1701 LOG (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1704 c = connection_get (&msg->cid);
1707 GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1712 fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1713 GNUNET_YES : GNUNET_NO;
1715 /* Check if origin is as expected */
1716 neighbor = connection_get_hop (c, fwd);
1717 if (peer_get (peer)->id != neighbor->id)
1719 GNUNET_break_op (0);
1723 connection_change_state (c, MESH_CONNECTION_READY);
1724 connection_reset_timeout (c, fwd);
1726 if (GMC_is_terminal (c, fwd))
1729 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1730 send_prebuilt_message_connection (message, c, NULL, fwd);
1737 * Send an ACK on the appropriate connection/channel, depending on
1738 * the direction and the position of the peer.
1740 * @param c Which connection to send the hop-by-hop ACK.
1741 * @param ch Channel, if any.
1742 * @param fwd Is this a fwd ACK? (will go dest->root)
1745 send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1747 unsigned int buffer;
1749 LOG (GNUNET_ERROR_TYPE_DEBUG,
1750 "send ack %s on %p %p\n",
1751 fwd ? "FWD" : "BCK", c, ch);
1752 if (NULL == c || GMC_is_terminal (c, fwd))
1754 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n");
1755 buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
1759 LOG (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
1760 buffer = connection_get_buffer (c, fwd);
1762 LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1764 if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
1765 (NULL != c && connection_is_origin (c, fwd)) )
1767 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1770 GNUNET_assert (NULL != ch);
1771 LOG (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1772 send_local_ack (ch, fwd);
1777 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1778 GNUNET_assert (NULL != ch);
1779 channel_send_connections_ack (ch, buffer, fwd);
1783 LOG (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
1784 connection_send_ack (c, buffer, fwd);
1791 * Initialize the connections subsystem
1793 * @param c Configuration handle.
1796 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
1799 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
1802 LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1803 "MESH", "MAX_MSGS_QUEUE", "MISSING");
1804 GNUNET_SCHEDULER_shutdown ();
1809 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
1812 LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1813 "MESH", "MAX_CONNECTIONS", "MISSING");
1814 GNUNET_SCHEDULER_shutdown ();
1819 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
1820 &refresh_connection_time))
1822 LOG_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1823 "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
1824 GNUNET_SCHEDULER_shutdown ();
1827 connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1831 * Shut down the connections subsystem.
1839 struct MeshConnection *
1840 GMC_new (const struct GNUNET_HashCode *cid,
1841 struct MeshTunnel2 *t,
1842 struct MeshPeerPath *p,
1843 unsigned int own_pos)
1845 struct MeshConnection *c;
1846 unsigned int own_pos;
1848 c = GNUNET_new (struct MeshConnection);
1850 GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
1851 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1852 fc_init (&c->fwd_fc);
1853 fc_init (&c->bck_fc);
1858 if (own_pos > p->length - 1)
1864 c->own_pos = own_pos;
1869 c->fwd_maintenance_task =
1870 GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1871 &connection_fwd_keepalive, c);
1873 register_neighbors (c);
1879 GMC_destroy (struct MeshConnection *c)
1881 struct MeshPeer *peer;
1886 LOG (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s[%X]\n",
1887 peer2s (c->t->peer),
1890 /* Cancel all traffic */
1891 connection_cancel_queues (c, GNUNET_YES);
1892 connection_cancel_queues (c, GNUNET_NO);
1894 /* Cancel maintainance task (keepalive/timeout) */
1895 if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
1896 GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
1897 if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
1898 GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
1900 /* Deregister from neighbors */
1901 peer = connection_get_next_hop (c);
1902 if (NULL != peer && NULL != peer->connections)
1903 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
1904 peer = connection_get_prev_hop (c);
1905 if (NULL != peer && NULL != peer->connections)
1906 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
1909 GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
1910 GNUNET_CONTAINER_DLL_remove (c->t->connection_head, c->t->connection_tail, c);
1916 * Get the connection ID.
1918 * @param c Connection to get the ID from.
1920 * @return ID of the connection.
1922 const struct GNUNET_HashCode *
1923 GMC_get_id (const struct MeshConnection *c)
1929 * Notify other peers on a connection of a broken link. Mark connections
1930 * to destroy after all traffic has been sent.
1932 * @param c Connection on which there has been a disconnection.
1933 * @param peer Peer that disconnected.
1934 * @param my_full_id My ID (to send to other peers).
1937 GMC_notify_broken (struct MeshConnection *c,
1938 struct MeshPeer *peer,
1939 struct GNUNET_PeerIdentity *my_full_id)
1941 struct MeshConnection *c = value;
1942 struct GNUNET_MESH_ConnectionBroken msg;
1945 fwd = peer == connection_get_prev_hop (c);
1947 connection_cancel_queues (c, !fwd);
1948 if (GMC_is_terminal (c, fwd))
1950 /* Local shutdown, no one to notify about this. */
1955 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
1956 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
1958 msg.peer1 = *my_full_id;
1959 msg.peer2 = *GNUNET_PEER_resolve2 (peer->id);
1960 GMC_send_prebuilt_message (&msg.header, c, NULL, fwd);
1961 c->destroy = GNUNET_YES;
1968 * Is this peer the first one on the connection?
1970 * @param c Connection.
1971 * @param fwd Is this about fwd traffic?
1973 * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
1976 GMC_is_origin (struct MeshConnection *c, int fwd)
1978 if (!fwd && c->path->length - 1 == c->own_pos )
1980 if (fwd && 0 == c->own_pos)
1987 * Is this peer the last one on the connection?
1989 * @param c Connection.
1990 * @param fwd Is this about fwd traffic?
1991 * Note that the ROOT is the terminal for BCK traffic!
1993 * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
1996 GMC_is_terminal (struct MeshConnection *c, int fwd)
1998 return GMC_is_origin (c, !fwd);
2003 * Count connections in a DLL.
2005 * @param head Head of the DLL.
2008 GMC_count (const struct MeshConnection *head)
2011 struct MeshConnection *iter;
2013 for (count = 0, iter = head; NULL != iter; iter = iter->next, count++);
2020 * Sends an already built message on a connection, properly registering
2021 * all used resources.
2023 * @param message Message to send. Function makes a copy of it.
2024 * If message is not hop-by-hop, decrements TTL of copy.
2025 * @param c Connection on which this message is transmitted.
2026 * @param ch Channel on which this message is transmitted, or NULL.
2027 * @param fwd Is this a fwd message?
2030 GMC_send_prebuilt_message ( const struct GNUNET_MessageHeader *message,
2031 struct MeshConnection *c,
2032 struct MeshChannel *ch,
2039 size = ntohs (message->size);
2040 data = GNUNET_malloc (size);
2041 memcpy (data, message, size);
2042 type = ntohs (message->type);
2043 LOG (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
2044 GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
2048 struct GNUNET_MESH_Encrypted *emsg;
2049 struct GNUNET_MESH_ACK *amsg;
2050 struct GNUNET_MESH_Poll *pmsg;
2051 struct GNUNET_MESH_ConnectionDestroy *dmsg;
2052 struct GNUNET_MESH_ConnectionBroken *bmsg;
2055 case GNUNET_MESSAGE_TYPE_MESH_FWD:
2056 case GNUNET_MESSAGE_TYPE_MESH_BCK:
2057 emsg = (struct GNUNET_MESH_Encrypted *) data;
2058 ttl = ntohl (emsg->ttl);
2061 GNUNET_break_op (0);
2065 emsg->ttl = htonl (ttl - 1);
2066 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2067 LOG (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
2070 case GNUNET_MESSAGE_TYPE_MESH_ACK:
2071 amsg = (struct GNUNET_MESH_ACK *) data;
2073 LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2076 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2077 pmsg = (struct GNUNET_MESH_Poll *) data;
2079 pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
2080 LOG (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2083 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2084 dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2089 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2090 bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2095 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2096 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2103 GMP_queue_add (data,