Copyright years
[oweals/gnunet.git] / src / util / connection.c
index f6182ebbd9433fc096e6796a57b65a40f9c1f3cc..5aa277546a3eadf0230e4680fc1293d2cb77c4c0 100644 (file)
@@ -1,10 +1,10 @@
 /*
      This file is part of GNUnet.
 /*
      This file is part of GNUnet.
-     (C) 2009, 2012 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2009-2013 GNUnet e.V.
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 2, or (at your
+     by the Free Software Foundation; either version 3, or (at your
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
      option) any later version.
 
      GNUnet is distributed in the hope that it will be useful, but
@@ -14,8 +14,8 @@
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
 
      You should have received a copy of the GNU General Public License
      along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
+     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+     Boston, MA 02110-1301, USA.
 */
 
 /**
 */
 
 /**
  * These rules should apply in general, but for this
  * module they are VERY, VERY important.
  */
  * These rules should apply in general, but for this
  * module they are VERY, VERY important.
  */
-
 #include "platform.h"
 #include "platform.h"
-#include "gnunet_common.h"
-#include "gnunet_connection_lib.h"
-#include "gnunet_container_lib.h"
+#include "gnunet_util_lib.h"
 #include "gnunet_resolver_service.h"
 #include "gnunet_resolver_service.h"
-#include "gnunet_scheduler_lib.h"
-#include "gnunet_server_lib.h"
 
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
 
 
 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
@@ -75,7 +70,7 @@ struct GNUNET_CONNECTION_TransmitHandle
   /**
    * Task called on timeout.
    */
   /**
    * Task called on timeout.
    */
-  GNUNET_SCHEDULER_TaskIdentifier timeout_task;
+  struct GNUNET_SCHEDULER_Task * timeout_task;
 
   /**
    * At what number of bytes available in the
 
   /**
    * At what number of bytes available in the
@@ -126,7 +121,7 @@ struct AddressProbe
   /**
    * Task waiting for the connection to finish connecting.
    */
   /**
    * Task waiting for the connection to finish connecting.
    */
-  GNUNET_SCHEDULER_TaskIdentifier task;
+  struct GNUNET_SCHEDULER_Task * task;
 };
 
 
 };
 
 
@@ -175,7 +170,7 @@ struct GNUNET_CONNECTION_Handle
   GNUNET_CONNECTION_Receiver receiver;
 
   /**
   GNUNET_CONNECTION_Receiver receiver;
 
   /**
-   * Closure for receiver.
+   * Closure for @e receiver.
    */
   void *receiver_cls;
 
    */
   void *receiver_cls;
 
@@ -185,36 +180,36 @@ struct GNUNET_CONNECTION_Handle
   char *write_buffer;
 
   /**
   char *write_buffer;
 
   /**
-   * Current size of our write buffer.
+   * Current size of our @e write_buffer.
    */
   size_t write_buffer_size;
 
   /**
    */
   size_t write_buffer_size;
 
   /**
-   * Current write-offset in write buffer (where
+   * Current write-offset in @e write_buffer (where
    * would we write next).
    */
   size_t write_buffer_off;
 
   /**
    * would we write next).
    */
   size_t write_buffer_off;
 
   /**
-   * Current read-offset in write buffer (how many
+   * Current read-offset in @e write_buffer (how many
    * bytes have already been sent).
    */
   size_t write_buffer_pos;
 
   /**
    * bytes have already been sent).
    */
   size_t write_buffer_pos;
 
   /**
-   * Length of addr.
+   * Length of @e addr.
    */
   socklen_t addrlen;
 
   /**
    * Read task that we may need to wait for.
    */
    */
   socklen_t addrlen;
 
   /**
    * Read task that we may need to wait for.
    */
-  GNUNET_SCHEDULER_TaskIdentifier read_task;
+  struct GNUNET_SCHEDULER_Task *read_task;
 
   /**
    * Write task that we may need to wait for.
    */
 
   /**
    * Write task that we may need to wait for.
    */
-  GNUNET_SCHEDULER_TaskIdentifier write_task;
+  struct GNUNET_SCHEDULER_Task *write_task;
 
   /**
    * Handle to a pending DNS lookup request.
 
   /**
    * Handle to a pending DNS lookup request.
@@ -247,7 +242,19 @@ struct GNUNET_CONNECTION_Handle
    * termination as a signal (because only then will the leaked
    * socket be freed!)
    */
    * termination as a signal (because only then will the leaked
    * socket be freed!)
    */
-  int16_t persist;
+  int8_t persist;
+
+  /**
+   * Usually 0.  Set to 1 if this handle is in use, and should
+   * #GNUNET_CONNECTION_destroy() be called right now, the action needs
+   * to be deferred by setting it to -1.
+   */
+  int8_t destroy_later;
+
+  /**
+   * Handle to subsequent connection after proxy handshake completes,
+   */
+  struct GNUNET_CONNECTION_Handle *proxy_handshake;
 
 };
 
 
 };
 
@@ -275,7 +282,7 @@ GNUNET_CONNECTION_persist_ (struct GNUNET_CONNECTION_Handle *connection)
  * reach the other side before the process is terminated.
  *
  * @param connection the connection to make flushing and blocking
  * reach the other side before the process is terminated.
  *
  * @param connection the connection to make flushing and blocking
- * @return GNUNET_OK on success
+ * @return #GNUNET_OK on success
  */
 int
 GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle *connection)
  */
 int
 GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle *connection)
@@ -287,7 +294,7 @@ GNUNET_CONNECTION_disable_corking (struct GNUNET_CONNECTION_Handle *connection)
 /**
  * Create a connection handle by boxing an existing OS socket.  The OS
  * socket should henceforth be no longer used directly.
 /**
  * Create a connection handle by boxing an existing OS socket.  The OS
  * socket should henceforth be no longer used directly.
- * GNUNET_connection_destroy will close it.
+ * #GNUNET_connection_destroy() will close it.
  *
  * @param osSocket existing socket to box
  * @return the boxed connection handle
  *
  * @param osSocket existing socket to box
  * @return the boxed connection handle
@@ -297,7 +304,7 @@ GNUNET_CONNECTION_create_from_existing (struct GNUNET_NETWORK_Handle *osSocket)
 {
   struct GNUNET_CONNECTION_Handle *connection;
 
 {
   struct GNUNET_CONNECTION_Handle *connection;
 
-  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
+  connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->sock = osSocket;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->sock = osSocket;
@@ -309,14 +316,14 @@ GNUNET_CONNECTION_create_from_existing (struct GNUNET_NETWORK_Handle *osSocket)
  * Create a connection handle by accepting on a listen socket.  This
  * function may block if the listen socket has no connection ready.
  *
  * Create a connection handle by accepting on a listen socket.  This
  * function may block if the listen socket has no connection ready.
  *
- * @param access function to use to check if access is allowed
- * @param access_cls closure for access
+ * @param access_cb function to use to check if access is allowed
+ * @param access_cb_cls closure for @a access_cb
  * @param lsock listen socket
  * @return the connection handle, NULL on error
  */
 struct GNUNET_CONNECTION_Handle *
  * @param lsock listen socket
  * @return the connection handle, NULL on error
  */
 struct GNUNET_CONNECTION_Handle *
-GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
-                                      void *access_cls,
+GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access_cb,
+                                      void *access_cb_cls,
                                       struct GNUNET_NETWORK_Handle *lsock)
 {
   struct GNUNET_CONNECTION_Handle *connection;
                                       struct GNUNET_NETWORK_Handle *lsock)
 {
   struct GNUNET_CONNECTION_Handle *connection;
@@ -340,7 +347,8 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
       GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen);
   if (NULL == sock)
   {
       GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen);
   if (NULL == sock)
   {
-    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
+    if (EAGAIN != errno)
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
     return NULL;
   }
   if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
     return NULL;
   }
   if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
@@ -355,7 +363,7 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
   if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
   {
     /* convert to V4 address */
   if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
   {
     /* convert to V4 address */
-    v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
+    v4 = GNUNET_new (struct sockaddr_in);
     memset (v4, 0, sizeof (struct sockaddr_in));
     v4->sin_family = AF_INET;
 #if HAVE_SOCKADDR_IN_SIN_LEN
     memset (v4, 0, sizeof (struct sockaddr_in));
     v4->sin_family = AF_INET;
 #if HAVE_SOCKADDR_IN_SIN_LEN
@@ -413,25 +421,28 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
 #endif
   }
 
 #endif
   }
 
-  if ((NULL != access) &&
-      (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen))))
+  if ((NULL != access_cb) &&
+      (GNUNET_YES != (aret = access_cb (access_cb_cls, gcp, uaddr, addrlen))))
   {
     if (GNUNET_NO == aret)
   {
     if (GNUNET_NO == aret)
-      LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"),
-           GNUNET_a2s (uaddr, addrlen));
+      LOG (GNUNET_ERROR_TYPE_INFO,
+           _("Access denied to `%s'\n"),
+           GNUNET_a2s (uaddr,
+                       addrlen));
     GNUNET_break (GNUNET_OK ==
     GNUNET_break (GNUNET_OK ==
-                  GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR));
+                  GNUNET_NETWORK_socket_shutdown (sock,
+                                                  SHUT_RDWR));
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
     GNUNET_free (uaddr);
     return NULL;
   }
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
     GNUNET_free (uaddr);
     return NULL;
   }
-  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
+  connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->addr = uaddr;
   connection->addrlen = addrlen;
   connection->sock = sock;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->addr = uaddr;
   connection->addrlen = addrlen;
   connection->sock = sock;
-  LOG (GNUNET_ERROR_TYPE_INFO, 
+  LOG (GNUNET_ERROR_TYPE_INFO,
        _("Accepting connection from `%s': %p\n"),
        GNUNET_a2s (uaddr, addrlen), connection);
   return connection;
        _("Accepting connection from `%s': %p\n"),
        GNUNET_a2s (uaddr, addrlen), connection);
   return connection;
@@ -443,12 +454,13 @@ GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
  *
  * @param connection the client to get the address for
  * @param addr where to store the address
  *
  * @param connection the client to get the address for
  * @param addr where to store the address
- * @param addrlen where to store the length of the address
- * @return GNUNET_OK on success
+ * @param addrlen where to store the length of the @a addr
+ * @return #GNUNET_OK on success
  */
 int
 GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection,
  */
 int
 GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection,
-                               void **addr, size_t * addrlen)
+                               void **addr,
+                               size_t *addrlen)
 {
   if ((NULL == connection->addr) || (0 == connection->addrlen))
     return GNUNET_NO;
 {
   if ((NULL == connection->addr) || (0 == connection->addrlen))
     return GNUNET_NO;
@@ -466,17 +478,23 @@ GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection,
  * @param errcode error code to send
  */
 static void
  * @param errcode error code to send
  */
 static void
-signal_receive_error (struct GNUNET_CONNECTION_Handle *connection, int errcode)
+signal_receive_error (struct GNUNET_CONNECTION_Handle *connection,
+                      int errcode)
 {
   GNUNET_CONNECTION_Receiver receiver;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
 {
   GNUNET_CONNECTION_Receiver receiver;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Receive encounters error (%s), connection closed (%p)\n", 
+       "Receive encounters error (%s), connection closed (%p)\n",
        STRERROR (errcode),
        connection);
   GNUNET_assert (NULL != (receiver = connection->receiver));
   connection->receiver = NULL;
        STRERROR (errcode),
        connection);
   GNUNET_assert (NULL != (receiver = connection->receiver));
   connection->receiver = NULL;
-  receiver (connection->receiver_cls, NULL, 0, connection->addr, connection->addrlen, errcode);
+  receiver (connection->receiver_cls,
+            NULL,
+            0,
+            connection->addr,
+            connection->addrlen,
+            errcode);
 }
 
 
 }
 
 
@@ -490,7 +508,8 @@ signal_receive_timeout (struct GNUNET_CONNECTION_Handle *connection)
 {
   GNUNET_CONNECTION_Receiver receiver;
 
 {
   GNUNET_CONNECTION_Receiver receiver;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Connection signals timeout to receiver (%p)!\n",
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Connection signals timeout to receiver (%p)!\n",
        connection);
   GNUNET_assert (NULL != (receiver = connection->receiver));
   connection->receiver = NULL;
        connection);
   GNUNET_assert (NULL != (receiver = connection->receiver));
   connection->receiver = NULL;
@@ -516,16 +535,18 @@ signal_transmit_error (struct GNUNET_CONNECTION_Handle *connection,
        connection);
   if (NULL != connection->sock)
   {
        connection);
   if (NULL != connection->sock)
   {
-    GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR);
-    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
+    (void) GNUNET_NETWORK_socket_shutdown (connection->sock,
+                                           SHUT_RDWR);
+    GNUNET_break (GNUNET_OK ==
+                  GNUNET_NETWORK_socket_close (connection->sock));
     connection->sock = NULL;
     connection->sock = NULL;
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task);
+    GNUNET_assert (NULL == connection->write_task);
   }
   }
-  if (GNUNET_SCHEDULER_NO_TASK != connection->read_task)
+  if (NULL != connection->read_task)
   {
     /* send errors trigger read errors... */
     GNUNET_SCHEDULER_cancel (connection->read_task);
   {
     /* send errors trigger read errors... */
     GNUNET_SCHEDULER_cancel (connection->read_task);
-    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
+    connection->read_task = NULL;
     signal_receive_timeout (connection);
     return;
   }
     signal_receive_timeout (connection);
     return;
   }
