gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] [gnunet] branch master updated (1c9f269ea -> cadf55989)


From: gnunet
Subject: [GNUnet-SVN] [gnunet] branch master updated (1c9f269ea -> cadf55989)
Date: Mon, 28 Jan 2019 11:05:12 +0100

This is an automated email from the git hooks/post-receive script.

grothoff pushed a change to branch master
in repository gnunet.

    from 1c9f269ea in principle finished with #5385, could use some testing...
     new 644837673 more work on TCP communicator
     new cadf55989 more work on TCP communicator

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/include/gnunet_crypto_lib.h          |    4 +-
 src/include/gnunet_protocols.h           |   17 +-
 src/include/gnunet_signatures.h          |    5 +
 src/transport/gnunet-communicator-tcp.c  | 1079 ++++++++++++++++++++++++++----
 src/transport/gnunet-communicator-unix.c |    2 +-
 5 files changed, 975 insertions(+), 132 deletions(-)

diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 6342862eb..6a9eddd7c 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -740,8 +740,8 @@ GNUNET_CRYPTO_hash_context_abort (struct GNUNET_HashContext 
*hc);
  */
 void
 GNUNET_CRYPTO_hmac_raw (const void *key, size_t key_len,
-                    const void *plaintext, size_t plaintext_len,
-                    struct GNUNET_HashCode *hmac);
+                       const void *plaintext, size_t plaintext_len,
+                       struct GNUNET_HashCode *hmac);
 
 
 /**
diff --git a/src/include/gnunet_protocols.h b/src/include/gnunet_protocols.h
index 1cd06de8d..409356d77 100644
--- a/src/include/gnunet_protocols.h
+++ b/src/include/gnunet_protocols.h
@@ -3219,7 +3219,22 @@ extern "C"
 
 
 /**
- * Next available: 1450
+ * TCP communicator rekey message.
+ */
+#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY 1450
+
+/**
+ * TCP communicator payload box
+ */
+#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX 1451
+
+/**
+ * TCP communicator end of stream.
+ */ 
+#define GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH 1452
+
+/**
+ * Next available: 1500
  */
 
 
diff --git a/src/include/gnunet_signatures.h b/src/include/gnunet_signatures.h
index 738a414ab..4f4d546ff 100644
--- a/src/include/gnunet_signatures.h
+++ b/src/include/gnunet_signatures.h
@@ -207,6 +207,11 @@ extern "C"
  */ 
 #define GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE 31
 
+/**
+ * Signature used by TCP communicator rekey.
+ */ 
+#define GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY 32
+
 #if 0                           /* keep Emacsens' auto-indent happy */
 {
 #endif
diff --git a/src/transport/gnunet-communicator-tcp.c 
b/src/transport/gnunet-communicator-tcp.c
index 6e3faa44a..a94559bd2 100644
--- a/src/transport/gnunet-communicator-tcp.c
+++ b/src/transport/gnunet-communicator-tcp.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     Copyright (C) 2010-2014, 2018 GNUnet e.V.
+     Copyright (C) 2010-2014, 2018, 2019 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -24,15 +24,19 @@
  * @author Christian Grothoff
  *
  * TODO:
- * - lots of basic adaptations (see FIXMEs)
- * - better message queue management
- * - actually encrypt, hmac, decrypt
- * - actually transmit
- * - 
+ * - lots of basic adaptations (see FIXMEs), need NAT service
+ *   to determine our own listen IPs! Parsing of bindto spec!
+ * - actual decryption and handling of boxes and rekeys!
+ * - message queue management: flow control towards CORE!
+ *   (stop reading from socket until MQ send to core is done;
+ *    will need a counter as ONE read from socket may generate
+ *    multiple messages en route to CORE; tricky bit: queue
+ *    may die before we get MQ sent-done callbacks!)
  */
 #include "platform.h"
 #include "gnunet_util_lib.h"
 #include "gnunet_protocols.h"
+#include "gnunet_signatures.h"
 #include "gnunet_constants.h"
 #include "gnunet_nt_lib.h"
 #include "gnunet_statistics_service.h"
@@ -48,6 +52,35 @@
  */
 #define DEFAULT_MAX_QUEUE_LENGTH 8
 
+/**
+ * Size of our IO buffers for ciphertext data. Must be at
+ * least UINT_MAX + sizeof (struct TCPBox).
+ */
+#define BUF_SIZE (2 * 64 * 1024 + sizeof (struct TCPBox))
+
+/**
+ * How often do we rekey based on time (at least)
+ */ 
+#define REKEY_TIME_INTERVAL GNUNET_TIME_UNIT_DAYS
+
+/**
+ * How long do we wait until we must have received the initial KX?
+ */ 
+#define PROTO_QUEUE_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+/**
+ * How often do we rekey based on number of bytes transmitted?
+ * (additionally randomized).
+ */ 
+#define REKEY_MAX_BYTES (1024LLU * 1024 * 1024 * 4LLU)
+
+/**
+ * Size of the initial key exchange message sent first in both
+ * directions.
+ */
+#define INITIAL_KX_SIZE (sizeof (struct GNUNET_CRYPTO_EcdhePublicKey)+sizeof 
(struct TCPConfirmation))
+
+
 /**
  * Address prefix used by the communicator.
  */
@@ -60,19 +93,6 @@
 
 GNUNET_NETWORK_STRUCT_BEGIN
 
-/**
- * TCP initial bytes on the wire (in either direction), used to 
- * establish a shared secret.
- */
-struct TCPHandshake
-{
-  /**
-   * First bytes: ephemeral key for KX.
-   */
-  struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
-
-};
-
 
 /**
  * Signature we use to verify that the ephemeral key was really chosen by
@@ -139,7 +159,10 @@ struct TCPBox
 {
   
   /**
-   * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX.
+   * Type is #GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX.  Warning: the
+   * header size EXCLUDES the size of the `struct TCPBox`. We usually
+   * never do this, but here the payload may truly be 64k *after* the
+   * TCPBox (as we have no MTU)!!
    */ 
   struct GNUNET_MessageHeader header;
 
