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"
27 #include "gnunet-service-mesh_peer.h"
28 #include "gnunet-service-mesh_dht.h"
29 #include "gnunet-service-mesh_connection.h"
30 #include "gnunet-service-mesh_local.h"
31 #include "mesh_path.h"
33 /******************************************************************************/
34 /******************************** STRUCTS **********************************/
35 /******************************************************************************/
38 * Struct containing all information regarding a given peer
48 * Last time we heard from this peer
50 struct GNUNET_TIME_Absolute last_contact;
53 * Paths to reach the peer, ordered by ascending hop count
55 struct MeshPeerPath *path_head;
58 * Paths to reach the peer, ordered by ascending hop count
60 struct MeshPeerPath *path_tail;
63 * Handle to stop the DHT search for paths to this peer
65 struct GMD_search_handle *search_h;
68 * Tunnel to this peer, if any.
70 struct MeshTunnel2 *tunnel;
73 * Connections that go through this peer, indexed by tid;
75 struct GNUNET_CONTAINER_MultiHashMap *connections;
78 * Handle for queued transmissions
80 struct GNUNET_CORE_TransmitHandle *core_transmit;
83 * Transmission queue to core DLL head
85 struct MeshPeerQueue *queue_head;
88 * Transmission queue to core DLL tail
90 struct MeshPeerQueue *queue_tail;
93 * How many messages are in the queue to this peer.
99 /******************************************************************************/
100 /******************************* GLOBALS ***********************************/
101 /******************************************************************************/
104 * Peers known, indexed by PeerIdentity (MeshPeer).
106 static struct GNUNET_CONTAINER_MultiPeerMap *peers;
109 * How many peers do we want to remember?
111 static unsigned long long max_peers;
114 * Percentage of messages that will be dropped (for test purposes only).
116 static unsigned long long drop_percent;
119 * Handle to communicate with core.
121 static struct GNUNET_CORE_Handle *core_handle;
124 * Local peer own ID (full value).
126 const static struct GNUNET_PeerIdentity *my_full_id;
128 /******************************************************************************/
129 /***************************** CORE CALLBACKS *********************************/
130 /******************************************************************************/
134 * Iterator to notify all connections of a broken link. Mark connections
135 * to destroy after all traffic has been sent.
137 * @param cls Closure (peer disconnected).
138 * @param key Current key code (peer id).
139 * @param value Value in the hash map (connection).
141 * @return GNUNET_YES if we should continue to iterate,
145 notify_broken (void *cls,
146 const struct GNUNET_HashCode *key,
149 struct MeshPeer *peer = cls;
150 struct MeshConnection *c = value;
152 GMC_notify_broken (c, peer, my_full_id);
158 * Method called whenever a given peer connects.
161 * @param peer peer identity this notification is about
164 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
167 struct MeshPeerPath *path;
169 LOG ("Peer connected\n");
170 LOG (" %s\n", GNUNET_i2s (&my_full_id));
171 pi = peer_get (peer);
174 DEBUG_CONN (" (self)\n");
179 DEBUG_CONN (" %s\n", GNUNET_i2s (peer));
181 path->peers[1] = pi->id;
182 GNUNET_PEER_change_rc (pi->id, 1);
183 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
185 path->peers[0] = myid;
186 GNUNET_PEER_change_rc (myid, 1);
187 peer_add_path (pi, path, GNUNET_YES);
189 pi->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
195 * Method called whenever a peer disconnects.
198 * @param peer peer identity this notification is about
201 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
205 DEBUG_CONN ("Peer disconnected\n");
206 pi = GNUNET_CONTAINER_multipeermap_get (peers, peer);
213 GNUNET_CONTAINER_multihashmap_iterate (pi->connections, ¬ify_broken, pi);
214 GNUNET_CONTAINER_multihashmap_destroy (pi->connections);
215 pi->connections = NULL;
216 if (NULL != pi->core_transmit)
218 GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit);
219 pi->core_transmit = NULL;
223 DEBUG_CONN (" (self)\n");
225 GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
233 * To be called on core init/fail.
235 * @param cls Closure (config)
236 * @param identity the public identity of this peer
239 core_init (void *cls,
240 const struct GNUNET_PeerIdentity *identity)
242 const struct GNUNET_CONFIGURATION_Handle *c = cls;
245 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
246 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
248 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
249 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
251 GNUNET_i2s (identity));
252 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
254 GNUNET_i2s (&my_full_id));
255 GNUNET_CORE_disconnect (core_handle);
256 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
257 NULL, /* Closure passed to MESH functions */
258 &core_init, /* Call core_init once connected */
259 &core_connect, /* Handle connects */
260 &core_disconnect, /* remove peers on disconnects */
261 NULL, /* Don't notify about all incoming messages */
262 GNUNET_NO, /* For header only in notification */
263 NULL, /* Don't notify about all outbound messages */
264 GNUNET_NO, /* For header-only out notification */
265 core_handlers); /* Register these handlers */
274 * Core callback to write a pre-constructed data packet to core buffer
276 * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
277 * @param size Number of bytes available in buf.
278 * @param buf Where the to write the message.
280 * @return number of bytes written to buf
283 send_core_data_raw (void *cls, size_t size, void *buf)
285 struct GNUNET_MessageHeader *msg = cls;
288 GNUNET_assert (NULL != msg);
289 total_size = ntohs (msg->size);
291 if (total_size > size)
296 memcpy (buf, msg, total_size);
303 * Function to send a create connection message to a peer.
305 * @param c Connection to create.
306 * @param size number of bytes available in buf
307 * @param buf where the callee should write the message
308 * @return number of bytes written to buf
311 send_core_connection_create (struct MeshConnection *c, size_t size, void *buf)
313 struct GNUNET_MESH_ConnectionCreate *msg;
314 struct GNUNET_PeerIdentity *peer_ptr;
315 struct MeshPeerPath *p = c->path;
319 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
321 sizeof (struct GNUNET_MESH_ConnectionCreate) +
322 p->length * sizeof (struct GNUNET_PeerIdentity);
324 if (size < size_needed || NULL == buf)
329 msg = (struct GNUNET_MESH_ConnectionCreate *) buf;
330 msg->header.size = htons (size_needed);
331 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE);
334 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
335 for (i = 0; i < p->length; i++)
337 GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
340 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
341 "CONNECTION CREATE (%u bytes long) sent!\n", size_needed);
347 * Creates a path ack message in buf and frees all unused resources.
349 * @param c Connection to send an ACK on.
350 * @param size number of bytes available in buf
351 * @param buf where the callee should write the message
353 * @return number of bytes written to buf
356 send_core_connection_ack (struct MeshConnection *c, size_t size, void *buf)
358 struct GNUNET_MESH_ConnectionACK *msg = buf;
359 struct MeshTunnel2 *t = c->t;
361 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
362 GNUNET_assert (NULL != t);
363 if (sizeof (struct GNUNET_MESH_ConnectionACK) > size)
368 msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK));
369 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK);
373 /* TODO add signature */
375 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
376 return sizeof (struct GNUNET_MESH_ConnectionACK);
380 /******************************************************************************/
381 /******************************** STATIC ***********************************/
382 /******************************************************************************/
385 * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
388 * @param key current key code
389 * @param value value in the hash map
390 * @return #GNUNET_YES if we should continue to iterate,
394 shutdown_tunnel (void *cls,
395 const struct GNUNET_PeerIdentity *key,
398 struct MeshPeer *p = value;
399 struct MeshTunnel2 *t = p->tunnel;
409 * Destroy the peer_info and free any allocated resources linked to it
411 * @param peer The peer_info to destroy.
413 * @return GNUNET_OK on success
416 peer_destroy (struct MeshPeer *peer)
418 struct GNUNET_PeerIdentity id;
419 struct MeshPeerPath *p;
420 struct MeshPeerPath *nextp;
422 GNUNET_PEER_resolve (peer->id, &id);
423 GNUNET_PEER_change_rc (peer->id, -1);
426 GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
429 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
430 "removing peer %s, not in peermap\n", GNUNET_i2s (&id));
432 if (NULL != peer->search_h)
434 GMD_search_stop (peer->search_h);
440 GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
444 tunnel_destroy_empty (peer->tunnel);
451 * Returns if peer is used (has a tunnel, is neighbor).
453 * @peer Peer to check.
455 * @return GNUNET_YES if peer is in use.
458 peer_is_used (struct MeshPeer *peer)
460 struct MeshPeerPath *p;
462 if (NULL != peer->tunnel)
465 for (p = peer->path_head; NULL != p; p = p->next)
475 * Iterator over all the peers to get the oldest timestamp.
477 * @param cls Closure (unsued).
478 * @param key ID of the peer.
479 * @param value Peer_Info of the peer.
482 peer_get_oldest (void *cls,
483 const struct GNUNET_PeerIdentity *key,
486 struct MeshPeer *p = value;
487 struct GNUNET_TIME_Absolute *abs = cls;
489 /* Don't count active peers */
490 if (GNUNET_YES == peer_is_used (p))
493 if (abs->abs_value_us < p->last_contact.abs_value_us)
494 abs->abs_value_us = p->last_contact.abs_value_us;
501 * Iterator over all the peers to remove the oldest entry.
503 * @param cls Closure (unsued).
504 * @param key ID of the peer.
505 * @param value Peer_Info of the peer.
508 peer_timeout (void *cls,
509 const struct GNUNET_PeerIdentity *key,
512 struct MeshPeer *p = value;
513 struct GNUNET_TIME_Absolute *abs = cls;
515 if (p->last_contact.abs_value_us == abs->abs_value_us &&
516 GNUNET_NO == peer_is_used (p))
526 * Delete oldest unused peer.
529 peer_delete_oldest (void)
531 struct GNUNET_TIME_Absolute abs;
533 abs = GNUNET_TIME_UNIT_FOREVER_ABS;
535 GNUNET_CONTAINER_multipeermap_iterate (peers,
538 GNUNET_CONTAINER_multipeermap_iterate (peers,
545 * Retrieve the MeshPeer stucture associated with the peer, create one
546 * and insert it in the appropriate structures if the peer is not known yet.
548 * @param peer Full identity of the peer.
550 * @return Existing or newly created peer info.
552 static struct MeshPeer *
553 peer_get (const struct GNUNET_PeerIdentity *peer_id)
555 struct MeshPeer *peer;
557 peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
560 peer = GNUNET_new (struct MeshPeer);
561 if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
563 peer_delete_oldest ();
565 GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
566 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
567 peer->id = GNUNET_PEER_intern (peer_id);
569 peer->last_contact = GNUNET_TIME_absolute_get();
576 * Retrieve the MeshPeer stucture associated with the peer, create one
577 * and insert it in the appropriate structures if the peer is not known yet.
579 * @param peer Short identity of the peer.
581 * @return Existing or newly created peer info.
583 static struct MeshPeer *
584 peer_get_short (const GNUNET_PEER_Id peer)
586 return peer_get (GNUNET_PEER_resolve2 (peer));
591 * Get a cost of a path for a peer considering existing tunnel connections.
593 * @param peer Peer towards which the path is considered.
594 * @param path Candidate path.
596 * @return Cost of the path (path length + number of overlapping nodes)
599 peer_get_path_cost (const struct MeshPeer *peer,
600 const struct MeshPeerPath *path)
602 struct MeshConnection *c;
603 unsigned int overlap;
611 GNUNET_assert (NULL != peer->tunnel);
613 for (i = 0; i < path->length; i++)
615 for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
617 for (j = 0; j < c->path->length; j++)
619 if (path->peers[i] == c->path->peers[j])
627 return (path->length + overlap) * (path->score * -1);
632 * Choose the best path towards a peer considering the tunnel properties.
634 * @param peer The destination peer.
636 * @return Best current known path towards the peer, if any.
638 static struct MeshPeerPath *
639 peer_get_best_path (const struct MeshPeer *peer)
641 struct MeshPeerPath *best_p;
642 struct MeshPeerPath *p;
643 struct MeshConnection *c;
644 unsigned int best_cost;
647 best_cost = UINT_MAX;
649 for (p = peer->path_head; NULL != p; p = p->next)
651 for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
655 continue; /* If path is in use in a connection, skip it. */
657 if ((cost = peer_get_path_cost (peer, p)) < best_cost)
668 * Add the path to the peer and update the path used to reach it in case this
671 * @param peer_info Destination peer to add the path to.
672 * @param path New path to add. Last peer must be the peer in arg 1.
673 * Path will be either used of freed if already known.
674 * @param trusted Do we trust that this path is real?
677 peer_add_path (struct MeshPeer *peer_info, struct MeshPeerPath *path,
680 struct MeshPeerPath *aux;
684 if ((NULL == peer_info) || (NULL == path))
690 if (path->peers[path->length - 1] != peer_info->id)
696 if (2 >= path->length && GNUNET_NO == trusted)
698 /* Only allow CORE to tell us about direct paths */
702 for (l = 1; l < path->length; l++)
704 if (path->peers[l] == myid)
706 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
707 for (l2 = 0; l2 < path->length - l; l2++)
709 path->peers[l2] = path->peers[l + l2];
714 GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
719 path->length, peer2s (peer_info));
721 l = path_get_length (path);
728 GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
729 for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
731 l2 = path_get_length (aux);
734 GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
735 peer_info->path_tail, aux, path);
740 if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
747 GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
754 * Add the path to the origin peer and update the path used to reach it in case
755 * this is the shortest.
756 * The path is given in peer_info -> destination, therefore we turn the path
759 * @param peer_info Peer to add the path to, being the origin of the path.
760 * @param path New path to add after being inversed.
761 * Path will be either used or freed.
762 * @param trusted Do we trust that this path is real?
765 peer_add_path_to_origin (struct MeshPeer *peer_info,
766 struct MeshPeerPath *path, int trusted)
771 peer_add_path (peer_info, path, trusted);
776 * Adds a path to the peer_infos of all the peers in the path
778 * @param p Path to process.
779 * @param confirmed Whether we know if the path works or not.
782 path_add_to_peers (struct MeshPeerPath *p, int confirmed)
786 /* TODO: invert and add */
787 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
788 for (i++; i < p->length; i++)
790 struct MeshPeer *aux;
791 struct MeshPeerPath *copy;
793 aux = peer_get_short (p->peers[i]);
794 copy = path_duplicate (p);
795 copy->length = i + 1;
796 peer_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
802 * Function to process paths received for a new peer addition. The recorded
803 * paths form the initial tunnel, which can be optimized later.
804 * Called on each result obtained for the DHT search.
810 search_handler (void *cls, struct MeshPeerPath *path)
812 struct MeshPeer *peer = cls;
813 unsigned int connection_count;
815 path_add_to_peers (path, GNUNET_NO);
817 /* Count connections */
818 connection_count = GMC_count (peer->tunnel->connection_head);
820 /* If we already have 3 (or more (?!)) connections, it's enough */
821 if (3 <= connection_count)
824 if (peer->tunnel->state == MESH_TUNNEL_SEARCHING)
826 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
834 * Core callback to write a queued packet to core buffer
836 * @param cls Closure (peer info).
837 * @param size Number of bytes available in buf.
838 * @param buf Where the to write the message.
840 * @return number of bytes written to buf
843 queue_send (void *cls, size_t size, void *buf)
845 struct MeshPeer *peer = cls;
846 struct MeshFlowControl *fc;
847 struct MeshConnection *c;
848 struct GNUNET_MessageHeader *msg;
849 struct MeshPeerQueue *queue;
850 struct MeshTunnel2 *t;
851 struct MeshChannel *ch;
852 const struct GNUNET_PeerIdentity *dst_id;
858 peer->core_transmit = NULL;
859 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Queue send (max %u)\n", size);
861 if (NULL == buf || 0 == size)
863 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Buffer size 0.\n");
868 queue = peer_get_first_message (peer);
871 GNUNET_break (0); /* Core tmt_rdy should've been canceled */
876 fc = fwd ? &c->fwd_fc : &c->bck_fc;
878 dst_id = GNUNET_PEER_resolve2 (peer->id);
879 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* towards %s\n", GNUNET_i2s (dst_id));
880 /* Check if buffer size is enough for the message */
881 if (queue->size > size)
883 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* not enough room, reissue\n");
884 peer->core_transmit =
885 GNUNET_CORE_notify_transmit_ready (core_handle,
888 GNUNET_TIME_UNIT_FOREVER_REL,
895 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* size %u ok\n", queue->size);
897 t = (NULL != c) ? c->t : NULL;
903 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
904 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
905 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
906 case GNUNET_MESSAGE_TYPE_MESH_FWD:
907 case GNUNET_MESSAGE_TYPE_MESH_BCK:
908 case GNUNET_MESSAGE_TYPE_MESH_ACK:
909 case GNUNET_MESSAGE_TYPE_MESH_POLL:
910 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
912 GNUNET_MESH_DEBUG_M2S (queue->type));
913 data_size = send_core_data_raw (queue->cls, size, buf);
914 msg = (struct GNUNET_MessageHeader *) buf;
915 type = ntohs (msg->type);
917 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
918 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path create\n");
919 if (GMC_is_origin (c, GNUNET_YES))
920 data_size = send_core_connection_create (queue->c, size, buf);
922 data_size = send_core_data_raw (queue->cls, size, buf);
924 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
925 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* path ack\n");
926 if (GMC_is_origin (c, GNUNET_NO) ||
927 GMC_is_origin (c, GNUNET_YES))
928 data_size = send_core_connection_ack (queue->c, size, buf);
930 data_size = send_core_data_raw (queue->cls, size, buf);
932 case GNUNET_MESSAGE_TYPE_MESH_DATA:
933 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
934 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
935 /* This should be encapsulted */
941 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "* type unknown: %u\n",
946 if (0 < drop_percent &&
947 GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, 101) < drop_percent)
949 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
950 "Dropping message of type %s\n",
951 GNUNET_MESH_DEBUG_M2S (queue->type));
955 /* Free queue, but cls was freed by send_core_* */
957 queue_destroy (queue, GNUNET_NO);
959 /* Send ACK if needed, after accounting for sent ID in fc->queue_n */
962 case GNUNET_MESSAGE_TYPE_MESH_FWD:
963 case GNUNET_MESSAGE_TYPE_MESH_BCK:
964 pid = ntohl ( ((struct GNUNET_MESH_Encrypted *) buf)->pid );
965 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* accounting pid %u\n", pid);
966 fc->last_pid_sent = pid;
967 send_ack (c, ch, fwd);
973 /* If more data in queue, send next */
974 queue = peer_get_first_message (peer);
977 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* more data!\n");
978 if (NULL == peer->core_transmit) {
979 peer->core_transmit =
980 GNUNET_CORE_notify_transmit_ready(core_handle,
983 GNUNET_TIME_UNIT_FOREVER_REL,
991 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
992 "* tmt rdy called somewhere else\n");
994 if (GNUNET_SCHEDULER_NO_TASK == fc->poll_task)
996 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* starting poll timeout\n");
998 GNUNET_SCHEDULER_add_delayed (fc->poll_time, &connection_poll, fc);
1003 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task)
1005 GNUNET_SCHEDULER_cancel (fc->poll_task);
1006 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
1011 c->pending_messages--;
1012 if (GNUNET_YES == c->destroy && 0 == c->pending_messages)
1014 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying connection!\n");
1021 t->pending_messages--;
1022 if (GNUNET_YES == t->destroy && 0 == t->pending_messages)
1024 // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* destroying tunnel!\n");
1028 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "* Return %d\n", data_size);
1035 * Get first sendable message.
1037 * @param peer The destination peer.
1039 * @return Best current known path towards the peer, if any.
1041 static struct MeshPeerQueue *
1042 peer_get_first_message (const struct MeshPeer *peer)
1044 struct MeshPeerQueue *q;
1046 for (q = peer->queue_head; NULL != q; q = q->next)
1048 if (queue_is_sendable (q))
1057 queue_is_sendable (struct MeshPeerQueue *q)
1059 struct MeshFlowControl *fc;
1061 /* Is PID-independent? */
1064 case GNUNET_MESSAGE_TYPE_MESH_ACK:
1065 case GNUNET_MESSAGE_TYPE_MESH_POLL:
1069 /* Is PID allowed? */
1070 fc = q->fwd ? &q->c->fwd_fc : &q->c->bck_fc;
1071 if (GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
1078 /******************************************************************************/
1079 /******************************** API ***********************************/
1080 /******************************************************************************/
1084 * Free a transmission that was already queued with all resources
1085 * associated to the request.
1087 * @param queue Queue handler to cancel.
1088 * @param clear_cls Is it necessary to free associated cls?
1091 GMP_queue_destroy (struct MeshPeerQueue *queue, int clear_cls)
1093 struct MeshPeer *peer;
1094 struct MeshFlowControl *fc;
1099 GNUNET_assert (NULL != queue->c);
1100 fc = fwd ? &queue->c->fwd_fc : &queue->c->bck_fc;
1102 if (GNUNET_YES == clear_cls)
1104 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " queue destroy type %s\n",
1105 GNUNET_MESH_DEBUG_M2S (queue->type));
1106 switch (queue->type)
1108 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY:
1109 case GNUNET_MESSAGE_TYPE_MESH_TUNNEL_DESTROY:
1110 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "destroying a DESTROY message\n");
1111 GNUNET_break (GNUNET_YES == queue->c->destroy);
1113 case GNUNET_MESSAGE_TYPE_MESH_FWD:
1114 case GNUNET_MESSAGE_TYPE_MESH_BCK:
1115 case GNUNET_MESSAGE_TYPE_MESH_ACK:
1116 case GNUNET_MESSAGE_TYPE_MESH_POLL:
1117 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK:
1118 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE:
1119 case GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN:
1120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " prebuilt message\n");;
1121 GNUNET_free_non_null (queue->cls);
1126 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, " type %s unknown!\n",
1127 GNUNET_MESH_DEBUG_M2S (queue->type));
1131 GNUNET_CONTAINER_DLL_remove (peer->queue_head, peer->queue_tail, queue);
1133 if (queue->type != GNUNET_MESSAGE_TYPE_MESH_ACK &&
1134 queue->type != GNUNET_MESSAGE_TYPE_MESH_POLL)
1136 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Q_N- %p %u\n", fc, fc->queue_n);
1140 if (NULL != queue->c)
1142 queue->c->pending_messages--;
1143 if (NULL != queue->c->t)
1145 queue->c->t->pending_messages--;
1149 GNUNET_free (queue);
1154 * @brief Queue and pass message to core when possible.
1156 * @param cls Closure (@c type dependant). It will be used by queue_send to
1157 * build the message to be sent if not already prebuilt.
1158 * @param type Type of the message, 0 for a raw message.
1159 * @param size Size of the message.
1160 * @param c Connection this message belongs to (cannot be NULL).
1161 * @param ch Channel this message belongs to, if applicable (otherwise NULL).
1162 * @param fwd Is this a message going root->dest? (FWD ACK are NOT FWD!)
1165 GMP_queue_add (void *cls, uint16_t type, size_t size,
1166 struct MeshConnection *c,
1167 struct MeshChannel *ch,
1170 struct MeshPeerQueue *queue;
1171 struct MeshFlowControl *fc;
1172 struct MeshPeer *peer;
1176 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1177 "queue add %s %s (%u) on c %p, ch %p\n",
1178 fwd ? "FWD" : "BCK", GNUNET_MESH_DEBUG_M2S (type), size, c, ch);
1179 GNUNET_assert (NULL != c);
1181 fc = fwd ? &c->fwd_fc : &c->bck_fc;
1182 peer = fwd ? connection_get_next_hop (c) : connection_get_prev_hop (c);
1190 if (NULL == peer->connections)
1192 /* We are not connected to this peer, ignore request. */
1193 GNUNET_break_op (0);
1199 if (GNUNET_MESSAGE_TYPE_MESH_POLL == type ||
1200 GNUNET_MESSAGE_TYPE_MESH_ACK == type)
1205 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "priority %d\n", priority);
1206 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "fc %p\n", fc);
1207 if (fc->queue_n >= fc->queue_max && 0 == priority)
1209 GNUNET_STATISTICS_update (stats, "# messages dropped (buffer full)",
1212 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1213 "queue full: %u/%u\n",
1214 fc->queue_n, fc->queue_max);
1215 return; /* Drop this message */
1218 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "last pid %u\n", fc->last_pid_sent);
1219 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ack %u\n", fc->last_ack_recv);
1220 if (GMC_is_pid_bigger (fc->last_pid_sent + 1, fc->last_ack_recv))
1222 call_core = GNUNET_NO;
1223 if (GNUNET_SCHEDULER_NO_TASK == fc->poll_task &&
1224 GNUNET_MESSAGE_TYPE_MESH_POLL != type)
1226 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1227 "no buffer space (%u > %u): starting poll\n",
1228 fc->last_pid_sent + 1, fc->last_ack_recv);
1229 fc->poll_task = GNUNET_SCHEDULER_add_delayed (fc->poll_time,
1235 call_core = GNUNET_YES;
1236 queue = GNUNET_malloc (sizeof (struct MeshPeerQueue));
1244 if (100 <= priority)
1246 struct MeshPeerQueue *copy;
1247 struct MeshPeerQueue *next;
1249 for (copy = peer->queue_head; NULL != copy; copy = next)
1252 if (copy->type == type && copy->c == c && copy->fwd == fwd)
1254 /* Example: also a FWD ACK for connection XYZ */
1255 queue_destroy (copy, GNUNET_YES);
1258 GNUNET_CONTAINER_DLL_insert (peer->queue_head, peer->queue_tail, queue);
1262 GNUNET_CONTAINER_DLL_insert_tail (peer->queue_head, peer->queue_tail, queue);
1263 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Q_N+ %p %u\n", fc, fc->queue_n);
1268 if (NULL == peer->core_transmit && GNUNET_YES == call_core)
1270 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1271 "calling core tmt rdy towards %s for %u bytes\n",
1272 peer2s (peer), size);
1273 peer->core_transmit =
1274 GNUNET_CORE_notify_transmit_ready (core_handle,
1277 GNUNET_TIME_UNIT_FOREVER_REL,
1278 GNUNET_PEER_resolve2 (peer->id),
1285 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1286 "core tmt rdy towards %s already called\n",
1290 c->pending_messages++;
1292 c->t->pending_messages++;
1298 * Initialize the peer subsystem.
1300 * @param c Configuration.
1301 * @param id Peer identity
1304 GMP_init (const struct GNUNET_CONFIGURATION_Handle *c,
1305 const struct GNUNET_PeerIdentity *id)
1308 peers = GNUNET_CONTAINER_multipeermap_create (128, GNUNET_NO);
1310 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
1313 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1314 "MESH", "MAX_PEERS", "USING DEFAULT");
1319 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT",
1326 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1327 "\n***************************************\n"
1328 "Mesh is running with drop mode enabled.\n"
1329 "This is NOT a good idea!\n"
1330 "Remove the DROP_PERCENT option from your configuration.\n"
1331 "***************************************\n");
1334 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
1335 NULL, /* Closure passed to MESH functions */
1336 &core_init, /* Call core_init once connected */
1337 &core_connect, /* Handle connects */
1338 &core_disconnect, /* remove peers on disconnects */
1339 NULL, /* Don't notify about all incoming messages */
1340 GNUNET_NO, /* For header only in notification */
1341 NULL, /* Don't notify about all outbound messages */
1342 GNUNET_NO, /* For header-only out notification */
1343 core_handlers); /* Register these handlers */
1344 if (NULL == core_handle)
1347 GNUNET_SCHEDULER_shutdown ();
1353 * Shut down the peer subsystem.
1358 GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
1363 * Try to establish a new connection to this peer in the given tunnel.
1364 * If the peer doesn't have any path to it yet, try to get one.
1365 * If the peer already has some path, send a CREATE CONNECTION towards it.
1367 * @param peer PeerInfo of the peer.
1370 GMP_connect (struct MeshPeer *peer)
1372 struct MeshTunnel2 *t;
1373 struct MeshPeerPath *p;
1374 struct MeshConnection *c;
1377 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1378 "peer_connect towards %s\n",
1382 rerun_search = GNUNET_NO;
1384 if (NULL != peer->path_head)
1386 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "path exists\n");
1387 p = peer_get_best_path (peer);
1390 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u hops\n", p->length);
1391 c = tunnel_use_path (t, p);
1394 /* This case can happen when the path includes a first hop that is
1395 * not yet known to be connected.
1397 * This happens quite often during testing when running mesh
1398 * under valgrind: core connect notifications come very late and the
1399 * DHT result has already come and created a valid path.
1400 * In this case, the peer->connections hashmap will be NULL and
1401 * tunnel_use_path will not be able to create a connection from that
1404 * Re-running the DHT GET should give core time to callback.
1407 rerun_search = GNUNET_YES;
1411 send_connection_create (c);
1417 if (NULL != peer->search_h && GNUNET_YES == rerun_search)
1419 GMD_search_stop (peer->search_h);
1420 peer->search_h = NULL;
1421 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1422 " Stopping DHT GET for peer %s\n", peer2s (peer));
1425 if (NULL == peer->search_h)
1427 const struct GNUNET_PeerIdentity *id;
1429 id = GNUNET_PEER_resolve2 (peer->id);
1430 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1431 " Starting DHT GET for peer %s\n", peer2s (peer));
1432 peer->search_h = GMD_search (id, &search_handler, peer);
1433 if (MESH_TUNNEL_NEW == t->state)
1434 tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
1439 * Get the static string for a peer ID.
1443 * @return Static string for it's ID.
1446 GMP_2s (const struct MeshPeer *peer)
1450 return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));