transport fixes, hello API extension
authorChristian Grothoff <christian@grothoff.org>
Sun, 12 Jul 2009 22:11:16 +0000 (22:11 +0000)
committerChristian Grothoff <christian@grothoff.org>
Sun, 12 Jul 2009 22:11:16 +0000 (22:11 +0000)
src/datastore/datastore_api.c
src/hello/hello.c
src/include/gnunet_hello_lib.h
src/topology/gnunet-daemon-topology.c
src/transport/gnunet-service-transport.c
src/transport/plugin_transport_tcp.c
src/transport/test_transport_api.c
src/transport/transport_api.c

index a024d9e96bb16dae4185082a4771dac099f469c6..5e87affaf7e2cf3cb3fb4e2439530df49a459678 100644 (file)
@@ -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,
index 79d0edf8dac6049265d8fab6d9c7315fbd97a39f..a7aaf7d54790330eec7ad6cb481f992848857999 100644 (file)
@@ -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 */
index 2ba6df6ab13031390d2fcc334d4c618469998bf5..8978890f0e5631a077b589bb13d1a1b3e62bf5d2 100644 (file)
@@ -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
index 20d541eb2b277d8179789a9364a2820954dfdb5f..73fb84981cc10cbe75b8f5d758054512c6e92d1a 100644 (file)
@@ -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)
     {
index c34efec6cf4c9570ee99c6ff99878382c3116eab..d7bd13317ca13c616109cb1c462b556feb800e23 100644 (file)
@@ -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],
index 9a2a548906d1dc14a2c2c179d7f710f438d99928..0d08fec6918df3b9a11711e34a67dd433cbcb605 100644 (file)
@@ -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);
index ea22b9f12e3f416b258c29a24a93c0ffef6ba89f..a6a914023400e8ee2924cc1fb6fdc8e95c14f51e 100644 (file)
@@ -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);
 }
index 92f8f1f5c11538cab84c4bc8cea0529f0592929f..be811953cd23ff1698574e4bb9fccfab59493c55 100644 (file)
@@ -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",