@@ -153,7 +176,8 @@ struct TCPBox
    */ 
   struct GNUNET_ShortHashCode hmac;
 
-  /* followed by as may bytes of payload as indicated in @e header */
+  /* followed by as may bytes of payload as indicated in @e header,
+     excluding the TCPBox itself! */
   
 };
 
@@ -186,7 +210,7 @@ struct TCPRekey
   struct GNUNET_CRYPTO_EcdhePublicKey ephemeral;
   
   /**
-   * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE
+   * Sender's signature of type #GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY
    */
   struct GNUNET_CRYPTO_EddsaSignature sender_sig;
 
@@ -260,10 +284,16 @@ struct Queue
   struct GNUNET_HashCode in_hmac;
 
   /**
-   * Shared secret for HMAC generation on outgoing data.
+   * Shared secret for HMAC generation on outgoing data, ratcheted after
+   * each operation.
    */ 
   struct GNUNET_HashCode out_hmac;
 
+  /**
+   * Our ephemeral key. Stored here temporarily during rekeying / key 
generation.
+   */
+  struct GNUNET_CRYPTO_EcdhePrivateKey ephemeral;
+  
   /**
    * ID of read task for this connection.
    */
@@ -296,12 +326,6 @@ struct Queue
    */
   socklen_t address_len;
 
-  /**
-   * Message currently scheduled for transmission, non-NULL if and only
-   * if this queue is in the #queue_head DLL.
-   */
-  const struct GNUNET_MessageHeader *msg;
-
   /**
    * Message queue we are providing for the #ch.
    */
@@ -317,6 +341,50 @@ struct Queue
    */
   unsigned long long bytes_in_queue;
 
+  /**
+   * Buffer for reading ciphertext from network into.
+   */
+  char cread_buf[BUF_SIZE];
+
+  /**
+   * buffer for writing ciphertext to network.
+   */
+  char cwrite_buf[BUF_SIZE];
+
+  /**
+   * Plaintext buffer for decrypted plaintext.
+   */
+  char pread_buf[UINT16_MAX + 1 + sizeof (struct TCPBox)];
+
+  /**
+   * Plaintext buffer for messages to be encrypted.
+   */
+  char pwrite_buf[UINT16_MAX + 1 + sizeof (struct TCPBox)];
+  
+  /**
+   * At which offset in the ciphertext read buffer should we
+   * append more ciphertext for transmission next?
+   */
+  size_t cread_off;
+
+  /**
+   * At which offset in the ciphertext write buffer should we
+   * append more ciphertext from reading next?
+   */
+  size_t cwrite_off;
+  
+  /**
+   * At which offset in the plaintext input buffer should we
+   * append more plaintext from decryption next?
+   */
+  size_t pread_off;
+  
+  /**
+   * At which offset in the plaintext output buffer should we
+   * append more plaintext for encryption next?
+   */
+  size_t pwrite_off;
+
   /**
    * Timeout for this queue.
    */
@@ -326,7 +394,78 @@ struct Queue
    * Which network type does this queue use?
    */
   enum GNUNET_NetworkType nt;
+
+  /**
+   * Is MQ awaiting a #GNUNET_MQ_impl_send_continue() call?
+   */
+  int mq_awaits_continue;
   
+  /**
+   * Did we enqueue a finish message and are closing down the queue?
+   */
+  int finishing;
+
+  /**
+   * #GNUNET_YES after #inject_key() placed the rekey message into the
+   * plaintext buffer. Once the plaintext buffer is drained, this
+   * means we must switch to the new key material.
+   */
+  int rekey_state;
+};
+
+
+/**
+ * Handle for an incoming connection where we do not yet have enough
+ * information to setup a full queue.
+ */
+struct ProtoQueue
+{
+
+  /**
+   * Kept in a DLL.
+   */ 
+  struct ProtoQueue *next;
+
+  /**
+   * Kept in a DLL.
+   */ 
+  struct ProtoQueue *prev;
+  
+  /**
+   * socket that we transmit all data with on this queue
+   */
+  struct GNUNET_NETWORK_Handle *sock;
+
+  /**
+   * ID of read task for this connection.
+   */
+  struct GNUNET_SCHEDULER_Task *read_task;
+
+  /**
+   * Address of the other peer.
+   */
+  struct sockaddr *address;
+
+  /**
+   * Length of the address.
+   */
+  socklen_t address_len;
+
+  /**
+   * Timeout for this protoqueue.
+   */
+  struct GNUNET_TIME_Absolute timeout;
+
+  /** 
+   * Buffer for reading all the information we need to upgrade from 
+   * protoqueue to queue.
+   */
+  char ibuf[INITIAL_KX_SIZE];
+
+  /**
+   * Current offset for reading into @e ibuf.
+   */ 
+  size_t ibuf_off;
 };
 
 
@@ -370,6 +509,31 @@ static struct GNUNET_NETWORK_Handle *listen_sock;
  */
 static struct GNUNET_TRANSPORT_AddressIdentifier *ai;
 
