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-enc.c
23 * @brief GNUnet MESH service with encryption
24 * @author Bartlomiej Polot
27 * - when sending in-order buffered data, wait for client ACKs
30 * - set connection IDs independently from tunnel, tunnel has no ID
33 * - relay corking down to core
34 * - set ttl relative to path length
38 * - peer: other mesh instance. If there is direct connection it's a neighbor.
39 * - tunnel: encrypted connection to a peer, neighbor or not.
40 * - channel: connection between two clients, on the same or different peers.
41 * have properties like reliability.
42 * - path: series of directly connected peer from one peer to another.
43 * - connection: path which is being used in a tunnel.
47 #include "gnunet_util_lib.h"
49 #include "mesh_protocol_enc.h"
50 #include "mesh_path.h"
51 #include "block_mesh.h"
52 #include "gnunet_dht_service.h"
53 #include "gnunet_statistics_service.h"
55 #include "gnunet-service-mesh_local.h"
56 #include "gnunet-service-mesh_channel.h"
57 #include "gnunet-service-mesh_connection.h"
59 #define MESH_BLOOM_SIZE 128
60 #define MESH_MAX_POLL_TIME GNUNET_TIME_relative_multiply (\
61 GNUNET_TIME_UNIT_MINUTES,\
63 #define MESH_RETRANSMIT_TIME GNUNET_TIME_UNIT_SECONDS
64 #define MESH_RETRANSMIT_MARGIN 4
66 #define MESH_DEBUG_DHT GNUNET_NO
67 #define MESH_DEBUG_CONNECTION GNUNET_NO
68 #define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO
71 #define DEBUG_DHT(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
73 #define DEBUG_DHT(...)
76 #if MESH_DEBUG_CONNECTION
77 #define DEBUG_CONN(...) GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, __VA_ARGS__)
79 #define DEBUG_CONN(...)
86 struct timespec __mesh_start;
87 struct timespec __mesh_end;
88 #define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start))
89 #define INTERVAL_END \
91 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\
92 double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\
93 if (__diff < 0) __diff += 1000000000;\
97 #define INTERVAL_SHOW \
99 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", __sum/__count)
101 #define INTERVAL_START
103 #define INTERVAL_SHOW
107 * All the states a tunnel can be in.
112 * Uninitialized status, should never appear in operation.
117 * Path to the peer not known yet
119 MESH_TUNNEL_SEARCHING,
122 * Request sent, not yet answered.
127 * Peer connected and ready to accept data
132 * Peer connected previosly but not responding
134 MESH_TUNNEL_RECONNECTING
139 /******************************************************************************/
140 /************************ DATA STRUCTURES ****************************/
141 /******************************************************************************/
143 /** FWD declaration */
147 struct MeshConnection;
152 * Struct containing all information regarding a given peer
162 * Last time we heard from this peer
164 struct GNUNET_TIME_Absolute last_contact;
167 * Paths to reach the peer, ordered by ascending hop count
169 struct MeshPeerPath *path_head;
172 * Paths to reach the peer, ordered by ascending hop count
174 struct MeshPeerPath *path_tail;
177 * Handle to stop the DHT search for paths to this peer
179 struct GNUNET_DHT_GetHandle *dhtget;
182 * Tunnel to this peer, if any.
184 struct MeshTunnel2 *tunnel;
187 * Connections that go through this peer, indexed by tid;
189 struct GNUNET_CONTAINER_MultiHashMap *connections;
192 * Handle for queued transmissions
194 struct GNUNET_CORE_TransmitHandle *core_transmit;
197 * Transmission queue to core DLL head
199 struct MeshPeerQueue *queue_head;
202 * Transmission queue to core DLL tail
204 struct MeshPeerQueue *queue_tail;
207 * How many messages are in the queue to this peer.
209 unsigned int queue_n;
216 * Struct used to queue messages in a tunnel.
218 struct MeshTunnelQueue
223 struct MeshTunnelQueue *next;
224 struct MeshTunnelQueue *prev;
229 struct MeshChannel *ch;
234 /* struct GNUNET_MessageHeader *msg; */
239 * Struct containing all information regarding a tunnel to a peer.
244 * Endpoint of the tunnel.
246 struct MeshPeer *peer;
249 * State of the tunnel.
251 enum MeshTunnelState state;
254 * Local peer ephemeral private key
256 struct GNUNET_CRYPTO_EccPrivateKey *my_eph_key;
259 * Local peer ephemeral public key
261 struct GNUNET_CRYPTO_EccPublicSignKey *my_eph;
264 * Remote peer's public key.
266 struct GNUNET_CRYPTO_EccPublicSignKey *peers_eph;
269 * Encryption ("our") key.
271 struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
274 * Decryption ("their") key.
276 struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
279 * Paths that are actively used to reach the destination peer.
281 struct MeshConnection *connection_head;
282 struct MeshConnection *connection_tail;
285 * Next connection number.
290 * Channels inside this tunnel.
292 struct MeshChannel *channel_head;
293 struct MeshChannel *channel_tail;
296 * Channel ID for the next created channel.
298 MESH_ChannelNumber next_chid;
301 * Channel ID for the next incoming channel.
303 MESH_ChannelNumber next_local_chid;
306 * Pending message count.
308 int pending_messages;
311 * Destroy flag: if true, destroy on last message.
316 * Queued messages, to transmit once tunnel gets connected.
318 struct MeshTunnelQueue *tq_head;
319 struct MeshTunnelQueue *tq_tail;
324 /******************************************************************************/
325 /************************ DEBUG FUNCTIONS ****************************/
326 /******************************************************************************/
330 * GNUNET_SCHEDULER_Task for printing a message after some operation is done
331 * @param cls string to print
332 * @param success GNUNET_OK if the PUT was transmitted,
333 * GNUNET_NO on timeout,
334 * GNUNET_SYSERR on disconnect from service
335 * after the PUT message was transmitted
336 * (so we don't know if it was received or not)
341 mesh_debug (void *cls, int success)
345 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
351 /******************************************************************************/
352 /*********************** GLOBAL VARIABLES ****************************/
353 /******************************************************************************/
355 /************************** Configuration parameters **************************/
358 * How often to PUT own ID in the DHT.
360 static struct GNUNET_TIME_Relative id_announce_time;
363 * Maximum time allowed to connect to a peer found by string.
365 static struct GNUNET_TIME_Relative connect_timeout;
368 * Default TTL for payload packets.
370 static unsigned long long default_ttl;
373 * DHT replication level, see DHT API: GNUNET_DHT_get_start, GNUNET_DHT_put.
375 static unsigned long long dht_replication_level;
378 * How many peers do we want to remember?
380 static unsigned long long max_peers;
383 * Percentage of messages that will be dropped (for test purposes only).
385 static unsigned long long drop_percent;
387 /*************************** Static global variables **************************/
390 * Peers known, indexed by PeerIdentity (MeshPeer).
392 static struct GNUNET_CONTAINER_MultiPeerMap *peers;
395 * Handle to communicate with core.
397 static struct GNUNET_CORE_Handle *core_handle;
402 static struct GNUNET_DHT_Handle *dht_handle;
405 * Handle to the statistics service.
407 static struct GNUNET_STATISTICS_Handle *stats;
410 * Local peer own ID (memory efficient handle).
412 static GNUNET_PEER_Id myid;
415 * Local peer own ID (full value).
417 static struct GNUNET_PeerIdentity my_full_id;
422 static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
425 * Task to periodically announce itself in the network.
427 GNUNET_SCHEDULER_TaskIdentifier announce_id_task;
430 /******************************************************************************/
431 /*********************** DECLARATIONS **************************/
432 /******************************************************************************/
435 * Function to process paths received for a new peer addition. The recorded
436 * paths form the initial tunnel, which can be optimized later.
437 * Called on each result obtained for the DHT search.
440 * @param exp when will this value expire
441 * @param key key of the result
442 * @param type type of the result
443 * @param size number of bytes in data
444 * @param data pointer to the result data
447 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
448 const struct GNUNET_HashCode * key,
449 const struct GNUNET_PeerIdentity *get_path,
450 unsigned int get_path_length,
451 const struct GNUNET_PeerIdentity *put_path,
452 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
453 size_t size, const void *data);
457 * Retrieve the MeshPeer stucture associated with the peer, create one
458 * and insert it in the appropriate structures if the peer is not known yet.
460 * @param peer Full identity of the peer.
462 * @return Existing or newly created peer info.
464 static struct MeshPeer *
465 peer_get (const struct GNUNET_PeerIdentity *peer);
469 * Retrieve the MeshPeer stucture associated with the peer, create one
470 * and insert it in the appropriate structures if the peer is not known yet.
472 * @param peer Short identity of the peer.
474 * @return Existing or newly created peer info.
476 static struct MeshPeer *
477 peer_get_short (const GNUNET_PEER_Id peer);
481 * Build a PeerPath from the paths returned from the DHT, reversing the paths
482 * to obtain a local peer -> destination path and interning the peer ids.
484 * @return Newly allocated and created path
486 static struct MeshPeerPath *
487 path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
488 unsigned int get_path_length,
489 const struct GNUNET_PeerIdentity *put_path,
490 unsigned int put_path_length);
494 * Adds a path to the data structs of all the peers in the path
496 * @param p Path to process.
497 * @param confirmed Whether we know if the path works or not.
500 path_add_to_peers (struct MeshPeerPath *p, int confirmed);
504 * Change the tunnel state.
506 * @param t Tunnel whose state to change.
507 * @param state New state.
510 tunnel_change_state (struct MeshTunnel2 *t, enum MeshTunnelState state);
514 * Notify a tunnel that a connection has broken that affects at least
517 * @param t Tunnel affected.
518 * @param p1 Peer that got disconnected from p2.
519 * @param p2 Peer that got disconnected from p1.
521 * @return Short ID of the peer disconnected (either p1 or p2).
522 * 0 if the tunnel remained unaffected.
524 static GNUNET_PEER_Id
525 tunnel_notify_connection_broken (struct MeshTunnel2 *t,
526 GNUNET_PEER_Id p1, GNUNET_PEER_Id p2);
529 * @brief Use the given path for the tunnel.
530 * Update the next and prev hops (and RCs).
531 * (Re)start the path refresh in case the tunnel is locally owned.
533 * @param t Tunnel to update.
534 * @param p Path to use.
536 * @return Connection created.
538 static struct MeshConnection *
539 tunnel_use_path (struct MeshTunnel2 *t, struct MeshPeerPath *p);
542 * Tunnel is empty: destroy it.
544 * Notifies all participants (peers, cleints) about the destruction.
546 * @param t Tunnel to destroy.
549 tunnel_destroy_empty (struct MeshTunnel2 *t);
552 * Destroy the tunnel.
554 * This function does not generate any warning traffic to clients or peers.
557 * Cancel messages belonging to this tunnel queued to neighbors.
558 * Free any allocated resources linked to the tunnel.
560 * @param t The tunnel to destroy.
563 tunnel_destroy (struct MeshTunnel2 *t);
567 * Demultiplex by message type and call appropriate handler for a message
568 * towards a channel of a local tunnel.
570 * @param t Tunnel this message came on.
571 * @param msgh Message header.
572 * @param fwd Is this message fwd?
575 handle_decrypted (struct MeshTunnel2 *t,
576 const struct GNUNET_MessageHeader *msgh,
581 * Dummy function to separate declarations from definitions in function list.
584 __mesh_divider______________________________________________________________();
588 * Get string description for tunnel state.
590 * @param s Tunnel state.
592 * @return String representation.
595 GNUNET_MESH_DEBUG_TS2S (enum MeshTunnelState s)
597 static char buf[128];
601 case MESH_TUNNEL_NEW:
602 return "MESH_TUNNEL_NEW";
603 case MESH_TUNNEL_SEARCHING:
604 return "MESH_TUNNEL_SEARCHING";
605 case MESH_TUNNEL_WAITING:
606 return "MESH_TUNNEL_WAITING";
607 case MESH_TUNNEL_READY:
608 return "MESH_TUNNEL_READY";
609 case MESH_TUNNEL_RECONNECTING:
610 return "MESH_TUNNEL_RECONNECTING";
613 sprintf (buf, "%u (UNKNOWN STATE)", s);
620 * Get string description for tunnel state.
622 * @param s Tunnel state.
624 * @return String representation.
627 GNUNET_MESH_DEBUG_CS2S (enum MeshTunnelState s)
631 case MESH_CONNECTION_NEW:
632 return "MESH_CONNECTION_NEW";
633 case MESH_CONNECTION_SENT:
634 return "MESH_CONNECTION_SENT";
635 case MESH_CONNECTION_ACK:
636 return "MESH_CONNECTION_ACK";
637 case MESH_CONNECTION_READY:
638 return "MESH_CONNECTION_READY";
640 return "MESH_CONNECTION_STATE_ERROR";
646 /******************************************************************************/
647 /************************ PERIODIC FUNCTIONS ****************************/
648 /******************************************************************************/
651 * Periodically announce self id in the DHT
654 * @param tc task context
657 announce_id (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
660 struct GNUNET_HashCode phash;
662 if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
664 announce_id_task = GNUNET_SCHEDULER_NO_TASK;
668 * - Set data expiration in function of X
671 DEBUG_DHT ("DHT_put for ID %s started.\n", GNUNET_i2s (&my_full_id));
673 block.id = my_full_id;
674 GNUNET_CRYPTO_hash (&my_full_id, sizeof (struct GNUNET_PeerIdentity), &phash);
675 GNUNET_DHT_put (dht_handle, /* DHT handle */
676 &phash, /* Key to use */
677 dht_replication_level, /* Replication level */
678 GNUNET_DHT_RO_RECORD_ROUTE | GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE, /* DHT options */
679 GNUNET_BLOCK_TYPE_MESH_PEER, /* Block type */
680 sizeof (block), /* Size of the data */
681 (const char *) &block, /* Data itself */
682 GNUNET_TIME_UNIT_FOREVER_ABS, /* Data expiration */
683 GNUNET_TIME_UNIT_FOREVER_REL, /* Retry time */
684 NULL, /* Continuation */
685 NULL); /* Continuation closure */
687 GNUNET_SCHEDULER_add_delayed (id_announce_time, &announce_id, cls);
691 /******************************************************************************/
692 /****************** GENERAL HELPER FUNCTIONS ************************/
693 /******************************************************************************/
697 * Get the static string for a peer ID.
701 * @return Static string for it's ID.
704 peer2s (const struct MeshPeer *peer)
708 return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
714 * Count established (ready) connections of a tunnel.
716 * @param t Tunnel on which to send the message.
718 * @return Number of connections.
721 tunnel_count_connections (struct MeshTunnel2 *t)
723 struct MeshConnection *c;
726 for (c = t->connection_head, i = 0; NULL != c; c = c->next, i++);
733 * Pick a connection on which send the next data message.
735 * @param t Tunnel on which to send the message.
736 * @param fwd Is this a fwd message?
738 * @return The connection on which to send the next message.
740 static struct MeshConnection *
741 tunnel_get_connection (struct MeshTunnel2 *t, int fwd)
743 struct MeshConnection *c;
744 struct MeshConnection *best;
745 struct MeshFlowControl *fc;
746 unsigned int lowest_q;
748 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n",
752 for (c = t->connection_head; NULL != c; c = c->next)
754 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n",
755 GNUNET_h2s (&c->id), c->state);
756 if (MESH_CONNECTION_READY == c->state)
758 fc = fwd ? &c->fwd_fc : &c->bck_fc;
764 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", fc->queue_n);
765 if (fc->queue_n < lowest_q)
768 lowest_q = fc->queue_n;
779 * Get the total buffer space for a tunnel.
782 * @param fwd Is this for FWD traffic?
784 * @return Buffer space offered by all connections in the tunnel.
787 tunnel_get_buffer (struct MeshTunnel2 *t, int fwd)
789 struct MeshConnection *c;
790 struct MeshFlowControl *fc;
793 c = t->connection_head;
796 /* If terminal, return biggest channel buffer */
797 if (NULL == c || GMC_is_terminal (c, fwd))
799 struct MeshChannel *ch;
802 if (NULL == t->channel_head)
805 for (ch = t->channel_head; NULL != ch; ch = ch->next)
807 ch_buf = channel_get_buffer (ch, fwd);
814 /* If not terminal, return sum of connection buffers */
817 if (c->state != MESH_CONNECTION_READY)
823 fc = fwd ? &c->fwd_fc : &c->bck_fc;
824 buffer += fc->queue_max - fc->queue_n;
833 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
834 * Encrypt data with the tunnel key.
836 * @param t Tunnel whose key to use.
837 * @param dst Destination for the encrypted data.
838 * @param src Source of the plaintext.
839 * @param size Size of the plaintext.
840 * @param iv Initialization Vector to use.
841 * @param fwd Is this a fwd message?
844 tunnel_encrypt (struct MeshTunnel2 *t,
845 void *dst, const void *src,
846 size_t size, uint64_t iv, int fwd)
848 memcpy (dst, src, size);
853 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
854 * Decrypt data with the tunnel key.
856 * @param t Tunnel whose key to use.
857 * @param dst Destination for the plaintext.
858 * @param src Source of the encrypted data.
859 * @param size Size of the encrypted data.
860 * @param iv Initialization Vector to use.
861 * @param fwd Is this a fwd message?
864 tunnel_decrypt (struct MeshTunnel2 *t,
865 void *dst, const void *src,
866 size_t size, uint64_t iv, int fwd)
868 memcpy (dst, src, size);
873 * Sends an already built message on a tunnel, choosing the best connection.
875 * @param message Message to send. Function modifies it.
876 * @param t Tunnel on which this message is transmitted.
877 * @param ch Channel on which this message is transmitted.
878 * @param fwd Is this a fwd message?
881 send_prebuilt_message_tunnel (struct GNUNET_MESH_Encrypted *msg,
882 struct MeshTunnel2 *t,
883 struct MeshChannel *ch,
886 struct MeshConnection *c;
889 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send on Tunnel %s\n",
891 c = tunnel_get_connection (t, fwd);
894 GNUNET_break (GNUNET_YES == t->destroy);
897 type = ntohs (msg->header.type);
900 case GNUNET_MESSAGE_TYPE_MESH_FWD:
901 case GNUNET_MESSAGE_TYPE_MESH_BCK:
902 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
903 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
905 msg->ttl = htonl (default_ttl);
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
909 GNUNET_MESH_DEBUG_M2S (type));
914 send_prebuilt_message_connection (&msg->header, c, ch, fwd);
920 * Sends a CREATE CONNECTION message for a path to a peer.
921 * Changes the connection and tunnel states if necessary.
923 * @param connection Connection to create.
926 send_connection_create (struct MeshConnection *connection)
928 struct MeshTunnel2 *t;
931 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
933 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
934 sizeof (struct GNUNET_MESH_ConnectionCreate) +
935 (connection->path->length *
936 sizeof (struct GNUNET_PeerIdentity)),
941 (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
942 tunnel_change_state (t, MESH_TUNNEL_WAITING);
943 if (MESH_CONNECTION_NEW == connection->state)
944 connection_change_state (connection, MESH_CONNECTION_SENT);
949 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
952 * @param connection Connection to confirm.
953 * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
956 send_connection_ack (struct MeshConnection *connection, int fwd)
958 struct MeshTunnel2 *t;
961 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
963 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
964 sizeof (struct GNUNET_MESH_ConnectionACK),
968 if (MESH_TUNNEL_NEW == t->state)
969 tunnel_change_state (t, MESH_TUNNEL_WAITING);
970 if (MESH_CONNECTION_READY != connection->state)
971 connection_change_state (connection, MESH_CONNECTION_SENT);
976 * Core callback to write a pre-constructed data packet to core buffer
978 * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
979 * @param size Number of bytes available in buf.
980 * @param buf Where the to write the message.
982 * @return number of bytes written to buf
985 send_core_data_raw (void *cls, size_t size, void *buf)
987 struct GNUNET_MessageHeader *msg = cls;
990 GNUNET_assert (NULL != msg);
991 total_size = ntohs (msg->size);
993 if (total_size > size)
998 memcpy (buf, msg, total_size);
1005 * Function to send a create connection message to a peer.
1007 * @param c Connection to create.
1008 * @param size number of bytes available in buf
1009 * @param buf where the callee should write the message
1010 * @return number of bytes written to buf
1013 send_core_connection_create (struct MeshConnection *c, size_t size, void *buf)
1015 struct GNUNET_MESH_ConnectionCreate *msg;
1016 struct GNUNET_PeerIdentity *peer_ptr;
1017 struct MeshPeerPath *p = c->path;
1021 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
1023 sizeof (struct GNUNET_MESH_ConnectionCreate) +
1024 p->length * sizeof (struct GNUNET_PeerIdentity);
1026 if (size < size_needed || NULL == buf)
1031 msg = (struct GNUNET_MESH_ConnectionCreate *) buf;
1032 msg->header.size = htons (size_needed);
1033 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE);
1036 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
1037 for (i = 0; i < p->length; i++)
1039 GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
1042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1043 "CONNECTION CREATE (%u bytes long) sent!\n", size_needed);
1049 * Creates a path ack message in buf and frees all unused resources.
1051 * @param c Connection to send an ACK on.
1052 * @param size number of bytes available in buf
1053 * @param buf where the callee should write the message
1055 * @return number of bytes written to buf
1058 send_core_connection_ack (struct MeshConnection *c, size_t size, void *buf)
1060 struct GNUNET_MESH_ConnectionACK *msg = buf;
1061 struct MeshTunnel2 *t = c->t;
1063 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
1064 GNUNET_assert (NULL != t);
1065 if (sizeof (struct GNUNET_MESH_ConnectionACK) > size)
1070 msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK));
1071 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK);
1075 /* TODO add signature */
1077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
1078 return sizeof (struct GNUNET_MESH_ConnectionACK);
1083 * Destroy the peer_info and free any allocated resources linked to it
1085 * @param peer The peer_info to destroy.
1087 * @return GNUNET_OK on success
1090 peer_destroy (struct MeshPeer *peer)
1092 struct GNUNET_PeerIdentity id;
1093 struct MeshPeerPath *p;
1094 struct MeshPeerPath *nextp;
1096 GNUNET_PEER_resolve (peer->id, &id);
1097 GNUNET_PEER_change_rc (peer->id, -1);
1100 GNUNET_CONTAINER_multipeermap_remove (peers, &id, peer))
1103 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1104 "removing peer %s, not in peermap\n", GNUNET_i2s (&id));
1106 if (NULL != peer->dhtget)
1108 GNUNET_DHT_get_stop (peer->dhtget);
1110 p = peer->path_head;
1114 GNUNET_CONTAINER_DLL_remove (peer->path_head, peer->path_tail, p);
1118 tunnel_destroy_empty (peer->tunnel);
1125 * Returns if peer is used (has a tunnel, is neighbor).
1127 * @peer Peer to check.
1129 * @return GNUNET_YES if peer is in use.
1132 peer_is_used (struct MeshPeer *peer)
1134 struct MeshPeerPath *p;
1136 if (NULL != peer->tunnel)
1139 for (p = peer->path_head; NULL != p; p = p->next)
1149 * Iterator over all the peers to get the oldest timestamp.
1151 * @param cls Closure (unsued).
1152 * @param key ID of the peer.
1153 * @param value Peer_Info of the peer.
1156 peer_get_oldest (void *cls,
1157 const struct GNUNET_PeerIdentity *key,
1160 struct MeshPeer *p = value;
1161 struct GNUNET_TIME_Absolute *abs = cls;
1163 /* Don't count active peers */
1164 if (GNUNET_YES == peer_is_used (p))
1167 if (abs->abs_value_us < p->last_contact.abs_value_us)
1168 abs->abs_value_us = p->last_contact.abs_value_us;
1175 * Iterator over all the peers to remove the oldest entry.
1177 * @param cls Closure (unsued).
1178 * @param key ID of the peer.
1179 * @param value Peer_Info of the peer.
1182 peer_timeout (void *cls,
1183 const struct GNUNET_PeerIdentity *key,
1186 struct MeshPeer *p = value;
1187 struct GNUNET_TIME_Absolute *abs = cls;
1189 if (p->last_contact.abs_value_us == abs->abs_value_us &&
1190 GNUNET_NO == peer_is_used (p))
1200 * Delete oldest unused peer.
1203 peer_delete_oldest (void)
1205 struct GNUNET_TIME_Absolute abs;
1207 abs = GNUNET_TIME_UNIT_FOREVER_ABS;
1209 GNUNET_CONTAINER_multipeermap_iterate (peers,
1212 GNUNET_CONTAINER_multipeermap_iterate (peers,
1219 * Retrieve the MeshPeer stucture associated with the peer, create one
1220 * and insert it in the appropriate structures if the peer is not known yet.
1222 * @param peer Full identity of the peer.
1224 * @return Existing or newly created peer info.
1226 static struct MeshPeer *
1227 peer_get (const struct GNUNET_PeerIdentity *peer_id)
1229 struct MeshPeer *peer;
1231 peer = GNUNET_CONTAINER_multipeermap_get (peers, peer_id);
1234 peer = GNUNET_new (struct MeshPeer);
1235 if (GNUNET_CONTAINER_multipeermap_size (peers) > max_peers)
1237 peer_delete_oldest ();
1239 GNUNET_CONTAINER_multipeermap_put (peers, peer_id, peer,
1240 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1241 peer->id = GNUNET_PEER_intern (peer_id);
1243 peer->last_contact = GNUNET_TIME_absolute_get();
1250 * Retrieve the MeshPeer stucture associated with the peer, create one
1251 * and insert it in the appropriate structures if the peer is not known yet.
1253 * @param peer Short identity of the peer.
1255 * @return Existing or newly created peer info.
1257 static struct MeshPeer *
1258 peer_get_short (const GNUNET_PEER_Id peer)
1260 return peer_get (GNUNET_PEER_resolve2 (peer));
1265 * Get a cost of a path for a peer considering existing tunnel connections.
1267 * @param peer Peer towards which the path is considered.
1268 * @param path Candidate path.
1270 * @return Cost of the path (path length + number of overlapping nodes)
1273 peer_get_path_cost (const struct MeshPeer *peer,
1274 const struct MeshPeerPath *path)
1276 struct MeshConnection *c;
1277 unsigned int overlap;
1285 GNUNET_assert (NULL != peer->tunnel);
1287 for (i = 0; i < path->length; i++)
1289 for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
1291 for (j = 0; j < c->path->length; j++)
1293 if (path->peers[i] == c->path->peers[j])
1301 return (path->length + overlap) * (path->score * -1);
1306 * Choose the best path towards a peer considering the tunnel properties.
1308 * @param peer The destination peer.
1310 * @return Best current known path towards the peer, if any.
1312 static struct MeshPeerPath *
1313 peer_get_best_path (const struct MeshPeer *peer)
1315 struct MeshPeerPath *best_p;
1316 struct MeshPeerPath *p;
1317 struct MeshConnection *c;
1318 unsigned int best_cost;
1321 best_cost = UINT_MAX;
1323 for (p = peer->path_head; NULL != p; p = p->next)
1325 for (c = peer->tunnel->connection_head; NULL != c; c = c->next)
1329 continue; /* If path is in use in a connection, skip it. */
1331 if ((cost = peer_get_path_cost (peer, p)) < best_cost)
1343 * Try to establish a new connection to this peer in the given tunnel.
1344 * If the peer doesn't have any path to it yet, try to get one.
1345 * If the peer already has some path, send a CREATE CONNECTION towards it.
1347 * @param peer PeerInfo of the peer.
1350 peer_connect (struct MeshPeer *peer)
1352 struct MeshTunnel2 *t;
1353 struct MeshPeerPath *p;
1354 struct MeshConnection *c;
1357 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1358 "peer_connect towards %s\n",
1362 rerun_dhtget = GNUNET_NO;
1364 if (NULL != peer->path_head)
1366 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "path exists\n");
1367 p = peer_get_best_path (peer);
1370 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u hops\n", p->length);
1371 c = tunnel_use_path (t, p);
1374 /* This case can happen when the path includes a first hop that is
1375 * not yet known to be connected.
1377 * This happens quite often during testing when running mesh
1378 * under valgrind: core connect notifications come very late and the
1379 * DHT result has already come and created a valid path.
1380 * In this case, the peer->connections hashmap will be NULL and
1381 * tunnel_use_path will not be able to create a connection from that
1384 * Re-running the DHT GET should give core time to callback.
1387 rerun_dhtget = GNUNET_YES;
1391 send_connection_create (c);
1397 if (NULL != peer->dhtget && GNUNET_YES == rerun_dhtget)
1399 GNUNET_DHT_get_stop (peer->dhtget);
1400 peer->dhtget = NULL;
1401 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1402 " Stopping DHT GET for peer %s\n", peer2s (peer));
1405 if (NULL == peer->dhtget)
1407 const struct GNUNET_PeerIdentity *id;
1408 struct GNUNET_HashCode phash;
1410 id = GNUNET_PEER_resolve2 (peer->id);
1411 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1412 " Starting DHT GET for peer %s\n", peer2s (peer));
1413 GNUNET_CRYPTO_hash (&id, sizeof (struct GNUNET_PeerIdentity), &phash);
1414 peer->dhtget = GNUNET_DHT_get_start (dht_handle, /* handle */
1415 GNUNET_BLOCK_TYPE_MESH_PEER, /* type */
1416 &phash, /* key to search */
1417 dht_replication_level, /* replication level */
1418 GNUNET_DHT_RO_RECORD_ROUTE |
1419 GNUNET_DHT_RO_DEMULTIPLEX_EVERYWHERE,
1421 0, /* xquery bits */
1422 &dht_get_id_handler, peer);
1423 if (MESH_TUNNEL_NEW == t->state)
1424 tunnel_change_state (t, MESH_TUNNEL_SEARCHING);
1431 * Add the path to the peer and update the path used to reach it in case this
1434 * @param peer_info Destination peer to add the path to.
1435 * @param path New path to add. Last peer must be the peer in arg 1.
1436 * Path will be either used of freed if already known.
1437 * @param trusted Do we trust that this path is real?
1440 peer_add_path (struct MeshPeer *peer_info, struct MeshPeerPath *path,
1443 struct MeshPeerPath *aux;
1447 if ((NULL == peer_info) || (NULL == path))
1450 path_destroy (path);
1453 if (path->peers[path->length - 1] != peer_info->id)
1456 path_destroy (path);
1459 if (2 >= path->length && GNUNET_NO == trusted)
1461 /* Only allow CORE to tell us about direct paths */
1462 path_destroy (path);
1465 for (l = 1; l < path->length; l++)
1467 if (path->peers[l] == myid)
1469 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shortening path by %u\n", l);
1470 for (l2 = 0; l2 < path->length - l; l2++)
1472 path->peers[l2] = path->peers[l + l2];
1477 GNUNET_realloc (path->peers, path->length * sizeof (GNUNET_PEER_Id));
1481 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "adding path [%u] to peer %s\n",
1482 path->length, peer2s (peer_info));
1484 l = path_get_length (path);
1487 path_destroy (path);
1491 GNUNET_assert (peer_info->id == path->peers[path->length - 1]);
1492 for (aux = peer_info->path_head; aux != NULL; aux = aux->next)
1494 l2 = path_get_length (aux);
1497 GNUNET_CONTAINER_DLL_insert_before (peer_info->path_head,
1498 peer_info->path_tail, aux, path);
1503 if (l2 == l && memcmp (path->peers, aux->peers, l) == 0)
1505 path_destroy (path);
1510 GNUNET_CONTAINER_DLL_insert_tail (peer_info->path_head, peer_info->path_tail,
1517 * Add the path to the origin peer and update the path used to reach it in case
1518 * this is the shortest.
1519 * The path is given in peer_info -> destination, therefore we turn the path
1520 * upside down first.
1522 * @param peer_info Peer to add the path to, being the origin of the path.
1523 * @param path New path to add after being inversed.
1524 * Path will be either used or freed.
1525 * @param trusted Do we trust that this path is real?
1528 peer_add_path_to_origin (struct MeshPeer *peer_info,
1529 struct MeshPeerPath *path, int trusted)
1534 peer_add_path (peer_info, path, trusted);
1538 * Build a PeerPath from the paths returned from the DHT, reversing the paths
1539 * to obtain a local peer -> destination path and interning the peer ids.
1541 * @return Newly allocated and created path
1543 static struct MeshPeerPath *
1544 path_build_from_dht (const struct GNUNET_PeerIdentity *get_path,
1545 unsigned int get_path_length,
1546 const struct GNUNET_PeerIdentity *put_path,
1547 unsigned int put_path_length)
1549 struct MeshPeerPath *p;
1555 GNUNET_PEER_change_rc (myid, 1);
1556 i = get_path_length;
1557 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " GET has %d hops.\n", i);
1558 for (i--; i >= 0; i--)
1560 id = GNUNET_PEER_intern (&get_path[i]);
1561 if (p->length > 0 && id == p->peers[p->length - 1])
1563 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n");
1564 GNUNET_PEER_change_rc (id, -1);
1568 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from GET: %s.\n",
1569 GNUNET_i2s (&get_path[i]));
1571 p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
1572 p->peers[p->length - 1] = id;
1575 i = put_path_length;
1576 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PUT has %d hops.\n", i);
1577 for (i--; i >= 0; i--)
1579 id = GNUNET_PEER_intern (&put_path[i]);
1582 /* PUT path went through us, so discard the path up until now and start
1583 * from here to get a much shorter (and loop-free) path.
1588 if (p->length > 0 && id == p->peers[p->length - 1])
1590 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Optimizing 1 hop out.\n");
1591 GNUNET_PEER_change_rc (id, -1);
1595 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Adding from PUT: %s.\n",
1596 GNUNET_i2s (&put_path[i]));
1598 p->peers = GNUNET_realloc (p->peers, sizeof (GNUNET_PEER_Id) * p->length);
1599 p->peers[p->length - 1] = id;
1603 if (get_path_length > 0)
1604 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of GET: %s)\n",
1605 GNUNET_i2s (&get_path[0]));
1606 if (put_path_length > 0)
1607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " (first of PUT: %s)\n",
1608 GNUNET_i2s (&put_path[0]));
1609 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " In total: %d hops\n",
1611 for (i = 0; i < p->length; i++)
1613 struct GNUNET_PeerIdentity peer_id;
1615 GNUNET_PEER_resolve (p->peers[i], &peer_id);
1616 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " %u: %s\n", p->peers[i],
1617 GNUNET_i2s (&peer_id));
1625 * Adds a path to the peer_infos of all the peers in the path
1627 * @param p Path to process.
1628 * @param confirmed Whether we know if the path works or not.
1631 path_add_to_peers (struct MeshPeerPath *p, int confirmed)
1635 /* TODO: invert and add */
1636 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
1637 for (i++; i < p->length; i++)
1639 struct MeshPeer *aux;
1640 struct MeshPeerPath *copy;
1642 aux = peer_get_short (p->peers[i]);
1643 copy = path_duplicate (p);
1644 copy->length = i + 1;
1645 peer_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
1652 fc_debug (struct MeshFlowControl *fc)
1654 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
1655 fc->last_pid_recv, fc->last_ack_sent);
1656 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
1657 fc->last_pid_sent, fc->last_ack_recv);
1658 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
1659 fc->queue_n, fc->queue_max);
1663 connection_debug (struct MeshConnection *c)
1667 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
1670 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
1671 peer2s (c->t->peer), GNUNET_h2s (&c->id));
1672 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
1673 c->state, c->pending_messages);
1674 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
1675 fc_debug (&c->fwd_fc);
1676 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
1677 fc_debug (&c->bck_fc);
1684 * Change the tunnel state.
1686 * @param t Tunnel whose state to change.
1687 * @param state New state.
1690 tunnel_change_state (struct MeshTunnel2* t, enum MeshTunnelState state)
1694 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1695 "Tunnel %s state was %s\n",
1697 GNUNET_MESH_DEBUG_TS2S (t->state));
1698 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1699 "Tunnel %s state is now %s\n",
1701 GNUNET_MESH_DEBUG_TS2S (state));
1707 * Send all cached messages that we can, tunnel is online.
1709 * @param t Tunnel that holds the messages.
1710 * @param fwd Is this fwd?
1713 tunnel_send_queued_data (struct MeshTunnel2 *t, int fwd)
1715 struct MeshTunnelQueue *tq;
1716 struct MeshTunnelQueue *next;
1719 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1720 "tunnel_send_queued_data on tunnel %s\n",
1722 room = tunnel_get_buffer (t, fwd);
1723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
1724 for (tq = t->tq_head; NULL != tq && room > 0; tq = next)
1728 GNUNET_CONTAINER_DLL_remove (t->tq_head, t->tq_tail, tq);
1729 send_prebuilt_message_channel ((struct GNUNET_MessageHeader *) &tq[1],
1738 * Cache a message to be sent once tunnel is online.
1740 * @param t Tunnel to hold the message.
1741 * @param ch Channel the message is about.
1742 * @param msg Message itself (copy will be made).
1743 * @param fwd Is this fwd?
1746 tunnel_queue_data (struct MeshTunnel2 *t,
1747 struct MeshChannel *ch,
1748 struct GNUNET_MessageHeader *msg,
1751 struct MeshTunnelQueue *tq;
1752 uint16_t size = ntohs (msg->size);
1754 tq = GNUNET_malloc (sizeof (struct MeshTunnelQueue) + size);
1757 memcpy (&tq[1], msg, size);
1758 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tq);
1760 if (MESH_TUNNEL_READY == t->state)
1761 tunnel_send_queued_data (t, fwd);
1768 static struct MeshConnection *
1769 tunnel_use_path (struct MeshTunnel2 *t, struct MeshPeerPath *p)
1771 struct MeshConnection *c;
1772 struct GNUNET_HashCode cid;
1773 struct MeshPeer *peer;
1774 unsigned int own_pos;
1776 if (NULL == t || NULL == p)
1782 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE, &cid);
1784 c = connection_new (&cid);
1786 GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, c);
1787 for (own_pos = 0; own_pos < p->length; own_pos++)
1789 if (p->peers[own_pos] == myid)
1792 if (own_pos > p->length - 1)
1795 connection_destroy (c);
1798 c->own_pos = own_pos;
1803 c->fwd_maintenance_task =
1804 GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1805 &connection_fwd_keepalive, c);
1808 peer = connection_get_next_hop (c);
1809 if (NULL == peer->connections)
1811 connection_destroy (c);
1814 GNUNET_CONTAINER_multihashmap_put (peer->connections, &c->id, c,
1815 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1816 peer = connection_get_prev_hop (c);
1817 if (NULL == peer->connections)
1819 connection_destroy (c);
1822 GNUNET_CONTAINER_multihashmap_put (peer->connections, &c->id, c,
1823 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1829 * Notifies a tunnel that a connection has broken that affects at least
1830 * some of its peers. Sends a notification towards the root of the tree.
1831 * In case the peer is the owner of the tree, notifies the client that owns
1832 * the tunnel and tries to reconnect.
1834 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
1836 * @param t Tunnel affected.
1837 * @param p1 Peer that got disconnected from p2.
1838 * @param p2 Peer that got disconnected from p1.
1840 * @return Short ID of the peer disconnected (either p1 or p2).
1841 * 0 if the tunnel remained unaffected.
1843 static GNUNET_PEER_Id
1844 tunnel_notify_connection_broken (struct MeshTunnel2* t,
1845 GNUNET_PEER_Id p1, GNUNET_PEER_Id p2)
1847 // if (myid != p1 && myid != p2) FIXME
1852 // if (tree_get_predecessor (t->tree) != 0)
1854 // /* We are the peer still connected, notify owner of the disconnection. */
1855 // struct GNUNET_MESH_PathBroken msg;
1856 // struct GNUNET_PeerIdentity neighbor;
1858 // msg.header.size = htons (sizeof (msg));
1859 // msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
1860 // GNUNET_PEER_resolve (t->id.oid, &msg.oid);
1861 // msg.tid = htonl (t->id.tid);
1862 // msg.peer1 = my_full_id;
1863 // GNUNET_PEER_resolve (pid, &msg.peer2);
1864 // GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
1865 // send_prebuilt_message (&msg.header, &neighbor, t);
1874 * Send an ACK on the appropriate connection/channel, depending on
1875 * the direction and the position of the peer.
1877 * @param c Which connection to send the hop-by-hop ACK.
1878 * @param ch Channel, if any.
1879 * @param fwd Is this a fwd ACK? (will go dest->root)
1882 send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1884 unsigned int buffer;
1886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1887 "send ack %s on %p %p\n",
1888 fwd ? "FWD" : "BCK", c, ch);
1889 if (NULL == c || GMC_is_terminal (c, fwd))
1891 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n");
1892 buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
1896 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
1897 buffer = connection_get_buffer (c, fwd);
1899 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1901 if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
1902 (NULL != c && connection_is_origin (c, fwd)) )
1904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1907 GNUNET_assert (NULL != ch);
1908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1909 send_local_ack (ch, fwd);
1914 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1915 GNUNET_assert (NULL != ch);
1916 channel_send_connections_ack (ch, buffer, fwd);
1920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
1921 connection_send_ack (c, buffer, fwd);
1929 * Confirm we got a channel create.
1931 * @param ch The channel to confirm.
1932 * @param fwd Should we send the ACK fwd?
1935 channel_send_ack (struct MeshChannel *ch, int fwd)
1937 struct GNUNET_MESH_ChannelManage msg;
1939 msg.header.size = htons (sizeof (msg));
1940 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK);
1941 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1942 " sending channel %s ack for channel %s:%X\n",
1943 fwd ? "FWD" : "BCK", peer2s (ch->t->peer),
1946 msg.chid = htonl (ch->gid);
1947 send_prebuilt_message_channel (&msg.header, ch, !fwd);
1952 * Send a message to all clients (local and remote) of this channel
1953 * notifying that the channel is no longer valid.
1955 * If some peer or client should not receive the message,
1956 * should be zero'ed out before calling this function.
1958 * @param ch The channel whose clients to notify.
1961 channel_send_destroy (struct MeshChannel *ch)
1963 struct GNUNET_MESH_ChannelManage msg;
1965 msg.header.size = htons (sizeof (msg));
1966 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY);
1967 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1968 " sending channel destroy for channel %s:%X\n",
1969 peer2s (ch->t->peer),
1972 if (channel_is_terminal (ch, GNUNET_NO))
1974 if (NULL != ch->root && GNUNET_NO == ch->root->shutting_down)
1976 msg.chid = htonl (ch->lid_root);
1977 send_local_channel_destroy (ch, GNUNET_NO);
1982 msg.chid = htonl (ch->gid);
1983 send_prebuilt_message_channel (&msg.header, ch, GNUNET_NO);
1986 if (channel_is_terminal (ch, GNUNET_YES))
1988 if (NULL != ch->dest && GNUNET_NO == ch->dest->shutting_down)
1990 msg.chid = htonl (ch->lid_dest);
1991 send_local_channel_destroy (ch, GNUNET_YES);
1996 msg.chid = htonl (ch->gid);
1997 send_prebuilt_message_channel (&msg.header, ch, GNUNET_YES);
2005 static struct MeshTunnel2 *
2008 struct MeshTunnel2 *t;
2010 t = GNUNET_new (struct MeshTunnel2);
2012 t->next_local_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
2014 // GNUNET_CONTAINER_multihashmap_put (tunnels, tid, t,
2015 // GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
2017 // GNUNET_break (0);
2018 // tunnel_destroy (t);
2022 // char salt[] = "salt";
2023 // GNUNET_CRYPTO_kdf (&t->e_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
2024 // salt, sizeof (salt),
2025 // &t->e_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
2026 // &my_full_id, sizeof (struct GNUNET_PeerIdentity),
2027 // GNUNET_PEER_resolve2 (t->peer->id), sizeof (struct GNUNET_PeerIdentity),
2029 // GNUNET_CRYPTO_kdf (&t->d_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
2030 // salt, sizeof (salt),
2031 // &t->d_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
2032 // GNUNET_PEER_resolve2 (t->peer->id), sizeof (struct GNUNET_PeerIdentity),
2033 // &my_full_id, sizeof (struct GNUNET_PeerIdentity),
2041 * Add a connection to a tunnel.
2044 * @param c Connection.
2047 tunnel_add_connection (struct MeshTunnel2 *t, struct MeshConnection *c)
2049 struct MeshConnection *aux;
2051 for (aux = t->connection_head; aux != NULL; aux = aux->next)
2054 GNUNET_CONTAINER_DLL_insert_tail (t->connection_head, t->connection_tail, c);
2060 tunnel_destroy (struct MeshTunnel2 *t)
2062 struct MeshConnection *c;
2063 struct MeshConnection *next;
2068 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n",
2071 // if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &t->id, t))
2072 // GNUNET_break (0);
2074 for (c = t->connection_head; NULL != c; c = next)
2077 connection_destroy (c);
2080 GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
2081 t->peer->tunnel = NULL;
2088 * Tunnel is empty: destroy it.
2090 * Notifies all connections about the destruction.
2092 * @param t Tunnel to destroy.
2095 tunnel_destroy_empty (struct MeshTunnel2 *t)
2097 struct MeshConnection *c;
2099 for (c = t->connection_head; NULL != c; c = c->next)
2101 if (GNUNET_NO == c->destroy)
2102 connection_send_destroy (c);
2105 if (0 == t->pending_messages)
2108 t->destroy = GNUNET_YES;
2113 * Destroy tunnel if empty (no more channels).
2115 * @param t Tunnel to destroy if empty.
2118 tunnel_destroy_if_empty (struct MeshTunnel2 *t)
2120 if (NULL != t->channel_head)
2123 tunnel_destroy_empty (t);
2127 /******************************************************************************/
2128 /**************** MESH NETWORK HANDLER HELPERS ***********************/
2129 /******************************************************************************/
2136 /******************************************************************************/
2137 /******************** MESH NETWORK HANDLERS **************************/
2138 /******************************************************************************/
2142 * Generic handler for mesh network payload traffic.
2144 * @param t Tunnel on which we got this message.
2145 * @param message Unencryted data message.
2146 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
2149 handle_data (struct MeshTunnel2 *t, const struct GNUNET_MESH_Data *msg, int fwd)
2151 struct MeshChannelReliability *rel;
2152 struct MeshChannel *ch;
2153 struct MeshClient *c;
2159 size = ntohs (msg->header.size);
2161 sizeof (struct GNUNET_MESH_Data) +
2162 sizeof (struct GNUNET_MessageHeader))
2167 type = ntohs (msg->header.type);
2168 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message\n",
2169 GNUNET_MESH_DEBUG_M2S (type));
2170 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " payload of type %s\n",
2171 GNUNET_MESH_DEBUG_M2S (ntohs (msg[1].header.type)));
2174 ch = channel_get (t, ntohl (msg->chid));
2177 GNUNET_STATISTICS_update (stats, "# data on unknown channel", 1, GNUNET_NO);
2178 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING channel %u unknown\n",
2183 /* Initialize FWD/BCK data */
2184 c = fwd ? ch->dest : ch->root;
2185 rel = fwd ? ch->dest_rel : ch->root_rel;
2193 tunnel_change_state (t, MESH_TUNNEL_READY);
2195 GNUNET_STATISTICS_update (stats, "# data received", 1, GNUNET_NO);
2197 mid = ntohl (msg->mid);
2198 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " mid %u\n", mid);
2200 if (GNUNET_NO == ch->reliable ||
2201 ( !GMC_is_pid_bigger (rel->mid_recv, mid) &&
2202 GMC_is_pid_bigger (rel->mid_recv + 64, mid) ) )
2204 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! RECV %u\n", mid);
2205 if (GNUNET_YES == ch->reliable)
2207 /* Is this the exact next expected messasge? */
2208 if (mid == rel->mid_recv)
2210 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "as expected\n");
2212 channel_send_client_data (ch, msg, fwd);
2216 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "save for later\n");
2217 channel_rel_add_buffered_data (msg, rel);
2222 /* Tunnel is unreliable: send to clients directly */
2223 /* FIXME: accept Out Of Order traffic */
2224 rel->mid_recv = mid + 1;
2225 channel_send_client_data (ch, msg, fwd);
2230 GNUNET_break_op (0);
2231 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2232 " MID %u not expected (%u - %u), dropping!\n",
2233 mid, rel->mid_recv, rel->mid_recv + 64);
2236 channel_send_data_ack (ch, fwd);
2240 * Handler for mesh network traffic end-to-end ACKs.
2242 * @param t Tunnel on which we got this message.
2243 * @param message Data message.
2244 * @param fwd Is this a fwd ACK? (dest->orig)
2247 handle_data_ack (struct MeshTunnel2 *t,
2248 const struct GNUNET_MESH_DataACK *msg, int fwd)
2250 struct MeshChannelReliability *rel;
2251 struct MeshReliableMessage *copy;
2252 struct MeshReliableMessage *next;
2253 struct MeshChannel *ch;
2258 type = ntohs (msg->header.type);
2259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a %s message!\n",
2260 GNUNET_MESH_DEBUG_M2S (type));
2261 ch = channel_get (t, ntohl (msg->chid));
2264 GNUNET_STATISTICS_update (stats, "# ack on unknown channel", 1, GNUNET_NO);
2267 ack = ntohl (msg->mid);
2268 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! %s ACK %u\n",
2269 (GNUNET_YES == fwd) ? "FWD" : "BCK", ack);
2271 if (GNUNET_YES == fwd)
2285 for (work = GNUNET_NO, copy = rel->head_sent; copy != NULL; copy = next)
2287 if (GMC_is_pid_bigger (copy->mid, ack))
2289 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! head %u, out!\n", copy->mid);
2290 channel_rel_free_sent (rel, msg);
2294 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! id %u\n", copy->mid);
2296 rel_message_free (copy);
2298 /* ACK client if needed */
2299 // channel_send_ack (t, type, GNUNET_MESSAGE_TYPE_MESH_UNICAST_ACK == type);
2301 /* If some message was free'd, update the retransmission delay*/
2302 if (GNUNET_YES == work)
2304 if (GNUNET_SCHEDULER_NO_TASK != rel->retry_task)
2306 GNUNET_SCHEDULER_cancel (rel->retry_task);
2307 if (NULL == rel->head_sent)
2309 rel->retry_task = GNUNET_SCHEDULER_NO_TASK;
2313 struct GNUNET_TIME_Absolute new_target;
2314 struct GNUNET_TIME_Relative delay;
2316 delay = GNUNET_TIME_relative_multiply (rel->retry_timer,
2317 MESH_RETRANSMIT_MARGIN);
2318 new_target = GNUNET_TIME_absolute_add (rel->head_sent->timestamp,
2320 delay = GNUNET_TIME_absolute_get_remaining (new_target);
2322 GNUNET_SCHEDULER_add_delayed (delay,
2323 &channel_retransmit_message,
2334 * Core handler for connection creation.
2336 * @param cls Closure (unused).
2337 * @param peer Sender (neighbor).
2338 * @param message Message.
2340 * @return GNUNET_OK to keep the connection open,
2341 * GNUNET_SYSERR to close it (signal serious error)
2344 handle_mesh_connection_create (void *cls,
2345 const struct GNUNET_PeerIdentity *peer,
2346 const struct GNUNET_MessageHeader *message)
2348 struct GNUNET_MESH_ConnectionCreate *msg;
2349 struct GNUNET_PeerIdentity *id;
2350 struct GNUNET_HashCode *cid;
2351 struct MeshPeerPath *path;
2352 struct MeshPeer *dest_peer;
2353 struct MeshPeer *orig_peer;
2354 struct MeshConnection *c;
2355 unsigned int own_pos;
2359 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
2360 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection create msg\n");
2363 size = ntohs (message->size);
2364 if (size < sizeof (struct GNUNET_MESH_ConnectionCreate))
2366 GNUNET_break_op (0);
2370 /* Calculate hops */
2371 size -= sizeof (struct GNUNET_MESH_ConnectionCreate);
2372 if (size % sizeof (struct GNUNET_PeerIdentity))
2374 GNUNET_break_op (0);
2377 size /= sizeof (struct GNUNET_PeerIdentity);
2380 GNUNET_break_op (0);
2383 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " path has %u hops.\n", size);
2385 /* Get parameters */
2386 msg = (struct GNUNET_MESH_ConnectionCreate *) message;
2388 id = (struct GNUNET_PeerIdentity *) &msg[1];
2389 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2390 " connection %s (%s).\n",
2391 GNUNET_h2s (cid), GNUNET_i2s (id));
2393 /* Create connection */
2394 c = connection_get (cid);
2397 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating connection\n");
2398 c = connection_new (cid);
2401 connection_reset_timeout (c, GNUNET_YES);
2404 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Creating path...\n");
2405 path = path_new (size);
2407 for (i = 0; i < size; i++)
2409 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... adding %s\n",
2410 GNUNET_i2s (&id[i]));
2411 path->peers[i] = GNUNET_PEER_intern (&id[i]);
2412 if (path->peers[i] == myid)
2415 if (own_pos == 0 && path->peers[own_pos] != myid)
2417 /* create path: self not found in path through self */
2418 GNUNET_break_op (0);
2419 path_destroy (path);
2420 connection_destroy (c);
2423 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Own position: %u\n", own_pos);
2424 path_add_to_peers (path, GNUNET_NO);
2425 c->path = path_duplicate (path);
2426 c->own_pos = own_pos;
2432 if (MESH_CONNECTION_NEW == c->state)
2433 connection_change_state (c, MESH_CONNECTION_SENT);
2435 /* Remember peers */
2436 dest_peer = peer_get (&id[size - 1]);
2437 orig_peer = peer_get (&id[0]);
2439 /* Is it a connection to us? */
2440 if (c->own_pos == size - 1)
2442 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " It's for us!\n");
2443 peer_add_path_to_origin (orig_peer, path, GNUNET_YES);
2445 if (NULL == orig_peer->tunnel)
2447 orig_peer->tunnel = tunnel_new ();
2448 orig_peer->tunnel->peer = orig_peer;
2450 tunnel_add_connection (orig_peer->tunnel, c);
2451 if (MESH_TUNNEL_NEW == c->t->state)
2452 tunnel_change_state (c->t, MESH_TUNNEL_WAITING);
2454 send_connection_ack (c, GNUNET_NO);
2455 if (MESH_CONNECTION_SENT == c->state)
2456 connection_change_state (c, MESH_CONNECTION_ACK);
2458 /* Keep tunnel alive in direction dest->owner*/
2459 connection_reset_timeout (c, GNUNET_NO);
2463 /* It's for somebody else! Retransmit. */
2464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Retransmitting.\n");
2465 peer_add_path (dest_peer, path_duplicate (path), GNUNET_NO);
2466 peer_add_path_to_origin (orig_peer, path, GNUNET_NO);
2467 send_prebuilt_message_connection (message, c, NULL, GNUNET_YES);
2474 * Core handler for path ACKs
2476 * @param cls closure
2477 * @param message message
2478 * @param peer peer identity this notification is about
2480 * @return GNUNET_OK to keep the connection open,
2481 * GNUNET_SYSERR to close it (signal serious error)
2484 handle_mesh_connection_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
2485 const struct GNUNET_MessageHeader *message)
2487 struct GNUNET_MESH_ConnectionACK *msg;
2488 struct MeshConnection *c;
2489 struct MeshPeerPath *p;
2490 struct MeshPeer *pi;
2493 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
2494 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received a connection ACK msg\n");
2495 msg = (struct GNUNET_MESH_ConnectionACK *) message;
2496 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " on connection %s\n",
2497 GNUNET_h2s (&msg->cid));
2498 c = connection_get (&msg->cid);
2501 GNUNET_STATISTICS_update (stats, "# control on unknown connection",
2503 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " don't know the connection!\n");
2508 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " via peer %s\n",
2510 pi = peer_get (peer);
2511 if (connection_get_next_hop (c) == pi)
2513 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " SYNACK\n");
2515 if (MESH_CONNECTION_SENT == c->state)
2516 connection_change_state (c, MESH_CONNECTION_ACK);
2518 else if (connection_get_prev_hop (c) == pi)
2520 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK\n");
2522 connection_change_state (c, MESH_CONNECTION_READY);
2526 GNUNET_break_op (0);
2529 connection_reset_timeout (c, fwd);
2531 /* Add path to peers? */
2535 path_add_to_peers (p, GNUNET_YES);
2542 /* Message for us as creator? */
2543 if (connection_is_origin (c, GNUNET_YES))
2545 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection (SYN)ACK for us!\n");
2546 connection_change_state (c, MESH_CONNECTION_READY);
2547 if (MESH_TUNNEL_READY != c->t->state)
2548 tunnel_change_state (c->t, MESH_TUNNEL_READY);
2549 send_connection_ack (c, GNUNET_YES);
2550 tunnel_send_queued_data (c->t, GNUNET_YES);
2551 if (3 <= tunnel_count_connections (c->t) && NULL != c->t->peer->dhtget)
2553 GNUNET_DHT_get_stop (c->t->peer->dhtget);
2554 c->t->peer->dhtget = NULL;
2559 /* Message for us as destination? */
2560 if (GMC_is_terminal (c, GNUNET_YES))
2562 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Connection ACK for us!\n");
2563 if (MESH_TUNNEL_READY != c->t->state)
2564 tunnel_change_state (c->t, MESH_TUNNEL_READY);
2565 connection_change_state (c, MESH_CONNECTION_READY);
2566 tunnel_send_queued_data (c->t, GNUNET_NO);
2570 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2571 send_prebuilt_message_connection (message, c, NULL, fwd);
2577 * Core handler for notifications of broken paths
2579 * @param cls Closure (unused).
2580 * @param peer Peer identity of sending neighbor.
2581 * @param message Message.
2583 * @return GNUNET_OK to keep the connection open,
2584 * GNUNET_SYSERR to close it (signal serious error)
2587 handle_mesh_connection_broken (void *cls, const struct GNUNET_PeerIdentity *peer,
2588 const struct GNUNET_MessageHeader *message)
2590 struct GNUNET_MESH_ConnectionBroken *msg;
2591 struct MeshConnection *c;
2593 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2594 "Received a CONNECTION BROKEN msg from %s\n", GNUNET_i2s (peer));
2595 msg = (struct GNUNET_MESH_ConnectionBroken *) message;
2596 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
2597 GNUNET_i2s (&msg->peer1));
2598 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " regarding %s\n",
2599 GNUNET_i2s (&msg->peer2));
2600 c = connection_get (&msg->cid);
2603 GNUNET_break_op (0);
2606 tunnel_notify_connection_broken (c->t, GNUNET_PEER_search (&msg->peer1),
2607 GNUNET_PEER_search (&msg->peer2));
2614 * Core handler for tunnel destruction
2616 * @param cls Closure (unused).
2617 * @param peer Peer identity of sending neighbor.
2618 * @param message Message.
2620 * @return GNUNET_OK to keep the connection open,
2621 * GNUNET_SYSERR to close it (signal serious error)
2624 handle_mesh_connection_destroy (void *cls,
2625 const struct GNUNET_PeerIdentity *peer,
2626 const struct GNUNET_MessageHeader *message)
2628 struct GNUNET_MESH_ConnectionDestroy *msg;
2629 struct MeshConnection *c;
2633 msg = (struct GNUNET_MESH_ConnectionDestroy *) message;
2634 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2635 "Got a CONNECTION DESTROY message from %s\n",
2637 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2638 " for connection %s\n",
2639 GNUNET_h2s (&msg->cid));
2640 c = connection_get (&msg->cid);
2643 /* Probably already got the message from another path,
2644 * destroyed the tunnel and retransmitted to children.
2647 GNUNET_STATISTICS_update (stats, "# control on unknown tunnel",
2651 id = GNUNET_PEER_search (peer);
2652 if (id == connection_get_prev_hop (c)->id)
2654 else if (id == connection_get_next_hop (c)->id)
2658 GNUNET_break_op (0);
2661 send_prebuilt_message_connection (message, c, NULL, fwd);
2662 c->destroy = GNUNET_YES;
2669 * Handler for channel create messages.
2671 * @param t Tunnel this channel is to be created in.
2672 * @param msg Message.
2673 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
2676 handle_channel_create (struct MeshTunnel2 *t,
2677 struct GNUNET_MESH_ChannelCreate *msg,
2680 MESH_ChannelNumber chid;
2681 struct MeshChannel *ch;
2682 struct MeshClient *c;
2685 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Channel Create\n");
2686 /* Check message size */
2687 if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_ChannelCreate))
2689 GNUNET_break_op (0);
2693 /* Check if channel exists */
2694 chid = ntohl (msg->chid);
2695 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " chid %u\n", chid);
2696 ch = channel_get (t, chid);
2699 /* Probably a retransmission, safe to ignore */
2700 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " already exists...\n");
2701 if (NULL != ch->dest)
2703 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " duplicate CC!!\n");
2704 channel_send_ack (ch, !fwd);
2710 /* Create channel */
2711 ch = channel_new (t, NULL, 0);
2713 channel_set_options (ch, ntohl (msg->opt));
2716 /* Find a destination client */
2717 port = ntohl (msg->port);
2718 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " port %u\n", port);
2719 c = GNUNET_CONTAINER_multihashmap32_get (ports, port);
2722 /* TODO send reject */
2723 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " no client has port registered\n");
2728 channel_add_client (ch, c);
2729 if (GNUNET_YES == ch->reliable)
2730 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "!!! Reliable\n");
2732 send_local_channel_create (ch);
2733 channel_send_ack (ch, fwd);
2734 send_local_ack (ch, !fwd);
2739 * Handler for channel ack messages.
2741 * @param t Tunnel this channel is to be created in.
2742 * @param msg Message.
2743 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
2746 handle_channel_ack (struct MeshTunnel2 *t,
2747 struct GNUNET_MESH_ChannelManage *msg,
2750 MESH_ChannelNumber chid;
2751 struct MeshChannel *ch;
2753 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Received Channel ACK\n");
2754 /* Check message size */
2755 if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_ChannelManage))
2757 GNUNET_break_op (0);
2761 /* Check if channel exists */
2762 chid = ntohl (msg->chid);
2763 ch = channel_get (t, chid);
2766 GNUNET_break_op (0);
2767 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " channel %u unknown!!\n", chid);
2771 channel_confirm (ch, !fwd);
2776 * Handler for channel destroy messages.
2778 * @param t Tunnel this channel is to be destroyed of.
2779 * @param msg Message.
2780 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
2783 handle_channel_destroy (struct MeshTunnel2 *t,
2784 struct GNUNET_MESH_ChannelManage *msg,
2787 MESH_ChannelNumber chid;
2788 struct MeshChannel *ch;
2790 /* Check message size */
2791 if (ntohs (msg->header.size) != sizeof (struct GNUNET_MESH_ChannelManage))
2793 GNUNET_break_op (0);
2797 /* Check if channel exists */
2798 chid = ntohl (msg->chid);
2799 ch = channel_get (t, chid);
2802 /* Probably a retransmission, safe to ignore */
2805 if ( (fwd && NULL == ch->dest) || (!fwd && NULL == ch->root) )
2807 /* Not for us (don't destroy twice a half-open loopback channel) */
2811 send_local_channel_destroy (ch, fwd);
2812 channel_destroy (ch);
2817 handle_decrypted (struct MeshTunnel2 *t,
2818 const struct GNUNET_MessageHeader *msgh,
2821 switch (ntohs (msgh->type))
2823 case GNUNET_MESSAGE_TYPE_MESH_DATA:
2824 /* Don't send hop ACK, wait for client to ACK */
2825 handle_data (t, (struct GNUNET_MESH_Data *) msgh, fwd);
2828 case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
2829 handle_data_ack (t, (struct GNUNET_MESH_DataACK *) msgh, fwd);
2832 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
2833 handle_channel_create (t,
2834 (struct GNUNET_MESH_ChannelCreate *) msgh,
2838 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
2839 handle_channel_ack (t,
2840 (struct GNUNET_MESH_ChannelManage *) msgh,
2844 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
2845 handle_channel_destroy (t,
2846 (struct GNUNET_MESH_ChannelManage *) msgh,
2851 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2852 "end-to-end message not known (%u)\n",
2853 ntohs (msgh->type));
2859 * Generic handler for mesh network encrypted traffic.
2861 * @param peer Peer identity this notification is about.
2862 * @param message Encrypted message.
2863 * @param fwd Is this FWD traffic? GNUNET_YES : GNUNET_NO;
2865 * @return GNUNET_OK to keep the connection open,
2866 * GNUNET_SYSERR to close it (signal serious error)
2869 handle_mesh_encrypted (const struct GNUNET_PeerIdentity *peer,
2870 const struct GNUNET_MESH_Encrypted *msg,
2873 struct MeshConnection *c;
2874 struct MeshTunnel2 *t;
2875 struct MeshPeer *neighbor;
2876 struct MeshFlowControl *fc;
2883 size = ntohs (msg->header.size);
2885 sizeof (struct GNUNET_MESH_Encrypted) +
2886 sizeof (struct GNUNET_MessageHeader))
2888 GNUNET_break_op (0);
2891 type = ntohs (msg->header.type);
2892 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
2893 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a %s message from %s\n",
2894 GNUNET_MESH_DEBUG_M2S (type), GNUNET_i2s (peer));
2896 /* Check connection */
2897 c = connection_get (&msg->cid);
2900 GNUNET_STATISTICS_update (stats, "# unknown connection", 1, GNUNET_NO);
2901 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "WARNING connection unknown\n");
2905 fc = fwd ? &c->bck_fc : &c->fwd_fc;
2907 /* Check if origin is as expected */
2908 neighbor = connection_get_hop (c, !fwd);
2909 if (peer_get (peer)->id != neighbor->id)
2911 GNUNET_break_op (0);
2916 pid = ntohl (msg->pid);
2917 if (GMC_is_pid_bigger (pid, fc->last_ack_sent))
2919 GNUNET_STATISTICS_update (stats, "# unsolicited message", 1, GNUNET_NO);
2920 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2921 "WARNING Received PID %u, (prev %u), ACK %u\n",
2922 pid, fc->last_pid_recv, fc->last_ack_sent);
2925 if (GNUNET_NO == GMC_is_pid_bigger (pid, fc->last_pid_recv))
2927 GNUNET_STATISTICS_update (stats, "# duplicate PID", 1, GNUNET_NO);
2928 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
2929 " Pid %u not expected (%u+), dropping!\n",
2930 pid, fc->last_pid_recv + 1);
2933 if (MESH_CONNECTION_SENT == c->state)
2934 connection_change_state (c, MESH_CONNECTION_READY);
2935 connection_reset_timeout (c, fwd);
2936 fc->last_pid_recv = pid;
2938 /* Is this message for us? */
2939 if (GMC_is_terminal (c, fwd))
2941 size_t dsize = size - sizeof (struct GNUNET_MESH_Encrypted);
2943 struct GNUNET_MessageHeader *msgh;
2946 /* TODO signature verification */
2947 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " message for us!\n");
2948 GNUNET_STATISTICS_update (stats, "# messages received", 1, GNUNET_NO);
2950 fc->last_pid_recv = pid;
2951 tunnel_decrypt (t, cbuf, &msg[1], dsize, msg->iv, fwd);
2955 msgh = (struct GNUNET_MessageHeader *) &cbuf[off];
2956 handle_decrypted (t, msgh, fwd);
2957 off += ntohs (msgh->size);
2959 send_ack (c, NULL, fwd);
2963 /* Message not for us: forward to next hop */
2964 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " not for us, retransmitting...\n");
2965 ttl = ntohl (msg->ttl);
2966 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ttl: %u\n", ttl);
2969 GNUNET_STATISTICS_update (stats, "# TTL drops", 1, GNUNET_NO);
2970 GNUNET_log (GNUNET_ERROR_TYPE_WARNING, " TTL is 0, DROPPING!\n");
2971 send_ack (c, NULL, fwd);
2974 GNUNET_STATISTICS_update (stats, "# messages forwarded", 1, GNUNET_NO);
2976 send_prebuilt_message_connection (&msg->header, c, NULL, fwd);
2983 * Core handler for mesh network traffic going orig->dest.
2985 * @param cls Closure (unused).
2986 * @param message Message received.
2987 * @param peer Peer who sent the message.
2989 * @return GNUNET_OK to keep the connection open,
2990 * GNUNET_SYSERR to close it (signal serious error)
2993 handle_mesh_fwd (void *cls, const struct GNUNET_PeerIdentity *peer,
2994 const struct GNUNET_MessageHeader *message)
2996 return handle_mesh_encrypted (peer,
2997 (struct GNUNET_MESH_Encrypted *)message,
3002 * Core handler for mesh network traffic going dest->orig.
3004 * @param cls Closure (unused).
3005 * @param message Message received.
3006 * @param peer Peer who sent the message.
3008 * @return GNUNET_OK to keep the connection open,
3009 * GNUNET_SYSERR to close it (signal serious error)
3012 handle_mesh_bck (void *cls, const struct GNUNET_PeerIdentity *peer,
3013 const struct GNUNET_MessageHeader *message)
3015 return handle_mesh_encrypted (peer,
3016 (struct GNUNET_MESH_Encrypted *)message,
3022 * Core handler for mesh network traffic point-to-point acks.
3024 * @param cls closure
3025 * @param message message
3026 * @param peer peer identity this notification is about
3028 * @return GNUNET_OK to keep the connection open,
3029 * GNUNET_SYSERR to close it (signal serious error)
3032 handle_mesh_ack (void *cls, const struct GNUNET_PeerIdentity *peer,
3033 const struct GNUNET_MessageHeader *message)
3035 struct GNUNET_MESH_ACK *msg;
3036 struct MeshConnection *c;
3037 struct MeshFlowControl *fc;
3042 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
3043 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got an ACK packet from %s!\n",
3045 msg = (struct GNUNET_MESH_ACK *) message;
3047 c = connection_get (&msg->cid);
3051 GNUNET_STATISTICS_update (stats, "# ack on unknown connection", 1,
3056 /* Is this a forward or backward ACK? */
3057 id = GNUNET_PEER_search (peer);
3058 if (connection_get_next_hop (c)->id == id)
3060 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
3064 else if (connection_get_prev_hop (c)->id == id)
3066 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
3072 GNUNET_break_op (0);
3076 ack = ntohl (msg->ack);
3077 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ACK %u (was %u)\n",
3078 ack, fc->last_ack_recv);
3079 if (GMC_is_pid_bigger (ack, fc->last_ack_recv))
3080 fc->last_ack_recv = ack;
3082 /* Cancel polling if the ACK is big enough. */
3083 if (GNUNET_SCHEDULER_NO_TASK != fc->poll_task &&
3084 GMC_is_pid_bigger (fc->last_ack_recv, fc->last_pid_sent))
3086 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " Cancel poll\n");
3087 GNUNET_SCHEDULER_cancel (fc->poll_task);
3088 fc->poll_task = GNUNET_SCHEDULER_NO_TASK;
3089 fc->poll_time = GNUNET_TIME_UNIT_SECONDS;
3092 connection_unlock_queue (c, fwd);
3099 * Core handler for mesh network traffic point-to-point ack polls.
3101 * @param cls closure
3102 * @param message message
3103 * @param peer peer identity this notification is about
3105 * @return GNUNET_OK to keep the connection open,
3106 * GNUNET_SYSERR to close it (signal serious error)
3109 handle_mesh_poll (void *cls, const struct GNUNET_PeerIdentity *peer,
3110 const struct GNUNET_MessageHeader *message)
3112 struct GNUNET_MESH_Poll *msg;
3113 struct MeshConnection *c;
3114 struct MeshFlowControl *fc;
3119 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "\n\n");
3120 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got a POLL packet from %s!\n",
3123 msg = (struct GNUNET_MESH_Poll *) message;
3125 c = connection_get (&msg->cid);
3129 GNUNET_STATISTICS_update (stats, "# poll on unknown connection", 1,
3131 GNUNET_break_op (0);
3135 /* Is this a forward or backward ACK?
3136 * Note: a poll should never be needed in a loopback case,
3137 * since there is no possiblility of packet loss there, so
3138 * this way of discerining FWD/BCK should not be a problem.
3140 id = GNUNET_PEER_search (peer);
3141 if (connection_get_next_hop (c)->id == id)
3143 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD ACK\n");
3146 else if (connection_get_prev_hop (c)->id == id)
3148 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK ACK\n");
3153 GNUNET_break_op (0);
3157 pid = ntohl (msg->pid);
3158 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " PID %u, OLD %u\n",
3159 pid, fc->last_pid_recv);
3160 fc->last_pid_recv = pid;
3161 fwd = fc == &c->fwd_fc;
3162 send_ack (c, NULL, fwd);
3169 * Core handler for mesh keepalives.
3171 * @param cls closure
3172 * @param message message
3173 * @param peer peer identity this notification is about
3174 * @return GNUNET_OK to keep the connection open,
3175 * GNUNET_SYSERR to close it (signal serious error)
3177 * TODO: Check who we got this from, to validate route.
3180 handle_mesh_keepalive (void *cls, const struct GNUNET_PeerIdentity *peer,
3181 const struct GNUNET_MessageHeader *message)
3183 struct GNUNET_MESH_ConnectionKeepAlive *msg;
3184 struct MeshConnection *c;
3185 struct MeshPeer *neighbor;
3188 msg = (struct GNUNET_MESH_ConnectionKeepAlive *) message;
3189 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "got a keepalive packet from %s\n",
3192 c = connection_get (&msg->cid);
3195 GNUNET_STATISTICS_update (stats, "# keepalive on unknown connection", 1,
3200 fwd = GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE == ntohs (message->type) ?
3201 GNUNET_YES : GNUNET_NO;
3203 /* Check if origin is as expected */
3204 neighbor = connection_get_hop (c, fwd);
3205 if (peer_get (peer)->id != neighbor->id)
3207 GNUNET_break_op (0);
3211 connection_change_state (c, MESH_CONNECTION_READY);
3212 connection_reset_timeout (c, fwd);
3214 if (GMC_is_terminal (c, fwd))
3217 GNUNET_STATISTICS_update (stats, "# keepalives forwarded", 1, GNUNET_NO);
3218 send_prebuilt_message_connection (message, c, NULL, fwd);
3226 * Functions to handle messages from core
3228 static struct GNUNET_CORE_MessageHandler core_handlers[] = {
3229 {&handle_mesh_connection_create, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
3231 {&handle_mesh_connection_ack, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
3232 sizeof (struct GNUNET_MESH_ConnectionACK)},
3233 {&handle_mesh_connection_broken, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_BROKEN,
3234 sizeof (struct GNUNET_MESH_ConnectionBroken)},
3235 {&handle_mesh_connection_destroy, GNUNET_MESSAGE_TYPE_MESH_CONNECTION_DESTROY,
3236 sizeof (struct GNUNET_MESH_ConnectionDestroy)},
3237 {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_FWD_KEEPALIVE,
3238 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
3239 {&handle_mesh_keepalive, GNUNET_MESSAGE_TYPE_MESH_BCK_KEEPALIVE,
3240 sizeof (struct GNUNET_MESH_ConnectionKeepAlive)},
3241 {&handle_mesh_ack, GNUNET_MESSAGE_TYPE_MESH_ACK,
3242 sizeof (struct GNUNET_MESH_ACK)},
3243 {&handle_mesh_poll, GNUNET_MESSAGE_TYPE_MESH_POLL,
3244 sizeof (struct GNUNET_MESH_Poll)},
3245 {&handle_mesh_fwd, GNUNET_MESSAGE_TYPE_MESH_FWD, 0},
3246 {&handle_mesh_bck, GNUNET_MESSAGE_TYPE_MESH_BCK, 0},
3252 * Function to process paths received for a new peer addition. The recorded
3253 * paths form the initial tunnel, which can be optimized later.
3254 * Called on each result obtained for the DHT search.
3256 * @param cls closure
3257 * @param exp when will this value expire
3258 * @param key key of the result
3259 * @param get_path path of the get request
3260 * @param get_path_length lenght of get_path
3261 * @param put_path path of the put request
3262 * @param put_path_length length of the put_path
3263 * @param type type of the result
3264 * @param size number of bytes in data
3265 * @param data pointer to the result data
3268 dht_get_id_handler (void *cls, struct GNUNET_TIME_Absolute exp,
3269 const struct GNUNET_HashCode * key,
3270 const struct GNUNET_PeerIdentity *get_path,
3271 unsigned int get_path_length,
3272 const struct GNUNET_PeerIdentity *put_path,
3273 unsigned int put_path_length, enum GNUNET_BLOCK_Type type,
3274 size_t size, const void *data)
3276 struct MeshPeer *peer = cls;
3277 struct MeshPeerPath *p;
3278 struct MeshConnection *c;
3279 struct GNUNET_PeerIdentity pi;
3280 unsigned int connection_count;
3282 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Got results from DHT!\n");
3283 GNUNET_PEER_resolve (peer->id, &pi);
3284 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " for %s\n", GNUNET_i2s (&pi));
3286 p = path_build_from_dht (get_path, get_path_length,
3287 put_path, put_path_length);
3288 path_add_to_peers (p, GNUNET_NO);
3291 /* Count connections */
3292 connection_count = GMC_count (peer->tunnel->connection_head);
3294 /* If we already have 3 (or more (?!)) connections, it's enough */
3295 if (3 <= connection_count)
3298 if (peer->tunnel->state == MESH_TUNNEL_SEARCHING)
3300 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
3301 peer_connect (peer);
3309 * Method called whenever a given peer connects.
3311 * @param cls closure
3312 * @param peer peer identity this notification is about
3315 core_connect (void *cls, const struct GNUNET_PeerIdentity *peer)
3317 struct MeshPeer *pi;
3318 struct MeshPeerPath *path;
3320 DEBUG_CONN ("Peer connected\n");
3321 DEBUG_CONN (" %s\n", GNUNET_i2s (&my_full_id));
3322 pi = peer_get (peer);
3325 DEBUG_CONN (" (self)\n");
3326 path = path_new (1);
3330 DEBUG_CONN (" %s\n", GNUNET_i2s (peer));
3331 path = path_new (2);
3332 path->peers[1] = pi->id;
3333 GNUNET_PEER_change_rc (pi->id, 1);
3334 GNUNET_STATISTICS_update (stats, "# peers", 1, GNUNET_NO);
3336 path->peers[0] = myid;
3337 GNUNET_PEER_change_rc (myid, 1);
3338 peer_add_path (pi, path, GNUNET_YES);
3340 pi->connections = GNUNET_CONTAINER_multihashmap_create (32, GNUNET_YES);
3346 * Method called whenever a peer disconnects.
3348 * @param cls closure
3349 * @param peer peer identity this notification is about
3352 core_disconnect (void *cls, const struct GNUNET_PeerIdentity *peer)
3354 struct MeshPeer *pi;
3356 DEBUG_CONN ("Peer disconnected\n");
3357 pi = GNUNET_CONTAINER_multipeermap_get (peers, peer);
3364 GNUNET_CONTAINER_multihashmap_iterate (pi->connections,
3367 GNUNET_CONTAINER_multihashmap_destroy (pi->connections);
3368 pi->connections = NULL;
3369 if (NULL != pi->core_transmit)
3371 GNUNET_CORE_notify_transmit_ready_cancel (pi->core_transmit);
3372 pi->core_transmit = NULL;
3376 DEBUG_CONN (" (self)\n");
3378 GNUNET_STATISTICS_update (stats, "# peers", -1, GNUNET_NO);
3386 * To be called on core init/fail.
3388 * @param cls Closure (config)
3389 * @param identity the public identity of this peer
3392 core_init (void *cls,
3393 const struct GNUNET_PeerIdentity *identity)
3395 const struct GNUNET_CONFIGURATION_Handle *c = cls;
3398 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Core init\n");
3399 if (0 != memcmp (identity, &my_full_id, sizeof (my_full_id)))
3401 GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Wrong CORE service\n"));
3402 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3404 GNUNET_i2s (identity));
3405 GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
3407 GNUNET_i2s (&my_full_id));
3408 GNUNET_CORE_disconnect (core_handle);
3409 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
3410 NULL, /* Closure passed to MESH functions */
3411 &core_init, /* Call core_init once connected */
3412 &core_connect, /* Handle connects */
3413 &core_disconnect, /* remove peers on disconnects */
3414 NULL, /* Don't notify about all incoming messages */
3415 GNUNET_NO, /* For header only in notification */
3416 NULL, /* Don't notify about all outbound messages */
3417 GNUNET_NO, /* For header-only out notification */
3418 core_handlers); /* Register these handlers */
3427 /******************************************************************************/
3428 /************************ MAIN FUNCTIONS ****************************/
3429 /******************************************************************************/
3432 * Iterator over tunnel hash map entries to destroy the tunnel during shutdown.
3434 * @param cls closure
3435 * @param key current key code
3436 * @param value value in the hash map
3437 * @return #GNUNET_YES if we should continue to iterate,
3438 * #GNUNET_NO if not.
3441 shutdown_tunnel (void *cls,
3442 const struct GNUNET_PeerIdentity *key,
3445 struct MeshPeer *p = value;
3446 struct MeshTunnel2 *t = p->tunnel;
3455 * Task run during shutdown.
3461 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
3463 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
3465 if (core_handle != NULL)
3467 GNUNET_CORE_disconnect (core_handle);
3470 GNUNET_CONTAINER_multipeermap_iterate (peers, &shutdown_tunnel, NULL);
3471 if (dht_handle != NULL)
3473 GNUNET_DHT_disconnect (dht_handle);
3477 if (GNUNET_SCHEDULER_NO_TASK != announce_id_task)
3479 GNUNET_SCHEDULER_cancel (announce_id_task);
3480 announce_id_task = GNUNET_SCHEDULER_NO_TASK;
3482 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
3487 * Process mesh requests.
3489 * @param cls closure
3490 * @param server the initialized server
3491 * @param c configuration to use
3494 run (void *cls, struct GNUNET_SERVER_Handle *server,
3495 const struct GNUNET_CONFIGURATION_Handle *c)
3497 struct GNUNET_CRYPTO_EccPrivateKey *pk;
3499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
3502 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "ID_ANNOUNCE_TIME",
3505 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3506 "MESH", "ID_ANNOUNCE_TIME", "MISSING");
3507 GNUNET_SCHEDULER_shutdown ();
3512 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
3515 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
3516 "MESH", "CONNECT_TIMEOUT", "MISSING");
3517 GNUNET_SCHEDULER_shutdown ();
3522 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
3525 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
3526 "MESH", "DEFAULT_TTL", "USING DEFAULT");
3531 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "MAX_PEERS",
3534 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
3535 "MESH", "MAX_PEERS", "USING DEFAULT");
3540 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT",
3547 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
3548 "\n***************************************\n"
3549 "Mesh is running with drop mode enabled.\n"
3550 "This is NOT a good idea!\n"
3551 "Remove the DROP_PERCENT option from your configuration.\n"
3552 "***************************************\n");
3556 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DHT_REPLICATION_LEVEL",
3557 &dht_replication_level))
3559 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
3560 "MESH", "DHT_REPLICATION_LEVEL", "USING DEFAULT");
3561 dht_replication_level = 3;
3564 peers = GNUNET_CONTAINER_multipeermap_create (32, GNUNET_NO);
3566 dht_handle = GNUNET_DHT_connect (c, 64);
3567 if (NULL == dht_handle)
3571 stats = GNUNET_STATISTICS_create ("mesh", c);
3573 /* Scheduled the task to clean up when shutdown is called */
3574 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
3576 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n");
3577 pk = GNUNET_CRYPTO_ecc_key_create_from_configuration (c);
3578 GNUNET_assert (NULL != pk);
3579 my_private_key = pk;
3580 GNUNET_CRYPTO_ecc_key_get_public_for_signature (my_private_key,
3581 &my_full_id.public_key);
3582 myid = GNUNET_PEER_intern (&my_full_id);
3583 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
3584 "Mesh for peer [%s] starting\n",
3585 GNUNET_i2s(&my_full_id));
3590 core_handle = GNUNET_CORE_connect (c, /* Main configuration */
3591 NULL, /* Closure passed to MESH functions */
3592 &core_init, /* Call core_init once connected */
3593 &core_connect, /* Handle connects */
3594 &core_disconnect, /* remove peers on disconnects */
3595 NULL, /* Don't notify about all incoming messages */
3596 GNUNET_NO, /* For header only in notification */
3597 NULL, /* Don't notify about all outbound messages */
3598 GNUNET_NO, /* For header-only out notification */
3599 core_handlers); /* Register these handlers */
3600 if (NULL == core_handle)
3603 GNUNET_SCHEDULER_shutdown ();
3606 announce_id_task = GNUNET_SCHEDULER_add_now (&announce_id, cls);
3607 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
3612 * The main function for the mesh service.
3614 * @param argc number of arguments from the command line
3615 * @param argv command line arguments
3616 * @return 0 ok, 1 on error
3619 main (int argc, char *const *argv)
3624 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
3625 r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
3627 ret = (GNUNET_OK == r) ? 0 : 1;
3628 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");