@@ -547,24 +568,37 @@ static void
 connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection)
 {
   LOG (GNUNET_ERROR_TYPE_INFO,
 connect_fail_continuation (struct GNUNET_CONNECTION_Handle *connection)
 {
   LOG (GNUNET_ERROR_TYPE_INFO,
-       _("Failed to establish TCP connection to `%s:%u', no further addresses to try.\n"),
-       connection->hostname, connection->port);
+       "Failed to establish TCP connection to `%s:%u', no further addresses to try.\n",
+       connection->hostname,
+    connection->port);
   GNUNET_break (NULL == connection->ap_head);
   GNUNET_break (NULL == connection->ap_tail);
   GNUNET_break (GNUNET_NO == connection->dns_active);
   GNUNET_break (NULL == connection->sock);
   GNUNET_break (NULL == connection->ap_head);
   GNUNET_break (NULL == connection->ap_tail);
   GNUNET_break (GNUNET_NO == connection->dns_active);
   GNUNET_break (NULL == connection->sock);
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task);
+  GNUNET_assert (NULL == connection->write_task);
+  GNUNET_assert (NULL == connection->proxy_handshake);
 
   /* signal errors for jobs that used to wait on the connection */
 
   /* signal errors for jobs that used to wait on the connection */
+  connection->destroy_later = 1;
   if (NULL != connection->receiver)
   if (NULL != connection->receiver)
-    signal_receive_error (connection, ECONNREFUSED);
+    signal_receive_error (connection,
+                          ECONNREFUSED);
   if (NULL != connection->nth.notify_ready)
   {
   if (NULL != connection->nth.notify_ready)
   {
-    GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK);
+    GNUNET_assert (NULL != connection->nth.timeout_task);
     GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
     GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
-    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
-    signal_transmit_error (connection, ECONNREFUSED);
+    connection->nth.timeout_task = NULL;
+    signal_transmit_error (connection,
+                           ECONNREFUSED);
   }
   }
+  if (-1 == connection->destroy_later)
+  {
+    /* do it now */
+    connection->destroy_later = 0;
+    GNUNET_CONNECTION_destroy (connection);
+    return;
+  }
+  connection->destroy_later = 0;
 }
 
 
 }
 
 
@@ -597,15 +631,17 @@ receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 static void
 connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
 {
 static void
 connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
 {
-  LOG (GNUNET_ERROR_TYPE_DEBUG, 
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Connection to `%s' succeeded! (%p)\n",
        "Connection to `%s' succeeded! (%p)\n",
-       GNUNET_a2s (connection->addr, connection->addrlen), connection);
+       GNUNET_a2s (connection->addr, connection->addrlen),
+       connection);
   /* trigger jobs that waited for the connection */
   if (NULL != connection->receiver)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
   /* trigger jobs that waited for the connection */
   if (NULL != connection->receiver)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Connection succeeded, starting with receiving data (%p)\n", 
+         "Connection succeeded, starting with receiving data (%p)\n",
         connection);
         connection);
+    GNUNET_assert (NULL == connection->read_task);
     connection->read_task =
       GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                      (connection->receive_timeout), connection->sock,
     connection->read_task =
       GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
                                      (connection->receive_timeout), connection->sock,
@@ -616,10 +652,10 @@ connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Connection succeeded, starting with sending data (%p)\n",
          connection);
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Connection succeeded, starting with sending data (%p)\n",
          connection);
-    GNUNET_assert (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK);
+    GNUNET_assert (connection->nth.timeout_task != NULL);
     GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
     GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
-    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
-    GNUNET_assert (connection->write_task == GNUNET_SCHEDULER_NO_TASK);
+    connection->nth.timeout_task = NULL;
+    GNUNET_assert (connection->write_task == NULL);
     connection->write_task =
         GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
                                         (connection->nth.transmit_timeout), connection->sock,
     connection->write_task =
         GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
                                         (connection->nth.transmit_timeout), connection->sock,
@@ -657,7 +693,9 @@ connect_probe_continuation (void *cls,
   {
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
     GNUNET_free (ap);
   {
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
     GNUNET_free (ap);
-    if ((NULL == connection->ap_head) && (GNUNET_NO == connection->dns_active))
+    if ((NULL == connection->ap_head) &&
+        (GNUNET_NO == connection->dns_active) &&
+        (NULL == connection->proxy_handshake))
       connect_fail_continuation (connection);
     return;
   }
       connect_fail_continuation (connection);
     return;
   }
@@ -684,12 +722,13 @@ connect_probe_continuation (void *cls,
  * Try to establish a connection given the specified address.
  * This function is called by the resolver once we have a DNS reply.
  *
  * Try to establish a connection given the specified address.
  * This function is called by the resolver once we have a DNS reply.
  *
- * @param cls our "struct GNUNET_CONNECTION_Handle *"
+ * @param cls our `struct GNUNET_CONNECTION_Handle *`
  * @param addr address to try, NULL for "last call"
  * @param addr address to try, NULL for "last call"
- * @param addrlen length of addr
+ * @param addrlen length of @a addr
  */
 static void
  */
 static void
-try_connect_using_address (void *cls, const struct sockaddr *addr,
+try_connect_using_address (void *cls,
+                           const struct sockaddr *addr,
                            socklen_t addrlen)
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
                            socklen_t addrlen)
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
@@ -699,7 +738,9 @@ try_connect_using_address (void *cls, const struct sockaddr *addr,
   if (NULL == addr)
   {
     connection->dns_active = NULL;
   if (NULL == addr)
   {
     connection->dns_active = NULL;
-    if ((NULL == connection->ap_head) && (NULL == connection->sock))
+    if ((NULL == connection->ap_head) &&
+        (NULL == connection->sock) &&
+        (NULL == connection->proxy_handshake))
       connect_fail_continuation (connection);
     return;
   }
       connect_fail_continuation (connection);
     return;
   }
@@ -708,8 +749,11 @@ try_connect_using_address (void *cls, const struct sockaddr *addr,
   GNUNET_assert (NULL == connection->addr);
   /* try to connect */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
   GNUNET_assert (NULL == connection->addr);
   /* try to connect */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Trying to connect using address `%s:%u/%s:%u'\n", connection->hostname, connection->port,
-       GNUNET_a2s (addr, addrlen), connection->port);
+       "Trying to connect using address `%s:%u/%s:%u'\n",
+       connection->hostname,
+       connection->port,
+       GNUNET_a2s (addr, addrlen),
+       connection->port);
   ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
   ap->addr = (const struct sockaddr *) &ap[1];
   memcpy (&ap[1], addr, addrlen);
   ap = GNUNET_malloc (sizeof (struct AddressProbe) + addrlen);
   ap->addr = (const struct sockaddr *) &ap[1];
   memcpy (&ap[1], addr, addrlen);
@@ -735,18 +779,16 @@ try_connect_using_address (void *cls, const struct sockaddr *addr,
     GNUNET_free (ap);
     return;                     /* not supported by OS */
   }
     GNUNET_free (ap);
     return;                     /* not supported by OS */
   }
-  LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"),
-       GNUNET_a2s (ap->addr, ap->addrlen), connection);
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Trying to connect to `%s' (%p)\n",
+       GNUNET_a2s (ap->addr, ap->addrlen),
+       connection);
   if ((GNUNET_OK !=
        GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) &&
       (EINPROGRESS != errno))
   {
     /* maybe refused / unsupported address, try next */
     LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
   if ((GNUNET_OK !=
        GNUNET_NETWORK_socket_connect (ap->sock, ap->addr, ap->addrlen)) &&
       (EINPROGRESS != errno))
   {
     /* maybe refused / unsupported address, try next */
     LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
-#if 0
-    LOG (GNUNET_ERROR_TYPE_INFO, _("Failed to connect to `%s' (%p)\n"),
-         GNUNET_a2s (ap->addr, ap->addrlen), connection);
-#endif
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
     GNUNET_free (ap);
     return;
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ap->sock));
     GNUNET_free (ap);
     return;
