From 434bd08c383c1128e4c95d84d8e546ced6dfb629 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Sun, 12 Jul 2009 22:11:16 +0000 Subject: [PATCH] transport fixes, hello API extension --- src/datastore/datastore_api.c | 5 +- src/hello/hello.c | 22 ++++ src/include/gnunet_hello_lib.h | 12 ++ src/topology/gnunet-daemon-topology.c | 4 +- src/transport/gnunet-service-transport.c | 9 +- src/transport/plugin_transport_tcp.c | 157 ++++++++++++----------- src/transport/test_transport_api.c | 16 +-- src/transport/transport_api.c | 9 +- 8 files changed, 132 insertions(+), 102 deletions(-) diff --git a/src/datastore/datastore_api.c b/src/datastore/datastore_api.c index a024d9e96..5e87affaf 100644 --- a/src/datastore/datastore_api.c +++ b/src/datastore/datastore_api.c @@ -29,6 +29,9 @@ #include "datastore.h" +/** + * + */ struct MessageQueue { /** @@ -113,7 +116,7 @@ struct GNUNET_DATASTORE_Handle *GNUNET_DATASTORE_connect (struct /** - * Transmit DROP message to Database service. + * Transmit DROP message to datastore service. */ static size_t transmit_drop (void *cls, diff --git a/src/hello/hello.c b/src/hello/hello.c index 79d0edf8d..a7aaf7d54 100644 --- a/src/hello/hello.c +++ b/src/hello/hello.c @@ -479,5 +479,27 @@ GNUNET_HELLO_get_key (const struct GNUNET_HELLO_Message *hello, } +/** + * Get the peer identity from a HELLO message. + * + * @param hello the hello message + * @param peer where to store the peer's identity + * @return GNUNET_SYSERR if the HELLO was malformed + */ +int +GNUNET_HELLO_get_id (const struct GNUNET_HELLO_Message *hello, + struct GNUNET_PeerIdentity *peer) +{ + uint16_t ret = ntohs (hello->header.size); + if ((ret < sizeof (struct GNUNET_HELLO_Message)) || + (ntohs (hello->header.type) != GNUNET_MESSAGE_TYPE_HELLO)) + return GNUNET_SYSERR; + GNUNET_CRYPTO_hash (&hello->publicKey, + sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), + &peer->hashPubKey); + return GNUNET_OK; +} + + /* end of hello.c */ diff --git a/src/include/gnunet_hello_lib.h b/src/include/gnunet_hello_lib.h index 2ba6df6ab..8978890f0 100644 --- a/src/include/gnunet_hello_lib.h +++ b/src/include/gnunet_hello_lib.h @@ -195,6 +195,18 @@ GNUNET_HELLO_get_key (const struct GNUNET_HELLO_Message *hello, *publicKey); +/** + * Get the peer identity from a HELLO message. + * + * @param hello the hello message + * @param peer where to store the peer's identity + * @return GNUNET_SYSERR if the HELLO was malformed + */ +int +GNUNET_HELLO_get_id (const struct GNUNET_HELLO_Message *hello, + struct GNUNET_PeerIdentity *peer); + + /* ifndef GNUNET_HELLO_LIB_H */ #endif diff --git a/src/topology/gnunet-daemon-topology.c b/src/topology/gnunet-daemon-topology.c index 20d541eb2..73fb84981 100644 --- a/src/topology/gnunet-daemon-topology.c +++ b/src/topology/gnunet-daemon-topology.c @@ -497,7 +497,6 @@ static void consider_for_advertising (const struct GNUNET_HELLO_Message *hello) { int have_address; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; struct GNUNET_PeerIdentity pid; struct HelloList *pos; uint16_t size; @@ -509,8 +508,7 @@ consider_for_advertising (const struct GNUNET_HELLO_Message *hello) &have_address); if (GNUNET_NO == have_address) return; /* no point in advertising this one... */ - GNUNET_HELLO_get_key (hello, &pkey); - GNUNET_CRYPTO_hash (&pkey, sizeof (pkey), &pid.hashPubKey); + GNUNET_HELLO_get_id (hello, &pid); pos = hellos; while (pos != NULL) { diff --git a/src/transport/gnunet-service-transport.c b/src/transport/gnunet-service-transport.c index c34efec6c..d7bd13317 100644 --- a/src/transport/gnunet-service-transport.c +++ b/src/transport/gnunet-service-transport.c @@ -1649,6 +1649,7 @@ check_hello_validated (void *cls, struct ValidationAddress *va; struct TransportPlugin *tp; int first_call; + struct GNUNET_PeerIdentity apeer; first_call = GNUNET_NO; if (chvc->e == NULL) @@ -1679,6 +1680,9 @@ check_hello_validated (void *cls, if (h != NULL) return; /* wait for next call */ /* finally, transmit validation attempts */ + GNUNET_assert (GNUNET_OK == + GNUNET_HELLO_get_id (chvc->hello, + &apeer)); va = chvc->e->addresses; while (va != NULL) { @@ -1686,13 +1690,14 @@ check_hello_validated (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Establishing `%s' connection to validate `%s' of `%4s'\n", va->transport_name, - "HELLO", GNUNET_i2s (peer)); + "HELLO", + GNUNET_i2s (&apeer)); #endif tp = find_transport (va->transport_name); GNUNET_assert (tp != NULL); if (GNUNET_OK != tp->api->validate (tp->api->cls, - peer, + &apeer, va->challenge, HELLO_VERIFICATION_TIMEOUT, &va[1], diff --git a/src/transport/plugin_transport_tcp.c b/src/transport/plugin_transport_tcp.c index 9a2a54890..0d08fec69 100644 --- a/src/transport/plugin_transport_tcp.c +++ b/src/transport/plugin_transport_tcp.c @@ -337,6 +337,8 @@ struct Session /** * Are we still expecting the welcome message? (GNUNET_YES/GNUNET_NO) + * GNUNET_SYSERR is used to mark non-welcoming connections (HELLO + * validation only). */ int expecting_welcome; @@ -500,80 +502,6 @@ create_session (struct Plugin *plugin, } -/** - * Create a new session connecting to the specified - * target at the specified address. - * - * @param plugin us - * @param target peer to connect to - * @param addrlen IPv4 or IPv6 - * @param addr either struct sockaddr_in or struct sockaddr_in6 - * @return NULL connection failed / invalid address - */ -static struct Session * -connect_and_create_session (struct Plugin *plugin, - const struct GNUNET_PeerIdentity *target, - const void *addr, size_t addrlen) -{ - struct GNUNET_SERVER_Client *client; - struct GNUNET_NETWORK_SocketHandle *conn; - struct Session *session; - int af; - - session = plugin->sessions; - while (session != NULL) - { - if ((0 == memcmp (target, - &session->target, - sizeof (struct GNUNET_PeerIdentity))) && - (session->connect_alen == addrlen) && - (0 == memcmp (session->connect_addr, addr, addrlen))) - return session; /* already exists! */ - session = session->next; - } - - if (addrlen == sizeof (struct sockaddr_in)) - af = AF_INET; - else if (addrlen == sizeof (struct sockaddr_in6)) - af = AF_INET6; - else - { - GNUNET_break_op (0); - return NULL; /* invalid address */ - } - conn = GNUNET_NETWORK_socket_create_from_sockaddr (plugin->env->sched, - af, - addr, - addrlen, - GNUNET_SERVER_MAX_MESSAGE_SIZE); - if (conn == NULL) - { -#if DEBUG_TCP - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, - "tcp", - "Failed to create connection to peer at `%s'.\n", - GNUNET_a2s(addr, addrlen)); -#endif - return NULL; - } - client = GNUNET_SERVER_connect_socket (plugin->server, conn); - GNUNET_assert (client != NULL); - session = create_session (plugin, target, client, addr, addrlen); - session->connect_alen = addrlen; - session->connect_addr = GNUNET_malloc (addrlen); - memcpy (session->connect_addr, addr, addrlen); -#if DEBUG_TCP - GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, - "tcp", - "Creating new session %p with `%s' based on `%s' request.\n", - session, - GNUNET_a2s(addr, addrlen), - "send_to"); -#endif - return session; -} - - /** * If we have pending messages, ask the server to * transmit them (schedule the respective tasks, etc.) @@ -703,6 +631,75 @@ process_pending_messages (struct Session *session) } + +/** + * Create a new session connecting to the specified + * target at the specified address. The session will + * be used to verify an address in a HELLO and should + * not expect to receive a WELCOME. + * + * @param plugin us + * @param target peer to connect to + * @param addrlen IPv4 or IPv6 + * @param addr either struct sockaddr_in or struct sockaddr_in6 + * @return NULL connection failed / invalid address + */ +static struct Session * +connect_and_create_validation_session (struct Plugin *plugin, + const struct GNUNET_PeerIdentity *target, + const void *addr, size_t addrlen) +{ + struct GNUNET_SERVER_Client *client; + struct GNUNET_NETWORK_SocketHandle *conn; + struct Session *session; + int af; + + if (addrlen == sizeof (struct sockaddr_in)) + af = AF_INET; + else if (addrlen == sizeof (struct sockaddr_in6)) + af = AF_INET6; + else + { + GNUNET_break_op (0); + return NULL; /* invalid address */ + } + conn = GNUNET_NETWORK_socket_create_from_sockaddr (plugin->env->sched, + af, + addr, + addrlen, + GNUNET_SERVER_MAX_MESSAGE_SIZE); + if (conn == NULL) + { +#if DEBUG_TCP + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, + "tcp", + "Failed to create connection to peer at `%s'.\n", + GNUNET_a2s(addr, addrlen)); +#endif + return NULL; + } + client = GNUNET_SERVER_connect_socket (plugin->server, conn); + GNUNET_assert (client != NULL); + session = create_session (plugin, target, client, addr, addrlen); + /* kill welcome */ + GNUNET_free (session->pending_messages); + session->pending_messages = NULL; + session->connect_alen = addrlen; + session->connect_addr = GNUNET_malloc (addrlen); + session->expecting_welcome = GNUNET_SYSERR; + memcpy (session->connect_addr, addr, addrlen); +#if DEBUG_TCP + GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, + "tcp", + "Creating new session %p with `%s' based on `%s' request.\n", + session, + GNUNET_a2s(addr, addrlen), + "send_to"); +#endif + return session; +} + + /** * Function that can be used by the transport service to validate that * another peer is reachable at a particular address (even if we @@ -729,7 +726,7 @@ tcp_plugin_validate (void *cls, struct PendingMessage *pm; struct ValidationChallengeMessage *vcm; - session = connect_and_create_session (plugin, target, addr, addrlen); + session = connect_and_create_validation_session (plugin, target, addr, addrlen); if (session == NULL) { #if DEBUG_TCP @@ -1566,7 +1563,7 @@ handle_tcp_pong (void *cls, } addrlen = ntohs(message->size) - sizeof(struct ValidationChallengeResponse); vcr = (const struct ValidationChallengeResponse *) message; - if ( (ntohs(vcr->purpose.size) != + if ( (ntohl(vcr->purpose.size) != sizeof (struct GNUNET_CRYPTO_RsaSignaturePurpose) + sizeof (uint32_t) + sizeof ( struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded) + @@ -1658,6 +1655,12 @@ handle_tcp_welcome (void *cls, GNUNET_free_non_null (vaddr); process_pending_messages (session_c); } + if (session_c->expecting_welcome != GNUNET_YES) + { + GNUNET_break_op (0); + GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); + return; + } session_c->expecting_welcome = GNUNET_NO; if (0 < (addrlen = msize - sizeof (struct WelcomeMessage))) { @@ -1747,7 +1750,7 @@ handle_tcp_data (void *cls, return; } session = find_session_by_client (plugin, client); - if ((NULL == session) || (GNUNET_YES == session->expecting_welcome)) + if ((NULL == session) || (GNUNET_NO != session->expecting_welcome)) { GNUNET_break_op (0); GNUNET_SERVER_receive_done (client, GNUNET_SYSERR); diff --git a/src/transport/test_transport_api.c b/src/transport/test_transport_api.c index ea22b9f12..a6a914023 100644 --- a/src/transport/test_transport_api.c +++ b/src/transport/test_transport_api.c @@ -185,7 +185,6 @@ exchange_hello_last (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *me = cls; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exchanging HELLO with peer (%p)!\n", cls); @@ -193,11 +192,8 @@ exchange_hello_last (void *cls, OKPP; GNUNET_assert (message != NULL); GNUNET_assert (GNUNET_OK == - GNUNET_HELLO_get_key ((const struct GNUNET_HELLO_Message *) - message, &pk)); - GNUNET_CRYPTO_hash (&pk, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &me->id.hashPubKey); + GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) + message, &me->id)); GNUNET_TRANSPORT_offer_hello (p1.th, message); GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Finished exchanging HELLOs, now waiting for transmission!\n"); @@ -215,7 +211,6 @@ exchange_hello (void *cls, const struct GNUNET_MessageHeader *message) { struct PeerContext *me = cls; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pk; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Exchanging HELLO with peer (%p)!\n", cls); @@ -223,11 +218,8 @@ exchange_hello (void *cls, OKPP; GNUNET_assert (message != NULL); GNUNET_assert (GNUNET_OK == - GNUNET_HELLO_get_key ((const struct GNUNET_HELLO_Message *) - message, &pk)); - GNUNET_CRYPTO_hash (&pk, - sizeof (struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &me->id.hashPubKey); + GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) + message, &me->id)); GNUNET_TRANSPORT_get_hello (p2.th, GNUNET_TIME_UNIT_MINUTES, &exchange_hello_last, &p2); } diff --git a/src/transport/transport_api.c b/src/transport/transport_api.c index 92f8f1f5c..be811953c 100644 --- a/src/transport/transport_api.c +++ b/src/transport/transport_api.c @@ -1475,7 +1475,6 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) const struct SendOkMessage *okm; struct HelloWaitList *hwl; struct NeighbourList *n; - struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded pkey; struct GNUNET_PeerIdentity me; struct GNUNET_TRANSPORT_TransmitHandle *th; uint16_t size; @@ -1524,16 +1523,12 @@ demultiplexer (void *cls, const struct GNUNET_MessageHeader *msg) { case GNUNET_MESSAGE_TYPE_HELLO: if (GNUNET_OK != - GNUNET_HELLO_get_key ((const struct GNUNET_HELLO_Message *) msg, - &pkey)) + GNUNET_HELLO_get_id ((const struct GNUNET_HELLO_Message *) msg, + &me)) { GNUNET_break (0); break; } - GNUNET_CRYPTO_hash (&pkey, - sizeof (struct - GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded), - &me.hashPubKey); #if DEBUG_TRANSPORT GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving (my own) `%s' message, I am `%4s'.\n", -- 2.25.1