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 "block_mesh.h"
50 #include "gnunet_statistics_service.h"
52 #include "gnunet-service-mesh_local.h"
53 #include "gnunet-service-mesh_channel.h"
54 #include "gnunet-service-mesh_connection.h"
55 #include "gnunet-service-mesh_dht.h"
56 #include "gnunet-service-mesh_peer.h"
58 #define MESH_BLOOM_SIZE 128
61 #define MESH_DEBUG_TIMING __LINUX__ && GNUNET_NO
68 struct timespec __mesh_start;
69 struct timespec __mesh_end;
70 #define INTERVAL_START clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_start))
71 #define INTERVAL_END \
73 clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &(__mesh_end));\
74 double __diff = __mesh_end.tv_nsec - __mesh_start.tv_nsec;\
75 if (__diff < 0) __diff += 1000000000;\
79 #define INTERVAL_SHOW \
81 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "AVG process time: %f ns\n", __sum/__count)
83 #define INTERVAL_START
89 * All the states a tunnel can be in.
94 * Uninitialized status, should never appear in operation.
99 * Path to the peer not known yet
101 MESH_TUNNEL_SEARCHING,
104 * Request sent, not yet answered.
109 * Peer connected and ready to accept data
114 * Peer connected previosly but not responding
116 MESH_TUNNEL_RECONNECTING
121 /******************************************************************************/
122 /************************ DATA STRUCTURES ****************************/
123 /******************************************************************************/
125 /** FWD declaration */
130 * Struct used to queue messages in a tunnel.
132 struct MeshTunnelQueue
137 struct MeshTunnelQueue *next;
138 struct MeshTunnelQueue *prev;
143 struct MeshChannel *ch;
148 /* struct GNUNET_MessageHeader *msg; */
153 * Struct containing all information regarding a tunnel to a peer.
158 * Endpoint of the tunnel.
160 struct MeshPeer *peer;
163 * State of the tunnel.
165 enum MeshTunnelState state;
168 * Local peer ephemeral private key
170 struct GNUNET_CRYPTO_EccPrivateKey *my_eph_key;
173 * Local peer ephemeral public key
175 struct GNUNET_CRYPTO_EccPublicSignKey *my_eph;
178 * Remote peer's public key.
180 struct GNUNET_CRYPTO_EccPublicSignKey *peers_eph;
183 * Encryption ("our") key.
185 struct GNUNET_CRYPTO_SymmetricSessionKey e_key;
188 * Decryption ("their") key.
190 struct GNUNET_CRYPTO_SymmetricSessionKey d_key;
193 * Paths that are actively used to reach the destination peer.
195 struct MeshConnection *connection_head;
196 struct MeshConnection *connection_tail;
199 * Next connection number.
204 * Channels inside this tunnel.
206 struct MeshChannel *channel_head;
207 struct MeshChannel *channel_tail;
210 * Channel ID for the next created channel.
212 MESH_ChannelNumber next_chid;
215 * Channel ID for the next incoming channel.
217 MESH_ChannelNumber next_local_chid;
220 * Pending message count.
222 int pending_messages;
225 * Destroy flag: if true, destroy on last message.
230 * Queued messages, to transmit once tunnel gets connected.
232 struct MeshTunnelQueue *tq_head;
233 struct MeshTunnelQueue *tq_tail;
238 /******************************************************************************/
239 /************************ DEBUG FUNCTIONS ****************************/
240 /******************************************************************************/
244 * GNUNET_SCHEDULER_Task for printing a message after some operation is done
245 * @param cls string to print
246 * @param success GNUNET_OK if the PUT was transmitted,
247 * GNUNET_NO on timeout,
248 * GNUNET_SYSERR on disconnect from service
249 * after the PUT message was transmitted
250 * (so we don't know if it was received or not)
255 mesh_debug (void *cls, int success)
259 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "%s (%d)\n", s, success);
265 /******************************************************************************/
266 /*********************** GLOBAL VARIABLES ****************************/
267 /******************************************************************************/
269 /************************** Configuration parameters **************************/
273 * Maximum time allowed to connect to a peer found by string.
275 static struct GNUNET_TIME_Relative connect_timeout;
278 * Default TTL for payload packets.
280 static unsigned long long default_ttl;
283 * Percentage of messages that will be dropped (for test purposes only).
285 static unsigned long long drop_percent;
287 /*************************** Static global variables **************************/
290 * Handle to the statistics service.
292 static struct GNUNET_STATISTICS_Handle *stats;
295 * Local peer own ID (memory efficient handle).
297 static GNUNET_PEER_Id myid;
300 * Local peer own ID (full value).
302 static struct GNUNET_PeerIdentity my_full_id;
307 static struct GNUNET_CRYPTO_EccPrivateKey *my_private_key;
310 /******************************************************************************/
311 /*********************** DECLARATIONS **************************/
312 /******************************************************************************/
315 * Adds a path to the data structs of all the peers in the path
317 * @param p Path to process.
318 * @param confirmed Whether we know if the path works or not.
321 path_add_to_peers (struct MeshPeerPath *p, int confirmed);
325 * Change the tunnel state.
327 * @param t Tunnel whose state to change.
328 * @param state New state.
331 tunnel_change_state (struct MeshTunnel2 *t, enum MeshTunnelState state);
335 * Notify a tunnel that a connection has broken that affects at least
338 * @param t Tunnel affected.
339 * @param p1 Peer that got disconnected from p2.
340 * @param p2 Peer that got disconnected from p1.
342 * @return Short ID of the peer disconnected (either p1 or p2).
343 * 0 if the tunnel remained unaffected.
345 static GNUNET_PEER_Id
346 tunnel_notify_connection_broken (struct MeshTunnel2 *t,
347 GNUNET_PEER_Id p1, GNUNET_PEER_Id p2);
350 * @brief Use the given path for the tunnel.
351 * Update the next and prev hops (and RCs).
352 * (Re)start the path refresh in case the tunnel is locally owned.
354 * @param t Tunnel to update.
355 * @param p Path to use.
357 * @return Connection created.
359 static struct MeshConnection *
360 tunnel_use_path (struct MeshTunnel2 *t, struct MeshPeerPath *p);
363 * Tunnel is empty: destroy it.
365 * Notifies all participants (peers, cleints) about the destruction.
367 * @param t Tunnel to destroy.
370 tunnel_destroy_empty (struct MeshTunnel2 *t);
373 * Destroy the tunnel.
375 * This function does not generate any warning traffic to clients or peers.
378 * Cancel messages belonging to this tunnel queued to neighbors.
379 * Free any allocated resources linked to the tunnel.
381 * @param t The tunnel to destroy.
384 tunnel_destroy (struct MeshTunnel2 *t);
388 * Demultiplex by message type and call appropriate handler for a message
389 * towards a channel of a local tunnel.
391 * @param t Tunnel this message came on.
392 * @param msgh Message header.
393 * @param fwd Is this message fwd?
396 handle_decrypted (struct MeshTunnel2 *t,
397 const struct GNUNET_MessageHeader *msgh,
402 * Dummy function to separate declarations from definitions in function list.
405 __mesh_divider______________________________________________________________();
409 * Get string description for tunnel state.
411 * @param s Tunnel state.
413 * @return String representation.
416 GNUNET_MESH_DEBUG_TS2S (enum MeshTunnelState s)
418 static char buf[128];
422 case MESH_TUNNEL_NEW:
423 return "MESH_TUNNEL_NEW";
424 case MESH_TUNNEL_SEARCHING:
425 return "MESH_TUNNEL_SEARCHING";
426 case MESH_TUNNEL_WAITING:
427 return "MESH_TUNNEL_WAITING";
428 case MESH_TUNNEL_READY:
429 return "MESH_TUNNEL_READY";
430 case MESH_TUNNEL_RECONNECTING:
431 return "MESH_TUNNEL_RECONNECTING";
434 sprintf (buf, "%u (UNKNOWN STATE)", s);
442 /******************************************************************************/
443 /****************** GENERAL HELPER FUNCTIONS ************************/
444 /******************************************************************************/
448 * Get the static string for a peer ID.
452 * @return Static string for it's ID.
455 peer2s (const struct MeshPeer *peer)
459 return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id));
465 * Count established (ready) connections of a tunnel.
467 * @param t Tunnel on which to send the message.
469 * @return Number of connections.
472 tunnel_count_connections (struct MeshTunnel2 *t)
474 struct MeshConnection *c;
477 for (c = t->connection_head, i = 0; NULL != c; c = c->next, i++);
484 * Pick a connection on which send the next data message.
486 * @param t Tunnel on which to send the message.
487 * @param fwd Is this a fwd message?
489 * @return The connection on which to send the next message.
491 static struct MeshConnection *
492 tunnel_get_connection (struct MeshTunnel2 *t, int fwd)
494 struct MeshConnection *c;
495 struct MeshConnection *best;
496 struct MeshFlowControl *fc;
497 unsigned int lowest_q;
499 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "tunnel_get_connection %s\n",
503 for (c = t->connection_head; NULL != c; c = c->next)
505 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n",
506 GNUNET_h2s (&c->id), c->state);
507 if (MESH_CONNECTION_READY == c->state)
509 fc = fwd ? &c->fwd_fc : &c->bck_fc;
515 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " q_n %u, \n", fc->queue_n);
516 if (fc->queue_n < lowest_q)
519 lowest_q = fc->queue_n;
530 * Get the total buffer space for a tunnel.
533 * @param fwd Is this for FWD traffic?
535 * @return Buffer space offered by all connections in the tunnel.
538 tunnel_get_buffer (struct MeshTunnel2 *t, int fwd)
540 struct MeshConnection *c;
541 struct MeshFlowControl *fc;
544 c = t->connection_head;
547 /* If terminal, return biggest channel buffer */
548 if (NULL == c || GMC_is_terminal (c, fwd))
550 struct MeshChannel *ch;
553 if (NULL == t->channel_head)
556 for (ch = t->channel_head; NULL != ch; ch = ch->next)
558 ch_buf = channel_get_buffer (ch, fwd);
565 /* If not terminal, return sum of connection buffers */
568 if (c->state != MESH_CONNECTION_READY)
574 fc = fwd ? &c->fwd_fc : &c->bck_fc;
575 buffer += fc->queue_max - fc->queue_n;
584 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
585 * Encrypt data with the tunnel key.
587 * @param t Tunnel whose key to use.
588 * @param dst Destination for the encrypted data.
589 * @param src Source of the plaintext.
590 * @param size Size of the plaintext.
591 * @param iv Initialization Vector to use.
592 * @param fwd Is this a fwd message?
595 tunnel_encrypt (struct MeshTunnel2 *t,
596 void *dst, const void *src,
597 size_t size, uint64_t iv, int fwd)
599 memcpy (dst, src, size);
604 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
605 * Decrypt data with the tunnel key.
607 * @param t Tunnel whose key to use.
608 * @param dst Destination for the plaintext.
609 * @param src Source of the encrypted data.
610 * @param size Size of the encrypted data.
611 * @param iv Initialization Vector to use.
612 * @param fwd Is this a fwd message?
615 tunnel_decrypt (struct MeshTunnel2 *t,
616 void *dst, const void *src,
617 size_t size, uint64_t iv, int fwd)
619 memcpy (dst, src, size);
624 * Sends an already built message on a tunnel, choosing the best connection.
626 * @param message Message to send. Function modifies it.
627 * @param t Tunnel on which this message is transmitted.
628 * @param ch Channel on which this message is transmitted.
629 * @param fwd Is this a fwd message?
632 send_prebuilt_message_tunnel (struct GNUNET_MESH_Encrypted *msg,
633 struct MeshTunnel2 *t,
634 struct MeshChannel *ch,
637 struct MeshConnection *c;
640 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send on Tunnel %s\n",
642 c = tunnel_get_connection (t, fwd);
645 GNUNET_break (GNUNET_YES == t->destroy);
648 type = ntohs (msg->header.type);
651 case GNUNET_MESSAGE_TYPE_MESH_FWD:
652 case GNUNET_MESSAGE_TYPE_MESH_BCK:
653 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
654 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
656 msg->ttl = htonl (default_ttl);
659 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "unkown type %s\n",
660 GNUNET_MESH_DEBUG_M2S (type));
665 send_prebuilt_message_connection (&msg->header, c, ch, fwd);
671 * Sends a CREATE CONNECTION message for a path to a peer.
672 * Changes the connection and tunnel states if necessary.
674 * @param connection Connection to create.
677 send_connection_create (struct MeshConnection *connection)
679 struct MeshTunnel2 *t;
682 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection create\n");
684 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE,
685 sizeof (struct GNUNET_MESH_ConnectionCreate) +
686 (connection->path->length *
687 sizeof (struct GNUNET_PeerIdentity)),
692 (MESH_TUNNEL_SEARCHING == t->state || MESH_TUNNEL_NEW == t->state))
693 tunnel_change_state (t, MESH_TUNNEL_WAITING);
694 if (MESH_CONNECTION_NEW == connection->state)
695 connection_change_state (connection, MESH_CONNECTION_SENT);
700 * Sends a CONNECTION ACK message in reponse to a received CONNECTION_CREATE
703 * @param connection Connection to confirm.
704 * @param fwd Is this a fwd ACK? (First is bck (SYNACK), second is fwd (ACK))
707 send_connection_ack (struct MeshConnection *connection, int fwd)
709 struct MeshTunnel2 *t;
712 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Send connection ack\n");
714 GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK,
715 sizeof (struct GNUNET_MESH_ConnectionACK),
719 if (MESH_TUNNEL_NEW == t->state)
720 tunnel_change_state (t, MESH_TUNNEL_WAITING);
721 if (MESH_CONNECTION_READY != connection->state)
722 connection_change_state (connection, MESH_CONNECTION_SENT);
727 * Core callback to write a pre-constructed data packet to core buffer
729 * @param cls Closure (MeshTransmissionDescriptor with data in "data" member).
730 * @param size Number of bytes available in buf.
731 * @param buf Where the to write the message.
733 * @return number of bytes written to buf
736 send_core_data_raw (void *cls, size_t size, void *buf)
738 struct GNUNET_MessageHeader *msg = cls;
741 GNUNET_assert (NULL != msg);
742 total_size = ntohs (msg->size);
744 if (total_size > size)
749 memcpy (buf, msg, total_size);
756 * Function to send a create connection message to a peer.
758 * @param c Connection to create.
759 * @param size number of bytes available in buf
760 * @param buf where the callee should write the message
761 * @return number of bytes written to buf
764 send_core_connection_create (struct MeshConnection *c, size_t size, void *buf)
766 struct GNUNET_MESH_ConnectionCreate *msg;
767 struct GNUNET_PeerIdentity *peer_ptr;
768 struct MeshPeerPath *p = c->path;
772 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION CREATE...\n");
774 sizeof (struct GNUNET_MESH_ConnectionCreate) +
775 p->length * sizeof (struct GNUNET_PeerIdentity);
777 if (size < size_needed || NULL == buf)
782 msg = (struct GNUNET_MESH_ConnectionCreate *) buf;
783 msg->header.size = htons (size_needed);
784 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_CREATE);
787 peer_ptr = (struct GNUNET_PeerIdentity *) &msg[1];
788 for (i = 0; i < p->length; i++)
790 GNUNET_PEER_resolve (p->peers[i], peer_ptr++);
793 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
794 "CONNECTION CREATE (%u bytes long) sent!\n", size_needed);
800 * Creates a path ack message in buf and frees all unused resources.
802 * @param c Connection to send an ACK on.
803 * @param size number of bytes available in buf
804 * @param buf where the callee should write the message
806 * @return number of bytes written to buf
809 send_core_connection_ack (struct MeshConnection *c, size_t size, void *buf)
811 struct GNUNET_MESH_ConnectionACK *msg = buf;
812 struct MeshTunnel2 *t = c->t;
814 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending CONNECTION ACK...\n");
815 GNUNET_assert (NULL != t);
816 if (sizeof (struct GNUNET_MESH_ConnectionACK) > size)
821 msg->header.size = htons (sizeof (struct GNUNET_MESH_ConnectionACK));
822 msg->header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CONNECTION_ACK);
826 /* TODO add signature */
828 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION ACK sent!\n");
829 return sizeof (struct GNUNET_MESH_ConnectionACK);
835 * Adds a path to the peer_infos of all the peers in the path
837 * @param p Path to process.
838 * @param confirmed Whether we know if the path works or not.
841 path_add_to_peers (struct MeshPeerPath *p, int confirmed)
845 /* TODO: invert and add */
846 for (i = 0; i < p->length && p->peers[i] != myid; i++) /* skip'em */ ;
847 for (i++; i < p->length; i++)
849 struct MeshPeer *aux;
850 struct MeshPeerPath *copy;
852 aux = peer_get_short (p->peers[i]);
853 copy = path_duplicate (p);
854 copy->length = i + 1;
855 peer_add_path (aux, copy, p->length < 3 ? GNUNET_NO : confirmed);
862 fc_debug (struct MeshFlowControl *fc)
864 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " IN: %u/%u\n",
865 fc->last_pid_recv, fc->last_ack_sent);
866 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " OUT: %u/%u\n",
867 fc->last_pid_sent, fc->last_ack_recv);
868 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " QUEUE: %u/%u\n",
869 fc->queue_n, fc->queue_max);
873 connection_debug (struct MeshConnection *c)
877 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "*** DEBUG NULL CONNECTION ***\n");
880 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connection %s:%X\n",
881 peer2s (c->t->peer), GNUNET_h2s (&c->id));
882 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " state: %u, pending msgs: %u\n",
883 c->state, c->pending_messages);
884 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " FWD FC\n");
885 fc_debug (&c->fwd_fc);
886 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " BCK FC\n");
887 fc_debug (&c->bck_fc);
894 * Change the tunnel state.
896 * @param t Tunnel whose state to change.
897 * @param state New state.
900 tunnel_change_state (struct MeshTunnel2* t, enum MeshTunnelState state)
904 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
905 "Tunnel %s state was %s\n",
907 GNUNET_MESH_DEBUG_TS2S (t->state));
908 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
909 "Tunnel %s state is now %s\n",
911 GNUNET_MESH_DEBUG_TS2S (state));
917 * Send all cached messages that we can, tunnel is online.
919 * @param t Tunnel that holds the messages.
920 * @param fwd Is this fwd?
923 tunnel_send_queued_data (struct MeshTunnel2 *t, int fwd)
925 struct MeshTunnelQueue *tq;
926 struct MeshTunnelQueue *next;
929 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
930 "tunnel_send_queued_data on tunnel %s\n",
932 room = tunnel_get_buffer (t, fwd);
933 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room);
934 for (tq = t->tq_head; NULL != tq && room > 0; tq = next)
938 GNUNET_CONTAINER_DLL_remove (t->tq_head, t->tq_tail, tq);
939 send_prebuilt_message_channel ((struct GNUNET_MessageHeader *) &tq[1],
948 * Cache a message to be sent once tunnel is online.
950 * @param t Tunnel to hold the message.
951 * @param ch Channel the message is about.
952 * @param msg Message itself (copy will be made).
953 * @param fwd Is this fwd?
956 tunnel_queue_data (struct MeshTunnel2 *t,
957 struct MeshChannel *ch,
958 struct GNUNET_MessageHeader *msg,
961 struct MeshTunnelQueue *tq;
962 uint16_t size = ntohs (msg->size);
964 tq = GNUNET_malloc (sizeof (struct MeshTunnelQueue) + size);
967 memcpy (&tq[1], msg, size);
968 GNUNET_CONTAINER_DLL_insert_tail (t->tq_head, t->tq_tail, tq);
970 if (MESH_TUNNEL_READY == t->state)
971 tunnel_send_queued_data (t, fwd);
978 static struct MeshConnection *
979 tunnel_use_path (struct MeshTunnel2 *t, struct MeshPeerPath *p)
981 struct MeshConnection *c;
982 struct GNUNET_HashCode cid;
983 struct MeshPeer *peer;
984 unsigned int own_pos;
986 if (NULL == t || NULL == p)
992 GNUNET_CRYPTO_hash_create_random (GNUNET_CRYPTO_QUALITY_NONCE, &cid);
994 c = connection_new (&cid);
996 GNUNET_CONTAINER_DLL_insert (t->connection_head, t->connection_tail, c);
997 for (own_pos = 0; own_pos < p->length; own_pos++)
999 if (p->peers[own_pos] == myid)
1002 if (own_pos > p->length - 1)
1005 connection_destroy (c);
1008 c->own_pos = own_pos;
1013 c->fwd_maintenance_task =
1014 GNUNET_SCHEDULER_add_delayed (refresh_connection_time,
1015 &connection_fwd_keepalive, c);
1018 peer = connection_get_next_hop (c);
1019 if (NULL == peer->connections)
1021 connection_destroy (c);
1024 GNUNET_CONTAINER_multihashmap_put (peer->connections, &c->id, c,
1025 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1026 peer = connection_get_prev_hop (c);
1027 if (NULL == peer->connections)
1029 connection_destroy (c);
1032 GNUNET_CONTAINER_multihashmap_put (peer->connections, &c->id, c,
1033 GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST);
1039 * Notifies a tunnel that a connection has broken that affects at least
1040 * some of its peers. Sends a notification towards the root of the tree.
1041 * In case the peer is the owner of the tree, notifies the client that owns
1042 * the tunnel and tries to reconnect.
1044 * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME
1046 * @param t Tunnel affected.
1047 * @param p1 Peer that got disconnected from p2.
1048 * @param p2 Peer that got disconnected from p1.
1050 * @return Short ID of the peer disconnected (either p1 or p2).
1051 * 0 if the tunnel remained unaffected.
1053 static GNUNET_PEER_Id
1054 tunnel_notify_connection_broken (struct MeshTunnel2* t,
1055 GNUNET_PEER_Id p1, GNUNET_PEER_Id p2)
1057 // if (myid != p1 && myid != p2) FIXME
1062 // if (tree_get_predecessor (t->tree) != 0)
1064 // /* We are the peer still connected, notify owner of the disconnection. */
1065 // struct GNUNET_MESH_PathBroken msg;
1066 // struct GNUNET_PeerIdentity neighbor;
1068 // msg.header.size = htons (sizeof (msg));
1069 // msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN);
1070 // GNUNET_PEER_resolve (t->id.oid, &msg.oid);
1071 // msg.tid = htonl (t->id.tid);
1072 // msg.peer1 = my_full_id;
1073 // GNUNET_PEER_resolve (pid, &msg.peer2);
1074 // GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor);
1075 // send_prebuilt_message (&msg.header, &neighbor, t);
1084 * Send an ACK on the appropriate connection/channel, depending on
1085 * the direction and the position of the peer.
1087 * @param c Which connection to send the hop-by-hop ACK.
1088 * @param ch Channel, if any.
1089 * @param fwd Is this a fwd ACK? (will go dest->root)
1092 send_ack (struct MeshConnection *c, struct MeshChannel *ch, int fwd)
1094 unsigned int buffer;
1096 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1097 "send ack %s on %p %p\n",
1098 fwd ? "FWD" : "BCK", c, ch);
1099 if (NULL == c || GMC_is_terminal (c, fwd))
1101 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from all connections\n");
1102 buffer = tunnel_get_buffer (NULL == c ? ch->t : c->t, fwd);
1106 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " getting from one connection\n");
1107 buffer = connection_get_buffer (c, fwd);
1109 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " buffer available: %u\n", buffer);
1111 if ( (NULL != ch && channel_is_origin (ch, fwd)) ||
1112 (NULL != c && connection_is_origin (c, fwd)) )
1114 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on channel...\n");
1117 GNUNET_assert (NULL != ch);
1118 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " really sending!\n");
1119 send_local_ack (ch, fwd);
1124 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on all connections\n");
1125 GNUNET_assert (NULL != ch);
1126 channel_send_connections_ack (ch, buffer, fwd);
1130 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " sending on connection\n");
1131 connection_send_ack (c, buffer, fwd);
1139 * Confirm we got a channel create.
1141 * @param ch The channel to confirm.
1142 * @param fwd Should we send the ACK fwd?
1145 channel_send_ack (struct MeshChannel *ch, int fwd)
1147 struct GNUNET_MESH_ChannelManage msg;
1149 msg.header.size = htons (sizeof (msg));
1150 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK);
1151 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1152 " sending channel %s ack for channel %s:%X\n",
1153 fwd ? "FWD" : "BCK", peer2s (ch->t->peer),
1156 msg.chid = htonl (ch->gid);
1157 send_prebuilt_message_channel (&msg.header, ch, !fwd);
1162 * Send a message to all clients (local and remote) of this channel
1163 * notifying that the channel is no longer valid.
1165 * If some peer or client should not receive the message,
1166 * should be zero'ed out before calling this function.
1168 * @param ch The channel whose clients to notify.
1171 channel_send_destroy (struct MeshChannel *ch)
1173 struct GNUNET_MESH_ChannelManage msg;
1175 msg.header.size = htons (sizeof (msg));
1176 msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY);
1177 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1178 " sending channel destroy for channel %s:%X\n",
1179 peer2s (ch->t->peer),
1182 if (channel_is_terminal (ch, GNUNET_NO))
1184 if (NULL != ch->root && GNUNET_NO == ch->root->shutting_down)
1186 msg.chid = htonl (ch->lid_root);
1187 send_local_channel_destroy (ch, GNUNET_NO);
1192 msg.chid = htonl (ch->gid);
1193 send_prebuilt_message_channel (&msg.header, ch, GNUNET_NO);
1196 if (channel_is_terminal (ch, GNUNET_YES))
1198 if (NULL != ch->dest && GNUNET_NO == ch->dest->shutting_down)
1200 msg.chid = htonl (ch->lid_dest);
1201 send_local_channel_destroy (ch, GNUNET_YES);
1206 msg.chid = htonl (ch->gid);
1207 send_prebuilt_message_channel (&msg.header, ch, GNUNET_YES);
1215 static struct MeshTunnel2 *
1218 struct MeshTunnel2 *t;
1220 t = GNUNET_new (struct MeshTunnel2);
1222 t->next_local_chid = GNUNET_MESH_LOCAL_CHANNEL_ID_SERV;
1224 // GNUNET_CONTAINER_multihashmap_put (tunnels, tid, t,
1225 // GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
1227 // GNUNET_break (0);
1228 // tunnel_destroy (t);
1232 // char salt[] = "salt";
1233 // GNUNET_CRYPTO_kdf (&t->e_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
1234 // salt, sizeof (salt),
1235 // &t->e_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
1236 // &my_full_id, sizeof (struct GNUNET_PeerIdentity),
1237 // GNUNET_PEER_resolve2 (t->peer->id), sizeof (struct GNUNET_PeerIdentity),
1239 // GNUNET_CRYPTO_kdf (&t->d_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
1240 // salt, sizeof (salt),
1241 // &t->d_key, sizeof (struct GNUNET_CRYPTO_SymmetricSessionKey),
1242 // GNUNET_PEER_resolve2 (t->peer->id), sizeof (struct GNUNET_PeerIdentity),
1243 // &my_full_id, sizeof (struct GNUNET_PeerIdentity),
1251 * Add a connection to a tunnel.
1254 * @param c Connection.
1257 tunnel_add_connection (struct MeshTunnel2 *t, struct MeshConnection *c)
1259 struct MeshConnection *aux;
1261 for (aux = t->connection_head; aux != NULL; aux = aux->next)
1264 GNUNET_CONTAINER_DLL_insert_tail (t->connection_head, t->connection_tail, c);
1270 tunnel_destroy (struct MeshTunnel2 *t)
1272 struct MeshConnection *c;
1273 struct MeshConnection *next;
1278 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "destroying tunnel %s\n",
1281 // if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_remove (tunnels, &t->id, t))
1282 // GNUNET_break (0);
1284 for (c = t->connection_head; NULL != c; c = next)
1287 connection_destroy (c);
1290 GNUNET_STATISTICS_update (stats, "# tunnels", -1, GNUNET_NO);
1291 t->peer->tunnel = NULL;
1298 * Tunnel is empty: destroy it.
1300 * Notifies all connections about the destruction.
1302 * @param t Tunnel to destroy.
1305 tunnel_destroy_empty (struct MeshTunnel2 *t)
1307 struct MeshConnection *c;
1309 for (c = t->connection_head; NULL != c; c = c->next)
1311 if (GNUNET_NO == c->destroy)
1312 connection_send_destroy (c);
1315 if (0 == t->pending_messages)
1318 t->destroy = GNUNET_YES;
1323 * Destroy tunnel if empty (no more channels).
1325 * @param t Tunnel to destroy if empty.
1328 tunnel_destroy_if_empty (struct MeshTunnel2 *t)
1330 if (NULL != t->channel_head)
1333 tunnel_destroy_empty (t);
1337 /******************************************************************************/
1338 /**************** MESH NETWORK HANDLER HELPERS ***********************/
1339 /******************************************************************************/
1346 /******************************************************************************/
1347 /******************** MESH NETWORK HANDLERS **************************/
1348 /******************************************************************************/
1351 handle_decrypted (struct MeshTunnel2 *t,
1352 const struct GNUNET_MessageHeader *msgh,
1355 switch (ntohs (msgh->type))
1357 case GNUNET_MESSAGE_TYPE_MESH_DATA:
1358 /* Don't send hop ACK, wait for client to ACK */
1359 handle_data (t, (struct GNUNET_MESH_Data *) msgh, fwd);
1362 case GNUNET_MESSAGE_TYPE_MESH_DATA_ACK:
1363 handle_data_ack (t, (struct GNUNET_MESH_DataACK *) msgh, fwd);
1366 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE:
1367 handle_channel_create (t,
1368 (struct GNUNET_MESH_ChannelCreate *) msgh,
1372 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK:
1373 handle_channel_ack (t,
1374 (struct GNUNET_MESH_ChannelManage *) msgh,
1378 case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY:
1379 handle_channel_destroy (t,
1380 (struct GNUNET_MESH_ChannelManage *) msgh,
1385 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1386 "end-to-end message not known (%u)\n",
1387 ntohs (msgh->type));
1393 * Function to process paths received for a new peer addition. The recorded
1394 * paths form the initial tunnel, which can be optimized later.
1395 * Called on each result obtained for the DHT search.
1397 * @param cls closure
1401 search_handler (void *cls, struct MeshPeerPath *path)
1403 // struct MeshConnection *c;
1404 unsigned int connection_count;
1406 path_add_to_peers (path, GNUNET_NO);
1408 /* Count connections */
1409 connection_count = GMC_count (peer->tunnel->connection_head);
1411 /* If we already have 3 (or more (?!)) connections, it's enough */
1412 if (3 <= connection_count)
1415 if (peer->tunnel->state == MESH_TUNNEL_SEARCHING)
1417 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n");
1418 peer_connect (peer);
1424 /******************************************************************************/
1425 /************************ MAIN FUNCTIONS ****************************/
1426 /******************************************************************************/
1432 * Task run during shutdown.
1438 shutdown_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
1440 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shutting down\n");
1447 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "shut down\n");
1452 * Process mesh requests.
1454 * @param cls closure
1455 * @param server the initialized server
1456 * @param c configuration to use
1459 run (void *cls, struct GNUNET_SERVER_Handle *server,
1460 const struct GNUNET_CONFIGURATION_Handle *c)
1462 struct GNUNET_CRYPTO_EccPrivateKey *pk;
1464 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "starting to run\n");
1467 GNUNET_CONFIGURATION_get_value_time (c, "MESH", "CONNECT_TIMEOUT",
1470 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
1471 "MESH", "CONNECT_TIMEOUT", "MISSING");
1472 GNUNET_SCHEDULER_shutdown ();
1477 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL",
1480 GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_WARNING,
1481 "MESH", "DEFAULT_TTL", "USING DEFAULT");
1486 GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DROP_PERCENT",
1493 GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
1494 "\n***************************************\n"
1495 "Mesh is running with drop mode enabled.\n"
1496 "This is NOT a good idea!\n"
1497 "Remove the DROP_PERCENT option from your configuration.\n"
1498 "***************************************\n");
1502 stats = GNUNET_STATISTICS_create ("mesh", c);
1504 /* Scheduled the task to clean up when shutdown is called */
1505 GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL, &shutdown_task,
1507 GNUNET_log (GNUNET_ERROR_TYPE_INFO, "reading key\n");
1508 pk = GNUNET_CRYPTO_ecc_key_create_from_configuration (c);
1509 GNUNET_assert (NULL != pk);
1510 my_private_key = pk;
1511 GNUNET_CRYPTO_ecc_key_get_public_for_signature (my_private_key,
1512 &my_full_id.public_key);
1513 myid = GNUNET_PEER_intern (&my_full_id);
1514 GNUNET_log (GNUNET_ERROR_TYPE_INFO,
1515 "Mesh for peer [%s] starting\n",
1516 GNUNET_i2s(&my_full_id));
1518 GML_init (server); /* Local clients */
1519 GMC_init (c); /* Connections */
1520 GMP_init (c); /* Peers */
1521 GMD_init (c, &my_full_id); /* DHT */
1523 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Mesh service running\n");
1528 * The main function for the mesh service.
1530 * @param argc number of arguments from the command line
1531 * @param argv command line arguments
1532 * @return 0 ok, 1 on error
1535 main (int argc, char *const *argv)
1540 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main()\n");
1541 r = GNUNET_SERVICE_run (argc, argv, "mesh", GNUNET_SERVICE_OPTION_NONE, &run,
1543 ret = (GNUNET_OK == r) ? 0 : 1;
1544 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "main() END\n");