@@ -756,8 +798,7 @@ try_connect_using_address (void *cls, const struct sockaddr *addr,
   if (NULL != connection->nth.notify_ready)
     delay =
         GNUNET_TIME_relative_min (delay,
   if (NULL != connection->nth.notify_ready)
     delay =
         GNUNET_TIME_relative_min (delay,
-                                  GNUNET_TIME_absolute_get_remaining (connection->
-                                                                      nth.transmit_timeout));
+                                  GNUNET_TIME_absolute_get_remaining (connection->nth.transmit_timeout));
   if (NULL != connection->receiver)
     delay =
         GNUNET_TIME_relative_min (delay,
   if (NULL != connection->receiver)
     delay =
         GNUNET_TIME_relative_min (delay,
@@ -780,14 +821,14 @@ try_connect_using_address (void *cls, const struct sockaddr *addr,
  * @return the connection handle
  */
 struct GNUNET_CONNECTION_Handle *
  * @return the connection handle
  */
 struct GNUNET_CONNECTION_Handle *
-GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle
-                                       *cfg, const char *hostname,
+GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                       const char *hostname,
                                        uint16_t port)
 {
   struct GNUNET_CONNECTION_Handle *connection;
 
   GNUNET_assert (0 < strlen (hostname));        /* sanity check */
                                        uint16_t port)
 {
   struct GNUNET_CONNECTION_Handle *connection;
 
   GNUNET_assert (0 < strlen (hostname));        /* sanity check */
-  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
+  connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
   connection->cfg = cfg;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->cfg = cfg;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
@@ -811,38 +852,38 @@ GNUNET_CONNECTION_create_from_connect (const struct GNUNET_CONFIGURATION_Handle
  * @return the connection handle, NULL on systems without UNIX support
  */
 struct GNUNET_CONNECTION_Handle *
  * @return the connection handle, NULL on systems without UNIX support
  */
 struct GNUNET_CONNECTION_Handle *
-GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct
-                                                   GNUNET_CONFIGURATION_Handle
-                                                   *cfg, const char *unixpath)
+GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct GNUNET_CONFIGURATION_Handle *cfg,
+                                                   const char *unixpath)
 {
 #ifdef AF_UNIX
   struct GNUNET_CONNECTION_Handle *connection;
   struct sockaddr_un *un;
 {
 #ifdef AF_UNIX
   struct GNUNET_CONNECTION_Handle *connection;
   struct sockaddr_un *un;
-  size_t slen;
 
   GNUNET_assert (0 < strlen (unixpath));        /* sanity check */
 
   GNUNET_assert (0 < strlen (unixpath));        /* sanity check */
-  un = GNUNET_malloc (sizeof (struct sockaddr_un));
+  un = GNUNET_new (struct sockaddr_un);
   un->sun_family = AF_UNIX;
   un->sun_family = AF_UNIX;
-  slen = strlen (unixpath);
-  if (slen >= sizeof (un->sun_path))
-    slen = sizeof (un->sun_path) - 1;
-  memcpy (un->sun_path, unixpath, slen);
-  un->sun_path[slen] = '\0';
-  slen = sizeof (struct sockaddr_un);
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  un->sun_len = (u_char) slen;
+  strncpy (un->sun_path, unixpath, sizeof (un->sun_path) - 1);
+#ifdef LINUX
+  {
+    int abstract;
+
+    abstract = GNUNET_CONFIGURATION_get_value_yesno (cfg, "TESTING",
+                                                     "USE_ABSTRACT_SOCKETS");
+    if (GNUNET_YES == abstract)
+      un->sun_path[0] = '\0';
+  }
 #endif
 #endif
-#if LINUX
-  un->sun_path[0] = '\0';
+#if HAVE_SOCKADDR_IN_SIN_LEN
+  un->sun_len = (u_char) sizeof (struct sockaddr_un);
 #endif
 #endif
-  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
+  connection = GNUNET_new (struct GNUNET_CONNECTION_Handle);
   connection->cfg = cfg;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->port = 0;
   connection->hostname = NULL;
   connection->addr = (struct sockaddr *) un;
   connection->cfg = cfg;
   connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
   connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
   connection->port = 0;
   connection->hostname = NULL;
   connection->addr = (struct sockaddr *) un;
-  connection->addrlen = slen;
+  connection->addrlen = sizeof (struct sockaddr_un);
   connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
   if (NULL == connection->sock)
   {
   connection->sock = GNUNET_NETWORK_socket_create (AF_UNIX, SOCK_STREAM, 0);
   if (NULL == connection->sock)
   {
@@ -851,8 +892,9 @@ GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct
     GNUNET_free (connection);
     return NULL;
   }
     GNUNET_free (connection);
     return NULL;
   }
-  if (GNUNET_OK !=
-      GNUNET_NETWORK_socket_connect (connection->sock, connection->addr, connection->addrlen))
+  if ( (GNUNET_OK !=
+       GNUNET_NETWORK_socket_connect (connection->sock, connection->addr, connection->addrlen)) &&
+       (EINPROGRESS != errno) )
   {
     /* Just return; we expect everything to work eventually so don't fail HARD */
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
   {
     /* Just return; we expect everything to work eventually so don't fail HARD */
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
@@ -872,32 +914,29 @@ GNUNET_CONNECTION_create_from_connect_to_unixpath (const struct
  * This function returns immediately, even if the connection has not
  * yet been established.  This function only creates TCP connections.
  *
  * This function returns immediately, even if the connection has not
  * yet been established.  This function only creates TCP connections.
  *
- * @param af_family address family to use
+ * @param s socket to connect
  * @param serv_addr server address
  * @param serv_addr server address
- * @param addrlen length of server address
+ * @param addrlen length of @a serv_addr
  * @return the connection handle
  */
 struct GNUNET_CONNECTION_Handle *
  * @return the connection handle
  */
 struct GNUNET_CONNECTION_Handle *
-GNUNET_CONNECTION_create_from_sockaddr (int af_family,
-                                        const struct sockaddr *serv_addr,
-                                        socklen_t addrlen)
+GNUNET_CONNECTION_connect_socket (struct GNUNET_NETWORK_Handle *s,
+                                  const struct sockaddr *serv_addr,
+                                  socklen_t addrlen)
 {
 {
-  struct GNUNET_NETWORK_Handle *s;
   struct GNUNET_CONNECTION_Handle *connection;
 
   struct GNUNET_CONNECTION_Handle *connection;
 
-  s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
-  if (NULL == s)
-  {
-    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "socket");
-    return NULL;
-  }
-  if ((GNUNET_OK != GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) &&
-      (EINPROGRESS != errno))
+  if ( (GNUNET_OK !=
+        GNUNET_NETWORK_socket_connect (s, serv_addr, addrlen)) &&
+       (EINPROGRESS != errno) )
   {
     /* maybe refused / unsupported address, try next */
   {
     /* maybe refused / unsupported address, try next */
-    LOG_STRERROR (GNUNET_ERROR_TYPE_INFO, "connect");
-    LOG (GNUNET_ERROR_TYPE_INFO, _("Attempt to connect to `%s' failed\n"),
-         GNUNET_a2s (serv_addr, addrlen));
+    LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG,
+                  "connect");
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Attempt to connect to `%s' failed\n",
+         GNUNET_a2s (serv_addr,
+                     addrlen));
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
     return NULL;
   }
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (s));
     return NULL;
   }
@@ -905,26 +944,61 @@ GNUNET_CONNECTION_create_from_sockaddr (int af_family,
   connection->addr = GNUNET_malloc (addrlen);
   memcpy (connection->addr, serv_addr, addrlen);
   connection->addrlen = addrlen;
   connection->addr = GNUNET_malloc (addrlen);
   memcpy (connection->addr, serv_addr, addrlen);
   connection->addrlen = addrlen;
-  LOG (GNUNET_ERROR_TYPE_INFO, _("Trying to connect to `%s' (%p)\n"),
-       GNUNET_a2s (serv_addr, addrlen), connection);
+  LOG (GNUNET_ERROR_TYPE_INFO,
+       "Trying to connect to `%s' (%p)\n",
+       GNUNET_a2s (serv_addr, addrlen),
+       connection);
   return connection;
 }
 
 
   return connection;
 }
 
 
+/**
+ * Create a connection handle by creating a socket and
+ * (asynchronously) connecting to a host.  This function returns
+ * immediately, even if the connection has not yet been established.
+ * This function only creates TCP connections.
+ *
+ * @param af_family address family to use
+ * @param serv_addr server address
+ * @param addrlen length of @a serv_addr
+ * @return the connection handle
+ */
+struct GNUNET_CONNECTION_Handle *
+GNUNET_CONNECTION_create_from_sockaddr (int af_family,
+                                        const struct sockaddr *serv_addr,
+                                        socklen_t addrlen)
+{
+  struct GNUNET_NETWORK_Handle *s;
+
+  s = GNUNET_NETWORK_socket_create (af_family, SOCK_STREAM, 0);
+  if (NULL == s)
+  {
+    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING | GNUNET_ERROR_TYPE_BULK, "socket");
+    return NULL;
+  }
+  return GNUNET_CONNECTION_connect_socket (s, serv_addr, addrlen);
+}
+
+
 /**
  * Check if connection is valid (no fatal errors have happened so far).
  * Note that a connection that is still trying to connect is considered
  * valid.
  *
  * @param connection connection to check
 /**
  * Check if connection is valid (no fatal errors have happened so far).
  * Note that a connection that is still trying to connect is considered
  * valid.
  *
  * @param connection connection to check
- * @return GNUNET_YES if valid, GNUNET_NO otherwise
+ * @return #GNUNET_YES if valid, #GNUNET_NO otherwise
  */
 int
 GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection)
 {
  */
 int
 GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *connection)
 {
-  if ((NULL != connection->ap_head) || (NULL != connection->dns_active))
+  if ((NULL != connection->ap_head) ||
+      (NULL != connection->dns_active) ||
+      (NULL != connection->proxy_handshake))
     return GNUNET_YES;          /* still trying to connect */
     return GNUNET_YES;          /* still trying to connect */
-  return (NULL == connection->sock) ? GNUNET_NO : GNUNET_YES;
+  if ( (0 != connection->destroy_later) ||
+       (NULL == connection->sock) )
+    return GNUNET_NO;
+  return GNUNET_YES;
 }
 
 
 }
 
 
@@ -940,24 +1014,31 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
 {
   struct AddressProbe *pos;
 
 {
   struct AddressProbe *pos;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection);
+  if (0 != connection->destroy_later)
+  {
+    connection->destroy_later = -1;
+    return;
+  }
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "Shutting down connection (%p)\n",
+       connection);
   GNUNET_assert (NULL == connection->nth.notify_ready);
   GNUNET_assert (NULL == connection->receiver);
   GNUNET_assert (NULL == connection->nth.notify_ready);
   GNUNET_assert (NULL == connection->receiver);
-  if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
+  if (NULL != connection->write_task)
   {
     GNUNET_SCHEDULER_cancel (connection->write_task);
   {
     GNUNET_SCHEDULER_cancel (connection->write_task);
-    connection->write_task = GNUNET_SCHEDULER_NO_TASK;
+    connection->write_task = NULL;
     connection->write_buffer_off = 0;
   }
     connection->write_buffer_off = 0;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != connection->read_task)
+  if (NULL != connection->read_task)
   {
     GNUNET_SCHEDULER_cancel (connection->read_task);
   {
     GNUNET_SCHEDULER_cancel (connection->read_task);
-    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
+    connection->read_task = NULL;
   }
   }
-  if (GNUNET_SCHEDULER_NO_TASK != connection->nth.timeout_task)
+  if (NULL != connection->nth.timeout_task)
   {
     GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
   {
     GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
-    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    connection->nth.timeout_task = NULL;
   }
   connection->nth.notify_ready = NULL;
   if (NULL != connection->dns_active)
   }
   connection->nth.notify_ready = NULL;
   if (NULL != connection->dns_active)
@@ -965,6 +1046,12 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
     GNUNET_RESOLVER_request_cancel (connection->dns_active);
     connection->dns_active = NULL;
   }
     GNUNET_RESOLVER_request_cancel (connection->dns_active);
     connection->dns_active = NULL;
   }
+  if (NULL != connection->proxy_handshake)
+  {
+    /* GNUNET_CONNECTION_destroy (connection->proxy_handshake); */
+    connection->proxy_handshake->destroy_later = -1;
+    connection->proxy_handshake = NULL;  /* Not leaked ??? */
+  }
   while (NULL != (pos = connection->ap_head))
   {
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
   while (NULL != (pos = connection->ap_head))
   {
     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
@@ -975,18 +1062,26 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
   if ( (NULL != connection->sock) &&
        (GNUNET_YES != connection->persist) )
   {
   if ( (NULL != connection->sock) &&
        (GNUNET_YES != connection->persist) )
   {
-    if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && 
-       (ENOTCONN != errno) && 
+    if ((GNUNET_OK !=
+         GNUNET_NETWORK_socket_shutdown (connection->sock,
+                                         SHUT_RDWR)) &&
+       (ENOTCONN != errno) &&
        (ECONNRESET != errno) )
        (ECONNRESET != errno) )
-      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown");    
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING,
+                    "shutdown");
   }
   if (NULL != connection->sock)
   {
     if (GNUNET_YES != connection->persist)
   }
   if (NULL != connection->sock)
   {
     if (GNUNET_YES != connection->persist)
-      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
+    {
+      GNUNET_break (GNUNET_OK ==
+                    GNUNET_NETWORK_socket_close (connection->sock));
+    }
     else
     else
-      GNUNET_free (connection->sock); /* at least no memory leak (we deliberately
-                                      * leak the socket in this special case) ... */
+    {
+      GNUNET_NETWORK_socket_free_memory_only_ (connection->sock); /* at least no memory leak (we deliberately
+                                                                  * leak the socket in this special case) ... */
+    }
   }
   GNUNET_free_non_null (connection->addr);
   GNUNET_free_non_null (connection->hostname);
   }
   GNUNET_free_non_null (connection->addr);
   GNUNET_free_non_null (connection->hostname);
@@ -1003,14 +1098,15 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
  * @param tc scheduler context
  */
 static void
  * @param tc scheduler context
  */
 static void
-receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+receive_ready (void *cls,
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   char buffer[connection->max];
   ssize_t ret;
   GNUNET_CONNECTION_Receiver receiver;
 
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   char buffer[connection->max];
   ssize_t ret;
   GNUNET_CONNECTION_Receiver receiver;
 
-  connection->read_task = GNUNET_SCHEDULER_NO_TASK;
+  connection->read_task = NULL;
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
   {
     /* ignore shutdown request, go again immediately */
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
   {
     /* ignore shutdown request, go again immediately */
@@ -1023,9 +1119,9 @@ receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_TIMEOUT))
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
-        "Receive from `%s' encounters error: timeout (%p)\n",
+        "Receive from `%s' encounters error: timeout (%s, %p)\n",
         GNUNET_a2s (connection->addr, connection->addrlen),
         GNUNET_a2s (connection->addr, connection->addrlen),
-        GNUNET_TIME_absolute_get_duration (connection->receive_timeout).rel_value,
+        GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration (connection->receive_timeout), GNUNET_YES),
         connection);
     signal_receive_timeout (connection);
     return;
         connection);
     signal_receive_timeout (connection);
     return;
