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;
292 * Get string description for tunnel state.
294 * @param s Tunnel state.
296 * @return String representation.
299 GMC_DEBUG_state2s (enum MeshTunnelState s)
303 case MESH_CONNECTION_NEW:
304 return "MESH_CONNECTION_NEW";
305 case MESH_CONNECTION_SENT:
306 return "MESH_CONNECTION_SENT";
307 case MESH_CONNECTION_ACK:
308 return "MESH_CONNECTION_ACK";
309 case MESH_CONNECTION_READY:
310 return "MESH_CONNECTION_READY";
312 return "MESH_CONNECTION_STATE_ERROR";
319 * Initialize a Flow Control structure to the initial state.
321 * @param fc Flow Control structure to initialize.
324 fc_init (struct MeshFlowControl *fc)
327 fc->last_pid_sent = (uint32_t) -1; /* Next (expected) = 0 */
328 fc->last_pid_recv = (uint32_t) -1;
329 fc->last_ack_sent = (uint32_t) 0;
330 fc->last_ack_recv = (uint32_t) 0;
331 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
332 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
334 fc->queue_max = (max_msgs_queue / max_connections) + 1;
341 * @param cid Connection ID.
343 static struct MeshConnection *
344 connection_get (const struct GNUNET_HashCode *cid)
346 return GNUNET_CONTAINER_multihashmap_get (connections, cid);
351 * Get first sendable message.
353 * @param peer The destination peer.
355 * @return Best current known path towards the peer, if any.
357 static struct MeshPeerQueue *
358 peer_get_first_message (const struct MeshPeer *peer)
360 struct MeshPeerQueue *q;
362 for (q = peer->queue_head; NULL != q; q = q->next)
364 if (queue_is_sendable (q))
373 queue_is_sendable (struct MeshPeerQueue *q)
375 struct MeshFlowControl *fc;
377 /* Is PID-independent? */
380 case GNUNET_MESSAGE_TYPE_MESH_ACK:
381 case GNUNET_MESSAGE_TYPE_MESH_POLL:
385 /* Is PID allowed? */
386 fc = q->fwd ? &q->c->fwd_fc : &q->c->bck_fc;
387 if (GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
396 * Free a transmission that was already queued with all resources
397 * associated to the request.
399 * @param queue Queue handler to cancel.
400 * @param clear_cls Is it necessary to free associated cls?
403 queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
405 struct MeshPeer *peer;
406 struct MeshFlowControl *fc;
411 GNUNET_assert (NULL != queue->c);
412 fc = fwd ? &queue->c->fwd_fc : &queue->c->bck_fc;
414 if (GNUNET_YES == clear_cls)
416 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " queue destroy type %s\n",
417 GNUNET_MESH_DEBUG_M2S (queue->type));
420 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
421 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
422 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
423 GNUNET_break (GNUNET_YES == queue->c->destroy);
425 case GNUNET_MESSAGE_TYPE_MESH_FWD:
426 case GNUNET_MESSAGE_TYPE_MESH_BCK:
427 case GNUNET_MESSAGE_TYPE_MESH_ACK:
428 case GNUNET_MESSAGE_TYPE_MESH_POLL:
429 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
430 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
431 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " prebuilt message\n");;
433 GNUNET_free_non_null (queue->cls);
438 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n",
439 GNUNET_MESH_DEBUG_M2S (queue->type));
443 GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
445 if (queue->type != GNUNET_MESSAGE_TYPE_MESH_ACK &&
446 queue->type != GNUNET_MESSAGE_TYPE_MESH_POLL)
448 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Q_N- %p %u\n", fc, fc->queue_n);
452 if (NULL != queue->c)
454 queue->c->pending_messages--;
455 if (NULL != queue->c->t)
457 queue->c->t->pending_messages--;
467 queue_send (void *cls, size_t size, void *buf)
469 struct MeshPeer *peer = cls;
470 struct MeshFlowControl *fc;
471 struct MeshConnection *c;
472 struct GNUNET_MessageHeader *msg;
473 struct MeshPeerQueue *queue;
474 struct MeshTunnel2 *t;
475 struct MeshChannel *ch;
476 const struct GNUNET_PeerIdentity *dst_id;
482 peer->core_transmit = NULL;
483 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send (max %u)\n", size);
485 if (NULL == buf || 0 == size)
487 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Buffer size 0.\n");
492 queue = peer_get_first_message (peer);
495 GNUNET_break (0); /* Core tmt_rdy should've been canceled */
500 fc = fwd ? &c->fwd_fc : &c->bck_fc;
502 dst_id = GNUNET_PEER_resolve2 (peer->id);
503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* towards %s\n", GNUNET_i2s (dst_id));
504 /* Check if buffer size is enough for the message */
505 if (queue->size > size)
507 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not enough room, reissue\n");
508 peer->core_transmit =
509 GNUNET_CORE_notify_transmit_ready (core_handle,
512 GNUNET_TIME_UNIT_FOREVER_REL,
519 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* size %u ok\n", queue->size);
521 t = (NULL != c) ? c->t : NULL;
527 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
528 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
529 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
530 case GNUNET_MESSAGE_TYPE_MESH_FWD:
531 case GNUNET_MESSAGE_TYPE_MESH_BCK:
532 case GNUNET_MESSAGE_TYPE_MESH_ACK:
533 case GNUNET_MESSAGE_TYPE_MESH_POLL:
534 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
536 GNUNET_MESH_DEBUG_M2S (queue->type));
537 data_size = send_core_data_raw (queue->cls, size, buf);
538 msg = (struct GNUNET_MessageHeader *) buf;
539 type = ntohs (msg->type);
541 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
542 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path create\n");
543 if (GMC_is_origin (c, GNUNET_YES))
544 data_size = send_core_connection_create (queue->c, size, buf);
546 data_size = send_core_data_raw (queue->cls, size, buf);
548 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
549 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n");
550 if (GMC_is_origin (c, GNUNET_NO) ||
551 GMC_is_origin (c, GNUNET_YES))
552 data_size = send_core_connection_ack (queue->c, size, buf);
554 data_size = send_core_data_raw (queue->cls, size, buf);
556 case GNUNET_MESSAGE_TYPE_MESH_DATA:
557 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
558 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
559 /* This should be encapsulted */
565 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "* type unknown: %u\n",
570 if (0 < drop_percent &&
571 GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
573 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
574 "Dropping message of type %s\n",
575 GNUNET_MESH_DEBUG_M2S (queue->type));
579 /* Free queue, but cls was freed by send_core_* */
581 queue_destroy (queue, GNUNET_NO);
583 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
586 case GNUNET_MESSAGE_TYPE_MESH_FWD:
587 case GNUNET_MESSAGE_TYPE_MESH_BCK:
588 pid = ntohl ( ((struct GNUNET_MESH_Encrypted *) buf)->pid );
589 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* accounting pid %u\n", pid);
590 fc->last_pid_sent = pid;
591 send_ack (c, ch, fwd);
597 /* If more data in queue, send next */
598 queue = peer_get_first_message (peer);
601 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n");
602 if (NULL == peer->core_transmit) {
603 peer->core_transmit =
604 GNUNET_CORE_notify_transmit_ready(core_handle,
607 GNUNET_TIME_UNIT_FOREVER_REL,
615 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
616 "* tmt rdy called somewhere else\n");
618 if (GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
620 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* starting poll timeout\n");
622 GNUNET_SCHEDULER_add_delayed (fc->poll_time, &connection_poll, fc);
627 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
629 GNUNET_SCHEDULER_cancel (fc->poll_task);
630 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
635 c->pending_messages--;
636 if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
638 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying connection!\n");
645 t->pending_messages--;
646 if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
648 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n");
652 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size);
659 queue_add (void *cls, uint16_t type, size_t size,
660 struct MeshConnection *c,
661 struct MeshChannel *ch,
664 struct MeshPeerQueue *queue;
665 struct MeshFlowControl *fc;
666 struct MeshPeer *peer;
670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
671 "queue add %s %s (%u) on c %p, ch %p\n",
672 fwd ? "FWD" : "BCK", GNUNET_MESH_DEBUG_M2S (type), size, c, ch);
673 GNUNET_assert (NULL != c);
675 fc = fwd ? &c->fwd_fc : &c->bck_fc;
676 peer = fwd ? connection_get_next_hop (c) : connection_get_prev_hop (c);
684 if (NULL == peer->connections)
686 /* We are not connected to this peer, ignore request. */
693 if (GNUNET_MESSAGE_TYPE_MESH_POLL == type ||
694 GNUNET_MESSAGE_TYPE_MESH_ACK == type)
699 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "fc %p\n", fc);
701 if (fc->queue_n >= fc->queue_max && 0 == priority)
703 GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
707 "queue full: %u/%u\n",
708 fc->queue_n, fc->queue_max);
709 return; /* Drop this message */
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "last pid %u\n", fc->last_pid_sent);
713 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", fc->last_ack_recv);
714 if (GMC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
716 call_core = GNUNET_NO;
717 if (GNUNET_SCHEDULER_NO_TASK == fc->poll_task &&
718 GNUNET_MESSAGE_TYPE_MESH_POLL != type)
720 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
721 "no buffer space (%u > %u): starting poll\n",
722 fc->last_pid_sent + 1, fc->last_ack_recv);
723 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
729 call_core = GNUNET_YES;
730 queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
740 struct MeshPeerQueue *copy;
741 struct MeshPeerQueue *next;
743 for (copy = peer->queue_head; NULL != copy; copy = next)
746 if (copy->type == type && copy->c == c && copy->fwd == fwd)
748 /* Example: also a FWD ACK for connection XYZ */
749 queue_destroy (copy, GNUNET_YES);
752 GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
756 GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue);
757 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n);
762 if (NULL == peer->core_transmit && GNUNET_YES == call_core)
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
765 "calling core tmt rdy towards %s for %u bytes\n",
766 peer2s (peer), size);
767 peer->core_transmit =
768 GNUNET_CORE_notify_transmit_ready (core_handle,
771 GNUNET_TIME_UNIT_FOREVER_REL,
772 GNUNET_PEER_resolve2 (peer->id),
779 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
780 "core tmt rdy towards %s already called\n",
784 c->pending_messages++;
786 c->t->pending_messages++;
793 * Sends an already built message on a connection, properly registering
794 * all used resources.
796 * @param message Message to send. Function makes a copy of it.
797 * If message is not hop-by-hop, decrements TTL of copy.
798 * @param c Connection on which this message is transmitted.
799 * @param ch Channel on which this message is transmitted, or NULL.
800 * @param fwd Is this a fwd message?
803 send_prebuilt_message_connection (const struct GNUNET_MessageHeader *message,
804 struct MeshConnection *c,
805 struct MeshChannel *ch,
812 size = ntohs (message->size);
813 data = GNUNET_malloc (size);
814 memcpy (data, message, size);
815 type = ntohs (message->type);
816 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send %s (%u) on connection %s\n",
817 GNUNET_MESH_DEBUG_M2S (type), size, GNUNET_h2s (&c->id));
821 struct GNUNET_MESH_Encrypted *emsg;
822 struct GNUNET_MESH_ACK *amsg;
823 struct GNUNET_MESH_Poll *pmsg;
824 struct GNUNET_MESH_ConnectionDestroy *dmsg;
825 struct GNUNET_MESH_ConnectionBroken *bmsg;
828 case GNUNET_MESSAGE_TYPE_MESH_FWD:
829 case GNUNET_MESSAGE_TYPE_MESH_BCK:
830 emsg = (struct GNUNET_MESH_Encrypted *) data;
831 ttl = ntohl (emsg->ttl);
838 emsg->ttl = htonl (ttl - 1);
839 emsg->pid = htonl (fwd ? c->fwd_fc.next_pid++ : c->bck_fc.next_pid++);
840 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " pid %u\n", ntohl (emsg->pid));
843 case GNUNET_MESSAGE_TYPE_MESH_ACK:
844 amsg = (struct GNUNET_MESH_ACK *) data;
846 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", ntohl (amsg->ack));
849 case GNUNET_MESSAGE_TYPE_MESH_POLL:
850 pmsg = (struct GNUNET_MESH_Poll *) data;
852 pmsg->pid = htonl (fwd ? c->fwd_fc.last_pid_sent : c->bck_fc.last_pid_sent);
853 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " poll %u\n", ntohl (pmsg->pid));
856 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
857 dmsg = (struct GNUNET_MESH_ConnectionDestroy *) data;
862 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
863 bmsg = (struct GNUNET_MESH_ConnectionBroken *) data;
868 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
869 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
887 struct MeshConnection *
888 GMC_new (const struct GNUNET_HashCode *cid)
890 struct MeshConnection *c;
892 c = GNUNET_new (struct MeshConnection);
894 GNUNET_CONTAINER_multihashmap_put (connections, &c->id, c,
895 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
896 fc_init (&c->fwd_fc);
897 fc_init (&c->bck_fc);
906 GMC_destroy (struct MeshConnection *c)
908 struct MeshPeer *peer;
913 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying connection %s[%X]\n",
917 /* Cancel all traffic */
918 connection_cancel_queues (c, GNUNET_YES);
919 connection_cancel_queues (c, GNUNET_NO);
921 /* Cancel maintainance task (keepalive/timeout) */
922 if (GNUNET_SCHEDULER_NO_TASK != c->fwd_maintenance_task)
923 GNUNET_SCHEDULER_cancel (c->fwd_maintenance_task);
924 if (GNUNET_SCHEDULER_NO_TASK != c->bck_maintenance_task)
925 GNUNET_SCHEDULER_cancel (c->bck_maintenance_task);
927 /* Deregister from neighbors */
928 peer = connection_get_next_hop (c);
929 if (NULL != peer && NULL != peer->connections)
930 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
931 peer = connection_get_prev_hop (c);
932 if (NULL != peer && NULL != peer->connections)
933 GNUNET_CONTAINER_multihashmap_remove (peer->connections, &c->id, c);
936 GNUNET_STATISTICS_update (stats, "# connections", -1, GNUNET_NO);
937 GNUNET_CONTAINER_DLL_remove (c->t->connection_head, c->t->connection_tail, c);
944 * Send an ACK informing the predecessor about the available buffer space.
946 * Note that for fwd ack, the FWD mean forward *traffic* (root->dest),
947 * the ACK itself goes "back" (dest->root).
949 * @param c Connection on which to send the ACK.
950 * @param buffer How much space free to advertise?
951 * @param fwd Is this FWD ACK? (Going dest->owner)
954 connection_send_ack (struct MeshConnection *c, unsigned int buffer, int fwd)
956 struct MeshFlowControl *next_fc;
957 struct MeshFlowControl *prev_fc;
958 struct GNUNET_MESH_ACK msg;
962 next_fc = fwd ? &c->fwd_fc : &c->bck_fc;
963 prev_fc = fwd ? &c->bck_fc : &c->fwd_fc;
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
966 "connection send %s ack on %s\n",
967 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
969 /* Check if we need to transmit the ACK */
970 if (prev_fc->last_ack_sent - prev_fc->last_pid_recv > 3)
972 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending ACK, buffer > 3\n");
973 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
974 " last pid recv: %u, last ack sent: %u\n",
975 prev_fc->last_pid_recv, prev_fc->last_ack_sent);
979 /* Ok, ACK might be necessary, what PID to ACK? */
980 delta = next_fc->queue_max - next_fc->queue_n;
981 ack = prev_fc->last_pid_recv + delta;
982 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u\n", ack);
983 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
984 " last pid %u, last ack %u, qmax %u, q %u\n",
985 prev_fc->last_pid_recv, prev_fc->last_ack_sent,
986 next_fc->queue_max, next_fc->queue_n);
987 if (ack == prev_fc->last_ack_sent)
989 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Not sending FWD ACK, not needed\n");
993 prev_fc->last_ack_sent = ack;
995 /* Build ACK message and send on connection */
996 msg.header.size = htons (sizeof (msg));
997 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_ACK);
998 msg.ack = htonl (ack);
1001 send_prebuilt_message_connection (&msg.header, c, NULL, !fwd);
1006 connection_change_state (struct MeshConnection* c,
1007 enum MeshConnectionState state)
1009 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1010 "Connection %s state was %s\n",
1011 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (c->state));
1012 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1013 "Connection %s state is now %s\n",
1014 GNUNET_h2s (&c->id), GNUNET_MESH_DEBUG_CS2S (state));
1021 * Send keepalive packets for a connection.
1023 * @param c Connection to keep alive..
1024 * @param fwd Is this a FWD keepalive? (owner -> dest).
1027 connection_keepalive (struct MeshConnection *c, int fwd)
1029 struct GNUNET_MESH_ConnectionKeepAlive *msg;
1030 size_t size = sizeof (struct GNUNET_MESH_ConnectionKeepAlive);
1034 type = fwd ? GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE :
1035 GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE;
1037 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1038 "sending %s keepalive for connection %s[%d]\n",
1039 fwd ? "FWD" : "BCK",
1040 peer2s (c->t->peer),
1043 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) cbuf;
1044 msg->header.size = htons (size);
1045 msg->header.type = htons (type);
1048 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
1053 * Send CONNECTION_{CREATE/ACK} packets for a connection.
1055 * @param c Connection for which to send the message.
1056 * @param fwd If GNUNET_YES, send CREATE, otherwise send ACK.
1059 connection_recreate (struct MeshConnection *c, int fwd)
1061 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "sending connection recreate\n");
1063 send_connection_create (c);
1065 send_connection_ack (c, GNUNET_NO);
1070 * Generic connection timer management.
1071 * Depending on the role of the peer in the connection will send the
1072 * appropriate message (build or keepalive)
1074 * @param c Conncetion to maintain.
1075 * @param fwd Is FWD?
1078 connection_maintain (struct MeshConnection *c, int fwd)
1080 if (MESH_TUNNEL_SEARCHING == c->t->state)
1082 /* TODO DHT GET with RO_BART */
1087 case MESH_CONNECTION_NEW:
1089 case MESH_CONNECTION_SENT:
1090 connection_recreate (c, fwd);
1092 case MESH_CONNECTION_READY:
1093 connection_keepalive (c, fwd);
1102 connection_fwd_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1104 struct MeshConnection *c = cls;
1106 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1107 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1110 connection_maintain (c, GNUNET_YES);
1111 c->fwd_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1112 &connection_fwd_keepalive,
1118 connection_bck_keepalive (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1120 struct MeshConnection *c = cls;
1122 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1123 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1126 connection_maintain (c, GNUNET_NO);
1127 c->bck_maintenance_task = GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1128 &connection_bck_keepalive,
1134 * Send a message to all peers in this connection that the connection
1135 * is no longer valid.
1137 * If some peer should not receive the message, it should be zero'ed out
1138 * before calling this function.
1140 * @param c The connection whose peers to notify.
1143 connection_send_destroy (struct MeshConnection *c)
1145 struct GNUNET_MESH_ConnectionDestroy msg;
1147 msg.header.size = htons (sizeof (msg));
1148 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY);;
1150 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1151 " sending connection destroy for connection %s[%X]\n",
1152 peer2s (c->t->peer),
1155 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_YES))
1156 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_YES);
1157 if (GNUNET_NO == GMC_is_terminal (c, GNUNET_NO))
1158 send_prebuilt_message_connection (&msg.header, c, NULL, GNUNET_NO);
1159 c->destroy = GNUNET_YES;
1164 * Get free buffer space in a connection.
1166 * @param c Connection.
1167 * @param fwd Is query about FWD traffic?
1169 * @return Free buffer space [0 - max_msgs_queue/max_connections]
1172 connection_get_buffer (struct MeshConnection *c, int fwd)
1174 struct MeshFlowControl *fc;
1176 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1178 return (fc->queue_max - fc->queue_n);
1183 * Get the first transmittable message for a connection.
1185 * @param c Connection.
1186 * @param fwd Is this FWD?
1188 * @return First transmittable message.
1190 static struct MeshPeerQueue *
1191 connection_get_first_message (struct MeshConnection *c, int fwd)
1193 struct MeshPeerQueue *q;
1196 p = connection_get_hop (c, fwd);
1198 for (q = p->queue_head; NULL != q; q = q->next)
1202 if (queue_is_sendable (q))
1211 * @brief Re-initiate traffic on this connection if necessary.
1213 * Check if there is traffic queued towards this peer
1214 * and the core transmit handle is NULL (traffic was stalled).
1215 * If so, call core tmt rdy.
1217 * @param c Connection on which initiate traffic.
1218 * @param fwd Is this about fwd traffic?
1221 connection_unlock_queue (struct MeshConnection *c, int fwd)
1223 struct MeshPeer *peer;
1224 struct MeshPeerQueue *q;
1227 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1228 "connection_unlock_queue %s on %s\n",
1229 fwd ? "FWD" : "BCK", GNUNET_h2s (&c->id));
1231 if (GMC_is_terminal (c, fwd))
1233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " is terminal!\n");
1237 peer = connection_get_hop (c, fwd);
1239 if (NULL != peer->core_transmit)
1241 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " already unlocked!\n");
1242 return; /* Already unlocked */
1245 q = connection_get_first_message (c, fwd);
1248 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " queue empty!\n");
1249 return; /* Nothing to transmit */
1253 peer->core_transmit =
1254 GNUNET_CORE_notify_transmit_ready (core_handle,
1257 GNUNET_TIME_UNIT_FOREVER_REL,
1258 GNUNET_PEER_resolve2 (peer->id),
1266 * Cancel all transmissions that belong to a certain connection.
1268 * @param c Connection which to cancel.
1269 * @param fwd Cancel fwd traffic?
1272 connection_cancel_queues (struct MeshConnection *c, int fwd)
1274 struct MeshPeerQueue *q;
1275 struct MeshPeerQueue *next;
1276 struct MeshFlowControl *fc;
1277 struct MeshPeer *peer;
1284 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1285 peer = connection_get_hop (c, fwd);
1287 for (q = peer->queue_head; NULL != q; q = next)
1292 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1293 "connection_cancel_queue %s\n",
1294 GNUNET_MESH_DEBUG_M2S (q->type));
1295 queue_destroy (q, GNUNET_YES);
1298 if (NULL == peer->queue_head)
1300 if (NULL != peer->core_transmit)
1302 GNUNET_CORE_notify_transmit_ready_cancel (peer->core_transmit);
1303 peer->core_transmit = NULL;
1305 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
1307 GNUNET_SCHEDULER_cancel (fc->poll_task);
1308 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1317 * Function called if a connection has been stalled for a while,
1318 * possibly due to a missed ACK. Poll the neighbor about its ACK status.
1320 * @param cls Closure (poll ctx).
1321 * @param tc TaskContext.
1324 connection_poll (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1326 struct MeshFlowControl *fc = cls;
1327 struct GNUNET_MESH_Poll msg;
1328 struct MeshConnection *c;
1330 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1331 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1337 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** Polling!\n");
1338 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** connection [%X]\n",
1339 GNUNET_h2s (&c->id));
1340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** %s\n",
1341 fc == &c->fwd_fc ? "FWD" : "BCK");
1343 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_POLL);
1344 msg.header.size = htons (sizeof (msg));
1345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " *** pid (%u)!\n", fc->last_pid_sent);
1346 send_prebuilt_message_connection (&msg.header, c, NULL, fc == &c->fwd_fc);
1347 fc->poll_time = GNUNET_TIME_STD_BACKOFF (fc->poll_time);
1348 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
1349 &connection_poll, fc);
1356 * Get the previous hop in a connection
1358 * @param c Connection.
1360 * @return Previous peer in the connection.
1362 static struct MeshPeer *
1363 connection_get_prev_hop (struct MeshConnection *c)
1367 if (0 == c->own_pos || c->path->length < 2)
1368 id = c->path->peers[0];
1370 id = c->path->peers[c->own_pos - 1];
1372 return peer_get_short (id);
1377 * Get the next hop in a connection
1379 * @param c Connection.
1381 * @return Next peer in the connection.
1383 static struct MeshPeer *
1384 connection_get_next_hop (struct MeshConnection *c)
1388 if ((c->path->length - 1) == c->own_pos || c->path->length < 2)
1389 id = c->path->peers[c->path->length - 1];
1391 id = c->path->peers[c->own_pos + 1];
1393 return peer_get_short (id);
1398 * Get the hop in a connection.
1400 * @param c Connection.
1401 * @param fwd Next hop?
1403 * @return Next peer in the connection.
1405 static struct MeshPeer *
1406 connection_get_hop (struct MeshConnection *c, int fwd)
1409 return connection_get_next_hop (c);
1410 return connection_get_prev_hop (c);
1417 * Timeout function due to lack of keepalive/traffic from the owner.
1418 * Destroys connection if called.
1420 * @param cls Closure (connection to destroy).
1421 * @param tc TaskContext.
1424 connection_fwd_timeout (void *cls,
1425 const struct GNUNET_SCHEDULER_TaskContext *tc)
1427 struct MeshConnection *c = cls;
1429 c->fwd_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1430 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1432 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1433 "Connection %s[%X] FWD timed out. Destroying.\n",
1434 peer2s (c->t->peer),
1437 if (GMC_is_origin (c, GNUNET_YES)) /* If local, leave. */
1445 * Timeout function due to lack of keepalive/traffic from the destination.
1446 * Destroys connection if called.
1448 * @param cls Closure (connection to destroy).
1449 * @param tc TaskContext
1452 connection_bck_timeout (void *cls,
1453 const struct GNUNET_SCHEDULER_TaskContext *tc)
1455 struct MeshConnection *c = cls;
1457 c->bck_maintenance_task = GNUNET_SCHEDULER_NO_TASK;
1458 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
1461 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1462 "Connection %s[%X] FWD timed out. Destroying.\n",
1463 peer2s (c->t->peer),
1466 if (GMC_is_origin (c, GNUNET_NO)) /* If local, leave. */
1474 * Resets the connection timeout task, some other message has done the
1476 * - For the first peer on the direction this means to send
1477 * a keepalive or a path confirmation message (either create or ACK).
1478 * - For all other peers, this means to destroy the connection,
1479 * due to lack of activity.
1480 * Starts the tiemout if no timeout was running (connection just created).
1482 * @param c Connection whose timeout to reset.
1483 * @param fwd Is this forward?
1485 * TODO use heap to improve efficiency of scheduler.
1488 connection_reset_timeout (struct MeshConnection *c, int fwd)
1490 GNUNET_SCHEDULER_TaskIdentifier *ti;
1491 GNUNET_SCHEDULER_Task f;
1493 ti = fwd ? &c->fwd_maintenance_task : &c->bck_maintenance_task;
1495 if (GNUNET_SCHEDULER_NO_TASK != *ti)
1496 GNUNET_SCHEDULER_cancel (*ti);
1498 if (GMC_is_origin (c, fwd)) /* Endpoint */
1500 f = fwd ? &connection_fwd_keepalive : &connection_bck_keepalive;
1501 *ti = GNUNET_SCHEDULER_add_delayed (refresh_connection_time, f, c);
1505 struct GNUNET_TIME_Relative delay;
1507 delay = GNUNET_TIME_relative_multiply (refresh_connection_time, 4);
1508 f = fwd ? &connection_fwd_timeout : &connection_bck_timeout;
1509 *ti = GNUNET_SCHEDULER_add_delayed (delay, f, c);
1518 * Method called whenever a given peer connects.
1520 * @param cls closure
1521 * @param peer peer identity this notification is about
1524 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
1526 struct MeshPeer *pi;
1527 struct MeshPeerPath *path;
1529 DEBUG_CONN ("Peer connected\n");
1530 DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id));
1531 pi = peer_get (peer);
1534 DEBUG_CONN (" (self)\n");
1535 path = path_new (1);
1539 DEBUG_CONN (" %s\n", GNUNET_i2s (peer));
1540 path = path_new (2);
1541 path->peers[1] = pi->id;
1542 GNUNET_PEER_change_rc (pi->id, 1);
1543 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
1545 path->peers[0] = myid;
1546 GNUNET_PEER_change_rc (myid, 1);
1547 peer_add_path (pi, path, GNUNET_YES);
1549 pi->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
1555 * Method called whenever a peer disconnects.
1557 * @param cls closure
1558 * @param peer peer identity this notification is about
1561 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
1563 struct MeshPeer *pi;
1565 DEBUG_CONN ("Peer disconnected\n");
1566 pi = GNUNET_CONTAINER_multipeermap_get (peers, peer);
1573 GNUNET_CONTAINER_multihashmap_iterate (pi->connections,
1576 GNUNET_CONTAINER_multihashmap_destroy (pi->connections);
1577 pi->connections = NULL;
1578 if (NULL != pi->core_transmit)
1580 GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit);
1581 pi->core_transmit = NULL;
1585 DEBUG_CONN (" (self)\n");
1587 GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
1595 * To be called on core init/fail.
1597 * @param cls Closure (config)
1598 * @param identity the public identity of this peer
1601 core_init (void *cls,
1602 const struct GNUNET_PeerIdentity *identity)
1604 const struct GNUNET_CONFIGURATION_Handle *c = cls;
1607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
1608 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
1610 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
1611 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1613 GNUNET_i2s (identity));
1614 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1616 GNUNET_i2s (&my_full_id));
1617 GNUNET_CORE_disconnect (core_handle);
1618 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1619 NULL, /* Closure passed to MESH functions */
1620 &core_init, /* Call core_init once connected */
1621 &core_connect, /* Handle connects */
1622 &core_disconnect, /* remove peers on disconnects */
1623 NULL, /* Don't notify about all incoming messages */
1624 GNUNET_NO, /* For header only in notification */
1625 NULL, /* Don't notify about all outbound messages */
1626 GNUNET_NO, /* For header-only out notification */
1627 core_handlers); /* Register these handlers */
1640 * Core handler for connection creation.
1642 * @param cls Closure (unused).
1643 * @param peer Sender (neighbor).
1644 * @param message Message.
1646 * @return GNUNET_OK to keep the connection open,
1647 * GNUNET_SYSERR to close it (signal serious error)
1650 handle_create (void *cls, const struct GNUNET_PeerIdentity *peer,
1651 const struct GNUNET_MessageHeader *message)
1653 struct GNUNET_MESH_ConnectionCreate *msg;
1654 struct GNUNET_PeerIdentity *id;
1655 struct GNUNET_HashCode *cid;
1656 struct MeshPeerPath *path;
1657 struct MeshPeer *dest_peer;
1658 struct MeshPeer *orig_peer;
1659 struct MeshConnection *c;
1660 unsigned int own_pos;
1664 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1665 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
1668 size = ntohs (message->size);
1669 if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
1671 GNUNET_break_op (0);
1675 /* Calculate hops */
1676 size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
1677 if (size % sizeof (struct GNUNET_PeerIdentity))
1679 GNUNET_break_op (0);
1682 size /= sizeof (struct GNUNET_PeerIdentity);
1685 GNUNET_break_op (0);
1688 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
1690 /* Get parameters */
1691 msg = (struct GNUNET_MESH_ConnectionCreate *) message;
1693 id = (struct GNUNET_PeerIdentity *) &msg[1];
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695 " connection %s (%s).\n",
1696 GNUNET_h2s (cid), GNUNET_i2s (id));
1698 /* Create connection */
1699 c = connection_get (cid);
1702 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
1703 c = connection_new (cid);
1706 connection_reset_timeout (c, GNUNET_YES);
1709 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
1710 path = path_new (size);
1712 for (i = 0; i < size; i++)
1714 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
1715 GNUNET_i2s (&id[i]));
1716 path->peers[i] = GNUNET_PEER_intern (&id[i]);
1717 if (path->peers[i] == myid)
1720 if (own_pos == 0 && path->peers[own_pos] != myid)
1722 /* create path: self not found in path through self */
1723 GNUNET_break_op (0);
1724 path_destroy (path);
1725 connection_destroy (c);
1728 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
1729 path_add_to_peers (path, GNUNET_NO);
1730 c->path = path_duplicate (path);
1731 c->own_pos = own_pos;
1737 if (MESH_CONNECTION_NEW == c->state)
1738 connection_change_state (c, MESH_CONNECTION_SENT);
1740 /* Remember peers */
1741 dest_peer = peer_get (&id[size - 1]);
1742 orig_peer = peer_get (&id[0]);
1744 /* Is it a connection to us? */
1745 if (c->own_pos == size - 1)
1747 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
1748 peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
1750 if (NULL == orig_peer->tunnel)
1752 orig_peer->tunnel = tunnel_new ();
1753 orig_peer->tunnel->peer = orig_peer;
1755 tunnel_add_connection (orig_peer->tunnel, c);
1756 if (MESH_TUNNEL_NEW == c->t->state)
1757 tunnel_change_state (c->t, MESH_TUNNEL_WAITING);
1759 send_connection_ack (c, GNUNET_NO);
1760 if (MESH_CONNECTION_SENT == c->state)
1761 connection_change_state (c, MESH_CONNECTION_ACK);
1763 /* Keep tunnel alive in direction dest->owner*/
1764 connection_reset_timeout (c, GNUNET_NO);
1768 /* It's for somebody else! Retransmit. */
1769 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
1770 peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
1771 peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
1772 send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
1779 * Core handler for path confirmations.
1781 * @param cls closure
1782 * @param message message
1783 * @param peer peer identity this notification is about
1785 * @return GNUNET_OK to keep the connection open,
1786 * GNUNET_SYSERR to close it (signal serious error)
1789 handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer,
1790 const struct GNUNET_MessageHeader *message)
1792 struct GNUNET_MESH_ConnectionACK *msg;
1793 struct MeshConnection *c;
1794 struct MeshPeerPath *p;
1795 struct MeshPeer *pi;
1798 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
1799 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
1800 msg = (struct GNUNET_MESH_ConnectionACK *) message;
1801 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n",
1802 GNUNET_h2s (&msg->cid));
1803 c = connection_get (&msg->cid);
1806 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
1808 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n");
1813 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
1815 pi = peer_get (peer);
1816 if (connection_get_next_hop (c) == pi)
1818 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
1820 if (MESH_CONNECTION_SENT == c->state)
1821 connection_change_state (c, MESH_CONNECTION_ACK);
1823 else if (connection_get_prev_hop (c) == pi)
1825 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK\n");
1827 connection_change_state (c, MESH_CONNECTION_READY);
1831 GNUNET_break_op (0);
1834 connection_reset_timeout (c, fwd);
1836 /* Add path to peers? */
1840 path_add_to_peers (p, GNUNET_YES);
1847 /* Message for us as creator? */
1848 if (connection_is_origin (c, GNUNET_YES))
1850 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
1851 connection_change_state (c, MESH_CONNECTION_READY);
1852 if (MESH_TUNNEL_READY != c->t->state)
1853 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1854 send_connection_ack (c, GNUNET_YES);
1855 tunnel_send_queued_data (c->t, GNUNET_YES);
1856 if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
1858 GNUNET_DHT_get_stop (c->t->peer->dhtget);
1859 c->t->peer->dhtget = NULL;
1864 /* Message for us as destination? */
1865 if (GMC_is_terminal (c, GNUNET_YES))
1867 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
1868 if (MESH_TUNNEL_READY != c->t->state)
1869 tunnel_change_state (c->t, MESH_TUNNEL_READY);
1870 connection_change_state (c, MESH_CONNECTION_READY);
1871 tunnel_send_queued_data (c->t, GNUNET_NO);
1875 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
1876 send_prebuilt_message_connection (message, c, NULL, fwd);
1882 * Core handler for notifications of broken paths
1884 * @param cls Closure (unused).
1885 * @param peer Peer identity of sending neighbor.
1886 * @param message Message.
1888 * @return GNUNET_OK to keep the connection open,
1889 * GNUNET_SYSERR to close it (signal serious error)
1892 handle_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
1893 const struct GNUNET_MessageHeader *message)
1895 struct GNUNET_MESH_ConnectionBroken *msg;
1896 struct MeshConnection *c;
1898 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1899 "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
1900 msg = (struct GNUNET_MESH_ConnectionBroken *) message;
1901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1902 GNUNET_i2s (&msg->peer1));
1903 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
1904 GNUNET_i2s (&msg->peer2));
1905 c = connection_get (&msg->cid);
1908 GNUNET_break_op (0);
1911 tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
1912 GNUNET_PEER_search (&msg->peer2));
1919 * Core handler for tunnel destruction
1921 * @param cls Closure (unused).
1922 * @param peer Peer identity of sending neighbor.
1923 * @param message Message.
1925 * @return GNUNET_OK to keep the connection open,
1926 * GNUNET_SYSERR to close it (signal serious error)
1929 handle_destroy (void *cls, const struct GNUNET_PeerIdentity *peer,
1930 const struct GNUNET_MessageHeader *message)
1932 struct GNUNET_MESH_ConnectionDestroy *msg;
1933 struct MeshConnection *c;
1937 msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
1938 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1939 "Got a CONNECTION DESTROY message from %s\n",
1941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1942 " for connection %s\n",
1943 GNUNET_h2s (&msg->cid));
1944 c = connection_get (&msg->cid);
1947 /* Probably already got the message from another path,
1948 * destroyed the tunnel and retransmitted to children.
1951 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
1955 id = GNUNET_PEER_search (peer);
1956 if (id == connection_get_prev_hop (c)->id)
1958 else if (id == connection_get_next_hop (c)->id)
1962 GNUNET_break_op (0);
1965 send_prebuilt_message_connection (message, c, NULL, fwd);
1966 c->destroy = GNUNET_YES;
1972 * Generic handler for mesh network encrypted traffic.
1974 * @param peer Peer identity this notification is about.
1975 * @param message Encrypted message.
1976 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
1978 * @return GNUNET_OK to keep the connection open,
1979 * GNUNET_SYSERR to close it (signal serious error)
1982 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
1983 const struct GNUNET_MESH_Encrypted *msg,
1986 struct MeshConnection *c;
1987 struct MeshTunnel2 *t;
1988 struct MeshPeer *neighbor;
1989 struct MeshFlowControl *fc;
1996 size = ntohs (msg->header.size);
1998 sizeof (struct GNUNET_MESH_Encrypted) +
1999 sizeof (struct GNUNET_MessageHeader))
2001 GNUNET_break_op (0);
2004 type = ntohs (msg->header.type);
2005 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
2006 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
2007 GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
2009 /* Check connection */
2010 c = connection_get (&msg->cid);
2013 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
2014 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
2018 fc = fwd ? &c->bck_fc : &c->fwd_fc;
2020 /* Check if origin is as expected */
2021 neighbor = connection_get_hop (c, !fwd);
2022 if (peer_get (peer)->id != neighbor->id)
2024 GNUNET_break_op (0);
2029 pid = ntohl (msg->pid);
2030 if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
2032 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
2033 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2034 "WARNING Received PID %u, (prev %u), ACK %u\n",
2035 pid, fc->last_pid_recv, fc->last_ack_sent);
2038 if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
2040 GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
2041 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2042 " Pid %u not expected (%u+), dropping!\n",
2043 pid, fc->last_pid_recv + 1);
2046 if (MESH_CONNECTION_SENT == c->state)
2047 connection_change_state (c, MESH_CONNECTION_READY);
2048 connection_reset_timeout (c, fwd);
2049 fc->last_pid_recv = pid;
2051 /* Is this message for us? */
2052 if (GMC_is_terminal (c, fwd))
2054 size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
2056 struct GNUNET_MessageHeader *msgh;
2059 /* TODO signature verification */
2060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
2061 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
2063 fc->last_pid_recv = pid;
2064 tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
2068 msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
2069 handle_decrypted (t, msgh, fwd);
2070 off += ntohs (msgh->size);
2072 send_ack (c, NULL, fwd);
2076 /* Message not for us: forward to next hop */
2077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2078 ttl = ntohl (msg->ttl);
2079 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
2082 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
2083 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
2084 send_ack (c, NULL, fwd);
2087 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
2089 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
2096 * Core handler for mesh network traffic going orig->dest.
2098 * @param cls Closure (unused).
2099 * @param message Message received.
2100 * @param peer Peer who sent the message.
2102 * @return GNUNET_OK to keep the connection open,
2103 * GNUNET_SYSERR to close it (signal serious error)
2106 handle_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
2107 const struct GNUNET_MessageHeader *message)
2109 return handle_mesh_encrypted (peer,
2110 (struct GNUNET_MESH_Encrypted *)message,
2115 * Core handler for mesh network traffic going dest->orig.
2117 * @param cls Closure (unused).
2118 * @param message Message received.
2119 * @param peer Peer who sent the message.
2121 * @return GNUNET_OK to keep the connection open,
2122 * GNUNET_SYSERR to close it (signal serious error)
2125 handle_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
2126 const struct GNUNET_MessageHeader *message)
2128 return handle_mesh_encrypted (peer,
2129 (struct GNUNET_MESH_Encrypted *)message,
2135 * Core handler for mesh network traffic point-to-point acks.
2137 * @param cls closure
2138 * @param message message
2139 * @param peer peer identity this notification is about
2141 * @return GNUNET_OK to keep the connection open,
2142 * GNUNET_SYSERR to close it (signal serious error)
2145 handle_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
2146 const struct GNUNET_MessageHeader *message)
2148 struct GNUNET_MESH_ACK *msg;
2149 struct MeshConnection *c;
2150 struct MeshFlowControl *fc;
2155 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
2156 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
2158 msg = (struct GNUNET_MESH_ACK *) message;
2160 c = connection_get (&msg->cid);
2164 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
2169 /* Is this a forward or backward ACK? */
2170 id = GNUNET_PEER_search (peer);
2171 if (connection_get_next_hop (c)->id == id)
2173 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
2177 else if (connection_get_prev_hop (c)->id == id)
2179 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
2185 GNUNET_break_op (0);
2189 ack = ntohl (msg->ack);
2190 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n",
2191 ack, fc->last_ack_recv);
2192 if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
2193 fc->last_ack_recv = ack;
2195 /* Cancel polling if the ACK is big enough. */
2196 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
2197 GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
2199 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
2200 GNUNET_SCHEDULER_cancel (fc->poll_task);
2201 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
2202 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
2205 connection_unlock_queue (c, fwd);
2212 * Core handler for mesh network traffic point-to-point ack polls.
2214 * @param cls closure
2215 * @param message message
2216 * @param peer peer identity this notification is about
2218 * @return GNUNET_OK to keep the connection open,
2219 * GNUNET_SYSERR to close it (signal serious error)
2222 handle_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
2223 const struct GNUNET_MessageHeader *message)
2225 struct GNUNET_MESH_Poll *msg;
2226 struct MeshConnection *c;
2227 struct MeshFlowControl *fc;
2232 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
2233 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
2236 msg = (struct GNUNET_MESH_Poll *) message;
2238 c = connection_get (&msg->cid);
2242 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
2244 GNUNET_break_op (0);
2248 /* Is this a forward or backward ACK?
2249 * Note: a poll should never be needed in a loopback case,
2250 * since there is no possiblility of packet loss there, so
2251 * this way of discerining FWD/BCK should not be a problem.
2253 id = GNUNET_PEER_search (peer);
2254 if (connection_get_next_hop (c)->id == id)
2256 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
2259 else if (connection_get_prev_hop (c)->id == id)
2261 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
2266 GNUNET_break_op (0);
2270 pid = ntohl (msg->pid);
2271 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n",
2272 pid, fc->last_pid_recv);
2273 fc->last_pid_recv = pid;
2274 fwd = fc == &c->fwd_fc;
2275 send_ack (c, NULL, fwd);
2282 * Core handler for mesh keepalives.
2284 * @param cls closure
2285 * @param message message
2286 * @param peer peer identity this notification is about
2287 * @return GNUNET_OK to keep the connection open,
2288 * GNUNET_SYSERR to close it (signal serious error)
2290 * TODO: Check who we got this from, to validate route.
2293 handle_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
2294 const struct GNUNET_MessageHeader *message)
2296 struct GNUNET_MESH_ConnectionKeepAlive *msg;
2297 struct MeshConnection *c;
2298 struct MeshPeer *neighbor;
2301 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
2302 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
2305 c = connection_get (&msg->cid);
2308 GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
2313 fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
2314 GNUNET_YES : GNUNET_NO;
2316 /* Check if origin is as expected */
2317 neighbor = connection_get_hop (c, fwd);
2318 if (peer_get (peer)->id != neighbor->id)
2320 GNUNET_break_op (0);
2324 connection_change_state (c, MESH_CONNECTION_READY);
2325 connection_reset_timeout (c, fwd);
2327 if (GMC_is_terminal (c, fwd))
2330 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
2331 send_prebuilt_message_connection (message, c, NULL, fwd);
2338 * Functions to handle messages from core
2340 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
2341 {&handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
2343 {&handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
2344 sizeof (struct GNUNET_MESH_ConnectionACK)},
2345 {&handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
2346 sizeof (struct GNUNET_MESH_ConnectionBroken)},
2347 {&handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
2348 sizeof (struct GNUNET_MESH_ConnectionDestroy)},
2349 {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE,
2350 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
2351 {&handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE,
2352 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
2353 {&handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
2354 sizeof (struct GNUNET_MESH_ACK)},
2355 {&handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
2356 sizeof (struct GNUNET_MESH_Poll)},
2357 {&handle_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0},
2358 {&handle_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0},
2365 * Iterator to notify all connections of a broken link. Mark connections
2366 * to destroy after all traffic has been sent.
2368 * @param cls Closure (peer disconnected).
2369 * @param key Current key code (tid).
2370 * @param value Value in the hash map (connection).
2372 * @return GNUNET_YES if we should continue to iterate,
2376 GMC_notify_broken (void *cls,
2377 const struct GNUNET_HashCode *key,
2380 struct MeshPeer *peer = cls;
2381 struct MeshConnection *c = value;
2382 struct GNUNET_MESH_ConnectionBroken msg;
2385 fwd = peer == connection_get_prev_hop (c);
2387 connection_cancel_queues (c, !fwd);
2388 if (GMC_is_terminal (c, fwd))
2390 /* Local shutdown, no one to notify about this. */
2395 msg.header.size = htons (sizeof (struct GNUNET_MESH_ConnectionBroken));
2396 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN);
2398 msg.peer1 = my_full_id;
2399 msg.peer2 = *GNUNET_PEER_resolve2 (peer->id);
2400 send_prebuilt_message_connection (&msg.header, c, NULL, fwd);
2401 c->destroy = GNUNET_YES;
2408 * Initialize the connections subsystem
2410 * @param c Configuration handle.
2413 GMC_init (const struct GNUNET_CONFIGURATION_Handle *c)
2416 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_MSGS_QUEUE",
2419 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2420 "MESH", "MAX_MSGS_QUEUE", "MISSING");
2421 GNUNET_SCHEDULER_shutdown ();
2426 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_CONNECTIONS",
2429 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2430 "MESH", "MAX_CONNECTIONS", "MISSING");
2431 GNUNET_SCHEDULER_shutdown ();
2436 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "REFRESH_CONNECTION_TIME",
2437 &refresh_connection_time))
2439 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
2440 "MESH", "REFRESH_CONNECTION_TIME", "MISSING");
2441 GNUNET_SCHEDULER_shutdown ();
2444 connections = GNUNET_CONTAINER_multihashmap_create (1024, GNUNET_YES);
2446 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
2447 NULL, /* Closure passed to MESH functions */
2448 &core_init, /* Call core_init once connected */
2449 &core_connect, /* Handle connects */
2450 &core_disconnect, /* remove peers on disconnects */
2451 NULL, /* Don't notify about all incoming messages */
2452 GNUNET_NO, /* For header only in notification */
2453 NULL, /* Don't notify about all outbound messages */
2454 GNUNET_NO, /* For header-only out notification */
2455 core_handlers); /* Register these handlers */
2456 if (NULL == core_handle)
2459 GNUNET_SCHEDULER_shutdown ();
2465 * Shut down the connections subsystem.
2470 if (core_handle != NULL)
2472 GNUNET_CORE_disconnect (core_handle);
2479 * Is this peer the first one on the connection?
2481 * @param c Connection.
2482 * @param fwd Is this about fwd traffic?
2484 * @return GNUNET_YES if origin, GNUNET_NO if relay/terminal.
2487 GMC_is_origin (struct MeshConnection *c, int fwd)
2489 if (!fwd && c->path->length - 1 == c->own_pos )
2491 if (fwd && 0 == c->own_pos)
2498 * Is this peer the last one on the connection?
2500 * @param c Connection.
2501 * @param fwd Is this about fwd traffic?
2502 * Note that the ROOT is the terminal for BCK traffic!
2504 * @return GNUNET_YES if terminal, GNUNET_NO if relay/origin.
2507 GMC_is_terminal (struct MeshConnection *c, int fwd)
2509 return GMC_is_origin (c, !fwd);