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-service-mesh_connection.h"
31 #include "gnunet-service-mesh_peer.h"
32 #include "mesh_protocol_enc.h"
33 #include "mesh_path.h"
36 #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
37 GNUNET_TIME_UNIT_MINUTES,\
39 #define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS
40 #define MESH_RETRANSMIT_MARGIN 4
44 * All the states a connection can be in.
46 enum MeshConnectionState
49 * Uninitialized status, should never appear in operation.
54 * Connection create message sent, waiting for ACK.
59 * Connection ACK sent, waiting for ACK.
64 * Connection confirmed, ready to carry traffic.
66 MESH_CONNECTION_READY,
72 * Struct containing info about a queued transmission to this peer
79 struct MeshPeerQueue *next;
84 struct MeshPeerQueue *prev;
87 * Peer this transmission is directed to.
89 struct MeshPeer *peer;
92 * Connection this message belongs to.
94 struct MeshConnection *c;
102 * Channel this message belongs to, if known.
104 struct MeshChannel *ch;
107 * Pointer to info stucture used as cls.
117 * Size of the message
124 * Struct to encapsulate all the Flow Control information to a peer to which
125 * we are directly connected (on a core level).
127 struct MeshFlowControl
130 * Connection this controls.
132 struct MeshConnection *c;
135 * How many messages are in the queue on this connection.
137 unsigned int queue_n;
140 * How many messages do we accept in the queue.
142 unsigned int queue_max;
150 * ID of the last packet sent towards the peer.
152 uint32_t last_pid_sent;
155 * ID of the last packet received from the peer.
157 uint32_t last_pid_recv;
160 * Last ACK sent to the peer (peer can't send more than this PID).
162 uint32_t last_ack_sent;
165 * Last ACK sent towards the origin (for traffic towards leaf node).
167 uint32_t last_ack_recv;
170 * Task to poll the peer in case of a lost ACK causes stall.
172 GNUNET_SCHEDULER_TaskIdentifier poll_task;
175 * How frequently to poll for ACKs.
177 struct GNUNET_TIME_Relative poll_time;
182 * Struct containing all information regarding a connection to a peer.
184 struct MeshConnection
189 struct MeshConnection *next;
190 struct MeshConnection *prev;
193 * Tunnel this connection is part of.
195 struct MeshTunnel2 *t;
198 * Flow control information for traffic fwd.
200 struct MeshFlowControl fwd_fc;
203 * Flow control information for traffic bck.
205 struct MeshFlowControl bck_fc;
208 * ID of the connection.
210 struct GNUNET_HashCode id;
213 * State of the connection.
215 enum MeshConnectionState state;
218 * Path being used for the tunnel.
220 struct MeshPeerPath *path;
223 * Position of the local peer in the path.
225 unsigned int own_pos;
228 * Task to keep the used paths alive at the owner,
229 * time tunnel out on all the other peers.
231 GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
234 * Task to keep the used paths alive at the destination,
235 * time tunnel out on all the other peers.
237 GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
240 * Pending message count.
242 int pending_messages;
245 * Destroy flag: if true, destroy on last message.
252 * Connections known, indexed by cid (MeshConnection).
254 static struct GNUNET_CONTAINER_MultiHashMap *connections;
257 * How many connections are we willing to maintain.
258 * Local connections are always allowed, even if there are more connections than max.
260 static unsigned long long max_connections;
263 * How many messages *in total* are we willing to queue, divide by number of
264 * connections to get connection queue size.
266 static unsigned long long max_msgs_queue;
269 * How often to send path keepalives. Paths timeout after 4 missed.
271 static struct GNUNET_TIME_Relative refresh_connection_time;
274 #if 0 // avoid compiler warning for unused static function
276 fc_debug (struct MeshFlowControl *fc)
278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
279 fc->last_pid_recv, fc->last_ack_sent);
280 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
281 fc->last_pid_sent, fc->last_ack_recv);
282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
283 fc->queue_n, fc->queue_max);
287 connection_debug (struct MeshConnection *c)
291 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
295 peer2s (c->t->peer), GNUNET_h2s (&c->id));
296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
297 c->state, c->pending_messages);
298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
299 fc_debug (&c->fwd_fc);
300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
301 fc_debug (&c->bck_fc);
306 * Get string description for tunnel state.
308 * @param s Tunnel state.
310 * @return String representation.
313 GMC_DEBUG_state2s (enum MeshTunnelState s)
317 case MESH_CONNECTION_NEW:
318 return "MESH_CONNECTION_NEW";
319 case MESH_CONNECTION_SENT:
320 return "MESH_CONNECTION_SENT";
321 case MESH_CONNECTION_ACK:
322 return "MESH_CONNECTION_ACK";
323 case MESH_CONNECTION_READY:
324 return "MESH_CONNECTION_READY";
326 return "MESH_CONNECTION_STATE_ERROR";
333 * Initialize a Flow Control structure to the initial state.
335 * @param fc Flow Control structure to initialize.
338 fc_init (struct MeshFlowControl *fc)
341 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
342 fc->last_pid_recv = (uint32_t) -1;
343 fc->last_ack_sent = (uint32_t) 0;
344 fc->last_ack_recv = (uint32_t) 0;
345 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
346 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
348 fc->queue_max = (max_msgs_queue / max_connections) + 1;
355 * @param cid Connection ID.
357 static struct MeshConnection *
358 connection_get (const struct GNUNET_HashCode *cid)
360 return GNUNET_CONTAINER_multihashmap_get (connections, cid);
365 * Send an ACK informing the predecessor about the available buffer space.
367 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
368 * the ACK itself goes "back" (dest->root).
370 * @param c Connection on which to send the ACK.
371 * @param buffer How much space free to advertise?
372 * @param fwd Is this FWD ACK? (Going dest->owner)
375 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
377 struct MeshFlowControl *next_fc;
378 struct MeshFlowControl *prev_fc;
379 struct GNUNET_MESH_ACK msg;
383 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
384 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
387 "connection send %s ack on %s\n",
388 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
390 /* Check if we need to transmit the ACK */
391 if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
393 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
394 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
395 " last pid recv: %u, last ack sent: %u\n",
396 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
400 /* Ok, ACK might be necessary, what PID to ACK? */
401 delta = next_fc->queue_max - next_fc->queue_n;
402 ack = prev_fc->last_pid_recv + delta;
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
405 " last pid %u, last ack %u, qmax %u, q %u\n",
406 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
407 next_fc->queue_max, next_fc->queue_n);
408 if (ack == prev_fc->last_ack_sent)
410 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
414 prev_fc->last_ack_sent = ack;
416 /* Build ACK message and send on connection */
417 msg.header.size = htons (sizeof (msg));
418 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
419 msg.ack = htonl (ack);
422 send_prebuilt_message_connection (&msg.header, c, NULL, !fwd);
427 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
430 * @param connection Connection to confirm.
431 * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
434 send_connection_ack (struct MeshConnection *connection, int fwd)
436 struct MeshTunnel2 *t;
439 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
441 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
442 sizeof (struct GNUNET_MESH_ConnectionACK),
446 if (MESH_TUNNEL_NEW == t->state)
447 tunnel_change_state (t, MESH_TUNNEL_WAITING);
448 if (MESH_CONNECTION_READY != connection->state)
449 connection_change_state (connection, MESH_CONNECTION_SENT);
454 * Sends a CREATE CONNECTION message for a path to a peer.
455 * Changes the connection and tunnel states if necessary.
457 * @param connection Connection to create.
460 send_connection_create (struct MeshConnection *connection)
462 struct MeshTunnel2 *t;
465 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
467 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
468 sizeof (struct GNUNET_MESH_ConnectionCreate) +
469 (connection->path->length *
470 sizeof (struct GNUNET_PeerIdentity)),
475 (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
476 tunnel_change_state (t, MESH_TUNNEL_WAITING);
477 if (MESH_CONNECTION_NEW == connection->state)
478 connection_change_state (connection, MESH_CONNECTION_SENT);
483 connection_change_state (struct MeshConnection* c,
484 enum MeshConnectionState state)
486 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
487 "Connection %s state was %s\n",
488 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (c->state));
489 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
490 "Connection %s state is now %s\n",
491 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (state));
498 * Send keepalive packets for a connection.
500 * @param c Connection to keep alive..
501 * @param fwd Is this a FWD keepalive? (owner -> dest).
504 connection_keepalive (struct MeshConnection *c, int fwd)
506 struct GNUNET_MESH_ConnectionKeepAlive *msg;
507 size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
511 type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
512 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
514 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
515 "sending %s keepalive for connection %s[%d]\n",
520 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
521 msg->header.size = htons (size);
522 msg->header.type = htons (type);
525 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
530 * Send CONNECTION_{CREATE/ACK} packets for a connection.
532 * @param c Connection for which to send the message.
533 * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
536 connection_recreate (struct MeshConnection *c, int fwd)
538 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
540 send_connection_create (c);
542 send_connection_ack (c, GNUNET_NO);
547 * Generic connection timer management.
548 * Depending on the role of the peer in the connection will send the
549 * appropriate message (build or keepalive)
551 * @param c Conncetion to maintain.
555 connection_maintain (struct MeshConnection *c, int fwd)
557 if (MESH_TUNNEL_SEARCHING == c->t->state)
559 /* TODO DHT GET with RO_BART */
564 case MESH_CONNECTION_NEW:
566 case MESH_CONNECTION_SENT:
567 connection_recreate (c, fwd);
569 case MESH_CONNECTION_READY:
570 connection_keepalive (c, fwd);
579 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
581 struct MeshConnection *c = cls;
583 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
584 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
587 connection_maintain (c, GNUNET_YES);
588 c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
589 &connection_fwd_keepalive,
595 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
597 struct MeshConnection *c = cls;
599 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
600 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
603 connection_maintain (c, GNUNET_NO);
604 c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
605 &connection_bck_keepalive,
611 * Send a message to all peers in this connection that the connection
612 * is no longer valid.
614 * If some peer should not receive the message, it should be zero'ed out
615 * before calling this function.
617 * @param c The connection whose peers to notify.
620 connection_send_destroy (struct MeshConnection *c)
622 struct GNUNET_MESH_ConnectionDestroy msg;
624 msg.header.size = htons (sizeof (msg));
625 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
627 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
628 " sending connection destroy for connection %s[%X]\n",
632 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
633 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_YES);
634 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
635 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_NO);
636 c->destroy = GNUNET_YES;
641 * Get free buffer space in a connection.
643 * @param c Connection.
644 * @param fwd Is query about FWD traffic?
646 * @return Free buffer space [0 - max_msgs_queue/max_connections]
649 connection_get_buffer (struct MeshConnection *c, int fwd)
651 struct MeshFlowControl *fc;
653 fc = fwd ? &c->fwd_fc : &c->bck_fc;
655 return (fc->queue_max - fc->queue_n);
660 * Get the first transmittable message for a connection.
662 * @param c Connection.
663 * @param fwd Is this FWD?
665 * @return First transmittable message.
667 static struct MeshPeerQueue *
668 connection_get_first_message (struct MeshConnection *c, int fwd)
670 struct MeshPeerQueue *q;
673 p = connection_get_hop (c, fwd);
675 for (q = p->queue_head; NULL != q; q = q->next)
679 if (queue_is_sendable (q))
688 * @brief Re-initiate traffic on this connection if necessary.
690 * Check if there is traffic queued towards this peer
691 * and the core transmit handle is NULL (traffic was stalled).
692 * If so, call core tmt rdy.
694 * @param c Connection on which initiate traffic.
695 * @param fwd Is this about fwd traffic?
698 connection_unlock_queue (struct MeshConnection *c, int fwd)
700 struct MeshPeer *peer;
701 struct MeshPeerQueue *q;
704 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
705 "connection_unlock_queue %s on %s\n",
706 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
708 if (GMC_is_terminal (c, fwd))
710 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
714 peer = connection_get_hop (c, fwd);
716 if (NULL != peer->core_transmit)
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n");
719 return; /* Already unlocked */
722 q = connection_get_first_message (c, fwd);
725 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n");
726 return; /* Nothing to transmit */
730 peer->core_transmit =
731 GNUNET_CORE_notify_transmit_ready (core_handle,
734 GNUNET_TIME_UNIT_FOREVER_REL,
735 GNUNET_PEER_resolve2 (peer->id),
743 * Cancel all transmissions that belong to a certain connection.
745 * @param c Connection which to cancel.
746 * @param fwd Cancel fwd traffic?
749 connection_cancel_queues (struct MeshConnection *c, int fwd)
751 struct MeshPeerQueue *q;
752 struct MeshPeerQueue *next;
753 struct MeshFlowControl *fc;
754 struct MeshPeer *peer;
761 fc = fwd ? &c->fwd_fc : &c->bck_fc;
762 peer = connection_get_hop (c, fwd);
764 for (q = peer->queue_head; NULL != q; q = next)
769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
770 "connection_cancel_queue %s\n",
771 GNUNET_MESH_DEBUG_M2S (q->type));
772 queue_destroy (q, GNUNET_YES);
775 if (NULL == peer->queue_head)
777 if (NULL != peer->core_transmit)
779 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
780 peer->core_transmit = NULL;
782 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
784 GNUNET_SCHEDULER_cancel (fc->poll_task);
785 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
794 * Function called if a connection has been stalled for a while,
795 * possibly due to a missed ACK. Poll the neighbor about its ACK status.
797 * @param cls Closure (poll ctx).
798 * @param tc TaskContext.
801 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
803 struct MeshFlowControl *fc = cls;
804 struct GNUNET_MESH_Poll msg;
805 struct MeshConnection *c;
807 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
808 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
815 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
816 GNUNET_h2s (&c->id));
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n",
818 fc == &c->fwd_fc ? "FWD" : "BCK");
820 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
821 msg.header.size = htons (sizeof (msg));
822 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
823 send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
824 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
825 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
826 &connection_poll, fc);
833 * Get the previous hop in a connection
835 * @param c Connection.
837 * @return Previous peer in the connection.
839 static struct MeshPeer *
840 connection_get_prev_hop (struct MeshConnection *c)
844 if (0 == c->own_pos || c->path->length < 2)
845 id = c->path->peers[0];
847 id = c->path->peers[c->own_pos - 1];
849 return peer_get_short (id);
854 * Get the next hop in a connection
856 * @param c Connection.
858 * @return Next peer in the connection.
860 static struct MeshPeer *
861 connection_get_next_hop (struct MeshConnection *c)
865 if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
866 id = c->path->peers[c->path->length - 1];
868 id = c->path->peers[c->own_pos + 1];
870 return peer_get_short (id);
875 * Get the hop in a connection.
877 * @param c Connection.
878 * @param fwd Next hop?
880 * @return Next peer in the connection.
882 static struct MeshPeer *
883 connection_get_hop (struct MeshConnection *c, int fwd)
886 return connection_get_next_hop (c);
887 return connection_get_prev_hop (c);
894 * Timeout function due to lack of keepalive/traffic from the owner.
895 * Destroys connection if called.
897 * @param cls Closure (connection to destroy).
898 * @param tc TaskContext.
901 connection_fwd_timeout (void *cls,
902 const struct GNUNET_SCHEDULER_TaskContext *tc)
904 struct MeshConnection *c = cls;
906 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
907 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
909 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
910 "Connection %s[%X] FWD timed out. Destroying.\n",
914 if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
922 * Timeout function due to lack of keepalive/traffic from the destination.
923 * Destroys connection if called.
925 * @param cls Closure (connection to destroy).
926 * @param tc TaskContext
929 connection_bck_timeout (void *cls,
930 const struct GNUNET_SCHEDULER_TaskContext *tc)
932 struct MeshConnection *c = cls;
934 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
935 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
939 "Connection %s[%X] FWD timed out. Destroying.\n",
943 if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
951 * Resets the connection timeout task, some other message has done the
953 * - For the first peer on the direction this means to send
954 * a keepalive or a path confirmation message (either create or ACK).
955 * - For all other peers, this means to destroy the connection,
956 * due to lack of activity.
957 * Starts the tiemout if no timeout was running (connection just created).
959 * @param c Connection whose timeout to reset.
960 * @param fwd Is this forward?
962 * TODO use heap to improve efficiency of scheduler.
965 connection_reset_timeout (struct MeshConnection *c, int fwd)
967 GNUNET_SCHEDULER_TaskIdentifier *ti;
968 GNUNET_SCHEDULER_Task f;
970 ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
972 if (GNUNET_SCHEDULER_NO_TASK != *ti)
973 GNUNET_SCHEDULER_cancel (*ti);
975 if (GMC_is_origin (c, fwd)) /* Endpoint */
977 f = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
978 *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
982 struct GNUNET_TIME_Relative delay;
984 delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
985 f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
986 *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
995 * Core handler for connection creation.
997 * @param cls Closure (unused).
998 * @param peer Sender (neighbor).
999 * @param message Message.
1001 * @return GNUNET_OK to keep the connection open,
1002 * GNUNET_SYSERR to close it (signal serious error)
1005 handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1006 const struct GNUNET_MessageHeader *message)
1008 struct GNUNET_MESH_ConnectionCreate *msg;
1009 struct GNUNET_PeerIdentity *id;
1010 struct GNUNET_HashCode *cid;
1011 struct MeshPeerPath *path;
1012 struct MeshPeer *dest_peer;
1013 struct MeshPeer *orig_peer;
1014 struct MeshConnection *c;
1015 unsigned int own_pos;
1019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1020 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1023 size = ntohs (message->size);
1024 if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1026 GNUNET_break_op (0);
1030 /* Calculate hops */
1031 size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1032 if (size % sizeof (struct GNUNET_PeerIdentity))
1034 GNUNET_break_op (0);
1037 size /= sizeof (struct GNUNET_PeerIdentity);
1040 GNUNET_break_op (0);
1043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
1045 /* Get parameters */
1046 msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1048 id = (struct GNUNET_PeerIdentity *) &msg[1];
1049 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1050 " connection %s (%s).\n",
1051 GNUNET_h2s (cid), GNUNET_i2s (id));
1053 /* Create connection */
1054 c = connection_get (cid);
1057 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
1058 c = connection_new (cid);
1061 connection_reset_timeout (c, GNUNET_YES);
1064 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
1065 path = path_new (size);
1067 for (i = 0; i < size; i++)
1069 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
1070 GNUNET_i2s (&id[i]));
1071 path->peers[i] = GNUNET_PEER_intern (&id[i]);
1072 if (path->peers[i] == myid)
1075 if (own_pos == 0 && path->peers[own_pos] != myid)
1077 /* create path: self not found in path through self */
1078 GNUNET_break_op (0);
1079 path_destroy (path);
1080 connection_destroy (c);
1083 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
1084 path_add_to_peers (path, GNUNET_NO);
1085 c->path = path_duplicate (path);
1086 c->own_pos = own_pos;
1092 if (MESH_CONNECTION_NEW == c->state)
1093 connection_change_state (c, MESH_CONNECTION_SENT);
1095 /* Remember peers */
1096 dest_peer = peer_get (&id[size - 1]);
1097 orig_peer = peer_get (&id[0]);
1099 /* Is it a connection to us? */
1100 if (c->own_pos == size - 1)
1102 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
1103 peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1105 if (NULL == orig_peer->tunnel)
1107 orig_peer->tunnel = tunnel_new ();
1108 orig_peer->tunnel->peer = orig_peer;
1110 tunnel_add_connection (orig_peer->tunnel, c);
1111 if (MESH_TUNNEL_NEW == c->t->state)
1112 tunnel_change_state (c->t, MESH_TUNNEL_WAITING);
1114 send_connection_ack (c, GNUNET_NO);
1115 if (MESH_CONNECTION_SENT == c->state)
1116 connection_change_state (c, MESH_CONNECTION_ACK);
1118 /* Keep tunnel alive in direction dest->owner*/
1119 connection_reset_timeout (c, GNUNET_NO);
1123 /* It's for somebody else! Retransmit. */
1124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
1125 peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1126 peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1127 send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
1134 * Core handler for path confirmations.
1136 * @param cls closure
1137 * @param message message
1138 * @param peer peer identity this notification is about
1140 * @return GNUNET_OK to keep the connection open,
1141 * GNUNET_SYSERR to close it (signal serious error)
1144 handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1145 const struct GNUNET_MessageHeader *message)
1147 struct GNUNET_MESH_ConnectionACK *msg;
1148 struct MeshConnection *c;
1149 struct MeshPeerPath *p;
1150 struct MeshPeer *pi;
1153 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1154 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1155 msg = (struct GNUNET_MESH_ConnectionACK *) message;
1156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n",
1157 GNUNET_h2s (&msg->cid));
1158 c = connection_get (&msg->cid);
1161 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1163 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n");
1168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
1170 pi = peer_get (peer);
1171 if (connection_get_next_hop (c) == pi)
1173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
1175 if (MESH_CONNECTION_SENT == c->state)
1176 connection_change_state (c, MESH_CONNECTION_ACK);
1178 else if (connection_get_prev_hop (c) == pi)
1180 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK\n");
1182 connection_change_state (c, MESH_CONNECTION_READY);
1186 GNUNET_break_op (0);
1189 connection_reset_timeout (c, fwd);
1191 /* Add path to peers? */
1195 path_add_to_peers (p, GNUNET_YES);
1202 /* Message for us as creator? */
1203 if (connection_is_origin (c, GNUNET_YES))
1205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
1206 connection_change_state (c, MESH_CONNECTION_READY);
1207 if (MESH_TUNNEL_READY != c->t->state)
1208 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1209 send_connection_ack (c, GNUNET_YES);
1210 tunnel_send_queued_data (c->t, GNUNET_YES);
1211 if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
1213 GNUNET_DHT_get_stop (c->t->peer->dhtget);
1214 c->t->peer->dhtget = NULL;
1219 /* Message for us as destination? */
1220 if (GMC_is_terminal (c, GNUNET_YES))
1222 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
1223 if (MESH_TUNNEL_READY != c->t->state)
1224 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1225 connection_change_state (c, MESH_CONNECTION_READY);
1226 tunnel_send_queued_data (c->t, GNUNET_NO);
1230 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1231 send_prebuilt_message_connection (message, c, NULL, fwd);
1237 * Core handler for notifications of broken paths
1239 * @param cls Closure (unused).
1240 * @param peer Peer identity of sending neighbor.
1241 * @param message Message.
1243 * @return GNUNET_OK to keep the connection open,
1244 * GNUNET_SYSERR to close it (signal serious error)
1247 handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1248 const struct GNUNET_MessageHeader *message)
1250 struct GNUNET_MESH_ConnectionBroken *msg;
1251 struct MeshConnection *c;
1253 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1254 "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1255 msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1257 GNUNET_i2s (&msg->peer1));
1258 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1259 GNUNET_i2s (&msg->peer2));
1260 c = connection_get (&msg->cid);
1263 GNUNET_break_op (0);
1266 tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1267 GNUNET_PEER_search (&msg->peer2));
1274 * Core handler for tunnel destruction
1276 * @param cls Closure (unused).
1277 * @param peer Peer identity of sending neighbor.
1278 * @param message Message.
1280 * @return GNUNET_OK to keep the connection open,
1281 * GNUNET_SYSERR to close it (signal serious error)
1284 handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1285 const struct GNUNET_MessageHeader *message)
1287 struct GNUNET_MESH_ConnectionDestroy *msg;
1288 struct MeshConnection *c;
1292 msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1294 "Got a CONNECTION DESTROY message from %s\n",
1296 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1297 " for connection %s\n",
1298 GNUNET_h2s (&msg->cid));
1299 c = connection_get (&msg->cid);
1302 /* Probably already got the message from another path,
1303 * destroyed the tunnel and retransmitted to children.
1306 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1310 id = GNUNET_PEER_search (peer);
1311 if (id == connection_get_prev_hop (c)->id)
1313 else if (id == connection_get_next_hop (c)->id)
1317 GNUNET_break_op (0);
1320 send_prebuilt_message_connection (message, c, NULL, fwd);
1321 c->destroy = GNUNET_YES;
1327 * Generic handler for mesh network encrypted traffic.
1329 * @param peer Peer identity this notification is about.
1330 * @param message Encrypted message.
1331 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1333 * @return GNUNET_OK to keep the connection open,
1334 * GNUNET_SYSERR to close it (signal serious error)
1337 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1338 const struct GNUNET_MESH_Encrypted *msg,
1341 struct MeshConnection *c;
1342 struct MeshTunnel2 *t;
1343 struct MeshPeer *neighbor;
1344 struct MeshFlowControl *fc;
1351 size = ntohs (msg->header.size);
1353 sizeof (struct GNUNET_MESH_Encrypted) +
1354 sizeof (struct GNUNET_MessageHeader))
1356 GNUNET_break_op (0);
1359 type = ntohs (msg->header.type);
1360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1362 GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1364 /* Check connection */
1365 c = connection_get (&msg->cid);
1368 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1369 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1373 fc = fwd ? &c->bck_fc : &c->fwd_fc;
1375 /* Check if origin is as expected */
1376 neighbor = connection_get_hop (c, !fwd);
1377 if (peer_get (peer)->id != neighbor->id)
1379 GNUNET_break_op (0);
1384 pid = ntohl (msg->pid);
1385 if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1387 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1388 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1389 "WARNING Received PID %u, (prev %u), ACK %u\n",
1390 pid, fc->last_pid_recv, fc->last_ack_sent);
1393 if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1395 GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1396 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1397 " Pid %u not expected (%u+), dropping!\n",
1398 pid, fc->last_pid_recv + 1);
1401 if (MESH_CONNECTION_SENT == c->state)
1402 connection_change_state (c, MESH_CONNECTION_READY);
1403 connection_reset_timeout (c, fwd);
1404 fc->last_pid_recv = pid;
1406 /* Is this message for us? */
1407 if (GMC_is_terminal (c, fwd))
1409 size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1411 struct GNUNET_MessageHeader *msgh;
1414 /* TODO signature verification */
1415 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
1416 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1418 fc->last_pid_recv = pid;
1419 tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1423 msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1424 handle_decrypted (t, msgh, fwd);
1425 off += ntohs (msgh->size);
1427 send_ack (c, NULL, fwd);
1431 /* Message not for us: forward to next hop */
1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1433 ttl = ntohl (msg->ttl);
1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
1437 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1438 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1439 send_ack (c, NULL, fwd);
1442 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1444 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1451 * Core handler for mesh network traffic going orig->dest.
1453 * @param cls Closure (unused).
1454 * @param message Message received.
1455 * @param peer Peer who sent the message.
1457 * @return GNUNET_OK to keep the connection open,
1458 * GNUNET_SYSERR to close it (signal serious error)
1461 handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1462 const struct GNUNET_MessageHeader *message)
1464 return handle_mesh_encrypted (peer,
1465 (struct GNUNET_MESH_Encrypted *)message,
1470 * Core handler for mesh network traffic going dest->orig.
1472 * @param cls Closure (unused).
1473 * @param message Message received.
1474 * @param peer Peer who sent the message.
1476 * @return GNUNET_OK to keep the connection open,
1477 * GNUNET_SYSERR to close it (signal serious error)
1480 handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1481 const struct GNUNET_MessageHeader *message)
1483 return handle_mesh_encrypted (peer,
1484 (struct GNUNET_MESH_Encrypted *)message,
1490 * Core handler for mesh network traffic point-to-point acks.
1492 * @param cls closure
1493 * @param message message
1494 * @param peer peer identity this notification is about
1496 * @return GNUNET_OK to keep the connection open,
1497 * GNUNET_SYSERR to close it (signal serious error)
1500 handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1501 const struct GNUNET_MessageHeader *message)
1503 struct GNUNET_MESH_ACK *msg;
1504 struct MeshConnection *c;
1505 struct MeshFlowControl *fc;
1510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1513 msg = (struct GNUNET_MESH_ACK *) message;
1515 c = connection_get (&msg->cid);
1519 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1524 /* Is this a forward or backward ACK? */
1525 id = GNUNET_PEER_search (peer);
1526 if (connection_get_next_hop (c)->id == id)
1528 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1532 else if (connection_get_prev_hop (c)->id == id)
1534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1540 GNUNET_break_op (0);
1544 ack = ntohl (msg->ack);
1545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n",
1546 ack, fc->last_ack_recv);
1547 if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1548 fc->last_ack_recv = ack;
1550 /* Cancel polling if the ACK is big enough. */
1551 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1552 GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1554 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
1555 GNUNET_SCHEDULER_cancel (fc->poll_task);
1556 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1557 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1560 connection_unlock_queue (c, fwd);
1567 * Core handler for mesh network traffic point-to-point ack polls.
1569 * @param cls closure
1570 * @param message message
1571 * @param peer peer identity this notification is about
1573 * @return GNUNET_OK to keep the connection open,
1574 * GNUNET_SYSERR to close it (signal serious error)
1577 handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1578 const struct GNUNET_MessageHeader *message)
1580 struct GNUNET_MESH_Poll *msg;
1581 struct MeshConnection *c;
1582 struct MeshFlowControl *fc;
1587 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1588 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1591 msg = (struct GNUNET_MESH_Poll *) message;
1593 c = connection_get (&msg->cid);
1597 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1599 GNUNET_break_op (0);
1603 /* Is this a forward or backward ACK?
1604 * Note: a poll should never be needed in a loopback case,
1605 * since there is no possiblility of packet loss there, so
1606 * this way of discerining FWD/BCK should not be a problem.
1608 id = GNUNET_PEER_search (peer);
1609 if (connection_get_next_hop (c)->id == id)
1611 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1614 else if (connection_get_prev_hop (c)->id == id)
1616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1621 GNUNET_break_op (0);
1625 pid = ntohl (msg->pid);
1626 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n",
1627 pid, fc->last_pid_recv);
1628 fc->last_pid_recv = pid;
1629 fwd = fc == &c->fwd_fc;
1630 send_ack (c, NULL, fwd);
1637 * Core handler for mesh keepalives.
1639 * @param cls closure
1640 * @param message message
1641 * @param peer peer identity this notification is about
1642 * @return GNUNET_OK to keep the connection open,
1643 * GNUNET_SYSERR to close it (signal serious error)
1645 * TODO: Check who we got this from, to validate route.
1648 handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1649 const struct GNUNET_MessageHeader *message)
1651 struct GNUNET_MESH_ConnectionKeepAlive *msg;
1652 struct MeshConnection *c;
1653 struct MeshPeer *neighbor;
1656 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1657 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1660 c = connection_get (&msg->cid);
1663 GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1668 fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1669 GNUNET_YES : GNUNET_NO;
1671 /* Check if origin is as expected */
1672 neighbor = connection_get_hop (c, fwd);
1673 if (peer_get (peer)->id != neighbor->id)
1675 GNUNET_break_op (0);
1679 connection_change_state (c, MESH_CONNECTION_READY);
1680 connection_reset_timeout (c, fwd);
1682 if (GMC_is_terminal (c, fwd))
1685 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1686 send_prebuilt_message_connection (message, c, NULL, fwd);
1693 * Functions to handle messages from core
1695 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1696 {&handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
1698 {&handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
1699 sizeof (struct GNUNET_MESH_ConnectionACK)},
1700 {&handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
1701 sizeof (struct GNUNET_MESH_ConnectionBroken)},
1702 {&handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
1703 sizeof (struct GNUNET_MESH_ConnectionDestroy)},
1704 {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE,
1705 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
1706 {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE,
1707 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
1708 {&handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
1709 sizeof (struct GNUNET_MESH_ACK)},
1710 {&handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
1711 sizeof (struct GNUNET_MESH_Poll)},
1712 {&handle_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0},
1713 {&handle_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0},
1720 * Send an ACK on the appropriate connection/channel, depending on
1721 * the direction and the position of the peer.
1723 * @param c Which connection to send the hop-by-hop ACK.
1724 * @param ch Channel, if any.
1725 * @param fwd Is this a fwd ACK? (will go dest->root)
1728 send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1730 unsigned int buffer;
1732 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1733 "send ack %s on %p %p\n",
1734 fwd ? "FWD" : "BCK", c, ch);
1735 if (NULL == c || GMC_is_terminal (c, fwd))
1737 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n");
1738 buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
1742 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
1743 buffer = connection_get_buffer (c, fwd);
1745 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1747 if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
1748 (NULL != c && connection_is_origin (c, fwd)) )
1750 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1753 GNUNET_assert (NULL != ch);
1754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1755 send_local_ack (ch, fwd);
1760 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1761 GNUNET_assert (NULL != ch);
1762 channel_send_connections_ack (ch, buffer, fwd);
1766 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
1767 connection_send_ack (c, buffer, fwd);
1774 * Initialize the connections subsystem
1776 * @param c Configuration handle.
1779 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
1782 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
1785 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1786 "MESH", "MAX_MSGS_QUEUE", "MISSING");
1787 GNUNET_SCHEDULER_shutdown ();
1792 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
1795 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1796 "MESH", "MAX_CONNECTIONS", "MISSING");
1797 GNUNET_SCHEDULER_shutdown ();
1802 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
1803 &refresh_connection_time))
1805 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1806 "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
1807 GNUNET_SCHEDULER_shutdown ();
1810 connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
1814 * Shut down the connections subsystem.
1819 if (core_handle != NULL)
1821 GNUNET_CORE_disconnect (core_handle);
1827 struct MeshConnection *
1828 GMC_new (const struct GNUNET_HashCode *cid)
1830 struct MeshConnection *c;
1832 c = GNUNET_new (struct MeshConnection);
1834 GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
1835 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1836 fc_init (&c->fwd_fc);
1837 fc_init (&c->bck_fc);
1846 GMC_destroy (struct MeshConnection *c)
1848 struct MeshPeer *peer;
1853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s[%X]\n",
1854 peer2s (c->t->peer),
1857 /* Cancel all traffic */
1858 connection_cancel_queues (c, GNUNET_YES);
1859 connection_cancel_queues (c, GNUNET_NO);
1861 /* Cancel maintainance task (keepalive/timeout) */
1862 if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
1863 GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
1864 if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
1865 GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
1867 /* Deregister from neighbors */
1868 peer = connection_get_next_hop (c);
1869 if (NULL != peer && NULL != peer->connections)
1870 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
1871 peer = connection_get_prev_hop (c);
1872 if (NULL != peer && NULL != peer->connections)
1873 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
1876 GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
1877 GNUNET_CONTAINER_DLL_remove (c->t->connection_head, c->t->connection_tail, c);
1883 * Notify other peers on a connection of a broken link. Mark connections
1884 * to destroy after all traffic has been sent.
1886 * @param c Connection on which there has been a disconnection.
1887 * @param peer Peer that disconnected.
1888 * @param my_full_id My ID (to send to other peers).
1891 GMC_notify_broken (struct MeshConnection *c,
1892 struct MeshPeer *peer,
1893 struct GNUNET_PeerIdentity *my_full_id)
1895 struct MeshConnection *c = value;
1896 struct GNUNET_MESH_ConnectionBroken msg;
1899 fwd = peer == connection_get_prev_hop (c);
1901 connection_cancel_queues (c, !fwd);
1902 if (GMC_is_terminal (c, fwd))
1904 /* Local shutdown, no one to notify about this. */
1909 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
1910 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
1912 msg.peer1 = *my_full_id;
1913 msg.peer2 = *GNUNET_PEER_resolve2 (peer->id);
1914 GMC_send_prebuilt_message (&msg.header, c, NULL, fwd);
1915 c->destroy = GNUNET_YES;
1922 * Is this peer the first one on the connection?
1924 * @param c Connection.
1925 * @param fwd Is this about fwd traffic?
1927 * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
1930 GMC_is_origin (struct MeshConnection *c, int fwd)
1932 if (!fwd && c->path->length - 1 == c->own_pos )
1934 if (fwd && 0 == c->own_pos)
1941 * Is this peer the last one on the connection?
1943 * @param c Connection.
1944 * @param fwd Is this about fwd traffic?
1945 * Note that the ROOT is the terminal for BCK traffic!
1947 * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
1950 GMC_is_terminal (struct MeshConnection *c, int fwd)
1952 return GMC_is_origin (c, !fwd);
1957 * Count connections in a DLL.
1960 GMC_count (const struct MeshConnection *head)
1963 struct MeshConnection *iter;
1965 for (count = 0, iter = head; NULL != iter; iter = iter->next, count++);
1972 * Sends an already built message on a connection, properly registering
1973 * all used resources.
1975 * @param message Message to send. Function makes a copy of it.
1976 * If message is not hop-by-hop, decrements TTL of copy.
1977 * @param c Connection on which this message is transmitted.
1978 * @param ch Channel on which this message is transmitted, or NULL.
1979 * @param fwd Is this a fwd message?
1982 GMC_send_prebuilt_message (const struct GNUNET_MessageHeader *message,
1983 struct MeshConnection *c,
1984 struct MeshChannel *ch,
1991 size = ntohs (message->size);
1992 data = GNUNET_malloc (size);
1993 memcpy (data, message, size);
1994 type = ntohs (message->type);
1995 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
1996 GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
2000 struct GNUNET_MESH_Encrypted *emsg;
2001 struct GNUNET_MESH_ACK *amsg;
2002 struct GNUNET_MESH_Poll *pmsg;
2003 struct GNUNET_MESH_ConnectionDestroy *dmsg;
2004 struct GNUNET_MESH_ConnectionBroken *bmsg;
2007 case GNUNET_MESSAGE_TYPE_MESH_FWD:
2008 case GNUNET_MESSAGE_TYPE_MESH_BCK:
2009 emsg = (struct GNUNET_MESH_Encrypted *) data;
2010 ttl = ntohl (emsg->ttl);
2013 GNUNET_break_op (0);
2017 emsg->ttl = htonl (ttl - 1);
2018 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
2019 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
2022 case GNUNET_MESSAGE_TYPE_MESH_ACK:
2023 amsg = (struct GNUNET_MESH_ACK *) data;
2025 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
2028 case GNUNET_MESSAGE_TYPE_MESH_POLL:
2029 pmsg = (struct GNUNET_MESH_Poll *) data;
2031 pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
2032 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
2035 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
2036 dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
2041 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
2042 bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
2047 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
2048 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
2055 GMP_queue_add (data,