@@ -1038,7 +1134,9 @@ receive_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   }
   GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock));
 RETRY:
   }
   GNUNET_assert (GNUNET_NETWORK_fdset_isset (tc->read_ready, connection->sock));
 RETRY:
-  ret = GNUNET_NETWORK_socket_recv (connection->sock, buffer, connection->max);
+  ret = GNUNET_NETWORK_socket_recv (connection->sock,
+                                    buffer,
+                                    connection->max);
   if (-1 == ret)
   {
     if (EINTR == errno)
   if (-1 == ret)
   {
     if (EINTR == errno)
@@ -1047,17 +1145,26 @@ RETRY:
     return;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
     return;
   }
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "receive_ready read %u/%u bytes from `%s' (%p)!\n", (unsigned int) ret,
-       connection->max, GNUNET_a2s (connection->addr, connection->addrlen), connection);
+       "receive_ready read %u/%u bytes from `%s' (%p)!\n",
+       (unsigned int) ret,
+       connection->max,
+       GNUNET_a2s (connection->addr,
+                   connection->addrlen),
+       connection);
   GNUNET_assert (NULL != (receiver = connection->receiver));
   connection->receiver = NULL;
   GNUNET_assert (NULL != (receiver = connection->receiver));
   connection->receiver = NULL;
