2 This file is part of GNUnet.
3 (C) 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.
23 #include "gnunet_util_lib.h"
25 #include "gnunet_core_service.h"
26 #include "gnunet_statistics_service.h"
28 #include "mesh_protocol_enc.h"
30 #include "gnunet-service-mesh_peer.h"
31 #include "gnunet-service-mesh_dht.h"
32 #include "gnunet-service-mesh_connection.h"
33 #include "gnunet-service-mesh_local.h"
34 #include "gnunet-service-mesh_tunnel.h"
35 #include "mesh_path.h"
37 #define LOG(level, ...) GNUNET_log_from (level,"mesh-p2p",__VA_ARGS__)
39 /******************************************************************************/
40 /******************************** STRUCTS **********************************/
41 /******************************************************************************/
44 * Struct containing all information regarding a given peer
54 * Last time we heard from this peer
56 struct GNUNET_TIME_Absolute last_contact;
59 * Paths to reach the peer, ordered by ascending hop count
61 struct MeshPeerPath *path_head;
64 * Paths to reach the peer, ordered by ascending hop count
66 struct MeshPeerPath *path_tail;
69 * Handle to stop the DHT search for paths to this peer
71 struct GMD_search_handle *search_h;
74 * Tunnel to this peer, if any.
76 struct MeshTunnel2 *tunnel;
79 * Connections that go through this peer, indexed by tid;
81 struct GNUNET_CONTAINER_MultiHashMap *connections;
84 * Handle for queued transmissions
86 struct GNUNET_CORE_TransmitHandle *core_transmit;
89 * Transmission queue to core DLL head
91 struct MeshPeerQueue *queue_head;
94 * Transmission queue to core DLL tail
96 struct MeshPeerQueue *queue_tail;
99 * How many messages are in the queue to this peer.
101 unsigned int queue_n;
105 /******************************************************************************/
106 /******************************* GLOBALS ***********************************/
107 /******************************************************************************/
110 * Global handle to the statistics service.
112 extern struct GNUNET_STATISTICS_Handle *stats;
115 * Peers known, indexed by PeerIdentity (MeshPeer).
117 static struct GNUNET_CONTAINER_MultiPeerMap *peers;
120 * How many peers do we want to remember?
122 static unsigned long long max_peers;
125 * Percentage of messages that will be dropped (for test purposes only).
127 static unsigned long long drop_percent;
130 * Handle to communicate with core.
132 static struct GNUNET_CORE_Handle *core_handle;
135 * Local peer own ID (full value).
137 const static struct GNUNET_PeerIdentity *my_full_id;
139 /******************************************************************************/
140 /***************************** CORE CALLBACKS *********************************/
141 /******************************************************************************/
145 * Iterator to notify all connections of a broken link. Mark connections
146 * to destroy after all traffic has been sent.
148 * @param cls Closure (peer disconnected).
149 * @param key Current key code (peer id).
150 * @param value Value in the hash map (connection).
152 * @return GNUNET_YES if we should continue to iterate,
156 notify_broken (void *cls,
157 const struct GNUNET_HashCode *key,
160 struct MeshPeer *peer = cls;
161 struct MeshConnection *c = value;
163 GMC_notify_broken (c, peer, my_full_id);
170 * Method called whenever a given peer connects.
173 * @param peer peer identity this notification is about
176 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
179 struct MeshPeerPath *path;
181 LOG ("Peer connected\n");
182 LOG (" %s\n", GNUNET_i2s (&my_full_id));
183 pi = peer_get (peer);
191 LOG (" %s\n", GNUNET_i2s (peer));
193 path->peers[1] = pi->id;
194 GNUNET_PEER_change_rc (pi->id, 1);
195 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
197 path->peers[0] = myid;
198 GNUNET_PEER_change_rc (myid, 1);
199 peer_add_path (pi, path, GNUNET_YES);
201 pi->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
207 * Method called whenever a peer disconnects.
210 * @param peer peer identity this notification is about
213 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
217 LOG ("Peer disconnected\n");
218 pi = GNUNET_CONTAINER_multipeermap_get (peers, peer);
225 GNUNET_CONTAINER_multihashmap_iterate (pi->connections, ¬ify_broken, pi);
226 GNUNET_CONTAINER_multihashmap_destroy (pi->connections);
227 pi->connections = NULL;
228 if (NULL != pi->core_transmit)
230 GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit);
231 pi->core_transmit = NULL;
237 GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
244 * Functions to handle messages from core
246 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
247 {&GMC_handle_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
249 {&GMC_handle_confirm, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
250 sizeof (struct GNUNET_MESH_ConnectionACK)},
251 {&GMC_handle_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
252 sizeof (struct GNUNET_MESH_ConnectionBroken)},
253 {&GMC_handle_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
254 sizeof (struct GNUNET_MESH_ConnectionDestroy)},
255 {&GMC_handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE,
256 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
257 {&GMC_handle_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE,
258 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
259 {&GMC_handle_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
260 sizeof (struct GNUNET_MESH_ACK)},
261 {&GMC_handle_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
262 sizeof (struct GNUNET_MESH_Poll)},
263 {&GMC_handle_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0},
264 {&GMC_handle_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0},
270 * To be called on core init/fail.
272 * @param cls Closure (config)
273 * @param identity the public identity of this peer
276 core_init (void *cls,
277 const struct GNUNET_PeerIdentity *identity)
279 const struct GNUNET_CONFIGURATION_Handle *c = cls;
282 LOG (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
283 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
285 LOG (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
286 LOG (GNUNET_ERROR_TYPE_ERROR, " core id %s\n", GNUNET_i2s (identity));
287 LOG (GNUNET_ERROR_TYPE_ERROR, " my id %s\n", GNUNET_i2s (&my_full_id));
288 GNUNET_CORE_disconnect (core_handle);
289 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
290 NULL, /* Closure passed to MESH functions */
291 &core_init, /* Call core_init once connected */
292 &core_connect, /* Handle connects */
293 &core_disconnect, /* remove peers on disconnects */
294 NULL, /* Don't notify about all incoming messages */
295 GNUNET_NO, /* For header only in notification */
296 NULL, /* Don't notify about all outbound messages */
297 GNUNET_NO, /* For header-only out notification */
298 core_handlers); /* Register these handlers */
307 * Core callback to write a pre-constructed data packet to core buffer
309 * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
310 * @param size Number of bytes available in buf.
311 * @param buf Where the to write the message.
313 * @return number of bytes written to buf
316 send_core_data_raw (void *cls, size_t size, void *buf)
318 struct GNUNET_MessageHeader *msg = cls;
321 GNUNET_assert (NULL != msg);
322 total_size = ntohs (msg->size);
324 if (total_size > size)
329 memcpy (buf, msg, total_size);
336 * Function to send a create connection message to a peer.
338 * @param c Connection to create.
339 * @param size number of bytes available in buf
340 * @param buf where the callee should write the message
341 * @return number of bytes written to buf
344 send_core_connection_create (struct MeshConnection *c, size_t size, void *buf)
346 struct GNUNET_MESH_ConnectionCreate *msg;
347 struct GNUNET_PeerIdentity *peer_ptr;
348 struct MeshPeerPath *p = c->path;
352 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
354 sizeof (struct GNUNET_MESH_ConnectionCreate) +
355 p->length * sizeof (struct GNUNET_PeerIdentity);
357 if (size < size_needed || NULL == buf)
362 msg = (struct GNUNET_MESH_ConnectionCreate *) buf;
363 msg->header.size = htons (size_needed);
364 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE);
367 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
368 for (i = 0; i < p->length; i++)
370 GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
373 LOG (GNUNET_ERROR_TYPE_DEBUG,
374 "CONNECTION CREATE (%u bytes long) sent!\n", size_needed);
380 * Creates a path ack message in buf and frees all unused resources.
382 * @param c Connection to send an ACK on.
383 * @param size number of bytes available in buf
384 * @param buf where the callee should write the message
386 * @return number of bytes written to buf
389 send_core_connection_ack (struct MeshConnection *c, size_t size, void *buf)
391 struct GNUNET_MESH_ConnectionACK *msg = buf;
392 struct MeshTunnel2 *t = c->t;
394 LOG (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
395 GNUNET_assert (NULL != t);
396 if (sizeof (struct GNUNET_MESH_ConnectionACK) > size)
401 msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK));
402 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK);
406 /* TODO add signature */
408 LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
409 return sizeof (struct GNUNET_MESH_ConnectionACK);
413 /******************************************************************************/
414 /******************************** STATIC ***********************************/
415 /******************************************************************************/
418 * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
421 * @param key current key code
422 * @param value value in the hash map
423 * @return #GNUNET_YES if we should continue to iterate,
427 shutdown_tunnel (void *cls,
428 const struct GNUNET_PeerIdentity *key,
431 struct MeshPeer *p = value;
432 struct MeshTunnel2 *t = p->tunnel;
442 * Destroy the peer_info and free any allocated resources linked to it
444 * @param peer The peer_info to destroy.
446 * @return GNUNET_OK on success
449 peer_destroy (struct MeshPeer *peer)
451 struct GNUNET_PeerIdentity id;
452 struct MeshPeerPath *p;
453 struct MeshPeerPath *nextp;
455 GNUNET_PEER_resolve (peer->id, &id);
456 GNUNET_PEER_change_rc (peer->id, -1);
459 GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
462 LOG (GNUNET_ERROR_TYPE_WARNING,
463 "removing peer %s, not in peermap\n", GNUNET_i2s (&id));
465 if (NULL != peer->search_h)
467 GMD_search_stop (peer->search_h);
473 GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
477 tunnel_destroy_empty (peer->tunnel);
484 * Returns if peer is used (has a tunnel, is neighbor).
486 * @peer Peer to check.
488 * @return GNUNET_YES if peer is in use.
491 peer_is_used (struct MeshPeer *peer)
493 struct MeshPeerPath *p;
495 if (NULL != peer->tunnel)
498 for (p = peer->path_head; NULL != p; p = p->next)
508 * Iterator over all the peers to get the oldest timestamp.
510 * @param cls Closure (unsued).
511 * @param key ID of the peer.
512 * @param value Peer_Info of the peer.
515 peer_get_oldest (void *cls,
516 const struct GNUNET_PeerIdentity *key,
519 struct MeshPeer *p = value;
520 struct GNUNET_TIME_Absolute *abs = cls;
522 /* Don't count active peers */
523 if (GNUNET_YES == peer_is_used (p))
526 if (abs->abs_value_us < p->last_contact.abs_value_us)
527 abs->abs_value_us = p->last_contact.abs_value_us;
534 * Iterator over all the peers to remove the oldest entry.
536 * @param cls Closure (unsued).
537 * @param key ID of the peer.
538 * @param value Peer_Info of the peer.
541 peer_timeout (void *cls,
542 const struct GNUNET_PeerIdentity *key,
545 struct MeshPeer *p = value;
546 struct GNUNET_TIME_Absolute *abs = cls;
548 if (p->last_contact.abs_value_us == abs->abs_value_us &&
549 GNUNET_NO == peer_is_used (p))
559 * Delete oldest unused peer.
562 peer_delete_oldest (void)
564 struct GNUNET_TIME_Absolute abs;
566 abs = GNUNET_TIME_UNIT_FOREVER_ABS;
568 GNUNET_CONTAINER_multipeermap_iterate (peers,
571 GNUNET_CONTAINER_multipeermap_iterate (peers,
578 * Retrieve the MeshPeer stucture associated with the peer, create one
579 * and insert it in the appropriate structures if the peer is not known yet.
581 * @param peer Full identity of the peer.
583 * @return Existing or newly created peer info.
585 static struct MeshPeer *
586 peer_get (const struct GNUNET_PeerIdentity *peer_id)
588 struct MeshPeer *peer;
590 peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
593 peer = GNUNET_new (struct MeshPeer);
594 if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
596 peer_delete_oldest ();
598 GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
599 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
600 peer->id = GNUNET_PEER_intern (peer_id);
602 peer->last_contact = GNUNET_TIME_absolute_get();
609 * Retrieve the MeshPeer stucture associated with the peer, create one
610 * and insert it in the appropriate structures if the peer is not known yet.
612 * @param peer Short identity of the peer.
614 * @return Existing or newly created peer info.
616 static struct MeshPeer *
617 peer_get_short (const GNUNET_PEER_Id peer)
619 return peer_get (GNUNET_PEER_resolve2 (peer));
624 * Get a cost of a path for a peer considering existing tunnel connections.
626 * @param peer Peer towards which the path is considered.
627 * @param path Candidate path.
629 * @return Cost of the path (path length + number of overlapping nodes)
632 peer_get_path_cost (const struct MeshPeer *peer,
633 const struct MeshPeerPath *path)
635 struct MeshConnection *c;
636 unsigned int overlap;
644 GNUNET_assert (NULL != peer->tunnel);
646 for (i = 0; i < path->length; i++)
648 for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
650 for (j = 0; j < c->path->length; j++)
652 if (path->peers[i] == c->path->peers[j])
660 return (path->length + overlap) * (path->score * -1);
665 * Choose the best path towards a peer considering the tunnel properties.
667 * @param peer The destination peer.
669 * @return Best current known path towards the peer, if any.
671 static struct MeshPeerPath *
672 peer_get_best_path (const struct MeshPeer *peer)
674 struct MeshPeerPath *best_p;
675 struct MeshPeerPath *p;
676 struct MeshConnection *c;
677 unsigned int best_cost;
680 best_cost = UINT_MAX;
682 for (p = peer->path_head; NULL != p; p = p->next)
684 for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
688 continue; /* If path is in use in a connection, skip it. */
690 if ((cost = peer_get_path_cost (peer, p)) < best_cost)
701 * Add the path to the peer and update the path used to reach it in case this
704 * @param peer_info Destination peer to add the path to.
705 * @param path New path to add. Last peer must be the peer in arg 1.
706 * Path will be either used of freed if already known.
707 * @param trusted Do we trust that this path is real?
710 peer_add_path (struct MeshPeer *peer_info, struct MeshPeerPath *path,
713 struct MeshPeerPath *aux;
717 if ((NULL == peer_info) || (NULL == path))
723 if (path->peers[path->length - 1] != peer_info->id)
729 if (2 >= path->length && GNUNET_NO == trusted)
731 /* Only allow CORE to tell us about direct paths */
735 for (l = 1; l < path->length; l++)
737 if (path->peers[l] == myid)
739 LOG (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
740 for (l2 = 0; l2 < path->length - l; l2++)
742 path->peers[l2] = path->peers[l + l2];
747 GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
751 LOG (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
752 path->length, peer2s (peer_info));
754 l = path_get_length (path);
761 GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
762 for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
764 l2 = path_get_length (aux);
767 GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
768 peer_info->path_tail, aux, path);
773 if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
780 GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
787 * Add the path to the origin peer and update the path used to reach it in case
788 * this is the shortest.
789 * The path is given in peer_info -> destination, therefore we turn the path
792 * @param peer_info Peer to add the path to, being the origin of the path.
793 * @param path New path to add after being inversed.
794 * Path will be either used or freed.
795 * @param trusted Do we trust that this path is real?
798 peer_add_path_to_origin (struct MeshPeer *peer_info,
799 struct MeshPeerPath *path, int trusted)
804 peer_add_path (peer_info, path, trusted);
809 * Adds a path to the peer_infos of all the peers in the path
811 * @param p Path to process.
812 * @param confirmed Whether we know if the path works or not.
815 path_add_to_peers (struct MeshPeerPath *p, int confirmed)
819 /* TODO: invert and add */
820 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
821 for (i++; i < p->length; i++)
823 struct MeshPeer *aux;
824 struct MeshPeerPath *copy;
826 aux = peer_get_short (p->peers[i]);
827 copy = path_duplicate (p);
828 copy->length = i + 1;
829 peer_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
835 * Function to process paths received for a new peer addition. The recorded
836 * paths form the initial tunnel, which can be optimized later.
837 * Called on each result obtained for the DHT search.
843 search_handler (void *cls, struct MeshPeerPath *path)
845 struct MeshPeer *peer = cls;
846 unsigned int connection_count;
848 path_add_to_peers (path, GNUNET_NO);
850 /* Count connections */
851 connection_count = GMC_count (peer->tunnel->connection_head);
853 /* If we already have 3 (or more (?!)) connections, it's enough */
854 if (3 <= connection_count)
857 if (peer->tunnel->state == MESH_TUNNEL_SEARCHING)
859 LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
867 * Core callback to write a queued packet to core buffer
869 * @param cls Closure (peer info).
870 * @param size Number of bytes available in buf.
871 * @param buf Where the to write the message.
873 * @return number of bytes written to buf
876 queue_send (void *cls, size_t size, void *buf)
878 struct MeshPeer *peer = cls;
879 struct MeshFlowControl *fc;
880 struct MeshConnection *c;
881 struct GNUNET_MessageHeader *msg;
882 struct MeshPeerQueue *queue;
883 struct MeshTunnel2 *t;
884 struct MeshChannel *ch;
885 const struct GNUNET_PeerIdentity *dst_id;
891 peer->core_transmit = NULL;
892 LOG (GNUNET_ERROR_TYPE_DEBUG, "* Queue send (max %u)\n", size);
894 if (NULL == buf || 0 == size)
896 LOG (GNUNET_ERROR_TYPE_DEBUG, "* Buffer size 0.\n");
901 queue = peer_get_first_message (peer);
904 GNUNET_break (0); /* Core tmt_rdy should've been canceled */
909 fc = fwd ? &c->fwd_fc : &c->bck_fc;
911 dst_id = GNUNET_PEER_resolve2 (peer->id);
912 LOG (GNUNET_ERROR_TYPE_DEBUG, "* towards %s\n", GNUNET_i2s (dst_id));
913 /* Check if buffer size is enough for the message */
914 if (queue->size > size)
916 LOG (GNUNET_ERROR_TYPE_DEBUG, "* not enough room, reissue\n");
917 peer->core_transmit =
918 GNUNET_CORE_notify_transmit_ready (core_handle,
921 GNUNET_TIME_UNIT_FOREVER_REL,
928 LOG (GNUNET_ERROR_TYPE_DEBUG, "* size %u ok\n", queue->size);
930 t = (NULL != c) ? c->t : NULL;
936 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
937 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
938 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
939 case GNUNET_MESSAGE_TYPE_MESH_FWD:
940 case GNUNET_MESSAGE_TYPE_MESH_BCK:
941 case GNUNET_MESSAGE_TYPE_MESH_ACK:
942 case GNUNET_MESSAGE_TYPE_MESH_POLL:
943 LOG (GNUNET_ERROR_TYPE_DEBUG,
945 GNUNET_MESH_DEBUG_M2S (queue->type));
946 data_size = send_core_data_raw (queue->cls, size, buf);
947 msg = (struct GNUNET_MessageHeader *) buf;
948 type = ntohs (msg->type);
950 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
951 LOG (GNUNET_ERROR_TYPE_DEBUG, "* path create\n");
952 if (GMC_is_origin (c, GNUNET_YES))
953 data_size = send_core_connection_create (queue->c, size, buf);
955 data_size = send_core_data_raw (queue->cls, size, buf);
957 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
958 LOG (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n");
959 if (GMC_is_origin (c, GNUNET_NO) ||
960 GMC_is_origin (c, GNUNET_YES))
961 data_size = send_core_connection_ack (queue->c, size, buf);
963 data_size = send_core_data_raw (queue->cls, size, buf);
965 case GNUNET_MESSAGE_TYPE_MESH_DATA:
966 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
967 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
968 /* This should be encapsulted */
974 LOG (GNUNET_ERROR_TYPE_WARNING, "* type unknown: %u\n",
979 if (0 < drop_percent &&
980 GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
982 LOG (GNUNET_ERROR_TYPE_WARNING,
983 "Dropping message of type %s\n",
984 GNUNET_MESH_DEBUG_M2S (queue->type));
988 /* Free queue, but cls was freed by send_core_* */
990 queue_destroy (queue, GNUNET_NO);
992 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
995 case GNUNET_MESSAGE_TYPE_MESH_FWD:
996 case GNUNET_MESSAGE_TYPE_MESH_BCK:
997 pid = ntohl ( ((struct GNUNET_MESH_Encrypted *) buf)->pid );
998 LOG (GNUNET_ERROR_TYPE_DEBUG, "* accounting pid %u\n", pid);
999 fc->last_pid_sent = pid;
1000 send_ack (c, ch, fwd);
1006 /* If more data in queue, send next */
1007 queue = peer_get_first_message (peer);
1010 LOG (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n");
1011 if (NULL == peer->core_transmit) {
1012 peer->core_transmit =
1013 GNUNET_CORE_notify_transmit_ready(core_handle,
1016 GNUNET_TIME_UNIT_FOREVER_REL,
1024 LOG (GNUNET_ERROR_TYPE_DEBUG,
1025 "* tmt rdy called somewhere else\n");
1027 if (GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
1029 LOG (GNUNET_ERROR_TYPE_DEBUG, "* starting poll timeout\n");
1031 GNUNET_SCHEDULER_add_delayed (fc->poll_time, &connection_poll, fc);
1036 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
1038 GNUNET_SCHEDULER_cancel (fc->poll_task);
1039 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1044 c->pending_messages--;
1045 if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
1047 LOG (GNUNET_ERROR_TYPE_DEBUG, "* destroying connection!\n");
1054 t->pending_messages--;
1055 if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
1057 // LOG (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n");
1061 LOG (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size);
1068 * Get first sendable message.
1070 * @param peer The destination peer.
1072 * @return Best current known path towards the peer, if any.
1074 static struct MeshPeerQueue *
1075 peer_get_first_message (const struct MeshPeer *peer)
1077 struct MeshPeerQueue *q;
1079 for (q = peer->queue_head; NULL != q; q = q->next)
1081 if (queue_is_sendable (q))
1090 queue_is_sendable (struct MeshPeerQueue *q)
1092 struct MeshFlowControl *fc;
1094 /* Is PID-independent? */
1097 case GNUNET_MESSAGE_TYPE_MESH_ACK:
1098 case GNUNET_MESSAGE_TYPE_MESH_POLL:
1102 /* Is PID allowed? */
1103 fc = q->fwd ? &q->c->fwd_fc : &q->c->bck_fc;
1104 if (GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1111 /******************************************************************************/
1112 /******************************** API ***********************************/
1113 /******************************************************************************/
1117 * Free a transmission that was already queued with all resources
1118 * associated to the request.
1120 * @param queue Queue handler to cancel.
1121 * @param clear_cls Is it necessary to free associated cls?
1124 GMP_queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
1126 struct MeshPeer *peer;
1127 struct MeshFlowControl *fc;
1132 GNUNET_assert (NULL != queue->c);
1133 fc = fwd ? &queue->c->fwd_fc : &queue->c->bck_fc;
1135 if (GNUNET_YES == clear_cls)
1137 LOG (GNUNET_ERROR_TYPE_DEBUG, " queue destroy type %s\n",
1138 GNUNET_MESH_DEBUG_M2S (queue->type));
1139 switch (queue->type)
1141 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
1142 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
1143 LOG (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
1144 GNUNET_break (GNUNET_YES == queue->c->destroy);
1146 case GNUNET_MESSAGE_TYPE_MESH_FWD:
1147 case GNUNET_MESSAGE_TYPE_MESH_BCK:
1148 case GNUNET_MESSAGE_TYPE_MESH_ACK:
1149 case GNUNET_MESSAGE_TYPE_MESH_POLL:
1150 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
1151 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
1152 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
1153 LOG (GNUNET_ERROR_TYPE_DEBUG, " prebuilt message\n");;
1154 GNUNET_free_non_null (queue->cls);
1159 LOG (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n",
1160 GNUNET_MESH_DEBUG_M2S (queue->type));
1164 GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
1166 if (queue->type != GNUNET_MESSAGE_TYPE_MESH_ACK &&
1167 queue->type != GNUNET_MESSAGE_TYPE_MESH_POLL)
1169 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N- %p %u\n", fc, fc->queue_n);
1173 if (NULL != queue->c)
1175 queue->c->pending_messages--;
1176 if (NULL != queue->c->t)
1178 queue->c->t->pending_messages--;
1182 GNUNET_free (queue);
1187 * @brief Queue and pass message to core when possible.
1189 * @param cls Closure (@c type dependant). It will be used by queue_send to
1190 * build the message to be sent if not already prebuilt.
1191 * @param type Type of the message, 0 for a raw message.
1192 * @param size Size of the message.
1193 * @param c Connection this message belongs to (cannot be NULL).
1194 * @param ch Channel this message belongs to, if applicable (otherwise NULL).
1195 * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
1198 GMP_queue_add (void *cls, uint16_t type, size_t size,
1199 struct MeshConnection *c,
1200 struct MeshChannel *ch,
1203 struct MeshPeerQueue *queue;
1204 struct MeshFlowControl *fc;
1205 struct MeshPeer *peer;
1209 LOG (GNUNET_ERROR_TYPE_DEBUG,
1210 "queue add %s %s (%u) on c %p, ch %p\n",
1211 fwd ? "FWD" : "BCK", GNUNET_MESH_DEBUG_M2S (type), size, c, ch);
1212 GNUNET_assert (NULL != c);
1214 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1215 peer = fwd ? connection_get_next_hop (c) : connection_get_prev_hop (c);
1223 if (NULL == peer->connections)
1225 /* We are not connected to this peer, ignore request. */
1226 GNUNET_break_op (0);
1232 if (GNUNET_MESSAGE_TYPE_MESH_POLL == type ||
1233 GNUNET_MESSAGE_TYPE_MESH_ACK == type)
1238 LOG (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
1239 LOG (GNUNET_ERROR_TYPE_DEBUG, "fc %p\n", fc);
1240 if (fc->queue_n >= fc->queue_max && 0 == priority)
1242 GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
1245 LOG (GNUNET_ERROR_TYPE_DEBUG,
1246 "queue full: %u/%u\n",
1247 fc->queue_n, fc->queue_max);
1248 return; /* Drop this message */
1251 LOG (GNUNET_ERROR_TYPE_DEBUG, "last pid %u\n", fc->last_pid_sent);
1252 LOG (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", fc->last_ack_recv);
1253 if (GMC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
1255 call_core = GNUNET_NO;
1256 if (GNUNET_SCHEDULER_NO_TASK == fc->poll_task &&
1257 GNUNET_MESSAGE_TYPE_MESH_POLL != type)
1259 LOG (GNUNET_ERROR_TYPE_DEBUG,
1260 "no buffer space (%u > %u): starting poll\n",
1261 fc->last_pid_sent + 1, fc->last_ack_recv);
1262 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
1268 call_core = GNUNET_YES;
1269 queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
1277 if (100 <= priority)
1279 struct MeshPeerQueue *copy;
1280 struct MeshPeerQueue *next;
1282 for (copy = peer->queue_head; NULL != copy; copy = next)
1285 if (copy->type == type && copy->c == c && copy->fwd == fwd)
1287 /* Example: also a FWD ACK for connection XYZ */
1288 queue_destroy (copy, GNUNET_YES);
1291 GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
1295 GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue);
1296 LOG (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n);
1301 if (NULL == peer->core_transmit && GNUNET_YES == call_core)
1303 LOG (GNUNET_ERROR_TYPE_DEBUG,
1304 "calling core tmt rdy towards %s for %u bytes\n",
1305 peer2s (peer), size);
1306 peer->core_transmit =
1307 GNUNET_CORE_notify_transmit_ready (core_handle,
1310 GNUNET_TIME_UNIT_FOREVER_REL,
1311 GNUNET_PEER_resolve2 (peer->id),
1318 LOG (GNUNET_ERROR_TYPE_DEBUG,
1319 "core tmt rdy towards %s already called\n",
1323 c->pending_messages++;
1325 c->t->pending_messages++;
1331 * Initialize the peer subsystem.
1333 * @param c Configuration.
1334 * @param id Peer identity
1337 GMP_init (const struct GNUNET_CONFIGURATION_Handle *c,
1338 const struct GNUNET_PeerIdentity *id)
1341 peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1343 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
1346 LOG_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1347 "MESH", "MAX_PEERS", "USING DEFAULT");
1352 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT",
1359 LOG (GNUNET_ERROR_TYPE_WARNING,
1360 "\n***************************************\n"
1361 "Mesh is running with drop mode enabled.\n"
1362 "This is NOT a good idea!\n"
1363 "Remove the DROP_PERCENT option from your configuration.\n"
1364 "***************************************\n");
1367 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1368 NULL, /* Closure passed to MESH functions */
1369 &core_init, /* Call core_init once connected */
1370 &core_connect, /* Handle connects */
1371 &core_disconnect, /* remove peers on disconnects */
1372 NULL, /* Don't notify about all incoming messages */
1373 GNUNET_NO, /* For header only in notification */
1374 NULL, /* Don't notify about all outbound messages */
1375 GNUNET_NO, /* For header-only out notification */
1376 core_handlers); /* Register these handlers */
1377 if (NULL == core_handle)
1380 GNUNET_SCHEDULER_shutdown ();
1386 * Shut down the peer subsystem.
1391 GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
1393 if (core_handle != NULL)
1395 GNUNET_CORE_disconnect (core_handle);
1402 * Try to establish a new connection to this peer in the given tunnel.
1403 * If the peer doesn't have any path to it yet, try to get one.
1404 * If the peer already has some path, send a CREATE CONNECTION towards it.
1406 * @param peer PeerInfo of the peer.
1409 GMP_connect (struct MeshPeer *peer)
1411 struct MeshTunnel2 *t;
1412 struct MeshPeerPath *p;
1413 struct MeshConnection *c;
1416 LOG (GNUNET_ERROR_TYPE_DEBUG,
1417 "peer_connect towards %s\n",
1421 rerun_search = GNUNET_NO;
1423 if (NULL != peer->path_head)
1425 LOG (GNUNET_ERROR_TYPE_DEBUG, "path exists\n");
1426 p = peer_get_best_path (peer);
1429 LOG (GNUNET_ERROR_TYPE_DEBUG, " %u hops\n", p->length);
1430 c = tunnel_use_path (t, p);
1433 /* This case can happen when the path includes a first hop that is
1434 * not yet known to be connected.
1436 * This happens quite often during testing when running mesh
1437 * under valgrind: core connect notifications come very late and the
1438 * DHT result has already come and created a valid path.
1439 * In this case, the peer->connections hashmap will be NULL and
1440 * tunnel_use_path will not be able to create a connection from that
1443 * Re-running the DHT GET should give core time to callback.
1446 rerun_search = GNUNET_YES;
1450 send_connection_create (c);
1456 if (NULL != peer->search_h && GNUNET_YES == rerun_search)
1458 GMD_search_stop (peer->search_h);
1459 peer->search_h = NULL;
1460 LOG (GNUNET_ERROR_TYPE_DEBUG,
1461 " Stopping DHT GET for peer %s\n", peer2s (peer));
1464 if (NULL == peer->search_h)
1466 const struct GNUNET_PeerIdentity *id;
1468 id = GNUNET_PEER_resolve2 (peer->id);
1469 LOG (GNUNET_ERROR_TYPE_DEBUG,
1470 " Starting DHT GET for peer %s\n", peer2s (peer));
1471 peer->search_h = GMD_search (id, &search_handler, peer);
1472 if (MESH_TUNNEL_NEW == t->state)
1473 GMT_change_state (t, MESH_TUNNEL_SEARCHING);
1485 GMP_set_tunnel (struct MeshPeer *peer, struct MeshTunnel2 *t)
1492 * Chech whether there is a direct (core level) connection to peer.
1494 * @param peer Peer to check.
1496 * @return GNUNET_YES if there is a direct connection.
1499 GMP_is_neighbor (const struct MeshPeer *peer)
1501 struct MeshPeerPath *path;
1503 if (NULL == peer->connections)
1506 for (path = peer->path_head; NULL != path; path = path->next)
1508 if (3 > path->length)
1512 GNUNET_break (0); /* Is not a neighbor but connections is not NULL */
1518 * Add a connection to a neighboring peer.
1520 * Store that the peer is the first hop of the connection in one
1521 * direction and that on peer disconnect the connection must be
1522 * notified and destroyed, for it will no longer be valid.
1524 * @param peer Peer to add connection to.
1525 * @param c Connection to add.
1527 * @return GNUNET_OK on success.
1530 GMP_add_connection (struct MeshPeer *peer,
1531 const struct MeshConnection *c)
1533 if (NULL == peer->connections)
1536 return GNUNET_SYSERR;
1538 return GNUNET_CONTAINER_multihashmap_put (peer->connections,
1541 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1546 GMP_remove_connection (struct MeshPeer *peer,
1547 const struct MeshConnection *c)
1549 if (NULL == peer || NULL == peer->connections)
1552 return GNUNET_SYSERR;
1554 return GNUNET_CONTAINER_multihashmap_remove (peer->connections,
1560 * Get the Full ID of a peer.
1562 * @param peer Peer to get from.
1564 * @return Full ID of peer.
1566 struct GNUNET_PeerIdentity *
1567 GMP_get_id (const struct MeshPeer *peer)
1569 return GNUNET_PEER_resolve2 (peer->id);
1574 * Get the Short ID of a peer.
1576 * @param peer Peer to get from.
1578 * @return Short ID of peer.
1581 GMP_get_short_id (const struct MeshPeer *peer)
1588 * Get the static string for a peer ID.
1592 * @return Static string for it's ID.
1595 GMP_2s (const struct MeshPeer *peer)
1599 return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));