+/**
+ * Our public key.
+ */
+static struct GNUNET_PeerIdentity my_identity;
+
+/**
+ * Our private key.
+ */
+static struct GNUNET_CRYPTO_EddsaPrivateKey *my_private_key;
+
+/**
+ * Our configuration.
+ */
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
+
+/**
+ * Protoqueues DLL head.
+ */ 
+static struct ProtoQueue *proto_head;
+
+/**
+ * Protoqueues DLL tail.
+ */ 
+static struct ProtoQueue *proto_tail;
+
 
 /**
  * We have been notified that our listen socket has something to
@@ -407,7 +571,7 @@ queue_destroy (struct Queue *queue)
                                                       &queue->target,
                                                       queue));
   GNUNET_STATISTICS_set (stats,
-                        "# UNIX queues active",
+                        "# queues active",
                         GNUNET_CONTAINER_multipeermap_size (queue_map),
                         GNUNET_NO);
   if (NULL != queue->read_task)
@@ -430,7 +594,88 @@ queue_destroy (struct Queue *queue)
                                                 listen_sock,
                                                 &listen_cb,
                                                 NULL);
+}
+
+
+/**
+ * Compute @a mac over @a buf, and ratched the @a hmac_secret.
+ *
+ * @param[in,out] hmac_secret secret for HMAC calculation
+ * @param buf buffer to MAC
+ * @param buf_size number of bytes in @a buf
+ * @param smac[out] where to write the HMAC
+ */
+static void
+hmac (struct GNUNET_HashCode *hmac_secret,
+      const void *buf,
+      size_t buf_size,
+      struct GNUNET_ShortHashCode *smac)
+{
+  struct GNUNET_HashCode mac;
+
+  GNUNET_CRYPTO_hmac_raw (hmac_secret,
+                         sizeof (struct GNUNET_HashCode),
+                         buf,
+                         buf_size,
+                         &mac);
+  /* truncate to `struct GNUNET_ShortHashCode` */
+  memcpy (smac,
+         &mac,
+         sizeof (struct GNUNET_ShortHashCode));
+  /* ratchet hmac key */
+  GNUNET_CRYPTO_hash (hmac_secret,
+                     sizeof (struct GNUNET_HashCode),
+                     hmac_secret);
+}
+
+
+/**
+ * Append a 'finish' message to the outgoing transmission. Once the
+ * finish has been transmitted, destroy the queue.
+ *
+ * @param queue queue to shut down nicely
+ */
+static void
+queue_finish (struct Queue *queue)
+{
+  struct TCPFinish fin;
 
+  memset (&fin,
+         0,
+         sizeof (fin));
+  fin.header.size = htons (sizeof (fin));
+  fin.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_FINISH);
+  hmac (&queue->out_hmac,
+       &fin,
+       sizeof (fin),
+       &fin.hmac);
+  /* if there is any message left in pwrite_buf, we 
+     overwrite it (possibly dropping the last message
+     from CORE hard here) */
+  memcpy (queue->pwrite_buf,
+         &fin,
+         sizeof (fin));
+  queue->pwrite_off = sizeof (fin);
+  /* This flag will ensure that #queue_write() no longer
+     notifies CORE about the possibility of sending
+     more data, and that #queue_write() will call
+     #queue_destroy() once the @c fin was fully written. */
+  queue->finishing = GNUNET_YES;
+}
+
+
+/**
+ * Increment queue timeout due to activity.  We do not immediately
+ * notify the monitor here as that might generate excessive
+ * signalling.
+ *
+ * @param queue queue for which the timeout should be rescheduled
+ */
+static void
+reschedule_queue_timeout (struct Queue *queue)
+{
+  queue->timeout
+    = GNUNET_TIME_relative_to_absolute 
(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
 }
 
 
@@ -444,12 +689,45 @@ queue_read (void *cls)
 {
   struct Queue *queue = cls;
   struct GNUNET_TIME_Relative left;
+  ssize_t rcvd;
 
   queue->read_task = NULL;
-  /* CHECK IF READ-ready, then perform read! */
+  rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
+                                    &queue->cread_buf[queue->cread_off],
+                                    BUF_SIZE - queue->cread_off);
+  if (-1 == rcvd)
+  {
+    if ( (EAGAIN != errno) &&
+        (EINTR != errno) )
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG,
+                          "recv");
+      queue_finish (queue);
+      return;
+    }
+    /* try again */
+    queue->read_task
+      = GNUNET_SCHEDULER_add_read_net (left,
+                                      queue->sock,
+                                      &queue_read,
+                                      queue);
+    return;
+  }
+  if (0 != rcvd)
+    reschedule_queue_timeout (queue);
+  queue->cread_off += rcvd;
+  if (queue->pread_off < sizeof (queue->pread_buf))
+  {
+    /* FIXME: decrypt */
+  
+    /* FIXME: check plaintext for complete messages, if complete, hand to CORE 
*/
+    /* FIXME: CORE flow control: suspend doing more until CORE has ACKed */
+  }
   
+  if (BUF_SIZE == queue->cread_off)
+    return; /* buffer full, suspend reading */
   left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
-  if (0 != left.rel_value_us)
+  if (0 != left.rel_value_us) 
   {
     /* not actually our turn yet, but let's at least update
        the monitor, it may think we're about to die ... */
@@ -458,6 +736,7 @@ queue_read (void *cls)
                                       queue->sock,
                                       &queue_read,
                                       queue);
+
     return;
   }
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -465,24 +744,7 @@ queue_read (void *cls)
              queue,
              GNUNET_STRINGS_relative_time_to_string 
(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
                                                      GNUNET_YES));