-  receiver (connection->receiver_cls, buffer, ret, connection->addr, connection->addrlen, 0);
+  receiver (connection->receiver_cls,
+            buffer,
+            ret,
+            connection->addr,
+            connection->addrlen,
+            0);
 }
 
 
 /**
  * Receive data from the given connection.  Note that this function will
 }
 
 
 /**
  * Receive data from the given connection.  Note that this function will
- * call "receiver" asynchronously using the scheduler.  It will
+ * call @a receiver asynchronously using the scheduler.  It will
  * "immediately" return.  Note that there MUST only be one active
  * receive call per connection at any given point in time (so do not
  * call receive again until the receiver callback has been invoked).
  * "immediately" return.  Note that there MUST only be one active
  * receive call per connection at any given point in time (so do not
  * call receive again until the receiver callback has been invoked).
@@ -1066,15 +1173,16 @@ RETRY:
  * @param max maximum number of bytes to read
  * @param timeout maximum amount of time to wait
  * @param receiver function to call with received data
  * @param max maximum number of bytes to read
  * @param timeout maximum amount of time to wait
  * @param receiver function to call with received data
- * @param receiver_cls closure for receiver
+ * @param receiver_cls closure for @a receiver
  */
 void
  */
 void
-GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t max,
+GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection,
+                           size_t max,
                            struct GNUNET_TIME_Relative timeout,
                            GNUNET_CONNECTION_Receiver receiver,
                            void *receiver_cls)
 {
                            struct GNUNET_TIME_Relative timeout,
                            GNUNET_CONNECTION_Receiver receiver,
                            void *receiver_cls)
 {
-  GNUNET_assert ((GNUNET_SCHEDULER_NO_TASK == connection->read_task) &&
+  GNUNET_assert ((NULL == connection->read_task) &&
                  (NULL == connection->receiver));
   GNUNET_assert (NULL != receiver);
   connection->receiver = receiver;
                  (NULL == connection->receiver));
   GNUNET_assert (NULL != receiver);
   connection->receiver = receiver;
@@ -1085,12 +1193,17 @@ GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t m
   {
     connection->read_task =
       GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
   {
     connection->read_task =
       GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_absolute_get_remaining
-                                     (connection->receive_timeout), connection->sock,
-                                     &receive_ready, connection);
+                                     (connection->receive_timeout),
+                                     connection->sock,
+                                     &receive_ready,
+                                     connection);
     return;
   }
     return;
   }
-  if ((NULL == connection->dns_active) && (NULL == connection->ap_head))
+  if ((NULL == connection->dns_active) &&
+      (NULL == connection->ap_head) &&
+      (NULL == connection->proxy_handshake))
   {
   {
+    connection->receiver = NULL;
     receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT);
     return;
   }
     receiver (receiver_cls, NULL, 0, NULL, 0, ETIMEDOUT);
     return;
   }
@@ -1108,10 +1221,11 @@ GNUNET_CONNECTION_receive (struct GNUNET_CONNECTION_Handle *connection, size_t m
 void *
 GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection)
 {
 void *
 GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection)
 {
-  if (GNUNET_SCHEDULER_NO_TASK == connection->read_task)
+  if (NULL != connection->read_task)
   {
   {
-    GNUNET_assert (connection == GNUNET_SCHEDULER_cancel (connection->read_task));
-    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
+    GNUNET_assert (connection ==
+                   GNUNET_SCHEDULER_cancel (connection->read_task));
+    connection->read_task = NULL;
   }
   connection->receiver = NULL;
   return connection->receiver_cls;
   }
   connection->receiver = NULL;
   return connection->receiver_cls;
@@ -1123,7 +1237,7 @@ GNUNET_CONNECTION_receive_cancel (struct GNUNET_CONNECTION_Handle *connection)
  * have enough space available first)!
  *
  * @param connection connection for which we should do this processing
  * have enough space available first)!
  *
  * @param connection connection for which we should do this processing
- * @return GNUNET_YES if we were able to call notify
+ * @return #GNUNET_YES if we were able to call notify
  */
 static int
 process_notify (struct GNUNET_CONNECTION_Handle *connection)
  */
 static int
 process_notify (struct GNUNET_CONNECTION_Handle *connection)
@@ -1133,19 +1247,30 @@ process_notify (struct GNUNET_CONNECTION_Handle *connection)
   size_t size;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
   size_t size;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "process_notify is running\n");
+  GNUNET_assert (NULL == connection->write_task);
   if (NULL == (notify = connection->nth.notify_ready))
   if (NULL == (notify = connection->nth.notify_ready))
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "No one to notify\n");
     return GNUNET_NO;
     return GNUNET_NO;
+  }
   used = connection->write_buffer_off - connection->write_buffer_pos;
   avail = connection->write_buffer_size - used;
   size = connection->nth.notify_size;
   if (size > avail)
   used = connection->write_buffer_off - connection->write_buffer_pos;
   avail = connection->write_buffer_size - used;
   size = connection->nth.notify_size;
   if (size > avail)
