X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=src%2Fmesh%2Fgnunet-service-mesh_tunnel.c;h=231eeabebb97d1a2941b24bd6946ba7c020184d4;hb=1ef7f26b7579ae2a6256751a3f5ebfbf60afbb2f;hp=b077d00b229f2da26e8d4645ae45daffae6400b3;hpb=9351b1e9bdf2b067b6db06562c26ba658cff42b8;p=oweals%2Fgnunet.git diff --git a/src/mesh/gnunet-service-mesh_tunnel.c b/src/mesh/gnunet-service-mesh_tunnel.c index b077d00b2..231eeabeb 100644 --- a/src/mesh/gnunet-service-mesh_tunnel.c +++ b/src/mesh/gnunet-service-mesh_tunnel.c @@ -33,6 +33,9 @@ #define LOG(level, ...) GNUNET_log_from(level,"mesh-tun",__VA_ARGS__) +#define START_FUNCTION LOG(GNUNET_ERROR_TYPE_DEBUG, "%s start\n", __FUNCTION__) +#define END_FUNCTION LOG(GNUNET_ERROR_TYPE_DEBUG, "%s end\n", __FUNCTION__) + /******************************************************************************/ /******************************** STRUCTS **********************************/ @@ -164,19 +167,19 @@ struct MeshTunnelQueue extern struct GNUNET_STATISTICS_Handle *stats; /** - * Default TTL for payload packets. + * Local peer own ID (memory efficient handle). */ -static unsigned long long default_ttl; +extern GNUNET_PEER_Id myid; /** - * Local peer own ID (memory efficient handle). + * Local peer own ID (full value). */ -static GNUNET_PEER_Id my_short_id; +extern struct GNUNET_PeerIdentity my_full_id; /** - * Local peer own ID (full value). + * Default TTL for payload packets. */ -const static struct GNUNET_PeerIdentity *my_full_id; +static unsigned long long default_ttl; /** * Own private key. @@ -257,6 +260,46 @@ tunnel_get_connection (struct MeshTunnel3 *t, int fwd) } +/** + * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME + * Encrypt data with the tunnel key. + * + * @param t Tunnel whose key to use. + * @param dst Destination for the GMT_encrypted data. + * @param src Source of the plaintext. + * @param size Size of the plaintext. + * @param iv Initialization Vector to use. + * @param fwd Is this a fwd message? + */ +static void +GMT_encrypt (struct MeshTunnel3 *t, + void *dst, const void *src, + size_t size, uint64_t iv, int fwd) +{ + memcpy (dst, src, size); +} + + +/** + * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME + * Decrypt data with the tunnel key. + * + * @param t Tunnel whose key to use. + * @param dst Destination for the plaintext. + * @param src Source of the GMT_encrypted data. + * @param size Size of the GMT_encrypted data. + * @param iv Initialization Vector to use. + * @param fwd Is this a fwd message? + */ +static void +GMT_decrypt (struct MeshTunnel3 *t, + void *dst, const void *src, + size_t size, uint64_t iv, int fwd) +{ + memcpy (dst, src, size); +} + + void handle_data (struct MeshTunnel3 *t, const struct GNUNET_MESH_Data *msg, @@ -331,6 +374,8 @@ handle_ch_create (struct MeshTunnel3 *t, const struct GNUNET_MESH_ChannelCreate *msg, int fwd) { + ; + struct MeshTChannel *tch; struct MeshChannel *ch; size_t size; @@ -352,12 +397,14 @@ handle_ch_create (struct MeshTunnel3 *t, } else { - ch = GMCH_handle_create (msg, fwd); + ch = GMCH_handle_create (t, msg, fwd); } tch = GNUNET_new (struct MeshTChannel); tch->ch = ch; GNUNET_CONTAINER_DLL_insert (t->channel_head, t->channel_tail, tch); + + ; } void @@ -417,9 +464,6 @@ handle_ch_destroy (struct MeshTunnel3 *t, GMCH_handle_destroy (ch, msg, fwd); } -/******************************************************************************/ -/******************************** API ***********************************/ -/******************************************************************************/ /** * Demultiplex by message type and call appropriate handler for a message @@ -429,10 +473,10 @@ handle_ch_destroy (struct MeshTunnel3 *t, * @param msgh Message header. * @param fwd Is this message fwd? */ -void -GMT_handle_decrypted (struct MeshTunnel3 *t, - const struct GNUNET_MessageHeader *msgh, - int fwd) +static void +handle_decrypted (struct MeshTunnel3 *t, + const struct GNUNET_MessageHeader *msgh, + int fwd) { uint16_t type; @@ -478,6 +522,40 @@ GMT_handle_decrypted (struct MeshTunnel3 *t, } } +/******************************************************************************/ +/******************************** API ***********************************/ +/******************************************************************************/ + + +/** + * Decrypt and demultiplex by message type. Call appropriate handler + * for every message. + * + * @param t Tunnel this message came on. + * @param msg Encrypted message. + * @param fwd Is this message fwd? + */ +void +GMT_handle_encrypted (struct MeshTunnel3 *t, + const struct GNUNET_MESH_Encrypted *msg, + int fwd) +{ + size_t size = ntohs (msg->header.size); + size_t payload_size = size - sizeof (struct GNUNET_MESH_Encrypted); + char cbuf[payload_size]; + struct GNUNET_MessageHeader *msgh; + unsigned int off; + + GMT_decrypt (t, cbuf, &msg[1], payload_size, msg->iv, fwd); + off = 0; + while (off < payload_size) + { + msgh = (struct GNUNET_MessageHeader *) &cbuf[off]; + handle_decrypted (t, msgh, fwd); + off += ntohs (msgh->size); + } +} + /** * Cache a message to be sent once tunnel is online. @@ -522,11 +600,12 @@ GMT_send_queued_data (struct MeshTunnel3 *t, int fwd) LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_send_queued_data on tunnel %s\n", - GMP_2s (t->peer)); + GMT_2s (t)); room = GMT_get_buffer (t, fwd); LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room); for (tq = t->tq_head; NULL != tq && room > 0; tq = next) { + LOG (GNUNET_ERROR_TYPE_DEBUG, " data on channel %s\n", GMCH_2s (tq->ch)); next = tq->next; room--; GNUNET_CONTAINER_DLL_remove (t->tq_head, t->tq_tail, tq); @@ -535,6 +614,9 @@ GMT_send_queued_data (struct MeshTunnel3 *t, int fwd) GNUNET_free (tq); } + LOG (GNUNET_ERROR_TYPE_DEBUG, + "GMT_send_queued_data end\n", + GMP_2s (t->peer)); } @@ -547,9 +629,9 @@ GMT_send_queued_data (struct MeshTunnel3 *t, int fwd) */ void GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, - const struct GNUNET_PeerIdentity *id, const struct GNUNET_CRYPTO_EddsaPrivateKey *key) { + LOG (GNUNET_ERROR_TYPE_DEBUG, "init\n"); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_number (c, "MESH", "DEFAULT_TTL", &default_ttl)) @@ -558,9 +640,7 @@ GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, "MESH", "DEFAULT_TTL", "USING DEFAULT"); default_ttl = 64; } - my_full_id = id; my_private_key = key; - my_short_id = GNUNET_PEER_intern (my_full_id); } @@ -570,20 +650,22 @@ GMT_init (const struct GNUNET_CONFIGURATION_Handle *c, void GMT_shutdown (void) { - GNUNET_PEER_change_rc (my_short_id, -1); } /** * Create a tunnel. + * + * @param destination Peer this tunnel is towards. */ struct MeshTunnel3 * -GMT_new (void) +GMT_new (struct MeshPeer *destination) { struct MeshTunnel3 *t; t = GNUNET_new (struct MeshTunnel3); t->next_chid = 0; + t->peer = destination; // if (GNUNET_OK != // GNUNET_CONTAINER_multihashmap_put (tunnels, tid, t, // GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST)) @@ -611,7 +693,6 @@ GMT_new (void) } - /** * Change the tunnel state. * @@ -827,48 +908,6 @@ GMT_destroy (struct MeshTunnel3 *t) } -/** - * Notifies a tunnel that a connection has broken that affects at least - * some of its peers. Sends a notification towards the root of the tree. - * In case the peer is the owner of the tree, notifies the client that owns - * the tunnel and tries to reconnect. - * - * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME - * - * @param t Tunnel affected. - * @param p1 Peer that got disconnected from p2. - * @param p2 Peer that got disconnected from p1. - * - * @return Short ID of the peer disconnected (either p1 or p2). - * 0 if the tunnel remained unaffected. - */ -GNUNET_PEER_Id -GMT_notify_connection_broken (struct MeshTunnel3* t, - GNUNET_PEER_Id p1, GNUNET_PEER_Id p2) -{ -// if (myid != p1 && myid != p2) FIXME -// { -// return; -// } -// -// if (tree_get_predecessor (t->tree) != 0) -// { -// /* We are the peer still connected, notify owner of the disconnection. */ -// struct GNUNET_MESH_PathBroken msg; -// struct GNUNET_PeerIdentity neighbor; -// -// msg.header.size = htons (sizeof (msg)); -// msg.header.type = htons (GNUNET_MESSAGE_TYPE_MESH_PATH_BROKEN); -// GNUNET_PEER_resolve (t->id.oid, &msg.oid); -// msg.tid = htonl (t->id.tid); -// msg.peer1 = my_full_id; -// GNUNET_PEER_resolve (pid, &msg.peer2); -// GNUNET_PEER_resolve (tree_get_predecessor (t->tree), &neighbor); -// send_prebuilt_message (&msg.header, &neighbor, t); -// } - return 0; -} - /** * @brief Use the given path for the tunnel. * Update the next and prev hops (and RCs). @@ -894,7 +933,7 @@ GMT_use_path (struct MeshTunnel3 *t, struct MeshPeerPath *p) for (own_pos = 0; own_pos < p->length; own_pos++) { - if (p->peers[own_pos] == my_short_id) + if (p->peers[own_pos] == myid) break; } if (own_pos > p->length - 1) @@ -910,48 +949,6 @@ GMT_use_path (struct MeshTunnel3 *t, struct MeshPeerPath *p) } -/** - * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME - * Encrypt data with the tunnel key. - * Make static? - * - * @param t Tunnel whose key to use. - * @param dst Destination for the encrypted data. - * @param src Source of the plaintext. - * @param size Size of the plaintext. - * @param iv Initialization Vector to use. - * @param fwd Is this a fwd message? - */ -void -GMT_encrypt (struct MeshTunnel3 *t, - void *dst, const void *src, - size_t size, uint64_t iv, int fwd) -{ - memcpy (dst, src, size); -} - - -/** - * FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME FIXME - * Decrypt data with the tunnel key. - * Make static? - * - * @param t Tunnel whose key to use. - * @param dst Destination for the plaintext. - * @param src Source of the encrypted data. - * @param size Size of the encrypted data. - * @param iv Initialization Vector to use. - * @param fwd Is this a fwd message? - */ -void -GMT_decrypt (struct MeshTunnel3 *t, - void *dst, const void *src, - size_t size, uint64_t iv, int fwd) -{ - memcpy (dst, src, size); -} - - /** * Count established (ready) connections of a tunnel. * @@ -987,7 +984,7 @@ GMT_count_channels (struct MeshTunnel3 *t) for (count = 0, iter = t->channel_head; NULL != iter; - iter = iter->next, count++); + iter = iter->next, count++) /* skip */; return count; } @@ -1011,10 +1008,13 @@ GMT_get_state (struct MeshTunnel3 *t) /** * Get the total buffer space for a tunnel. * + * If terminal, use the biggest channel buffer (or 64) if no channel exists. + * If not terminal, use the sum of all connection buffers. + * * @param t Tunnel. * @param fwd Is this for FWD traffic? * - * @return Buffer space offered by all connections in the tunnel. + * @return Buffer space offered by all entities (c/ch) in the tunnel. */ unsigned int GMT_get_buffer (struct MeshTunnel3 *t, int fwd) @@ -1032,7 +1032,10 @@ GMT_get_buffer (struct MeshTunnel3 *t, int fwd) unsigned int ch_buf; if (NULL == t->channel_head) + { + /* Probably getting buffer for a channel create/handshake. */ return 64; + } for (iter_ch = t->channel_head; NULL != iter_ch; iter_ch = iter_ch->next) { @@ -1099,7 +1102,129 @@ GMT_get_next_chid (struct MeshTunnel3 *t) /** - * Sends an already built message on a tunnel, encrypting it and + * Send ACK on one or more channels due to buffer in connections.. + * + * @param t Channel which has some free buffer space. + * @param fwd Is this for FWD traffic? (ACK goes to root) + */ +void +GMT_unchoke_channels (struct MeshTunnel3 *t, int fwd) +{ + struct MeshTChannel *iter; + unsigned int buffer; + unsigned int channels = GMT_count_channels (t); + unsigned int choked_n; + struct MeshChannel *choked[channels]; + + LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT_unchoke_channels on %s\n", GMT_2s (t)); + + if (NULL == t) + { + GNUNET_break (0); + return; + } + + /* Get buffer space */ + buffer = GMT_get_buffer (t, fwd); + if (0 == buffer) + { + return; + } + + /* Count and remember choked channels */ + choked_n = 0; + for (iter = t->channel_head; NULL != iter; iter = iter->next) + { + if (GNUNET_NO == GMCH_get_allowed (iter->ch, fwd)) + { + choked[choked_n++] = iter->ch; + } + } + + /* Unchoke random channels */ + while (0 < buffer && 0 < choked_n) + { + unsigned int r = GNUNET_CRYPTO_random_u32 (GNUNET_CRYPTO_QUALITY_WEAK, + choked_n); + GMCH_allow_client (choked[r], fwd); + choked_n--; + buffer--; + choked[r] = choked[choked_n]; + } +} + + +/** + * Send ACK on one or more connections due to buffer space to the client. + * + * Iterates all connections of the tunnel and sends ACKs appropriately. + * + * @param t Tunnel. + * @param fwd Is this in for FWD traffic? (ACK goes dest->root) + */ +void +GMT_send_acks (struct MeshTunnel3 *t, int fwd) +{ + struct MeshTConnection *iter; + uint32_t allowed; + uint32_t to_allow; + uint32_t allow_per_connection; + unsigned int cs; + unsigned int buffer; + + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Tunnel send %s ACKs on %s\n", + fwd ? "FWD" : "BCK", GMT_2s (t)); + + if (NULL == t) + { + GNUNET_break (0); + return; + } + if (NULL == t->channel_head || + GNUNET_NO == GMCH_is_origin (t->channel_head->ch, !fwd)) + { + GNUNET_break (0); + return; + } + + buffer = GMT_get_buffer (t, fwd); + + /* Count connections, how many messages are already allowed */ + cs = GMT_count_connections (t); + for (allowed = 0, iter = t->connection_head; NULL != iter; iter = iter->next) + { + allowed += GMC_get_allowed (iter->c, fwd); + } + + /* Make sure there is no overflow */ + if (allowed > buffer) + { + GNUNET_break (0); + return; + } + + /* Authorize connections to send more data */ + to_allow = buffer; /* - allowed; */ + + for (iter = t->connection_head; NULL != iter && to_allow > 0; iter = iter->next) + { + allow_per_connection = to_allow/cs; + to_allow -= allow_per_connection; + cs--; + if (GMC_get_allowed (iter->c, fwd) > 64 / 3) + { + continue; + } + GMC_allow (iter->c, buffer, fwd); + } + + GNUNET_break (to_allow == 0); +} + + +/** + * Sends an already built message on a tunnel, GMT_encrypting it and * choosing the best connection. * * @param message Message to send. Function modifies it. @@ -1120,7 +1245,7 @@ GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, uint64_t iv; uint16_t type; - LOG (GNUNET_ERROR_TYPE_DEBUG, "Send on Tunnel %s\n", GMP_2s (t->peer)); + LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMP_2s (t->peer)); iv = GNUNET_CRYPTO_random_u64 (GNUNET_CRYPTO_QUALITY_NONCE, UINT64_MAX); msg = (struct GNUNET_MESH_Encrypted *) cbuf; @@ -1137,10 +1262,10 @@ GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, type = ntohs (message->type); switch (type) { - case GNUNET_MESSAGE_TYPE_MESH_FWD: - case GNUNET_MESSAGE_TYPE_MESH_BCK: + case GNUNET_MESSAGE_TYPE_MESH_DATA: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_CREATE: case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_DESTROY: + case GNUNET_MESSAGE_TYPE_MESH_CHANNEL_ACK: msg->cid = *GMC_get_id (c); msg->ttl = htonl (default_ttl); break; @@ -1151,6 +1276,7 @@ GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, } msg->reserved = 0; + t->pending_messages++; GMC_send_prebuilt_message (&msg->header, c, ch, fwd); } @@ -1164,7 +1290,69 @@ GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, int GMT_is_loopback (const struct MeshTunnel3 *t) { - return (my_short_id == GMP_get_short_id(t->peer)); + return (myid == GMP_get_short_id(t->peer)); +} + + +/** + * Is the tunnel using this path already? + * + * @param t Tunnel. + * @param p Path. + * + * @return GNUNET_YES a connection uses this path. + */ +int +GMT_is_path_used (const struct MeshTunnel3 *t, const struct MeshPeerPath *p) +{ + struct MeshTConnection *iter; + + for (iter = t->connection_head; NULL != iter; iter = iter->next) + if (GMC_get_path (iter->c) == p) + return GNUNET_YES; + + return GNUNET_NO; +} + + +/** + * Get a cost of a path for a tunnel considering existing connections. + * + * @param t Tunnel. + * @param path Candidate path. + * + * @return Cost of the path (path length + number of overlapping nodes) + */ +unsigned int +GMT_get_path_cost (const struct MeshTunnel3 *t, + const struct MeshPeerPath *path) +{ + struct MeshTConnection *iter; + unsigned int overlap; + unsigned int i; + unsigned int j; + + if (NULL == path) + return 0; + + overlap = 0; + GNUNET_assert (NULL != t); + + for (i = 0; i < path->length; i++) + { + for (iter = t->connection_head; NULL != iter; iter = iter->next) + { + for (j = 0; j < GMC_get_path (iter->c)->length; j++) + { + if (path->peers[i] == GMC_get_path (iter->c)->peers[j]) + { + overlap++; + break; + } + } + } + } + return (path->length + overlap) * (path->score * -1); }