-  // FIXME: try to send 'finish' message first!?
-  queue_destroy (queue);
-}
-
-
-/**
- * Increment queue timeout due to activity.  We do not immediately
- * notify the monitor here as that might generate excessive
- * signalling.
- *
- * @param queue queue for which the timeout should be rescheduled
- */
-static void
-reschedule_queue_timeout (struct Queue *queue)
-{
-  GNUNET_assert (NULL != queue->read_task);
-  queue->timeout
-    = GNUNET_TIME_relative_to_absolute 
(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
+  queue_finish (queue);
 }
 
 
@@ -505,6 +767,175 @@ tcp_address_to_sockaddr (const char *bindto,
 }
 
 
+/**
+ * Setup @a cipher based on shared secret @a dh and decrypting
+ * peer @a pid.
+ *
+ * @param dh shared secret
+ * @param pid decrypting peer's identity
+ * @param cipher[out] cipher to initialize
+ * @param hmac_key[out] HMAC key to initialize
+ */
+static void
+setup_cipher (const struct GNUNET_HashCode *dh,
+             const struct GNUNET_PeerIdentity *pid,
+             gcry_cipher_hd_t *cipher,
+             struct GNUNET_HashCode *hmac_key)
+{
+  char key[256/8];
+  char ctr[128/8];
+
+  gcry_cipher_open (cipher,
+                   GCRY_CIPHER_AES256 /* low level: go for speed */,
+                   GCRY_CIPHER_MODE_CTR,
+                   0 /* flags */);
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CRYPTO_kdf (key,
+                                   sizeof (key),
+                                   "TCP-key",
+                                   strlen ("TCP-key"),
+                                   dh,
+                                   sizeof (*dh),
+                                   pid,
+                                   sizeof (*pid),
+                                   NULL, 0));
+  gcry_cipher_setkey (*cipher,
+                     key,
+                     sizeof (key));
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CRYPTO_kdf (ctr,
+                                   sizeof (ctr),
+                                   "TCP-ctr",
+                                   strlen ("TCP-ctr"),
+                                   dh,
+                                   sizeof (*dh),
+                                   pid,
+                                   sizeof (*pid),
+                                   NULL, 0));
+  gcry_cipher_setctr (*cipher,
+                     ctr,
+                     sizeof (ctr));
+  GNUNET_assert (GNUNET_YES ==
+                GNUNET_CRYPTO_kdf (hmac_key,
+                                   sizeof (struct GNUNET_HashCode),
+                                   "TCP-hmac",
+                                   strlen ("TCP-hmac"),
+                                   dh,
+                                   sizeof (*dh),
+                                   pid,
+                                   sizeof (*pid),
+                                   NULL, 0));
+}
+
+
+/**
+ * Setup cipher of @a queue for decryption.
+ *
+ * @param ephemeral ephemeral key we received from the other peer
+ * @param queue[in,out] queue to initialize decryption cipher for
+ */
+static void
+setup_in_cipher (const struct GNUNET_CRYPTO_EcdhePublicKey *ephemeral,
+                struct Queue *queue)
+{
+  struct GNUNET_HashCode dh;
+  
+  GNUNET_CRYPTO_eddsa_ecdh (my_private_key,
+                           ephemeral,
+                           &dh);
+  setup_cipher (&dh,
+               &my_identity,
+               &queue->in_cipher,
+               &queue->in_hmac);
+}
+               
+
+/**
+ * Setup cipher for outgoing data stream based on target and
+ * our ephemeral private key.
+ *
+ * @param queue queue to setup outgoing (encryption) cipher for
+ */
+static void
+setup_out_cipher (struct Queue *queue)
+{
+  struct GNUNET_HashCode dh;
+  
+  GNUNET_CRYPTO_ecdh_eddsa (&queue->ephemeral,
+                           &queue->target.public_key,
+                           &dh);
+  /* we don't need the private key anymore, drop it! */
+  memset (&queue->ephemeral,
+         0,
+         sizeof (queue->ephemeral));
+  setup_cipher (&dh,
+               &queue->target,
+               &queue->out_cipher,
+               &queue->out_hmac);
+  
+  queue->rekey_time = GNUNET_TIME_relative_to_absolute (REKEY_TIME_INTERVAL);
+  queue->rekey_left_bytes = GNUNET_CRYPTO_random_u64 
(GNUNET_CRYPTO_QUALITY_WEAK,
+                                                     REKEY_MAX_BYTES);
+}
+
+
+/**
+ * Inject a `struct TCPRekey` message into the queue's plaintext
+ * buffer.
+ *
+ * @param queue queue to perform rekeying on
+ */ 
+static void
+inject_rekey (struct Queue *queue)
+{
+  struct TCPRekey rekey;
+  struct TcpHandshakeSignature thp;
+  
+  GNUNET_assert (0 == queue->pwrite_off);
+  memset (&rekey,
+         0,
+         sizeof (rekey));
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CRYPTO_ecdhe_key_create2 (&queue->ephemeral));
+  rekey.header.type = ntohs (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_REKEY);
+  rekey.header.size = ntohs (sizeof (rekey));
+  GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral,
+                                     &rekey.ephemeral);
+  rekey.monotonic_time = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_absolute_get_monotonic (cfg));
+  thp.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_REKEY);
+  thp.purpose.size = htonl (sizeof (thp));
+  thp.sender = my_identity;
+  thp.receiver = queue->target;
+  thp.ephemeral = rekey.ephemeral;
+  thp.monotonic_time = rekey.monotonic_time;
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CRYPTO_eddsa_sign (my_private_key,
+                                          &thp.purpose,
+                                          &rekey.sender_sig));
+  hmac (&queue->out_hmac,
+       &rekey,
+       sizeof (rekey),
+       &rekey.hmac);
+  memcpy (queue->pwrite_buf,
+         &rekey,
+         sizeof (rekey));
+  queue->rekey_state = GNUNET_YES;
+}
+
+
+/**
+ * We encrypted the rekey message, now update actually swap the key
+ * material and update the key freshness parameters of @a queue.
+ */ 
+static void
+switch_key (struct Queue *queue)
+{
+  queue->rekey_state = GNUNET_NO; 
+  gcry_cipher_close (queue->out_cipher);
+  setup_out_cipher (queue);
+}
+
+
 /**
  * We have been notified that our socket is ready to write.
  * Then reschedule this function to be called again once more is available.
@@ -515,17 +946,75 @@ static void
 queue_write (void *cls)
 {
   struct Queue *queue = cls;
-  const struct GNUNET_MessageHeader *msg = queue->msg;
-  size_t msg_size = ntohs (msg->size);
+  ssize_t sent;
 
   queue->write_task = NULL;
-  /* FIXME: send 'msg' */
-  /* FIXME: check if we have more messages pending */
-  queue->write_task 
-    = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
-                                     queue->sock,
-                                     &queue_write,
-                                     queue);
+  sent = GNUNET_NETWORK_socket_send (queue->sock,
+                                    queue->cwrite_buf,
+                                    queue->cwrite_off);
+  if ( (-1 == sent) &&
+       (EAGAIN != errno) &&
+       (EINTR != errno) )
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+                        "send");
+    queue_destroy (queue);
+    return;                     
+  }
+  if (sent > 0)
+  {
+    size_t usent = (size_t) sent;
+
+    memmove (queue->cwrite_buf,
+            &queue->cwrite_buf[sent],
+            queue->cwrite_off - sent);
+    reschedule_queue_timeout (queue);
+ }
+  /* can we encrypt more? (always encrypt full messages, needed
+     such that #mq_cancel() can work!) */
+  if (queue->cwrite_off + queue->pwrite_off <= BUF_SIZE)
+  {
+    GNUNET_assert (0 ==
+                  gcry_cipher_encrypt (queue->out_cipher,
+                                       &queue->cwrite_buf[queue->cwrite_off],
+                                       queue->pwrite_off,
+                                       queue->pwrite_buf,
+                                       queue->pwrite_off));
+    if (queue->rekey_left_bytes > queue->pwrite_off)
+      queue->rekey_left_bytes -= queue->pwrite_off;
+    else
+      queue->rekey_left_bytes = 0;
+    queue->cwrite_off += queue->pwrite_off;
+    queue->pwrite_off = 0;
+  }
+  if ( (GNUNET_YES == queue->rekey_state) &&
+       (0 == queue->pwrite_off) )
+    switch_key (queue);
+  if ( (0 == queue->pwrite_off) &&
+       ( (0 == queue->rekey_left_bytes) ||
+        (0 == GNUNET_TIME_absolute_get_remaining 
(queue->rekey_time).rel_value_us) ) )
+    inject_rekey (queue);
+  if ( (0 == queue->pwrite_off) &&
+       (! queue->finishing) &&
+       (queue->mq_awaits_continue) )
+  {
+    queue->mq_awaits_continue = GNUNET_NO;
+    GNUNET_MQ_impl_send_continue (queue->mq);
+  }
+  /* did we just finish writing 'finish'? */
+  if ( (0 == queue->cwrite_off) &&
+       (GNUNET_YES == queue->finishing) )
+  {
+    queue_destroy (queue);
+    return;
+  }
+  /* do we care to write more? */
+  if (0 < queue->cwrite_off)
+    queue->write_task 
+      = GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_UNIT_FOREVER_REL,
+                                       queue->sock,
+                                       &queue_write,
+                                       queue);
 }
 
 
