From 1e5f21da1cb58795b034f54ebe2c2d0b8ebf10e5 Mon Sep 17 00:00:00 2001 From: Bart Polot Date: Wed, 27 Nov 2013 04:19:13 +0000 Subject: - tunnels need separate connectivity state and encryption/handshake states --- src/mesh/gnunet-service-mesh_channel.c | 2 +- src/mesh/gnunet-service-mesh_connection.c | 31 ++--- src/mesh/gnunet-service-mesh_peer.c | 15 +-- src/mesh/gnunet-service-mesh_tunnel.c | 201 +++++++++++++++++++++--------- src/mesh/gnunet-service-mesh_tunnel.h | 73 +++++++---- 5 files changed, 216 insertions(+), 106 deletions(-) diff --git a/src/mesh/gnunet-service-mesh_channel.c b/src/mesh/gnunet-service-mesh_channel.c index e741d96ff..2d9ebb660 100644 --- a/src/mesh/gnunet-service-mesh_channel.c +++ b/src/mesh/gnunet-service-mesh_channel.c @@ -1506,7 +1506,7 @@ GMCH_handle_local_create (struct MeshClient *c, if (GMP_get_short_id (peer) == myid) { - GMT_change_state (t, MESH_TUNNEL3_READY); + GMT_change_cstate (t, MESH_TUNNEL3_READY); } else { diff --git a/src/mesh/gnunet-service-mesh_connection.c b/src/mesh/gnunet-service-mesh_connection.c index 8d2ef4044..35502f8c7 100644 --- a/src/mesh/gnunet-service-mesh_connection.c +++ b/src/mesh/gnunet-service-mesh_connection.c @@ -710,8 +710,8 @@ send_connection_ack (struct MeshConnection *connection, int fwd) sizeof (struct GNUNET_MESH_ConnectionACK), connection, fwd, &message_sent, NULL); connection->pending_messages++; - if (MESH_TUNNEL3_NEW == GMT_get_state (t)) - GMT_change_state (t, MESH_TUNNEL3_WAITING); + if (MESH_TUNNEL3_NEW == GMT_get_cstate (t)) + GMT_change_cstate (t, MESH_TUNNEL3_WAITING); if (MESH_CONNECTION_READY != connection->state) connection_change_state (connection, MESH_CONNECTION_SENT); } @@ -803,7 +803,7 @@ connection_recreate (struct MeshConnection *c, int fwd) static void connection_maintain (struct MeshConnection *c, int fwd) { - if (MESH_TUNNEL3_SEARCHING == GMT_get_state (c->t)) + if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (c->t)) { /* TODO DHT GET with RO_BART */ return; @@ -1284,8 +1284,8 @@ GMC_handle_create (void *cls, const struct GNUNET_PeerIdentity *peer, GMP_add_path_to_origin (orig_peer, path_duplicate (path), GNUNET_YES); add_to_peer (c, orig_peer); - if (MESH_TUNNEL3_NEW == GMT_get_state (c->t)) - GMT_change_state (c->t, MESH_TUNNEL3_WAITING); + if (MESH_TUNNEL3_NEW == GMT_get_cstate (c->t)) + GMT_change_cstate (c->t, MESH_TUNNEL3_WAITING); send_connection_ack (c, GNUNET_NO); if (MESH_CONNECTION_SENT == c->state) @@ -1395,8 +1395,8 @@ GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, /* Change connection and tunnel state */ connection_change_state (c, MESH_CONNECTION_READY); - if (MESH_TUNNEL3_WAITING == GMT_get_state (c->t)) - GMT_change_state (c->t, MESH_TUNNEL3_READY); + if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t)) + GMT_change_cstate (c->t, MESH_TUNNEL3_READY); /* Send ACK (~TCP ACK)*/ send_connection_ack (c, GNUNET_YES); @@ -1418,8 +1418,8 @@ GMC_handle_confirm (void *cls, const struct GNUNET_PeerIdentity *peer, connection_reset_timeout (c, GNUNET_NO); /* Change tunnel state */ - if (MESH_TUNNEL3_WAITING == GMT_get_state (c->t)) - GMT_change_state (c->t, MESH_TUNNEL3_READY); + if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t)) + GMT_change_cstate (c->t, MESH_TUNNEL3_READY); return GNUNET_OK; } @@ -1734,8 +1734,8 @@ handle_mesh_kx (const struct GNUNET_PeerIdentity *peer, connection_reset_timeout (c, fwd); if (NULL != c->t) { - if (MESH_TUNNEL3_WAITING == GMT_get_state (c->t)) - GMT_change_state (c->t, MESH_TUNNEL3_READY); + if (MESH_TUNNEL3_WAITING == GMT_get_cstate (c->t)) + GMT_change_cstate (c->t, MESH_TUNNEL3_READY); } /* Is this message for us? */ @@ -2652,7 +2652,7 @@ GMC_cancel (struct MeshConnectionQueue *q) void GMC_send_create (struct MeshConnection *connection) { - enum MeshTunnel3State state; + enum MeshTunnel3CState state; size_t size; size = sizeof (struct GNUNET_MESH_ConnectionCreate); @@ -2664,9 +2664,9 @@ GMC_send_create (struct MeshConnection *connection) LOG (GNUNET_ERROR_TYPE_DEBUG, " C_P+ %p %u (create)\n", connection, connection->pending_messages); connection->pending_messages++; - state = GMT_get_state (connection->t); + state = GMT_get_cstate (connection->t); if (MESH_TUNNEL3_SEARCHING == state || MESH_TUNNEL3_NEW == state) - GMT_change_state (connection->t, MESH_TUNNEL3_WAITING); + GMT_change_cstate (connection->t, MESH_TUNNEL3_WAITING); if (MESH_CONNECTION_NEW == connection->state) connection_change_state (connection, MESH_CONNECTION_SENT); } @@ -2765,6 +2765,9 @@ GMC_stop_poll (struct MeshConnection *c, int fwd) const char * GMC_2s (struct MeshConnection *c) { + if (NULL == c) + return "NULL"; + if (NULL != c->t) { static char buf[128]; diff --git a/src/mesh/gnunet-service-mesh_peer.c b/src/mesh/gnunet-service-mesh_peer.c index a1389b539..1679e2e66 100644 --- a/src/mesh/gnunet-service-mesh_peer.c +++ b/src/mesh/gnunet-service-mesh_peer.c @@ -436,7 +436,7 @@ send_core_connection_create (struct MeshConnection *c, size_t size, void *buf) GNUNET_PEER_resolve (p->peers[i], peer_ptr++); } - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_DEBUG, "CONNECTION CREATE (%u bytes long) sent!\n", size_needed); return size_needed; @@ -738,7 +738,7 @@ search_handler (void *cls, const struct MeshPeerPath *path) if (3 <= connection_count) return; - if (MESH_TUNNEL3_SEARCHING == GMT_get_state (peer->tunnel)) + if (MESH_TUNNEL3_SEARCHING == GMT_get_cstate (peer->tunnel)) { LOG (GNUNET_ERROR_TYPE_DEBUG, " ... connect!\n"); GMP_connect (peer); @@ -755,7 +755,7 @@ search_handler (void *cls, const struct MeshPeerPath *path) * @param buf Where the to write the message. * * @return number of bytes written to buf - * + * * FIXME add GNUNET_MESSAGE_TYPE_MESH_KEEPALIVE */ static size_t @@ -787,6 +787,7 @@ queue_send (void *cls, size_t size, void *buf) dst_id = GNUNET_PEER_resolve2 (peer->id); LOG (GNUNET_ERROR_TYPE_DEBUG, "* towards %s\n", GNUNET_i2s (dst_id)); + LOG (GNUNET_ERROR_TYPE_DEBUG, "* on connection %s\n", GMC_2s (c)); /* Check if buffer size is enough for the message */ if (queue->size > size) { @@ -1341,7 +1342,7 @@ GMP_connect (struct MeshPeer *peer) { GMD_search_stop (peer->search_h); peer->search_h = NULL; - LOG (GNUNET_ERROR_TYPE_DEBUG, + LOG (GNUNET_ERROR_TYPE_DEBUG, " Stopping DHT GET for peer %s\n", GMP_2s (peer)); } @@ -1354,8 +1355,8 @@ GMP_connect (struct MeshPeer *peer) LOG (GNUNET_ERROR_TYPE_DEBUG, " Starting DHT GET for peer %s\n", GMP_2s (peer)); peer->search_h = GMD_search (id, &search_handler, peer); - if (MESH_TUNNEL3_NEW == GMT_get_state (t)) - GMT_change_state (t, MESH_TUNNEL3_SEARCHING); + if (MESH_TUNNEL3_NEW == GMT_get_cstate (t)) + GMT_change_cstate (t, MESH_TUNNEL3_SEARCHING); } } @@ -1709,4 +1710,4 @@ GMP_2s (const struct MeshPeer *peer) if (NULL == peer) return "(NULL)"; return GNUNET_i2s (GNUNET_PEER_resolve2 (peer->id)); -} \ No newline at end of file +} diff --git a/src/mesh/gnunet-service-mesh_tunnel.c b/src/mesh/gnunet-service-mesh_tunnel.c index a13d88fd5..56b27147e 100644 --- a/src/mesh/gnunet-service-mesh_tunnel.c +++ b/src/mesh/gnunet-service-mesh_tunnel.c @@ -82,9 +82,14 @@ struct MeshTunnel3 struct MeshPeer *peer; /** - * State of the tunnel. + * State of the tunnel connectivity. */ - enum MeshTunnel3State state; + enum MeshTunnel3CState cstate; + + /** + * State of the tunnel encryption. + */ + enum MeshTunnel3EState estate; /** * Key eXchange context. @@ -247,18 +252,18 @@ static struct GNUNET_TIME_Relative rekey_period; /******************************************************************************/ /** - * Get string description for tunnel state. + * Get string description for tunnel connectivity state. * - * @param s Tunnel state. + * @param cs Tunnel state. * * @return String representation. */ static const char * -GMT_state2s (enum MeshTunnel3State s) +cstate2s (enum MeshTunnel3CState cs) { static char buf[128]; - switch (s) + switch (cs) { case MESH_TUNNEL3_NEW: return "MESH_TUNNEL3_NEW"; @@ -266,19 +271,63 @@ GMT_state2s (enum MeshTunnel3State s) return "MESH_TUNNEL3_SEARCHING"; case MESH_TUNNEL3_WAITING: return "MESH_TUNNEL3_WAITING"; - case MESH_TUNNEL3_KEY_SENT: - return "MESH_TUNNEL3_KEY_SENT"; case MESH_TUNNEL3_READY: return "MESH_TUNNEL3_READY"; - case MESH_TUNNEL3_RECONNECTING: - return "MESH_TUNNEL3_RECONNECTING"; - case MESH_TUNNEL3_REKEY: - return "MESH_TUNNEL3_REKEY"; default: - sprintf (buf, "%u (UNKNOWN STATE)", s); + sprintf (buf, "%u (UNKNOWN STATE)", cs); return buf; } + return ""; +} + + +/** + * Get string description for tunnel encryption state. + * + * @param es Tunnel state. + * + * @return String representation. + */ +static const char * +estate2s (enum MeshTunnel3EState es) +{ + static char buf[128]; + + switch (es) + { + case MESH_TUNNEL3_KEY_UNINITIALIZED: + return "MESH_TUNNEL3_KEY_UNINITIALIZED"; + case MESH_TUNNEL3_KEY_SENT: + return "MESH_TUNNEL3_KEY_SENT"; + case MESH_TUNNEL3_KEY_PING: + return "MESH_TUNNEL3_KEY_PING"; + case MESH_TUNNEL3_KEY_OK: + return "MESH_TUNNEL3_KEY_OK"; + + default: + sprintf (buf, "%u (UNKNOWN STATE)", es); + return buf; + } + return ""; +} + + +/** + * @brief Check if tunnel is ready to send traffic. + * + * Tunnel must be connected and with encryption correctly set up. + * + * @param t Tunnel to check. + * + * @return #GNUNET_YES if ready, #GNUNET_NO otherwise + */ +static int +is_ready (struct MeshTunnel3 *t) +{ + return (MESH_TUNNEL3_READY == t->cstate + && MESH_TUNNEL3_KEY_OK == t->estate) + || GMT_is_loopback (t); } @@ -531,7 +580,7 @@ tunnel_get_connection (struct MeshTunnel3 *t) for (iter = t->connection_head; NULL != iter; iter = iter->next) { LOG (GNUNET_ERROR_TYPE_DEBUG, " connection %s: %u\n", - GNUNET_h2s (GMC_get_id (iter->c)), GMC_get_state (iter->c)); + GMC_2s (iter->c), GMC_get_state (iter->c)); if (MESH_CONNECTION_READY == GMC_get_state (iter->c)) { qn = GMC_get_qn (iter->c, GMC_is_origin (iter->c, GNUNET_YES)); @@ -543,6 +592,7 @@ tunnel_get_connection (struct MeshTunnel3 *t) } } } + LOG (GNUNET_ERROR_TYPE_DEBUG, " selected: connection %s\n", GMC_2s (best)); return best; } @@ -569,6 +619,13 @@ send_queued_data (struct MeshTunnel3 *t) return; } + if (GNUNET_NO == is_ready (t)) + { + LOG (GNUNET_ERROR_TYPE_DEBUG, " not ready yet: %s/%s\n", + estate2s (t->estate), cstate2s (t->cstate)); + return; + } + room = GMT_get_connections_buffer (t); LOG (GNUNET_ERROR_TYPE_DEBUG, " buffer space: %u\n", room); for (tq = t->tq_head; NULL != tq && room > 0; tq = next) @@ -606,7 +663,9 @@ queue_data (struct MeshTunnel3 *t, struct MeshTunnelDelayed *tq; uint16_t size = ntohs (msg->size); - if (MESH_TUNNEL3_READY == t->state) + LOG (GNUNET_ERROR_TYPE_DEBUG, "queue data on Tunnel %s\n", GMT_2s (t)); + + if (GNUNET_YES == is_ready (t)) { GNUNET_break (0); return; @@ -696,7 +755,7 @@ send_ephemeral (struct MeshTunnel3 *t) { LOG (GNUNET_ERROR_TYPE_DEBUG, "%s()\n", __FUNCTION__); - kx_msg.sender_status = htonl (t->state); + kx_msg.sender_status = htonl (t->estate); send_kx (t, &kx_msg.header); } @@ -777,18 +836,20 @@ rekey_tunnel (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc) t->kx_ctx->d_key_old = t->d_key; } send_ephemeral (t); - if (MESH_TUNNEL3_READY == t->state || MESH_TUNNEL3_REKEY == t->state) - { - send_ping (t); - t->state = MESH_TUNNEL3_REKEY; - } - else if (MESH_TUNNEL3_WAITING == t->state) + switch (t->estate) { - t->state = MESH_TUNNEL3_KEY_SENT; - } - else - { - LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected state %u\n", t->state); + case MESH_TUNNEL3_KEY_UNINITIALIZED: + t->estate = MESH_TUNNEL3_KEY_SENT; + break; + case MESH_TUNNEL3_KEY_SENT: + break; + case MESH_TUNNEL3_KEY_PING: + case MESH_TUNNEL3_KEY_OK: + send_ping (t); + t->estate = MESH_TUNNEL3_KEY_PING; + break; + default: + LOG (GNUNET_ERROR_TYPE_DEBUG, "Unexpected state %u\n", t->estate); } LOG (GNUNET_ERROR_TYPE_DEBUG, " next call in %s\n", @@ -932,7 +993,7 @@ handle_data (struct MeshTunnel3 *t, return; } - GMT_change_state (t, MESH_TUNNEL3_READY); + GMT_change_cstate (t, MESH_TUNNEL3_READY); GMCH_handle_data (ch, msg, fwd); } @@ -1154,11 +1215,11 @@ handle_ephemeral (struct MeshTunnel3 *t, LOG (GNUNET_ERROR_TYPE_DEBUG, " km is %s\n", GNUNET_h2s (&km)); derive_symmertic (&t->e_key, &my_full_id, GMP_get_id (t->peer), &km); derive_symmertic (&t->d_key, GMP_get_id (t->peer), &my_full_id, &km); - if (MESH_TUNNEL3_KEY_SENT == t->state) + if (MESH_TUNNEL3_KEY_SENT == t->estate) { LOG (GNUNET_ERROR_TYPE_DEBUG, " our key was sent, send ping\n"); send_ping (t); - t->state = MESH_TUNNEL3_REKEY; + t->estate = MESH_TUNNEL3_KEY_PING; } } @@ -1232,8 +1293,7 @@ handle_pong (struct MeshTunnel3 *t, t->rekey_task = GNUNET_SCHEDULER_NO_TASK; GNUNET_free (t->kx_ctx); t->kx_ctx = NULL; - t->state = MESH_TUNNEL3_READY; - send_queued_data (t); + GMT_change_estate (t, MESH_TUNNEL3_KEY_OK); } @@ -1450,44 +1510,65 @@ GMT_new (struct MeshPeer *destination) /** - * Change the tunnel state. + * Change the tunnel's connection state. * - * @param t Tunnel whose state to change. - * @param state New state. + * @param t Tunnel whose connection state to change. + * @param cstate New connection state. */ void -GMT_change_state (struct MeshTunnel3* t, enum MeshTunnel3State state) +GMT_change_cstate (struct MeshTunnel3* t, enum MeshTunnel3CState state) { if (NULL == t) return; LOG (GNUNET_ERROR_TYPE_DEBUG, - "Tunnel %s state was %s\n", - GMP_2s (t->peer), - GMT_state2s (t->state)); + "Tunnel %s cstate was %s\n", + GMP_2s (t->peer), cstate2s (t->cstate)); LOG (GNUNET_ERROR_TYPE_DEBUG, - "Tunnel %s state is now %s\n", - GMP_2s (t->peer), - GMT_state2s (state)); + "Tunnel %s cstate is now %s\n", + GMP_2s (t->peer), cstate2s (state)); if (myid != GMP_get_short_id (t->peer) && - MESH_TUNNEL3_WAITING == t->state && MESH_TUNNEL3_READY == state) + MESH_TUNNEL3_READY != t->cstate && + MESH_TUNNEL3_READY == state && + MESH_TUNNEL3_KEY_UNINITIALIZED == t->estate) { LOG (GNUNET_ERROR_TYPE_DEBUG, " triggered rekey\n"); rekey_tunnel (t, NULL); - LOG (GNUNET_ERROR_TYPE_DEBUG, - "Tunnel %s state is now %s\n", - GMP_2s (t->peer), - GMT_state2s (t->state)); - } - else - { - t->state = state; } + t->cstate = state; + if (MESH_TUNNEL3_READY == state && 3 <= GMT_count_connections (t)) { GMP_stop_search (t->peer); } } +/** + * Change the tunnel encryption state. + * + * @param t Tunnel whose encryption state to change. + * @param state New encryption state. + */ +void +GMT_change_estate (struct MeshTunnel3* t, enum MeshTunnel3EState state) +{ + if (NULL == t) + return; + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Tunnel %s estate was %s\n", + GMP_2s (t->peer), estate2s (t->estate)); + LOG (GNUNET_ERROR_TYPE_DEBUG, + "Tunnel %s estate is now %s\n", + GMP_2s (t->peer), estate2s (state)); + if (myid != GMP_get_short_id (t->peer) && + MESH_TUNNEL3_KEY_OK != t->estate && MESH_TUNNEL3_KEY_OK == state) + { + t->estate = state; + send_queued_data (t); + return; + } + t->estate = state; +} + /** * Add a connection to a tunnel. @@ -1781,21 +1862,21 @@ GMT_count_channels (struct MeshTunnel3 *t) /** - * Get the state of a tunnel. + * Get the connectivity state of a tunnel. * * @param t Tunnel. * - * @return Tunnel's state. + * @return Tunnel's connectivity state. */ -enum MeshTunnel3State -GMT_get_state (struct MeshTunnel3 *t) +enum MeshTunnel3CState +GMT_get_cstate (struct MeshTunnel3 *t) { if (NULL == t) { GNUNET_break (0); - return (enum MeshTunnel3State) -1; + return (enum MeshTunnel3CState) -1; } - return t->state; + return t->cstate; } @@ -2050,6 +2131,7 @@ GMT_cancel (struct MeshTunnel3Queue *q) /* message_sent() will be called and free q */ } + /** * Sends an already built message on a tunnel, encrypting it and * choosing the best connection. @@ -2078,13 +2160,14 @@ GMT_send_prebuilt_message (const struct GNUNET_MessageHeader *message, uint32_t iv; uint16_t type; - if (MESH_TUNNEL3_READY != t->state) + LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t)); + + if (GNUNET_NO == is_ready (t)) { queue_data (t, ch, message); /* FIXME */ return NULL; } - LOG (GNUNET_ERROR_TYPE_DEBUG, "GMT Send on Tunnel %s\n", GMT_2s (t)); if (GMT_is_loopback (t)) { diff --git a/src/mesh/gnunet-service-mesh_tunnel.h b/src/mesh/gnunet-service-mesh_tunnel.h index d4be562a2..8fabe0155 100644 --- a/src/mesh/gnunet-service-mesh_tunnel.h +++ b/src/mesh/gnunet-service-mesh_tunnel.h @@ -41,9 +41,9 @@ extern "C" #include "gnunet_util_lib.h" /** - * All the states a tunnel can be in. + * All the connectivity states a tunnel can be in. */ -enum MeshTunnel3State +enum MeshTunnel3CState { /** * Uninitialized status, should never appear in operation. @@ -60,27 +60,39 @@ enum MeshTunnel3State */ MESH_TUNNEL3_WAITING, - /** - * Ephemeral key sent, waiting for peer's key. - */ - MESH_TUNNEL3_KEY_SENT, - /** * Peer connected and ready to accept data. */ MESH_TUNNEL3_READY, +}; - /** - * Peer connected previosly but not responding. - */ - MESH_TUNNEL3_RECONNECTING, - /** - * New ephemeral key and ping sent, waiting for pong. - * This means that we DO have the peer's ephemeral key, otherwise the - * state would be KEY_SENT. - */ - MESH_TUNNEL3_REKEY, +/** + * All the encryption states a tunnel can be in. + */ +enum MeshTunnel3EState +{ + /** + * Uninitialized status, should never appear in operation. + */ + MESH_TUNNEL3_KEY_UNINITIALIZED, + + /** + * Ephemeral key sent, waiting for peer's key. + */ + MESH_TUNNEL3_KEY_SENT, + + /** + * New ephemeral key and ping sent, waiting for pong. + * This means that we DO have the peer's ephemeral key, otherwise the + * state would be KEY_SENT. + */ + MESH_TUNNEL3_KEY_PING, + + /** + * Handshake completed: session key available. + */ + MESH_TUNNEL3_KEY_OK, }; /** @@ -172,14 +184,25 @@ GMT_destroy_if_empty (struct MeshTunnel3 *t); void GMT_destroy (struct MeshTunnel3 *t); + +/** + * Change the tunnel's connection state. + * + * @param t Tunnel whose connection state to change. + * @param cstate New connection state. + */ +void +GMT_change_cstate (struct MeshTunnel3* t, enum MeshTunnel3CState state); + + /** - * Change the tunnel state. + * Change the tunnel encryption state. * - * @param t Tunnel whose state to change. - * @param state New state. + * @param t Tunnel whose encryption state to change. + * @param state New encryption state. */ void -GMT_change_state (struct MeshTunnel3* t, enum MeshTunnel3State state); +GMT_change_estate (struct MeshTunnel3* t, enum MeshTunnel3EState state); /** * Add a connection to a tunnel. @@ -284,14 +307,14 @@ unsigned int GMT_count_channels (struct MeshTunnel3 *t); /** - * Get the state of a tunnel. + * Get the connectivity state of a tunnel. * * @param t Tunnel. * - * @return Tunnel's state. + * @return Tunnel's connectivity state. */ -enum MeshTunnel3State -GMT_get_state (struct MeshTunnel3 *t); +enum MeshTunnel3CState +GMT_get_cstate (struct MeshTunnel3 *t); /** * Get the maximum buffer space for a tunnel towards a local client. -- cgit v1.2.3