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_core_service.h"
32 #include "gnunet-service-mesh_connection.h"
33 #include "gnunet-service-mesh_peer.h"
34 #include "gnunet-service-mesh_local.h"
35 #include "mesh_protocol_enc.h"
36 #include "mesh_path.h"
39 #define MESH_DEBUG_CONNECTION GNUNET_NO
40 #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
41 GNUNET_TIME_UNIT_MINUTES,\
43 #define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS
44 #define MESH_RETRANSMIT_MARGIN 4
47 #if MESH_DEBUG_CONNECTION
48 #define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
50 #define DEBUG_CONN(...)
55 * All the states a connection can be in.
57 enum MeshConnectionState
60 * Uninitialized status, should never appear in operation.
65 * Connection create message sent, waiting for ACK.
70 * Connection ACK sent, waiting for ACK.
75 * Connection confirmed, ready to carry traffic.
77 MESH_CONNECTION_READY,
83 * Struct containing info about a queued transmission to this peer
90 struct MeshPeerQueue *next;
95 struct MeshPeerQueue *prev;
98 * Peer this transmission is directed to.
100 struct MeshPeer *peer;
103 * Connection this message belongs to.
105 struct MeshConnection *c;
113 * Channel this message belongs to, if known.
115 struct MeshChannel *ch;
118 * Pointer to info stucture used as cls.
128 * Size of the message
135 * Struct to encapsulate all the Flow Control information to a peer to which
136 * we are directly connected (on a core level).
138 struct MeshFlowControl
141 * Connection this controls.
143 struct MeshConnection *c;
146 * How many messages are in the queue on this connection.
148 unsigned int queue_n;
151 * How many messages do we accept in the queue.
153 unsigned int queue_max;
161 * ID of the last packet sent towards the peer.
163 uint32_t last_pid_sent;
166 * ID of the last packet received from the peer.
168 uint32_t last_pid_recv;
171 * Last ACK sent to the peer (peer can't send more than this PID).
173 uint32_t last_ack_sent;
176 * Last ACK sent towards the origin (for traffic towards leaf node).
178 uint32_t last_ack_recv;
181 * Task to poll the peer in case of a lost ACK causes stall.
183 GNUNET_SCHEDULER_TaskIdentifier poll_task;
186 * How frequently to poll for ACKs.
188 struct GNUNET_TIME_Relative poll_time;
193 * Struct containing all information regarding a connection to a peer.
195 struct MeshConnection
200 struct MeshConnection *next;
201 struct MeshConnection *prev;
204 * Tunnel this connection is part of.
206 struct MeshTunnel2 *t;
209 * Flow control information for traffic fwd.
211 struct MeshFlowControl fwd_fc;
214 * Flow control information for traffic bck.
216 struct MeshFlowControl bck_fc;
219 * ID of the connection.
221 struct GNUNET_HashCode id;
224 * State of the connection.
226 enum MeshConnectionState state;
229 * Path being used for the tunnel.
231 struct MeshPeerPath *path;
234 * Position of the local peer in the path.
236 unsigned int own_pos;
239 * Task to keep the used paths alive at the owner,
240 * time tunnel out on all the other peers.
242 GNUNET_SCHEDULER_TaskIdentifier fwd_maintenance_task;
245 * Task to keep the used paths alive at the destination,
246 * time tunnel out on all the other peers.
248 GNUNET_SCHEDULER_TaskIdentifier bck_maintenance_task;
251 * Pending message count.
253 int pending_messages;
256 * Destroy flag: if true, destroy on last message.
263 * Connections known, indexed by cid (MeshConnection).
265 static struct GNUNET_CONTAINER_MultiHashMap *connections;
268 * How many connections are we willing to maintain.
269 * Local connections are always allowed, even if there are more connections than max.
271 static unsigned long long max_connections;
274 * How many messages *in total* are we willing to queue, divide by number of
275 * connections to get connection queue size.
277 static unsigned long long max_msgs_queue;
280 * How often to send path keepalives. Paths timeout after 4 missed.
282 static struct GNUNET_TIME_Relative refresh_connection_time;
285 * Handle to communicate with core.
287 static struct GNUNET_CORE_Handle *core_handle;
289 #if 0 // avoid compiler warning for unused static function
291 fc_debug (struct MeshFlowControl *fc)
293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
294 fc->last_pid_recv, fc->last_ack_sent);
295 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
296 fc->last_pid_sent, fc->last_ack_recv);
297 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
298 fc->queue_n, fc->queue_max);
302 connection_debug (struct MeshConnection *c)
306 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
309 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
310 peer2s (c->t->peer), GNUNET_h2s (&c->id));
311 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
312 c->state, c->pending_messages);
313 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
314 fc_debug (&c->fwd_fc);
315 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
316 fc_debug (&c->bck_fc);
321 * Get string description for tunnel state.
323 * @param s Tunnel state.
325 * @return String representation.
328 GMC_DEBUG_state2s (enum MeshTunnelState s)
332 case MESH_CONNECTION_NEW:
333 return "MESH_CONNECTION_NEW";
334 case MESH_CONNECTION_SENT:
335 return "MESH_CONNECTION_SENT";
336 case MESH_CONNECTION_ACK:
337 return "MESH_CONNECTION_ACK";
338 case MESH_CONNECTION_READY:
339 return "MESH_CONNECTION_READY";
341 return "MESH_CONNECTION_STATE_ERROR";
348 * Initialize a Flow Control structure to the initial state.
350 * @param fc Flow Control structure to initialize.
353 fc_init (struct MeshFlowControl *fc)
356 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
357 fc->last_pid_recv = (uint32_t) -1;
358 fc->last_ack_sent = (uint32_t) 0;
359 fc->last_ack_recv = (uint32_t) 0;
360 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
361 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
363 fc->queue_max = (max_msgs_queue / max_connections) + 1;
370 * @param cid Connection ID.
372 static struct MeshConnection *
373 connection_get (const struct GNUNET_HashCode *cid)
375 return GNUNET_CONTAINER_multihashmap_get (connections, cid);
380 * Sends an already built message on a connection, properly registering
381 * all used resources.
383 * @param message Message to send. Function makes a copy of it.
384 * If message is not hop-by-hop, decrements TTL of copy.
385 * @param c Connection on which this message is transmitted.
386 * @param ch Channel on which this message is transmitted, or NULL.
387 * @param fwd Is this a fwd message?
390 send_prebuilt_message_connection (const struct GNUNET_MessageHeader *message,
391 struct MeshConnection *c,
392 struct MeshChannel *ch,
399 size = ntohs (message->size);
400 data = GNUNET_malloc (size);
401 memcpy (data, message, size);
402 type = ntohs (message->type);
403 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
404 GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
408 struct GNUNET_MESH_Encrypted *emsg;
409 struct GNUNET_MESH_ACK *amsg;
410 struct GNUNET_MESH_Poll *pmsg;
411 struct GNUNET_MESH_ConnectionDestroy *dmsg;
412 struct GNUNET_MESH_ConnectionBroken *bmsg;
415 case GNUNET_MESSAGE_TYPE_MESH_FWD:
416 case GNUNET_MESSAGE_TYPE_MESH_BCK:
417 emsg = (struct GNUNET_MESH_Encrypted *) data;
418 ttl = ntohl (emsg->ttl);
425 emsg->ttl = htonl (ttl - 1);
426 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
427 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
430 case GNUNET_MESSAGE_TYPE_MESH_ACK:
431 amsg = (struct GNUNET_MESH_ACK *) data;
433 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
436 case GNUNET_MESSAGE_TYPE_MESH_POLL:
437 pmsg = (struct GNUNET_MESH_Poll *) data;
439 pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
443 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
444 dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
449 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
450 bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
455 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
456 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
472 * Send an ACK informing the predecessor about the available buffer space.
474 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
475 * the ACK itself goes "back" (dest->root).
477 * @param c Connection on which to send the ACK.
478 * @param buffer How much space free to advertise?
479 * @param fwd Is this FWD ACK? (Going dest->owner)
482 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
484 struct MeshFlowControl *next_fc;
485 struct MeshFlowControl *prev_fc;
486 struct GNUNET_MESH_ACK msg;
490 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
491 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
494 "connection send %s ack on %s\n",
495 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
497 /* Check if we need to transmit the ACK */
498 if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
500 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
501 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
502 " last pid recv: %u, last ack sent: %u\n",
503 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
507 /* Ok, ACK might be necessary, what PID to ACK? */
508 delta = next_fc->queue_max - next_fc->queue_n;
509 ack = prev_fc->last_pid_recv + delta;
510 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
511 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
512 " last pid %u, last ack %u, qmax %u, q %u\n",
513 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
514 next_fc->queue_max, next_fc->queue_n);
515 if (ack == prev_fc->last_ack_sent)
517 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
521 prev_fc->last_ack_sent = ack;
523 /* Build ACK message and send on connection */
524 msg.header.size = htons (sizeof (msg));
525 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
526 msg.ack = htonl (ack);
529 send_prebuilt_message_connection (&msg.header, c, NULL, !fwd);
534 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
537 * @param connection Connection to confirm.
538 * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
541 send_connection_ack (struct MeshConnection *connection, int fwd)
543 struct MeshTunnel2 *t;
546 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
548 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
549 sizeof (struct GNUNET_MESH_ConnectionACK),
553 if (MESH_TUNNEL_NEW == t->state)
554 tunnel_change_state (t, MESH_TUNNEL_WAITING);
555 if (MESH_CONNECTION_READY != connection->state)
556 connection_change_state (connection, MESH_CONNECTION_SENT);
561 * Sends a CREATE CONNECTION message for a path to a peer.
562 * Changes the connection and tunnel states if necessary.
564 * @param connection Connection to create.
567 send_connection_create (struct MeshConnection *connection)
569 struct MeshTunnel2 *t;
572 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
574 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
575 sizeof (struct GNUNET_MESH_ConnectionCreate) +
576 (connection->path->length *
577 sizeof (struct GNUNET_PeerIdentity)),
582 (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
583 tunnel_change_state (t, MESH_TUNNEL_WAITING);
584 if (MESH_CONNECTION_NEW == connection->state)
585 connection_change_state (connection, MESH_CONNECTION_SENT);
590 connection_change_state (struct MeshConnection* c,
591 enum MeshConnectionState state)
593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
594 "Connection %s state was %s\n",
595 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (c->state));
596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
597 "Connection %s state is now %s\n",
598 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (state));
605 * Send keepalive packets for a connection.
607 * @param c Connection to keep alive..
608 * @param fwd Is this a FWD keepalive? (owner -> dest).
611 connection_keepalive (struct MeshConnection *c, int fwd)
613 struct GNUNET_MESH_ConnectionKeepAlive *msg;
614 size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
618 type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
619 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
621 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
622 "sending %s keepalive for connection %s[%d]\n",
627 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
628 msg->header.size = htons (size);
629 msg->header.type = htons (type);
632 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
637 * Send CONNECTION_{CREATE/ACK} packets for a connection.
639 * @param c Connection for which to send the message.
640 * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
643 connection_recreate (struct MeshConnection *c, int fwd)
645 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
647 send_connection_create (c);
649 send_connection_ack (c, GNUNET_NO);
654 * Generic connection timer management.
655 * Depending on the role of the peer in the connection will send the
656 * appropriate message (build or keepalive)
658 * @param c Conncetion to maintain.
662 connection_maintain (struct MeshConnection *c, int fwd)
664 if (MESH_TUNNEL_SEARCHING == c->t->state)
666 /* TODO DHT GET with RO_BART */
671 case MESH_CONNECTION_NEW:
673 case MESH_CONNECTION_SENT:
674 connection_recreate (c, fwd);
676 case MESH_CONNECTION_READY:
677 connection_keepalive (c, fwd);
686 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
688 struct MeshConnection *c = cls;
690 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
691 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
694 connection_maintain (c, GNUNET_YES);
695 c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
696 &connection_fwd_keepalive,
702 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
704 struct MeshConnection *c = cls;
706 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
707 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
710 connection_maintain (c, GNUNET_NO);
711 c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
712 &connection_bck_keepalive,
718 * Send a message to all peers in this connection that the connection
719 * is no longer valid.
721 * If some peer should not receive the message, it should be zero'ed out
722 * before calling this function.
724 * @param c The connection whose peers to notify.
727 connection_send_destroy (struct MeshConnection *c)
729 struct GNUNET_MESH_ConnectionDestroy msg;
731 msg.header.size = htons (sizeof (msg));
732 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
734 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
735 " sending connection destroy for connection %s[%X]\n",
739 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
740 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_YES);
741 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
742 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_NO);
743 c->destroy = GNUNET_YES;
748 * Get free buffer space in a connection.
750 * @param c Connection.
751 * @param fwd Is query about FWD traffic?
753 * @return Free buffer space [0 - max_msgs_queue/max_connections]
756 connection_get_buffer (struct MeshConnection *c, int fwd)
758 struct MeshFlowControl *fc;
760 fc = fwd ? &c->fwd_fc : &c->bck_fc;
762 return (fc->queue_max - fc->queue_n);
767 * Get the first transmittable message for a connection.
769 * @param c Connection.
770 * @param fwd Is this FWD?
772 * @return First transmittable message.
774 static struct MeshPeerQueue *
775 connection_get_first_message (struct MeshConnection *c, int fwd)
777 struct MeshPeerQueue *q;
780 p = connection_get_hop (c, fwd);
782 for (q = p->queue_head; NULL != q; q = q->next)
786 if (queue_is_sendable (q))
795 * @brief Re-initiate traffic on this connection if necessary.
797 * Check if there is traffic queued towards this peer
798 * and the core transmit handle is NULL (traffic was stalled).
799 * If so, call core tmt rdy.
801 * @param c Connection on which initiate traffic.
802 * @param fwd Is this about fwd traffic?
805 connection_unlock_queue (struct MeshConnection *c, int fwd)
807 struct MeshPeer *peer;
808 struct MeshPeerQueue *q;
811 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
812 "connection_unlock_queue %s on %s\n",
813 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
815 if (GMC_is_terminal (c, fwd))
817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
821 peer = connection_get_hop (c, fwd);
823 if (NULL != peer->core_transmit)
825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n");
826 return; /* Already unlocked */
829 q = connection_get_first_message (c, fwd);
832 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n");
833 return; /* Nothing to transmit */
837 peer->core_transmit =
838 GNUNET_CORE_notify_transmit_ready (core_handle,
841 GNUNET_TIME_UNIT_FOREVER_REL,
842 GNUNET_PEER_resolve2 (peer->id),
850 * Cancel all transmissions that belong to a certain connection.
852 * @param c Connection which to cancel.
853 * @param fwd Cancel fwd traffic?
856 connection_cancel_queues (struct MeshConnection *c, int fwd)
858 struct MeshPeerQueue *q;
859 struct MeshPeerQueue *next;
860 struct MeshFlowControl *fc;
861 struct MeshPeer *peer;
868 fc = fwd ? &c->fwd_fc : &c->bck_fc;
869 peer = connection_get_hop (c, fwd);
871 for (q = peer->queue_head; NULL != q; q = next)
876 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
877 "connection_cancel_queue %s\n",
878 GNUNET_MESH_DEBUG_M2S (q->type));
879 queue_destroy (q, GNUNET_YES);
882 if (NULL == peer->queue_head)
884 if (NULL != peer->core_transmit)
886 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
887 peer->core_transmit = NULL;
889 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
891 GNUNET_SCHEDULER_cancel (fc->poll_task);
892 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
901 * Function called if a connection has been stalled for a while,
902 * possibly due to a missed ACK. Poll the neighbor about its ACK status.
904 * @param cls Closure (poll ctx).
905 * @param tc TaskContext.
908 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
910 struct MeshFlowControl *fc = cls;
911 struct GNUNET_MESH_Poll msg;
912 struct MeshConnection *c;
914 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
915 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
921 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
922 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
923 GNUNET_h2s (&c->id));
924 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n",
925 fc == &c->fwd_fc ? "FWD" : "BCK");
927 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
928 msg.header.size = htons (sizeof (msg));
929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
930 send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
931 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
932 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
933 &connection_poll, fc);
940 * Get the previous hop in a connection
942 * @param c Connection.
944 * @return Previous peer in the connection.
946 static struct MeshPeer *
947 connection_get_prev_hop (struct MeshConnection *c)
951 if (0 == c->own_pos || c->path->length < 2)
952 id = c->path->peers[0];
954 id = c->path->peers[c->own_pos - 1];
956 return peer_get_short (id);
961 * Get the next hop in a connection
963 * @param c Connection.
965 * @return Next peer in the connection.
967 static struct MeshPeer *
968 connection_get_next_hop (struct MeshConnection *c)
972 if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
973 id = c->path->peers[c->path->length - 1];
975 id = c->path->peers[c->own_pos + 1];
977 return peer_get_short (id);
982 * Get the hop in a connection.
984 * @param c Connection.
985 * @param fwd Next hop?
987 * @return Next peer in the connection.
989 static struct MeshPeer *
990 connection_get_hop (struct MeshConnection *c, int fwd)
993 return connection_get_next_hop (c);
994 return connection_get_prev_hop (c);
1001 * Timeout function due to lack of keepalive/traffic from the owner.
1002 * Destroys connection if called.
1004 * @param cls Closure (connection to destroy).
1005 * @param tc TaskContext.
1008 connection_fwd_timeout (void *cls,
1009 const struct GNUNET_SCHEDULER_TaskContext *tc)
1011 struct MeshConnection *c = cls;
1013 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1014 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1016 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1017 "Connection %s[%X] FWD timed out. Destroying.\n",
1018 peer2s (c->t->peer),
1021 if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
1029 * Timeout function due to lack of keepalive/traffic from the destination.
1030 * Destroys connection if called.
1032 * @param cls Closure (connection to destroy).
1033 * @param tc TaskContext
1036 connection_bck_timeout (void *cls,
1037 const struct GNUNET_SCHEDULER_TaskContext *tc)
1039 struct MeshConnection *c = cls;
1041 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1042 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1045 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1046 "Connection %s[%X] FWD timed out. Destroying.\n",
1047 peer2s (c->t->peer),
1050 if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
1058 * Resets the connection timeout task, some other message has done the
1060 * - For the first peer on the direction this means to send
1061 * a keepalive or a path confirmation message (either create or ACK).
1062 * - For all other peers, this means to destroy the connection,
1063 * due to lack of activity.
1064 * Starts the tiemout if no timeout was running (connection just created).
1066 * @param c Connection whose timeout to reset.
1067 * @param fwd Is this forward?
1069 * TODO use heap to improve efficiency of scheduler.
1072 connection_reset_timeout (struct MeshConnection *c, int fwd)
1074 GNUNET_SCHEDULER_TaskIdentifier *ti;
1075 GNUNET_SCHEDULER_Task f;
1077 ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
1079 if (GNUNET_SCHEDULER_NO_TASK != *ti)
1080 GNUNET_SCHEDULER_cancel (*ti);
1082 if (GMC_is_origin (c, fwd)) /* Endpoint */
1084 f = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
1085 *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
1089 struct GNUNET_TIME_Relative delay;
1091 delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
1092 f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
1093 *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
1102 * Method called whenever a given peer connects.
1104 * @param cls closure
1105 * @param peer peer identity this notification is about
1108 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
1110 struct MeshPeer *pi;
1111 struct MeshPeerPath *path;
1113 DEBUG_CONN ("Peer connected\n");
1114 DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id));
1115 pi = peer_get (peer);
1118 DEBUG_CONN (" (self)\n");
1119 path = path_new (1);
1123 DEBUG_CONN (" %s\n", GNUNET_i2s (peer));
1124 path = path_new (2);
1125 path->peers[1] = pi->id;
1126 GNUNET_PEER_change_rc (pi->id, 1);
1127 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
1129 path->peers[0] = myid;
1130 GNUNET_PEER_change_rc (myid, 1);
1131 peer_add_path (pi, path, GNUNET_YES);
1133 pi->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
1139 * Method called whenever a peer disconnects.
1141 * @param cls closure
1142 * @param peer peer identity this notification is about
1145 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
1147 struct MeshPeer *pi;
1149 DEBUG_CONN ("Peer disconnected\n");
1150 pi = GNUNET_CONTAINER_multipeermap_get (peers, peer);
1157 GNUNET_CONTAINER_multihashmap_iterate (pi->connections,
1160 GNUNET_CONTAINER_multihashmap_destroy (pi->connections);
1161 pi->connections = NULL;
1162 if (NULL != pi->core_transmit)
1164 GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit);
1165 pi->core_transmit = NULL;
1169 DEBUG_CONN (" (self)\n");
1171 GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
1179 * To be called on core init/fail.
1181 * @param cls Closure (config)
1182 * @param identity the public identity of this peer
1185 core_init (void *cls,
1186 const struct GNUNET_PeerIdentity *identity)
1188 const struct GNUNET_CONFIGURATION_Handle *c = cls;
1191 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
1192 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
1194 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
1195 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1197 GNUNET_i2s (identity));
1198 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1200 GNUNET_i2s (&my_full_id));
1201 GNUNET_CORE_disconnect (core_handle);
1202 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1203 NULL, /* Closure passed to MESH functions */
1204 &core_init, /* Call core_init once connected */
1205 &core_connect, /* Handle connects */
1206 &core_disconnect, /* remove peers on disconnects */
1207 NULL, /* Don't notify about all incoming messages */
1208 GNUNET_NO, /* For header only in notification */
1209 NULL, /* Don't notify about all outbound messages */
1210 GNUNET_NO, /* For header-only out notification */
1211 core_handlers); /* Register these handlers */
1224 * Core handler for connection creation.
1226 * @param cls Closure (unused).
1227 * @param peer Sender (neighbor).
1228 * @param message Message.
1230 * @return GNUNET_OK to keep the connection open,
1231 * GNUNET_SYSERR to close it (signal serious error)
1234 handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1235 const struct GNUNET_MessageHeader *message)
1237 struct GNUNET_MESH_ConnectionCreate *msg;
1238 struct GNUNET_PeerIdentity *id;
1239 struct GNUNET_HashCode *cid;
1240 struct MeshPeerPath *path;
1241 struct MeshPeer *dest_peer;
1242 struct MeshPeer *orig_peer;
1243 struct MeshConnection *c;
1244 unsigned int own_pos;
1248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1249 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1252 size = ntohs (message->size);
1253 if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1255 GNUNET_break_op (0);
1259 /* Calculate hops */
1260 size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1261 if (size % sizeof (struct GNUNET_PeerIdentity))
1263 GNUNET_break_op (0);
1266 size /= sizeof (struct GNUNET_PeerIdentity);
1269 GNUNET_break_op (0);
1272 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
1274 /* Get parameters */
1275 msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1277 id = (struct GNUNET_PeerIdentity *) &msg[1];
1278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1279 " connection %s (%s).\n",
1280 GNUNET_h2s (cid), GNUNET_i2s (id));
1282 /* Create connection */
1283 c = connection_get (cid);
1286 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
1287 c = connection_new (cid);
1290 connection_reset_timeout (c, GNUNET_YES);
1293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
1294 path = path_new (size);
1296 for (i = 0; i < size; i++)
1298 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
1299 GNUNET_i2s (&id[i]));
1300 path->peers[i] = GNUNET_PEER_intern (&id[i]);
1301 if (path->peers[i] == myid)
1304 if (own_pos == 0 && path->peers[own_pos] != myid)
1306 /* create path: self not found in path through self */
1307 GNUNET_break_op (0);
1308 path_destroy (path);
1309 connection_destroy (c);
1312 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
1313 path_add_to_peers (path, GNUNET_NO);
1314 c->path = path_duplicate (path);
1315 c->own_pos = own_pos;
1321 if (MESH_CONNECTION_NEW == c->state)
1322 connection_change_state (c, MESH_CONNECTION_SENT);
1324 /* Remember peers */
1325 dest_peer = peer_get (&id[size - 1]);
1326 orig_peer = peer_get (&id[0]);
1328 /* Is it a connection to us? */
1329 if (c->own_pos == size - 1)
1331 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
1332 peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1334 if (NULL == orig_peer->tunnel)
1336 orig_peer->tunnel = tunnel_new ();
1337 orig_peer->tunnel->peer = orig_peer;
1339 tunnel_add_connection (orig_peer->tunnel, c);
1340 if (MESH_TUNNEL_NEW == c->t->state)
1341 tunnel_change_state (c->t, MESH_TUNNEL_WAITING);
1343 send_connection_ack (c, GNUNET_NO);
1344 if (MESH_CONNECTION_SENT == c->state)
1345 connection_change_state (c, MESH_CONNECTION_ACK);
1347 /* Keep tunnel alive in direction dest->owner*/
1348 connection_reset_timeout (c, GNUNET_NO);
1352 /* It's for somebody else! Retransmit. */
1353 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
1354 peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1355 peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1356 send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
1363 * Core handler for path confirmations.
1365 * @param cls closure
1366 * @param message message
1367 * @param peer peer identity this notification is about
1369 * @return GNUNET_OK to keep the connection open,
1370 * GNUNET_SYSERR to close it (signal serious error)
1373 handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1374 const struct GNUNET_MessageHeader *message)
1376 struct GNUNET_MESH_ConnectionACK *msg;
1377 struct MeshConnection *c;
1378 struct MeshPeerPath *p;
1379 struct MeshPeer *pi;
1382 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1384 msg = (struct GNUNET_MESH_ConnectionACK *) message;
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n",
1386 GNUNET_h2s (&msg->cid));
1387 c = connection_get (&msg->cid);
1390 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1392 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n");
1397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
1399 pi = peer_get (peer);
1400 if (connection_get_next_hop (c) == pi)
1402 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
1404 if (MESH_CONNECTION_SENT == c->state)
1405 connection_change_state (c, MESH_CONNECTION_ACK);
1407 else if (connection_get_prev_hop (c) == pi)
1409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK\n");
1411 connection_change_state (c, MESH_CONNECTION_READY);
1415 GNUNET_break_op (0);
1418 connection_reset_timeout (c, fwd);
1420 /* Add path to peers? */
1424 path_add_to_peers (p, GNUNET_YES);
1431 /* Message for us as creator? */
1432 if (connection_is_origin (c, GNUNET_YES))
1434 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
1435 connection_change_state (c, MESH_CONNECTION_READY);
1436 if (MESH_TUNNEL_READY != c->t->state)
1437 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1438 send_connection_ack (c, GNUNET_YES);
1439 tunnel_send_queued_data (c->t, GNUNET_YES);
1440 if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
1442 GNUNET_DHT_get_stop (c->t->peer->dhtget);
1443 c->t->peer->dhtget = NULL;
1448 /* Message for us as destination? */
1449 if (GMC_is_terminal (c, GNUNET_YES))
1451 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
1452 if (MESH_TUNNEL_READY != c->t->state)
1453 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1454 connection_change_state (c, MESH_CONNECTION_READY);
1455 tunnel_send_queued_data (c->t, GNUNET_NO);
1459 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1460 send_prebuilt_message_connection (message, c, NULL, fwd);
1466 * Core handler for notifications of broken paths
1468 * @param cls Closure (unused).
1469 * @param peer Peer identity of sending neighbor.
1470 * @param message Message.
1472 * @return GNUNET_OK to keep the connection open,
1473 * GNUNET_SYSERR to close it (signal serious error)
1476 handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1477 const struct GNUNET_MessageHeader *message)
1479 struct GNUNET_MESH_ConnectionBroken *msg;
1480 struct MeshConnection *c;
1482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1483 "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1484 msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1485 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1486 GNUNET_i2s (&msg->peer1));
1487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1488 GNUNET_i2s (&msg->peer2));
1489 c = connection_get (&msg->cid);
1492 GNUNET_break_op (0);
1495 tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1496 GNUNET_PEER_search (&msg->peer2));
1503 * Core handler for tunnel destruction
1505 * @param cls Closure (unused).
1506 * @param peer Peer identity of sending neighbor.
1507 * @param message Message.
1509 * @return GNUNET_OK to keep the connection open,
1510 * GNUNET_SYSERR to close it (signal serious error)
1513 handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1514 const struct GNUNET_MessageHeader *message)
1516 struct GNUNET_MESH_ConnectionDestroy *msg;
1517 struct MeshConnection *c;
1521 msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1522 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1523 "Got a CONNECTION DESTROY message from %s\n",
1525 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1526 " for connection %s\n",
1527 GNUNET_h2s (&msg->cid));
1528 c = connection_get (&msg->cid);
1531 /* Probably already got the message from another path,
1532 * destroyed the tunnel and retransmitted to children.
1535 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1539 id = GNUNET_PEER_search (peer);
1540 if (id == connection_get_prev_hop (c)->id)
1542 else if (id == connection_get_next_hop (c)->id)
1546 GNUNET_break_op (0);
1549 send_prebuilt_message_connection (message, c, NULL, fwd);
1550 c->destroy = GNUNET_YES;
1556 * Generic handler for mesh network encrypted traffic.
1558 * @param peer Peer identity this notification is about.
1559 * @param message Encrypted message.
1560 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1562 * @return GNUNET_OK to keep the connection open,
1563 * GNUNET_SYSERR to close it (signal serious error)
1566 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1567 const struct GNUNET_MESH_Encrypted *msg,
1570 struct MeshConnection *c;
1571 struct MeshTunnel2 *t;
1572 struct MeshPeer *neighbor;
1573 struct MeshFlowControl *fc;
1580 size = ntohs (msg->header.size);
1582 sizeof (struct GNUNET_MESH_Encrypted) +
1583 sizeof (struct GNUNET_MessageHeader))
1585 GNUNET_break_op (0);
1588 type = ntohs (msg->header.type);
1589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
1591 GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
1593 /* Check connection */
1594 c = connection_get (&msg->cid);
1597 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
1598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
1602 fc = fwd ? &c->bck_fc : &c->fwd_fc;
1604 /* Check if origin is as expected */
1605 neighbor = connection_get_hop (c, !fwd);
1606 if (peer_get (peer)->id != neighbor->id)
1608 GNUNET_break_op (0);
1613 pid = ntohl (msg->pid);
1614 if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
1616 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
1617 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1618 "WARNING Received PID %u, (prev %u), ACK %u\n",
1619 pid, fc->last_pid_recv, fc->last_ack_sent);
1622 if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
1624 GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
1625 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1626 " Pid %u not expected (%u+), dropping!\n",
1627 pid, fc->last_pid_recv + 1);
1630 if (MESH_CONNECTION_SENT == c->state)
1631 connection_change_state (c, MESH_CONNECTION_READY);
1632 connection_reset_timeout (c, fwd);
1633 fc->last_pid_recv = pid;
1635 /* Is this message for us? */
1636 if (GMC_is_terminal (c, fwd))
1638 size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
1640 struct GNUNET_MessageHeader *msgh;
1643 /* TODO signature verification */
1644 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
1645 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
1647 fc->last_pid_recv = pid;
1648 tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
1652 msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
1653 handle_decrypted (t, msgh, fwd);
1654 off += ntohs (msgh->size);
1656 send_ack (c, NULL, fwd);
1660 /* Message not for us: forward to next hop */
1661 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1662 ttl = ntohl (msg->ttl);
1663 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
1666 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
1667 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
1668 send_ack (c, NULL, fwd);
1671 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
1673 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1680 * Core handler for mesh network traffic going orig->dest.
1682 * @param cls Closure (unused).
1683 * @param message Message received.
1684 * @param peer Peer who sent the message.
1686 * @return GNUNET_OK to keep the connection open,
1687 * GNUNET_SYSERR to close it (signal serious error)
1690 handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
1691 const struct GNUNET_MessageHeader *message)
1693 return handle_mesh_encrypted (peer,
1694 (struct GNUNET_MESH_Encrypted *)message,
1699 * Core handler for mesh network traffic going dest->orig.
1701 * @param cls Closure (unused).
1702 * @param message Message received.
1703 * @param peer Peer who sent the message.
1705 * @return GNUNET_OK to keep the connection open,
1706 * GNUNET_SYSERR to close it (signal serious error)
1709 handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
1710 const struct GNUNET_MessageHeader *message)
1712 return handle_mesh_encrypted (peer,
1713 (struct GNUNET_MESH_Encrypted *)message,
1719 * Core handler for mesh network traffic point-to-point acks.
1721 * @param cls closure
1722 * @param message message
1723 * @param peer peer identity this notification is about
1725 * @return GNUNET_OK to keep the connection open,
1726 * GNUNET_SYSERR to close it (signal serious error)
1729 handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
1730 const struct GNUNET_MessageHeader *message)
1732 struct GNUNET_MESH_ACK *msg;
1733 struct MeshConnection *c;
1734 struct MeshFlowControl *fc;
1739 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1740 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
1742 msg = (struct GNUNET_MESH_ACK *) message;
1744 c = connection_get (&msg->cid);
1748 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
1753 /* Is this a forward or backward ACK? */
1754 id = GNUNET_PEER_search (peer);
1755 if (connection_get_next_hop (c)->id == id)
1757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1761 else if (connection_get_prev_hop (c)->id == id)
1763 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1769 GNUNET_break_op (0);
1773 ack = ntohl (msg->ack);
1774 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n",
1775 ack, fc->last_ack_recv);
1776 if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
1777 fc->last_ack_recv = ack;
1779 /* Cancel polling if the ACK is big enough. */
1780 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
1781 GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1783 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
1784 GNUNET_SCHEDULER_cancel (fc->poll_task);
1785 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1786 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
1789 connection_unlock_queue (c, fwd);
1796 * Core handler for mesh network traffic point-to-point ack polls.
1798 * @param cls closure
1799 * @param message message
1800 * @param peer peer identity this notification is about
1802 * @return GNUNET_OK to keep the connection open,
1803 * GNUNET_SYSERR to close it (signal serious error)
1806 handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
1807 const struct GNUNET_MessageHeader *message)
1809 struct GNUNET_MESH_Poll *msg;
1810 struct MeshConnection *c;
1811 struct MeshFlowControl *fc;
1816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1817 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
1820 msg = (struct GNUNET_MESH_Poll *) message;
1822 c = connection_get (&msg->cid);
1826 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
1828 GNUNET_break_op (0);
1832 /* Is this a forward or backward ACK?
1833 * Note: a poll should never be needed in a loopback case,
1834 * since there is no possiblility of packet loss there, so
1835 * this way of discerining FWD/BCK should not be a problem.
1837 id = GNUNET_PEER_search (peer);
1838 if (connection_get_next_hop (c)->id == id)
1840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
1843 else if (connection_get_prev_hop (c)->id == id)
1845 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
1850 GNUNET_break_op (0);
1854 pid = ntohl (msg->pid);
1855 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n",
1856 pid, fc->last_pid_recv);
1857 fc->last_pid_recv = pid;
1858 fwd = fc == &c->fwd_fc;
1859 send_ack (c, NULL, fwd);
1866 * Core handler for mesh keepalives.
1868 * @param cls closure
1869 * @param message message
1870 * @param peer peer identity this notification is about
1871 * @return GNUNET_OK to keep the connection open,
1872 * GNUNET_SYSERR to close it (signal serious error)
1874 * TODO: Check who we got this from, to validate route.
1877 handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
1878 const struct GNUNET_MessageHeader *message)
1880 struct GNUNET_MESH_ConnectionKeepAlive *msg;
1881 struct MeshConnection *c;
1882 struct MeshPeer *neighbor;
1885 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
1886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
1889 c = connection_get (&msg->cid);
1892 GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
1897 fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
1898 GNUNET_YES : GNUNET_NO;
1900 /* Check if origin is as expected */
1901 neighbor = connection_get_hop (c, fwd);
1902 if (peer_get (peer)->id != neighbor->id)
1904 GNUNET_break_op (0);
1908 connection_change_state (c, MESH_CONNECTION_READY);
1909 connection_reset_timeout (c, fwd);
1911 if (GMC_is_terminal (c, fwd))
1914 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
1915 send_prebuilt_message_connection (message, c, NULL, fwd);
1922 * Functions to handle messages from core
1924 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
1925 {&handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
1927 {&handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
1928 sizeof (struct GNUNET_MESH_ConnectionACK)},
1929 {&handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
1930 sizeof (struct GNUNET_MESH_ConnectionBroken)},
1931 {&handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
1932 sizeof (struct GNUNET_MESH_ConnectionDestroy)},
1933 {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE,
1934 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
1935 {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE,
1936 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
1937 {&handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
1938 sizeof (struct GNUNET_MESH_ACK)},
1939 {&handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
1940 sizeof (struct GNUNET_MESH_Poll)},
1941 {&handle_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0},
1942 {&handle_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0},
1949 * Send an ACK on the appropriate connection/channel, depending on
1950 * the direction and the position of the peer.
1952 * @param c Which connection to send the hop-by-hop ACK.
1953 * @param ch Channel, if any.
1954 * @param fwd Is this a fwd ACK? (will go dest->root)
1957 send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1959 unsigned int buffer;
1961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1962 "send ack %s on %p %p\n",
1963 fwd ? "FWD" : "BCK", c, ch);
1964 if (NULL == c || GMC_is_terminal (c, fwd))
1966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n");
1967 buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
1971 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
1972 buffer = connection_get_buffer (c, fwd);
1974 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1976 if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
1977 (NULL != c && connection_is_origin (c, fwd)) )
1979 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1982 GNUNET_assert (NULL != ch);
1983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1984 send_local_ack (ch, fwd);
1989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1990 GNUNET_assert (NULL != ch);
1991 channel_send_connections_ack (ch, buffer, fwd);
1995 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
1996 connection_send_ack (c, buffer, fwd);
2001 struct MeshConnection *
2002 GMC_new (const struct GNUNET_HashCode *cid)
2004 struct MeshConnection *c;
2006 c = GNUNET_new (struct MeshConnection);
2008 GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
2009 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
2010 fc_init (&c->fwd_fc);
2011 fc_init (&c->bck_fc);
2020 GMC_destroy (struct MeshConnection *c)
2022 struct MeshPeer *peer;
2027 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s[%X]\n",
2028 peer2s (c->t->peer),
2031 /* Cancel all traffic */
2032 connection_cancel_queues (c, GNUNET_YES);
2033 connection_cancel_queues (c, GNUNET_NO);
2035 /* Cancel maintainance task (keepalive/timeout) */
2036 if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
2037 GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
2038 if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
2039 GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
2041 /* Deregister from neighbors */
2042 peer = connection_get_next_hop (c);
2043 if (NULL != peer && NULL != peer->connections)
2044 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
2045 peer = connection_get_prev_hop (c);
2046 if (NULL != peer && NULL != peer->connections)
2047 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
2050 GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
2051 GNUNET_CONTAINER_DLL_remove (c->t->connection_head, c->t->connection_tail, c);
2057 * Iterator to notify all connections of a broken link. Mark connections
2058 * to destroy after all traffic has been sent.
2060 * @param cls Closure (peer disconnected).
2061 * @param key Current key code (tid).
2062 * @param value Value in the hash map (connection).
2064 * @return GNUNET_YES if we should continue to iterate,
2068 GMC_notify_broken (void *cls,
2069 const struct GNUNET_HashCode *key,
2072 struct MeshPeer *peer = cls;
2073 struct MeshConnection *c = value;
2074 struct GNUNET_MESH_ConnectionBroken msg;
2077 fwd = peer == connection_get_prev_hop (c);
2079 connection_cancel_queues (c, !fwd);
2080 if (GMC_is_terminal (c, fwd))
2082 /* Local shutdown, no one to notify about this. */
2087 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
2088 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
2090 msg.peer1 = my_full_id;
2091 msg.peer2 = *GNUNET_PEER_resolve2 (peer->id);
2092 send_prebuilt_message_connection (&msg.header, c, NULL, fwd);
2093 c->destroy = GNUNET_YES;
2100 * Initialize the connections subsystem
2102 * @param c Configuration handle.
2105 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
2108 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
2111 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2112 "MESH", "MAX_MSGS_QUEUE", "MISSING");
2113 GNUNET_SCHEDULER_shutdown ();
2118 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
2121 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2122 "MESH", "MAX_CONNECTIONS", "MISSING");
2123 GNUNET_SCHEDULER_shutdown ();
2128 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
2129 &refresh_connection_time))
2131 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2132 "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
2133 GNUNET_SCHEDULER_shutdown ();
2136 connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
2138 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
2139 NULL, /* Closure passed to MESH functions */
2140 &core_init, /* Call core_init once connected */
2141 &core_connect, /* Handle connects */
2142 &core_disconnect, /* remove peers on disconnects */
2143 NULL, /* Don't notify about all incoming messages */
2144 GNUNET_NO, /* For header only in notification */
2145 NULL, /* Don't notify about all outbound messages */
2146 GNUNET_NO, /* For header-only out notification */
2147 core_handlers); /* Register these handlers */
2148 if (NULL == core_handle)
2151 GNUNET_SCHEDULER_shutdown ();
2157 * Shut down the connections subsystem.
2162 if (core_handle != NULL)
2164 GNUNET_CORE_disconnect (core_handle);
2171 * Is this peer the first one on the connection?
2173 * @param c Connection.
2174 * @param fwd Is this about fwd traffic?
2176 * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
2179 GMC_is_origin (struct MeshConnection *c, int fwd)
2181 if (!fwd && c->path->length - 1 == c->own_pos )
2183 if (fwd && 0 == c->own_pos)
2190 * Is this peer the last one on the connection?
2192 * @param c Connection.
2193 * @param fwd Is this about fwd traffic?
2194 * Note that the ROOT is the terminal for BCK traffic!
2196 * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
2199 GMC_is_terminal (struct MeshConnection *c, int fwd)
2201 return GMC_is_origin (c, !fwd);
2206 * Count connections in a DLL.
2209 GMC_count (const struct MeshConnection *head)
2212 struct MeshConnection *iter;
2214 for (count = 0, iter = head; NULL != iter; iter = iter->next, count++);