@@ -543,10 +1032,27 @@ mq_send (struct GNUNET_MQ_Handle *mq,
         void *impl_state)
 {
   struct Queue *queue = impl_state;
+  uint16_t msize = ntohs (msg->size);
+  struct TCPBox box;
 
   GNUNET_assert (mq == queue->mq);
-  GNUNET_assert (NULL == queue->msg);
-  queue->msg = msg;
+  if (GNUNET_YES == queue->finishing)
+    return; /* this queue is dying, drop msg */
+  GNUNET_assert (0 == queue->pread_off);
+  box.header.type = htons (GNUNET_MESSAGE_TYPE_COMMUNICATOR_TCP_BOX);
+  box.header.size = htons (msize);
+  hmac (&queue->out_hmac,
+       msg,
+       msize,
+       &box.hmac);
+  memcpy (&queue->pread_buf[queue->pread_off],
+         &box,
+         sizeof (box));
+  queue->pread_off += sizeof (box);
+  memcpy (&queue->pread_buf[queue->pread_off],
+         msg,
+         msize);
+  queue->pread_off += msize;
   GNUNET_assert (NULL != queue->sock);
   if (NULL == queue->write_task)
     queue->write_task =
@@ -574,7 +1080,7 @@ mq_destroy (struct GNUNET_MQ_Handle *mq,
   if (mq == queue->mq)
   {
     queue->mq = NULL;
-    queue_destroy (queue);
+    queue_finish (queue);
   }
 }
 
@@ -591,14 +1097,8 @@ mq_cancel (struct GNUNET_MQ_Handle *mq,
 {
   struct Queue *queue = impl_state;
 
-  GNUNET_assert (NULL != queue->msg);
-  queue->msg = NULL;
-  GNUNET_assert (NULL != queue->write_task);
-  if (1) // FIXME?
-  {
-    GNUNET_SCHEDULER_cancel (queue->write_task);
-    queue->write_task = NULL;
-  }
+  GNUNET_assert (0 != queue->pwrite_off);
+  queue->pwrite_off = 0;
 }
 
 
@@ -618,37 +1118,24 @@ mq_error (void *cls,
   struct Queue *queue = cls;
 
   GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-             "TCP MQ error in queue to %s: %d\n",
+             "MQ error in queue to %s: %d\n",
              GNUNET_i2s (&queue->target),
              (int) error);
-  queue_destroy (queue);
+  queue_finish (queue);
 }
 
 
 /**
- * Creates a new outbound queue the transport service will use to send
- * data to another peer.
+ * Add the given @a queue to our internal data structure.  Setup the
+ * MQ processing and inform transport that the queue is ready.  Must
+ * be called after the KX for outgoing messages has been bootstrapped.
  *
- * @param peer the target peer
- * @param cs inbound or outbound queue
- * @param in the address
- * @param in_len number of bytes in @a in
- * @return the queue or NULL of max connections exceeded
- */
-static struct Queue *
-setup_queue (struct GNUNET_NETWORK_Handle *sock,
-            enum GNUNET_TRANSPORT_ConnectionStatus cs,
-            const struct sockaddr *in,
-            socklen_t in_len)
+ * @param queue queue to boot
+ */ 
+static void
+boot_queue (struct Queue *queue,
+           enum GNUNET_TRANSPORT_ConnectionStatus cs)
 {
-  struct Queue *queue;
-
-  queue = GNUNET_new (struct Queue);
-  // queue->target = *target; // FIXME: handle case that we don't know the 
target yet!
-  queue->address = GNUNET_memdup (in,
-                                 in_len);
-  queue->address_len = in_len;
-  queue->sock = sock; 
   queue->nt = 0; // FIXME: determine NT!
   (void) GNUNET_CONTAINER_multipeermap_put (queue_map,
                                            &queue->target,
@@ -660,11 +1147,6 @@ setup_queue (struct GNUNET_NETWORK_Handle *sock,
                         GNUNET_NO);
   queue->timeout
     = GNUNET_TIME_relative_to_absolute 
(GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT);
-  queue->read_task
-    = GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
-                                    queue->sock,
-                                    &queue_read,
-                                    queue);
   queue->mq
     = GNUNET_MQ_queue_for_callbacks (&mq_send,
                                     &mq_destroy,
@@ -705,19 +1187,217 @@ setup_queue (struct GNUNET_NETWORK_Handle *sock,
                                              queue->mq);
     GNUNET_free (foreign_addr);
   }
-  return queue;
 }
 
 
 /**
- * We have been notified that our listen socket has something to
- * read. Do the read and reschedule this function to be called again
- * once more is available.
+ * Generate and transmit our ephemeral key and the signature for
+ * the initial KX with the other peer.  Must be called first, before
+ * any other bytes are ever written to the output buffer.  Note that
+ * our cipher must already be initialized when calling this function.
+ * Helper function for #start_initial_kx_out().
  *
- * @param cls NULL
+ * @param queue queue to do KX for
+ * @param epub our public key for the KX
  */
 static void
-listen_cb (void *cls);
+transmit_kx (struct Queue *queue,
+            const struct GNUNET_CRYPTO_EcdhePublicKey *epub)
+{
+  struct TcpHandshakeSignature ths;
+  struct TCPConfirmation tc;
+
+  memcpy (queue->cwrite_buf,
+         epub,
+         sizeof (*epub));
+  queue->cwrite_off = sizeof (epub);
+  /* compute 'tc' and append in encrypted format to cwrite_buf */
+  tc.sender = my_identity;
+  tc.monotonic_time = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_absolute_get_monotonic (cfg));
+  ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE);
+  ths.purpose.size = htonl (sizeof (ths));
+  ths.sender = my_identity;
+  ths.receiver = queue->target;
+  ths.ephemeral = *epub;
+  ths.monotonic_time = tc.monotonic_time;
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CRYPTO_eddsa_sign (my_private_key,
+                                          &ths.purpose,
+                                          &tc.sender_sig));
+  GNUNET_assert (0 ==
+                gcry_cipher_encrypt (queue->out_cipher,
+                                     &queue->cwrite_buf[queue->cwrite_off],
+                                     sizeof (tc),
+                                     &tc,
+                                     sizeof (tc)));
+  queue->cwrite_off += sizeof (tc);
+}
+
+
+/**
+ * Initialize our key material for outgoing transmissions and 
+ * inform the other peer about it. Must be called first before
+ * any data is sent.
+ *
+ * @param queue the queue to setup
+ */
+static void
+start_initial_kx_out (struct Queue *queue)
+{
+  struct GNUNET_CRYPTO_EcdhePublicKey epub;
+
+  GNUNET_assert (GNUNET_OK ==
+                GNUNET_CRYPTO_ecdhe_key_create2 (&queue->ephemeral)); 
+  GNUNET_CRYPTO_ecdhe_key_get_public (&queue->ephemeral,
+                                     &epub);
+  setup_out_cipher (queue);
+  transmit_kx (queue,
+              &epub);
+}
+
+
+/**
+ * We have received the first bytes from the other side on a @a queue.
+ * Decrypt the @a tc contained in @a ibuf and check the signature.
+ * Note that #setup_in_cipher() must have already been called.
+ *
+ * @param queue queue to decrypt initial bytes from other peer for
+ * @param tc[out] where to store the result
+ * @param ibuf incoming data, of size 
+ *        `INITIAL_KX_SIZE`
+ * @return #GNUNET_OK if the signature was OK, #GNUNET_SYSERR if not
+ */
+static int
+decrypt_and_check_tc (struct Queue *queue,
+                     struct TCPConfirmation *tc,
+                     char *ibuf)
+{
+  struct TcpHandshakeSignature ths;
+                       
+  GNUNET_assert (0 ==
+                gcry_cipher_decrypt (queue->in_cipher,
+                                     tc,
+                                     sizeof (*tc),
+                                     &ibuf[sizeof (struct 
GNUNET_CRYPTO_EcdhePublicKey)],
+                                     sizeof (tc)));
+  ths.purpose.purpose = htonl (GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE);
+  ths.purpose.size = htonl (sizeof (ths));
+  ths.sender = tc->sender;
+  ths.receiver = my_identity;
+  memcpy (&ths.ephemeral,
+         ibuf,
+         sizeof (struct GNUNET_CRYPTO_EcdhePublicKey));
+  ths.monotonic_time = tc->monotonic_time;
+  return GNUNET_CRYPTO_eddsa_verify 
(GNUNET_SIGNATURE_COMMUNICATOR_TCP_HANDSHAKE,
+                                    &ths.purpose,
+                                    &tc->sender_sig,
+                                    &tc->sender.public_key);
+}
+
+
+/**
+ * Closes socket and frees memory associated with @a pq.
+ *
+ * @param pq proto queue to free
+ */ 
+static void
+free_proto_queue (struct ProtoQueue *pq)
+{
+  GNUNET_NETWORK_socket_close (pq->sock);
+  GNUNET_free (pq->address);
+  GNUNET_CONTAINER_DLL_remove (proto_head,
+                              proto_tail,
+                              pq);
+  GNUNET_free (pq);
+}
+ 
+
+/**
+ * Read from the socket of the proto queue until we have enough data
+ * to upgrade to full queue.
+ *
+ * @param cls a `struct ProtoQueue`
+ */
+static void
+proto_read_kx (void *cls)
+{
+  struct ProtoQueue *pq = cls;
+  ssize_t rcvd;
+  struct GNUNET_TIME_Relative left;
+  struct Queue *queue;
+  struct TCPConfirmation tc;
+  
+  pq->read_task = NULL;
+  left = GNUNET_TIME_absolute_get_remaining (pq->timeout);
+  if (0 == left.rel_value_us)
+  {
+    free_proto_queue (pq);
+    return;
+  }
+  rcvd = GNUNET_NETWORK_socket_recv (pq->sock,
+                                    &pq->ibuf[pq->ibuf_off],
+                                    sizeof (pq->ibuf) - pq->ibuf_off);
+  if (-1 == rcvd)
+  {
+    if ( (EAGAIN != errno) &&
+        (EINTR != errno) )
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG,
+                          "recv");
+      free_proto_queue (pq);
+      return;
+    }
+    /* try again */
+    pq->read_task = GNUNET_SCHEDULER_add_read_net (left,
+                                                  pq->sock,
+                                                  &proto_read_kx,
+                                                  pq);
+    return;    
+  }
+  pq->ibuf_off += rcvd;
+  if (pq->ibuf_off > sizeof (pq->ibuf))
+  {
+    /* read more */
+    pq->read_task = GNUNET_SCHEDULER_add_read_net (left,
+                                                  pq->sock,
+                                                  &proto_read_kx,
+                                                  pq);
+    return;
+  }
+  /* we got all the data, let's find out who we are talking to! */
+  queue = GNUNET_new (struct Queue);
+  setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) pq->ibuf,
+                  queue);
+  if (GNUNET_OK !=
+      decrypt_and_check_tc (queue,
+                           &tc,
+                           pq->ibuf))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               "Invalid TCP KX received from %s\n",
+               GNUNET_a2s (queue->address,
+                           queue->address_len));
+    gcry_cipher_close (queue->in_cipher);
+    GNUNET_free (queue);
+    free_proto_queue (pq);
+    return;    
+  }
+  queue->address = pq->address; /* steals reference */
+  queue->address_len = pq->address_len;
+  queue->target = tc.sender;
+  start_initial_kx_out (queue);
+  boot_queue (queue,
+             GNUNET_TRANSPORT_CS_INBOUND);
+  queue->read_task
+    = GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+                                    queue->sock,
+                                    &queue_read,
+                                    queue);
+  GNUNET_CONTAINER_DLL_remove (proto_head,
+                              proto_tail,
+                              pq);
+  GNUNET_free (pq);
+}
 
 
 /**
@@ -730,13 +1410,10 @@ listen_cb (void *cls);
 static void
 listen_cb (void *cls)
 {
-  char buf[65536] GNUNET_ALIGN;
-  struct Queue *queue;
   struct sockaddr_storage in;
   socklen_t addrlen;
-  ssize_t ret;
-  uint16_t msize;
   struct GNUNET_NETWORK_Handle *sock;
+  struct ProtoQueue *pq;
 
   listen_task = NULL;
   GNUNET_assert (NULL != listen_sock);
@@ -765,18 +1442,112 @@ listen_cb (void *cls)
                          "accept");
     return;
   }
-  queue = setup_queue (sock,
-                      GNUNET_TRANSPORT_CS_INBOUND,
-                      (struct sockaddr *) &in,
-                      addrlen);
-  if (NULL == queue)
+  pq = GNUNET_new (struct ProtoQueue);
+  pq->address_len = addrlen;
+  pq->address = GNUNET_memdup (&in,
+                              addrlen);
+  pq->timeout = GNUNET_TIME_relative_to_absolute (PROTO_QUEUE_TIMEOUT);
+  pq->sock = sock;
+  pq->read_task = GNUNET_SCHEDULER_add_read_net (PROTO_QUEUE_TIMEOUT,
+                                                pq->sock,
+                                                &proto_read_kx,
+                                                pq);
+  GNUNET_CONTAINER_DLL_insert (proto_head,
+                              proto_tail,
+                              pq);
+}
+
+
+/**
+ * Read from the socket of the queue until we have enough data
+ * to initialize the decryption logic and can switch to regular
+ * reading.
+ *
+ * @param cls a `struct Queue`
+ */
+static void
+queue_read_kx (void *cls)
+{
+  struct Queue *queue = cls;
+  ssize_t rcvd;
+  struct GNUNET_TIME_Relative left;
+  struct TCPConfirmation tc;
+  
+  queue->read_task = NULL;
+  left = GNUNET_TIME_absolute_get_remaining (queue->timeout);
+  if (0 == left.rel_value_us)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-               _("Maximum number of TCP connections exceeded, dropping 
incoming connection\n"));
+    queue_destroy (queue);
+    return;
+  }
+  rcvd = GNUNET_NETWORK_socket_recv (queue->sock,
+                                    &queue->cread_buf[queue->cread_off],
+                                    BUF_SIZE - queue->cread_off);
+  if (-1 == rcvd)
+  {
+    if ( (EAGAIN != errno) &&
+        (EINTR != errno) )
+    {
+      GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG,
+                          "recv");
+      queue_destroy (queue);
+      return;
+    }
+    queue->read_task = GNUNET_SCHEDULER_add_read_net (left,
+                                                     queue->sock,
+                                                     &queue_read_kx,
+                                                     queue);
+    return;
+  }
+  queue->cread_off += rcvd;
+  if (queue->cread_off <
+      INITIAL_KX_SIZE)
+  {
+    /* read more */
+    queue->read_task = GNUNET_SCHEDULER_add_read_net (left,
+                                                     queue->sock,
+                                                     &queue_read_kx,
+                                                     queue);
+    return;
+  }
+  /* we got all the data, let's find out who we are talking to! */
+  setup_in_cipher ((const struct GNUNET_CRYPTO_EcdhePublicKey *) 
queue->cread_buf,
+                  queue);
+  if (GNUNET_OK !=
+      decrypt_and_check_tc (queue,
+                           &tc,
+                           queue->cread_buf))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+               "Invalid TCP KX received from %s\n",
+               GNUNET_a2s (queue->address,
+                           queue->address_len));
+    queue_destroy (queue);
+    return;
+  }
+  if (0 != memcmp (&tc.sender,
+                  &queue->target,
+                  sizeof (struct GNUNET_PeerIdentity)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               "Invalid sender in TCP KX received from %s\n",
+               GNUNET_a2s (queue->address,
+                           queue->address_len));
+    queue_destroy (queue);
     return;
   }