+  {
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Not enough buffer\n");
     return GNUNET_NO;
     return GNUNET_NO;
+  }
   connection->nth.notify_ready = NULL;
   if (connection->write_buffer_size - connection->write_buffer_off < size)
   {
     /* need to compact */
   connection->nth.notify_ready = NULL;
   if (connection->write_buffer_size - connection->write_buffer_off < size)
   {
     /* need to compact */
-    memmove (connection->write_buffer, &connection->write_buffer[connection->write_buffer_pos],
+    memmove (connection->write_buffer,
+             &connection->write_buffer[connection->write_buffer_pos],
              used);
     connection->write_buffer_off -= connection->write_buffer_pos;
     connection->write_buffer_pos = 0;
              used);
     connection->write_buffer_off -= connection->write_buffer_pos;
     connection->write_buffer_pos = 0;
@@ -1170,20 +1295,24 @@ process_notify (struct GNUNET_CONNECTION_Handle *connection)
  *
  * This task notifies the client about the timeout.
  *
  *
  * This task notifies the client about the timeout.
  *
- * @param cls the 'struct GNUNET_CONNECTION_Handle'
+ * @param cls the `struct GNUNET_CONNECTION_Handle`
  * @param tc scheduler context
  */
 static void
  * @param tc scheduler context
  */
 static void
-transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmit_timeout (void *cls,
+                  const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
-  connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  connection->nth.timeout_task = NULL;
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Transmit to `%s:%u/%s' fails, time out reached (%p).\n",
        connection->hostname,
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Transmit to `%s:%u/%s' fails, time out reached (%p).\n",
        connection->hostname,
-       connection->port, GNUNET_a2s (connection->addr, connection->addrlen), connection);
+       connection->port,
+       GNUNET_a2s (connection->addr,
+                   connection->addrlen),
+       connection);
   notify = connection->nth.notify_ready;
   GNUNET_assert (NULL != notify);
   connection->nth.notify_ready = NULL;
   notify = connection->nth.notify_ready;
   GNUNET_assert (NULL != notify);
   connection->nth.notify_ready = NULL;
@@ -1197,19 +1326,23 @@ transmit_timeout (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  *
  * This task notifies the client about the error.
  *
  *
  * This task notifies the client about the error.
  *
- * @param cls the 'struct GNUNET_CONNECTION_Handle'
+ * @param cls the `struct GNUNET_CONNECTION_Handle`
  * @param tc scheduler context
  */
 static void
  * @param tc scheduler context
  */
 static void
-connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+connect_error (void *cls,
+               const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Transmission request of size %u fails (%s/%u), connection failed (%p).\n",
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
        "Transmission request of size %u fails (%s/%u), connection failed (%p).\n",
-       connection->nth.notify_size, connection->hostname, connection->port, connection);
-  connection->write_task = GNUNET_SCHEDULER_NO_TASK;
+       connection->nth.notify_size,
+       connection->hostname,
+       connection->port,
+       connection);
+  connection->write_task = NULL;
   notify = connection->nth.notify_ready;
   connection->nth.notify_ready = NULL;
   notify (connection->nth.notify_ready_cls, 0, NULL);
   notify = connection->nth.notify_ready;
   connection->nth.notify_ready = NULL;
   notify (connection->nth.notify_ready_cls, 0, NULL);
@@ -1223,17 +1356,20 @@ connect_error (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
  * @param tc task context describing why we are here
  */
 static void
  * @param tc task context describing why we are here
  */
 static void
-transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+transmit_ready (void *cls,
+                const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
   ssize_t ret;
   size_t have;
 
 {
   struct GNUNET_CONNECTION_Handle *connection = cls;
   GNUNET_CONNECTION_TransmitReadyNotify notify;
   ssize_t ret;
   size_t have;
 
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "transmit_ready running (%p).\n", connection);
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK != connection->write_task);
-  connection->write_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task);
+  LOG (GNUNET_ERROR_TYPE_DEBUG,
+       "transmit_ready running (%p).\n",
+       connection);
+  GNUNET_assert (NULL != connection->write_task);
+  connection->write_task = NULL;
+  GNUNET_assert (NULL == connection->nth.timeout_task);
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
   {
     if (NULL != connection->sock)
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
   {
     if (NULL != connection->sock)
@@ -1253,7 +1389,9 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Transmit to `%s' fails, time out reached (%p).\n",
   {
     LOG (GNUNET_ERROR_TYPE_DEBUG,
          "Transmit to `%s' fails, time out reached (%p).\n",
-         GNUNET_a2s (connection->addr, connection->addrlen), connection);
+         GNUNET_a2s (connection->addr,
+                     connection->addrlen),
+         connection);
     notify = connection->nth.notify_ready;
     GNUNET_assert (NULL != notify);
     connection->nth.notify_ready = NULL;
     notify = connection->nth.notify_ready;
     GNUNET_assert (NULL != notify);
     connection->nth.notify_ready = NULL;
@@ -1261,7 +1399,7 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     return;
   }
   GNUNET_assert (NULL != connection->sock);
     return;
   }
   GNUNET_assert (NULL != connection->sock);