-}
 
+  /* update queue timeout */
+  reschedule_queue_timeout (queue);
+  /* prepare to continue with regular read task immediately */
+  memmove (queue->cread_buf,
+          &queue->cread_buf[INITIAL_KX_SIZE],
+          queue->cread_off - (INITIAL_KX_SIZE));
+  queue->cread_off -= INITIAL_KX_SIZE;
+  queue->read_task = GNUNET_SCHEDULER_add_now (&queue_read,
+                                              queue);
+}
+                                     
 
 /**
  * Function called by the transport service to initialize a
@@ -804,7 +1575,8 @@ mq_init (void *cls,
   const char *path;
   struct sockaddr *in;
   socklen_t in_len;
-
+  struct GNUNET_NETWORK_Handle *sock;
+  
   if (0 != strncmp (address,
                    COMMUNICATOR_ADDRESS_PREFIX "-",
                    strlen (COMMUNICATOR_ADDRESS_PREFIX "-")))
@@ -815,22 +1587,56 @@ mq_init (void *cls,
   path = &address[strlen (COMMUNICATOR_ADDRESS_PREFIX "-")];
   in = tcp_address_to_sockaddr (path,
                                &in_len);
-#if FIXME
-  queue = setup_queue (peer,
-                      GNUNET_TRANSPORT_CS_OUTBOUND,
-                      in,
-                      in_len);
-#endif
-  GNUNET_free (in);
+  
+  sock = GNUNET_NETWORK_socket_create (in->sa_family,
+                                      SOCK_STREAM,
+                                      IPPROTO_TCP);
+  if (NULL == sock)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               "socket(%d) failed: %s",
+               in->sa_family,
+               STRERROR (errno));
+    GNUNET_free (in);
+    return GNUNET_SYSERR;
+  }
+  if (GNUNET_OK !=
+      GNUNET_NETWORK_socket_connect (sock,
+                                    in,
+                                    in_len))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+               "connect to `%s' failed: %s",
+               address,
+               STRERROR (errno));
+    GNUNET_NETWORK_socket_close (sock);
+    GNUNET_free (in);
+    return GNUNET_SYSERR;
+  }
+
+  queue = GNUNET_new (struct Queue);
+  queue->target = *peer; 
+  queue->address = in;
+  queue->address_len = in_len;
+  queue->sock = sock;
+  boot_queue (queue,
+             GNUNET_TRANSPORT_CS_OUTBOUND);
+  queue->read_task
+    = GNUNET_SCHEDULER_add_read_net (GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT,
+                                    queue->sock,
+                                    &queue_read_kx,
+                                    queue);
   if (NULL == queue)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                "Failed to setup queue to %s at `%s'\n",
                GNUNET_i2s (peer),
                path);
+    GNUNET_NETWORK_socket_close (sock);
     return GNUNET_NO;
   }
-  return GNUNET_OK;
+  start_initial_kx_out (queue);
+  return GNUNET_OK;  
 }
 
 
@@ -895,6 +1701,11 @@ do_shutdown (void *cls)
                               GNUNET_NO);
     stats = NULL;
   }
+  if (NULL != my_private_key)
+  {
+    GNUNET_free (my_private_key);
+    my_private_key = NULL;
+  }
 }
 
 
@@ -903,7 +1714,7 @@ do_shutdown (void *cls)
  * acknowledgement for this communicator (!) via a different return
  * path.
  *
- * Not applicable for UNIX.
+ * Not applicable for TCP.
  *
  * @param cls closure
  * @param sender which peer sent the notification
@@ -927,13 +1738,13 @@ enc_notify_cb (void *cls,
  * @param cls NULL (always)
  * @param args remaining command-line arguments
  * @param cfgfile name of the configuration file used (for saving, can be 
NULL!)
- * @param cfg configuration
+ * @param c configuration
  */
 static void
 run (void *cls,
      char *const *args,
      const char *cfgfile,
-     const struct GNUNET_CONFIGURATION_Handle *cfg)
+     const struct GNUNET_CONFIGURATION_Handle *c)
 {
   char *bindto;
   struct sockaddr *in;
@@ -941,6 +1752,7 @@ run (void *cls,
   char *my_addr;
   (void) cls;
 
+  cfg = c;
   if (GNUNET_OK !=
       GNUNET_CONFIGURATION_get_value_filename (cfg,
                                               COMMUNICATOR_CONFIG_SECTION,
@@ -1002,6 +1814,17 @@ run (void *cls,
                                    cfg);
   GNUNET_SCHEDULER_add_shutdown (&do_shutdown,
                                 NULL);
+  my_private_key = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg);
+  if (NULL == my_private_key)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Transport service is lacking key configuration settings. 
Exiting.\n"));
+    GNUNET_SCHEDULER_shutdown ();
+    return;
+  }
+  GNUNET_CRYPTO_eddsa_key_get_public (my_private_key,
+                                      &my_identity.public_key);
+
   listen_task = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                               listen_sock,
                                               &listen_cb,
diff --git a/src/transport/gnunet-communicator-unix.c 
b/src/transport/gnunet-communicator-unix.c
index 08f02b66d..d30acbd5f 100644
--- a/src/transport/gnunet-communicator-unix.c
+++ b/src/transport/gnunet-communicator-unix.c
@@ -234,7 +234,7 @@ queue_destroy (struct Queue *queue)
                                                       &queue->target,
                                                       queue));
   GNUNET_STATISTICS_set (stats,
-                        "# UNIX queues active",
+                        "# queues active",
                         GNUNET_CONTAINER_multipeermap_size (queue_map),
                         GNUNET_NO);
   if (NULL != queue->timeout_task)

-- 
To stop receiving notification emails like this one, please contact
address@hidden



reply via email to

[Prev in Thread] Current Thread [Next in Thread]