-  if (NULL == tc->write_ready) 
+  if (NULL == tc->write_ready)
   {
     /* special circumstances (in particular, PREREQ_DONE after
      * connect): not yet ready to write, but no "fatal" error either.
   {
     /* special circumstances (in particular, PREREQ_DONE after
      * connect): not yet ready to write, but no "fatal" error either.
@@ -1270,7 +1408,7 @@ transmit_ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   }
   if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock))
   {
   }
   if (!GNUNET_NETWORK_fdset_isset (tc->write_ready, connection->sock))
   {
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->write_task);
+    GNUNET_assert (NULL == connection->write_task);
     /* special circumstances (in particular, shutdown): not yet ready
      * to write, but no "fatal" error either.  Hence retry.  */
     goto SCHEDULE_WRITE;
     /* special circumstances (in particular, shutdown): not yet ready
      * to write, but no "fatal" error either.  Hence retry.  */
     goto SCHEDULE_WRITE;
@@ -1302,10 +1440,10 @@ RETRY:
   {
     if (EINTR == errno)
       goto RETRY;
   {
     if (EINTR == errno)
       goto RETRY;
-    if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
+    if (NULL != connection->write_task)
     {
       GNUNET_SCHEDULER_cancel (connection->write_task);
     {
       GNUNET_SCHEDULER_cancel (connection->write_task);
-      connection->write_task = GNUNET_SCHEDULER_NO_TASK;
+      connection->write_task = NULL;
     }
     signal_transmit_error (connection, errno);
     return;
     }
     signal_transmit_error (connection, errno);
     return;
@@ -1328,7 +1466,7 @@ SCHEDULE_WRITE:
        "Re-scheduling transmit_ready (more to do) (%p).\n", connection);
   have = connection->write_buffer_off - connection->write_buffer_pos;
   GNUNET_assert ((NULL != connection->nth.notify_ready) || (have > 0));
        "Re-scheduling transmit_ready (more to do) (%p).\n", connection);
   have = connection->write_buffer_off - connection->write_buffer_pos;
   GNUNET_assert ((NULL != connection->nth.notify_ready) || (have > 0));
-  if (GNUNET_SCHEDULER_NO_TASK == connection->write_task)
+  if (NULL == connection->write_task)
     connection->write_task =
         GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready ==
                                          NULL) ? GNUNET_TIME_UNIT_FOREVER_REL :
     connection->write_task =
         GNUNET_SCHEDULER_add_write_net ((connection->nth.notify_ready ==
                                          NULL) ? GNUNET_TIME_UNIT_FOREVER_REL :
@@ -1340,15 +1478,15 @@ SCHEDULE_WRITE:
 
 /**
  * Ask the connection to call us once the specified number of bytes
 
 /**
  * Ask the connection to call us once the specified number of bytes
- * are free in the transmission buffer.  May call the notify
- * method immediately if enough space is available.
+ * are free in the transmission buffer.  Will never call the @a notify
+ * callback in this task, but always first go into the scheduler.
  *
  * @param connection connection
  * @param size number of bytes to send
  * @param timeout after how long should we give up (and call
  *
  * @param connection connection
  * @param size number of bytes to send
  * @param timeout after how long should we give up (and call
- *        notify with buf NULL and size 0)?
+ *        @a notify with buf NULL and size 0)?
  * @param notify function to call
  * @param notify function to call
- * @param notify_cls closure for notify
+ * @param notify_cls closure for @a notify
  * @return non-NULL if the notify callback was queued,
  *         NULL if we are already going to notify someone else (busy)
  */
  * @return non-NULL if the notify callback was queued,
  *         NULL if we are already going to notify someone else (busy)
  */
@@ -1374,22 +1512,26 @@ GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connec
   connection->nth.connection = connection;
   connection->nth.notify_size = size;
   connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
   connection->nth.connection = connection;
   connection->nth.notify_size = size;
   connection->nth.transmit_timeout = GNUNET_TIME_relative_to_absolute (timeout);
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->nth.timeout_task);
-  if ((NULL == connection->sock) && 
+  GNUNET_assert (NULL == connection->nth.timeout_task);
+  if ((NULL == connection->sock) &&
       (NULL == connection->ap_head) &&
       (NULL == connection->ap_head) &&
-      (NULL == connection->dns_active))
+      (NULL == connection->dns_active) &&
+      (NULL == connection->proxy_handshake))
   {
   {
-    if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
+    if (NULL != connection->write_task)
       GNUNET_SCHEDULER_cancel (connection->write_task);
       GNUNET_SCHEDULER_cancel (connection->write_task);
-    connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error, connection);
+    connection->write_task = GNUNET_SCHEDULER_add_now (&connect_error,
+                                                       connection);
     return &connection->nth;
   }
     return &connection->nth;
   }
-  if (GNUNET_SCHEDULER_NO_TASK != connection->write_task)
+  if (NULL != connection->write_task)
     return &connection->nth; /* previous transmission still in progress */
   if (NULL != connection->sock)
   {
     /* connected, try to transmit now */
     return &connection->nth; /* previous transmission still in progress */
   if (NULL != connection->sock)
   {
     /* connected, try to transmit now */
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Scheduling transmission (%p).\n", connection);
+    LOG (GNUNET_ERROR_TYPE_DEBUG,
+         "Scheduling transmission (%p).\n",
+         connection);
     connection->write_task =
         GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
                                         (connection->nth.transmit_timeout),
     connection->write_task =
         GNUNET_SCHEDULER_add_write_net (GNUNET_TIME_absolute_get_remaining
                                         (connection->nth.transmit_timeout),
@@ -1398,9 +1540,11 @@ GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connec
   }
   /* not yet connected, wait for connection */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
   }
   /* not yet connected, wait for connection */
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "Need to wait to schedule transmission for connection, adding timeout task (%p).\n", connection);
+       "Need to wait to schedule transmission for connection, adding timeout task (%p).\n",
+       connection);
   connection->nth.timeout_task =
   connection->nth.timeout_task =
-    GNUNET_SCHEDULER_add_delayed (timeout, &transmit_timeout, connection);
+    GNUNET_SCHEDULER_add_delayed (timeout,
+                                  &transmit_timeout, connection);
   return &connection->nth;
 }
 
   return &connection->nth;
 }
 
@@ -1411,22 +1555,57 @@ GNUNET_CONNECTION_notify_transmit_ready (struct GNUNET_CONNECTION_Handle *connec
  * @param th notification to cancel
  */
 void
  * @param th notification to cancel
  */
 void
-GNUNET_CONNECTION_notify_transmit_ready_cancel (struct
-                                                GNUNET_CONNECTION_TransmitHandle
-                                                *th)
+GNUNET_CONNECTION_notify_transmit_ready_cancel (struct GNUNET_CONNECTION_TransmitHandle *th)
 {
   GNUNET_assert (NULL != th->notify_ready);
   th->notify_ready = NULL;
 {
   GNUNET_assert (NULL != th->notify_ready);
   th->notify_ready = NULL;
-  if (GNUNET_SCHEDULER_NO_TASK != th->timeout_task)
+  if (NULL != th->timeout_task)
   {
     GNUNET_SCHEDULER_cancel (th->timeout_task);
   {
     GNUNET_SCHEDULER_cancel (th->timeout_task);
-    th->timeout_task = GNUNET_SCHEDULER_NO_TASK;
+    th->timeout_task = NULL;
   }
   }
-  if (GNUNET_SCHEDULER_NO_TASK != th->connection->write_task)
+  if (NULL != th->connection->write_task)
   {
     GNUNET_SCHEDULER_cancel (th->connection->write_task);
   {
     GNUNET_SCHEDULER_cancel (th->connection->write_task);
-    th->connection->write_task = GNUNET_SCHEDULER_NO_TASK;
+    th->connection->write_task = NULL;
   }
 }
 
   }
 }
 
+
+/**
+ * Create a connection to be proxied using a given connection.
+ *
+ * @param cph connection to proxy server
+ * @return connection to be proxied
+ */
+struct GNUNET_CONNECTION_Handle *
+GNUNET_CONNECTION_create_proxied_from_handshake (struct GNUNET_CONNECTION_Handle *cph)
+{
+  struct GNUNET_CONNECTION_Handle * proxied = GNUNET_CONNECTION_create_from_existing(NULL);
+  proxied->proxy_handshake = cph;
+  return proxied;
+}
+
+
+/**
+ * Activate proxied connection and destroy initial proxy handshake connection.
+ * There must not be any pending requests for reading or writing to the
+ * proxy hadshake connection at this time.
+ *
+ * @param proxied connection connection to proxy server
+ */
+void
+GNUNET_CONNECTION_acivate_proxied (struct GNUNET_CONNECTION_Handle *proxied)
+{
+  struct GNUNET_CONNECTION_Handle *cph = proxied->proxy_handshake;
+  GNUNET_assert (NULL != cph);
+  GNUNET_assert (NULL == proxied->sock);
+  GNUNET_assert (NULL != cph->sock);
+  proxied->sock=cph->sock;
+  cph->sock=NULL;
+  GNUNET_CONNECTION_destroy (cph);
+  connect_success_continuation (proxied);
+}
+
+
 /* end of connection.c */
 /* end of connection.c */