-simplifying destruction of connections, cleaning up server API -- all for #2274
authorChristian Grothoff <christian@grothoff.org>
Thu, 19 Apr 2012 11:55:40 +0000 (11:55 +0000)
committerChristian Grothoff <christian@grothoff.org>
Thu, 19 Apr 2012 11:55:40 +0000 (11:55 +0000)
src/datastore/gnunet-service-datastore.c
src/fs/gnunet-service-fs_lc.c
src/include/gnunet_connection_lib.h
src/include/gnunet_server_lib.h
src/transport/plugin_transport_tcp.c
src/util/connection.c
src/util/server.c
src/util/server_nc.c
src/util/test_connection.c
src/util/test_service.c

index 1d7e8cd2beb68e185c8820c0d929f8df4fe54f72..863cd3902e9588ccd45aa897be1abacf8ff1affb 100644 (file)
@@ -250,7 +250,7 @@ struct TransmitCallbackContext
   /**
    * Handle for the transmission request.
    */
-  struct GNUNET_CONNECTION_TransmitHandle *th;
+  struct GNUNET_SERVER_TransmitHandle *th;
 
   /**
    * Client that we are transmitting to.
@@ -1409,7 +1409,7 @@ cleaning_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
     GNUNET_CONTAINER_DLL_remove (tcc_head, tcc_tail, tcc);
     if (tcc->th != NULL)
     {
-      GNUNET_CONNECTION_notify_transmit_ready_cancel (tcc->th);
+      GNUNET_SERVER_notify_transmit_ready_cancel (tcc->th);
       GNUNET_SERVER_client_drop (tcc->client);
     }
     GNUNET_free (tcc->msg);
index 36aafdde9dd6fbc4dbdee73dd2fcf42d2a7a3a27..c2fbbecd7cb40606cc023d6732cd5dd401cb8dc4 100644 (file)
@@ -140,7 +140,7 @@ struct GSF_LocalClient
   /**
    * Context for sending replies.
    */
-  struct GNUNET_CONNECTION_TransmitHandle *th;
+  struct GNUNET_SERVER_TransmitHandle *th;
 
 };
 
@@ -498,7 +498,7 @@ GSF_client_disconnect_handler_ (void *cls, struct GNUNET_SERVER_Client *client)
   }
   if (pos->th != NULL)
   {
-    GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
+    GNUNET_SERVER_notify_transmit_ready_cancel (pos->th);
     pos->th = NULL;
   }
   GSF_handle_local_client_disconnect_ (pos);
index 5c9ead95e868b612666d24fab98c8528d91e4a3b..0806ccaa3784510b1b20a6d688ed0842282a5f5c 100644 (file)
@@ -230,10 +230,9 @@ GNUNET_CONNECTION_get_address (struct GNUNET_CONNECTION_Handle *connection,
 
 
 /**
- * Close the connection and free associated resources.  A pending
- * request for transmission is automatically cancelled (we might
- * want to change this in the future).  We require that there
- * are no active pending requests for reading from the connection.
+ * Close the connection and free associated resources.  There must
+ * not be any pending requests for reading or writing to the
+ * connection at this time.
  *
  * @param connection connection to destroy
  */
index 6fe9e79a795d7bc954aad77d50716a5800588f5c..2f939f18c884f4c2d0f9be6c83b9a3d1ec2f15be 100644 (file)
@@ -55,12 +55,16 @@ extern "C"
  */
 struct GNUNET_SERVER_Handle;
 
-
 /**
  * @brief opaque handle for a client of the server
  */
 struct GNUNET_SERVER_Client;
 
+/**
+ * @brief opaque handle server returns for aborting transmission to a client.
+ */
+struct GNUNET_SERVER_TransmitHandle;
+
 
 /**
  * Functions with this signature are called whenever a message is
@@ -190,10 +194,10 @@ GNUNET_SERVER_add_handlers (struct GNUNET_SERVER_Handle *server,
  * @param callback_cls closure for callback
  * @return non-NULL if the notify callback was queued; can be used
  *           to cancel the request using
- *           GNUNET_CONNECTION_notify_transmit_ready_cancel.
+ *           GNUNET_SERVER_notify_transmit_ready_cancel.
  *         NULL if we are already going to notify someone else (busy)
  */
-struct GNUNET_CONNECTION_TransmitHandle *
+struct GNUNET_SERVER_TransmitHandle *
 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
                                      size_t size,
                                      struct GNUNET_TIME_Relative timeout,
@@ -201,6 +205,15 @@ GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
                                      callback, void *callback_cls);
 
 
+/**
+ * Abort transmission request.
+ *
+ * @param th request to abort
+ */
+void
+GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th);
+
+
 /**
  * Set the persistent flag on this client, used to setup client connection
  * to only be killed when the service it's connected to is actually dead.
index ee94970e5cc16273f026dec9bc97d96d5c1ad7bb..ea8b6ee08f64a44fbd08e2f73cd84d81e7ad19b4 100644 (file)
@@ -267,7 +267,7 @@ struct Session
   /**
    * Handle for pending transmission request.
    */
-  struct GNUNET_CONNECTION_TransmitHandle *transmit_handle;
+  struct GNUNET_SERVER_TransmitHandle *transmit_handle;
 
   /**
    * To whom are we talking to (set to our identity
@@ -919,7 +919,7 @@ disconnect_session (struct Session *session)
   /* clean up state */
   if (session->transmit_handle != NULL)
   {
-    GNUNET_CONNECTION_notify_transmit_ready_cancel (session->transmit_handle);
+    GNUNET_SERVER_notify_transmit_ready_cancel (session->transmit_handle);
     session->transmit_handle = NULL;
   }
   session->plugin->env->session_end (session->plugin->env->cls,
index 8d0042b7bdc34fa14bc99f62d4220beab0cda51e..4473b7bb581f7647a217968583f62de01ed793c6 100644 (file)
@@ -62,12 +62,8 @@ enum ConnectContinuations
     /**
      * Call "transmit_ready".
      */
-  COCO_TRANSMIT_READY = 2,
+  COCO_TRANSMIT_READY = 2
 
-    /**
-     * Call "destroy_continuation".
-     */
-  COCO_DESTROY_CONTINUATION = 4
 };
 
 
@@ -242,11 +238,6 @@ struct GNUNET_CONNECTION_Handle
    */
   GNUNET_SCHEDULER_TaskIdentifier write_task;
 
-  /**
-   * Destroy task (if already scheduled).
-   */
-  GNUNET_SCHEDULER_TaskIdentifier destroy_task;
-
   /**
    * Handle to a pending DNS lookup request.
    */
@@ -514,96 +505,6 @@ static void
 receive_again (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
 
 
-/**
- * Scheduler let us know that the connect task is finished (or was
- * cancelled due to shutdown).  Now really clean up.
- *
- * @param cls our "struct GNUNET_CONNECTION_Handle *"
- * @param tc unused
- */
-static void
-destroy_continuation (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
-{
-  struct GNUNET_CONNECTION_Handle *connection = cls;
-  GNUNET_CONNECTION_TransmitReadyNotify notify;
-  struct AddressProbe *pos;
-
-  connection->destroy_task = GNUNET_SCHEDULER_NO_TASK;
-  GNUNET_assert (connection->dns_active == NULL);
-  if (0 != (connection->ccs & COCO_TRANSMIT_READY))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy waits for CCS-TR to be done (%p)\n",
-         connection);
-    connection->ccs |= COCO_DESTROY_CONTINUATION;
-    return;
-  }
-  if (connection->write_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "Destroy waits for write_task to be done (%p)\n", connection);
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task);
-    connection->destroy_task =
-        GNUNET_SCHEDULER_add_after (connection->write_task, &destroy_continuation,
-                                    connection);
-    return;
-  }
-  if (0 != (connection->ccs & COCO_RECEIVE_AGAIN))
-  {
-    connection->ccs |= COCO_DESTROY_CONTINUATION;
-    return;
-  }
-  if (connection->sock != NULL)
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG, "Shutting down connection (%p)\n", connection);
-    if (connection->persist != GNUNET_YES)
-    {
-      if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR))
-          && (errno != ENOTCONN) && (errno != ECONNRESET))
-        LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown");
-    }
-  }
-  if (connection->read_task != GNUNET_SCHEDULER_NO_TASK)
-  {
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task);
-    connection->destroy_task =
-        GNUNET_SCHEDULER_add_after (connection->read_task, &destroy_continuation,
-                                    connection);
-    return;
-  }
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Destroy actually runs (%p)!\n", connection);
-  while (NULL != (pos = connection->ap_head))
-  {
-    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
-    GNUNET_SCHEDULER_cancel (pos->task);
-    GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos);
-    GNUNET_free (pos);
-  }
-  GNUNET_assert (connection->nth.timeout_task == GNUNET_SCHEDULER_NO_TASK);
-  GNUNET_assert (connection->ccs == COCO_NONE);
-  if (NULL != (notify = connection->nth.notify_ready))
-  {
-    connection->nth.notify_ready = NULL;
-    notify (connection->nth.notify_ready_cls, 0, NULL);
-  }
-
-  if (connection->sock != NULL)
-  {
-    if (connection->persist != GNUNET_YES)
-      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
-    else
-      GNUNET_free (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_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task);
-  LOG (GNUNET_ERROR_TYPE_DEBUG, "Freeing memory of connection %p.\n", connection);
-  GNUNET_free (connection->write_buffer);
-  GNUNET_free (connection);
-}
-
-
-
 /**
  * See if we are now connected.  If not, wait longer for
  * connect to succeed.  If connected, we should be able
@@ -654,14 +555,6 @@ connect_fail_continuation (struct GNUNET_CONNECTION_Handle *h)
     GNUNET_assert (h->write_task == GNUNET_SCHEDULER_NO_TASK);
     h->write_task = GNUNET_SCHEDULER_add_now (&transmit_ready, h);
   }
-  if (0 != (h->ccs & COCO_DESTROY_CONTINUATION))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "connect_fail_continuation runs destroy_continuation (%p)\n", h);
-    h->ccs -= COCO_DESTROY_CONTINUATION;
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == h->destroy_task);
-    h->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, h);
-  }
 }
 
 
@@ -699,14 +592,6 @@ connect_success_continuation (struct GNUNET_CONNECTION_Handle *connection)
                                         (connection->nth.transmit_timeout), connection->sock,
                                         &transmit_ready, connection);
   }
-  if (0 != (connection->ccs & COCO_DESTROY_CONTINUATION))
-  {
-    LOG (GNUNET_ERROR_TYPE_DEBUG,
-         "connect_success_continuation runs destroy_continuation (%p)\n", connection);
-    connection->ccs -= COCO_DESTROY_CONTINUATION;
-    GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task);
-    connection->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, connection);
-  }
 }
 
 
@@ -1012,16 +897,19 @@ GNUNET_CONNECTION_check (struct GNUNET_CONNECTION_Handle *sock)
 
 
 /**
- * Close the connection and free associated resources.  A pending
- * request for transmission is automatically cancelled (we might
- * want to change this in the future).  We require that there
- * are no active pending requests for reading from the connection.
+ * Close the connection and free associated resources.  There must
+ * not be any pending requests for reading or writing to the
+ * connection at this time.
  *
  * @param connection connection to destroy
  */
 void
 GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
 {
+  struct AddressProbe *pos;
+
+  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 (GNUNET_SCHEDULER_NO_TASK == connection->read_task);
   if (connection->write_task != GNUNET_SCHEDULER_NO_TASK)
@@ -1030,14 +918,49 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
     connection->write_task = GNUNET_SCHEDULER_NO_TASK;
     connection->write_buffer_off = 0;
   }
+  if (connection->read_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (connection->read_task);
+    connection->read_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+  if (connection->nth.timeout_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (connection->nth.timeout_task);
+    connection->nth.timeout_task = GNUNET_SCHEDULER_NO_TASK;
+  }
   connection->nth.notify_ready = NULL;
-  if (connection->dns_active != NULL)
+  if (NULL != connection->dns_active)
   {
     GNUNET_RESOLVER_request_cancel (connection->dns_active);
     connection->dns_active = NULL;
   }
-  GNUNET_assert (GNUNET_SCHEDULER_NO_TASK == connection->destroy_task);
-  connection->destroy_task = GNUNET_SCHEDULER_add_now (&destroy_continuation, connection);
+  while (NULL != (pos = connection->ap_head))
+  {
+    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (pos->sock));
+    GNUNET_SCHEDULER_cancel (pos->task);
+    GNUNET_CONTAINER_DLL_remove (connection->ap_head, connection->ap_tail, pos);
+    GNUNET_free (pos);
+  }
+  if ( (NULL != connection->sock) &&
+       (connection->persist != GNUNET_YES) )
+  {
+    if ((GNUNET_YES != GNUNET_NETWORK_socket_shutdown (connection->sock, SHUT_RDWR)) && 
+       (errno != ENOTCONN) && 
+       (errno != ECONNRESET) )
+      LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "shutdown");    
+  }
+  if (connection->sock != NULL)
+  {
+    if (connection->persist != GNUNET_YES)
+      GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (connection->sock));
+    else
+      GNUNET_free (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 (connection->write_buffer);
+  GNUNET_free (connection);
 }
 
 
@@ -1045,15 +968,15 @@ GNUNET_CONNECTION_destroy (struct GNUNET_CONNECTION_Handle *connection)
  * Tell the receiver callback that a timeout was reached.
  */
 static void
-signal_timeout (struct GNUNET_CONNECTION_Handle *sh)
+signal_timeout (struct GNUNET_CONNECTION_Handle *connection)
 {
   GNUNET_CONNECTION_Receiver receiver;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG, "Network signals time out to receiver (%p)!\n",
-       sh);
-  GNUNET_assert (NULL != (receiver = sh->receiver));
-  sh->receiver = NULL;
-  receiver (sh->receiver_cls, NULL, 0, NULL, 0, 0);
+       connection);
+  GNUNET_assert (NULL != (receiver = connection->receiver));
+  connection->receiver = NULL;
+  receiver (connection->receiver_cls, NULL, 0, NULL, 0, 0);
 }
 
 
@@ -1061,13 +984,13 @@ signal_timeout (struct GNUNET_CONNECTION_Handle *sh)
  * Tell the receiver callback that we had an IO error.
  */
 static void
-signal_error (struct GNUNET_CONNECTION_Handle *sh, int errcode)
+signal_error (struct GNUNET_CONNECTION_Handle *connection, int errcode)
 {
   GNUNET_CONNECTION_Receiver receiver;
 
-  GNUNET_assert (NULL != (receiver = sh->receiver));
-  sh->receiver = NULL;
-  receiver (sh->receiver_cls, NULL, 0, sh->addr, sh->addrlen, errcode);
+  GNUNET_assert (NULL != (receiver = connection->receiver));
+  connection->receiver = NULL;
+  receiver (connection->receiver_cls, NULL, 0, connection->addr, connection->addrlen, errcode);
 }
 
 
index a3f63490a7f70d07ed866f9f9185c01c9ac871f0..ede31b558a68d424dd9eb7f4f59b6190d28079b2 100644 (file)
@@ -139,13 +139,51 @@ struct GNUNET_SERVER_Handle
    */
   int clients_ignore_shutdown;
 
+  /**
+   * Alternative function to create a MST instance.
+   */
   GNUNET_SERVER_MstCreateCallback mst_create;
+
+  /**
+   * Alternative function to destroy a MST instance.
+   */
   GNUNET_SERVER_MstDestroyCallback mst_destroy;
+
+  /**
+   * Alternative function to give data to a MST instance.
+   */
   GNUNET_SERVER_MstReceiveCallback mst_receive;
+
+  /**
+   * Closure for 'mst_'-callbacks.
+   */
   void *mst_cls;
 };
 
 
+/**
+ * Handle server returns for aborting transmission to a client.
+ */
+struct GNUNET_SERVER_TransmitHandle
+{
+  /**
+   * Function to call to get the message.
+   */
+  GNUNET_CONNECTION_TransmitReadyNotify callback;
+
+  /**
+   * Closure for 'callback'
+   */
+  void *callback_cls;
+
+  /**
+   * Active connection transmission handle.
+   */
+  struct GNUNET_CONNECTION_TransmitHandle *cth;
+
+};
+
+
 /**
  * @brief handle for a client of the server
  */
@@ -194,14 +232,10 @@ struct GNUNET_SERVER_Client
   struct GNUNET_TIME_Absolute last_activity;
 
   /**
-   *
+   * Transmission handle we return for this client from
+   * GNUNET_SERVER_notify_transmit_ready.
    */
-  GNUNET_CONNECTION_TransmitReadyNotify callback;
-
-  /**
-   * callback
-   */
-  void *callback_cls;
+  struct GNUNET_SERVER_TransmitHandle th;
 
   /**
    * After how long should an idle connection time
@@ -966,9 +1000,7 @@ GNUNET_SERVER_connect_socket (struct GNUNET_SERVER_Handle *server,
   client->next = server->clients;
   client->idle_timeout = server->idle_timeout;
   server->clients = client;
-  client->callback = NULL;
-  client->callback_cls = NULL;
-  if (server->mst_create != NULL)
+  if (NULL != server->mst_create)
     client->mst =
         server->mst_create (server->mst_cls, client);
   else
@@ -1231,9 +1263,13 @@ static size_t
 transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
 {
   struct GNUNET_SERVER_Client *client = cls;
+  GNUNET_CONNECTION_TransmitReadyNotify callback;
   size_t ret;
 
-  ret = client->callback (client->callback_cls, size, buf);
+  client->th.cth = NULL;
+  callback = client->th.callback;
+  client->th.callback = NULL;
+  ret = callback (client->th.callback_cls, size, buf);
   if (ret > 0)
     client->last_activity = GNUNET_TIME_absolute_get ();
   return ret;
@@ -1252,22 +1288,39 @@ transmit_ready_callback_wrapper (void *cls, size_t size, void *buf)
  * @param callback_cls closure for callback
  * @return non-NULL if the notify callback was queued; can be used
  *           to cancel the request using
- *           GNUNET_CONNECTION_notify_transmit_ready_cancel.
+ *           GNUNET_SERVER_notify_transmit_ready_cancel.
  *         NULL if we are already going to notify someone else (busy)
  */
-struct GNUNET_CONNECTION_TransmitHandle *
+struct GNUNET_SERVER_TransmitHandle *
 GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
                                      size_t size,
                                      struct GNUNET_TIME_Relative timeout,
                                      GNUNET_CONNECTION_TransmitReadyNotify
                                      callback, void *callback_cls)
 {
-  client->callback_cls = callback_cls;
-  client->callback = callback;
-  return GNUNET_CONNECTION_notify_transmit_ready (client->connection, size,
-                                                  timeout,
-                                                  &transmit_ready_callback_wrapper,
-                                                  client);
+  if (NULL != client->th.callback)
+    return NULL;
+  client->th.callback_cls = callback_cls;
+  client->th.callback = callback;
+  client->th.cth = GNUNET_CONNECTION_notify_transmit_ready (client->connection, size,
+                                                           timeout,
+                                                           &transmit_ready_callback_wrapper,
+                                                           client);
+  return &client->th;
+}
+
+
+/**
+ * Abort transmission request.
+ *
+ * @param th request to abort
+ */
+void
+GNUNET_SERVER_notify_transmit_ready_cancel (struct GNUNET_SERVER_TransmitHandle *th)
+{
+  GNUNET_CONNECTION_notify_transmit_ready_cancel (th->cth);
+  th->cth = NULL;
+  th->callback = NULL;
 }
 
 
index 08ffd4b0c6be4e5d542ce0f2c7a2c690dcf2c407..9717a45167480037c57b24f0ffed1f450e893013 100644 (file)
@@ -92,7 +92,7 @@ struct ClientList
   /**
    * Handle for pending transmission request to the client (or NULL).
    */
-  struct GNUNET_CONNECTION_TransmitHandle *th;
+  struct GNUNET_SERVER_TransmitHandle *th;
 
   /**
    * Head of linked list of requests queued for transmission.
@@ -187,7 +187,7 @@ handle_client_disconnect (void *cls, struct GNUNET_SERVER_Client *client)
   }
   if (pos->th != NULL)
   {
-    GNUNET_CONNECTION_notify_transmit_ready_cancel (pos->th);
+    GNUNET_SERVER_notify_transmit_ready_cancel (pos->th);
     pos->th = NULL;
   }
   GNUNET_SERVER_client_drop (client);
index 8664ca16f11a2760d8c0cb4586e1a50dcf20382e..4568f8ecbf5e8529bece2368bd6b86bbd303d2dc 100644 (file)
@@ -103,6 +103,7 @@ receive_check (void *cls, const void *buf, size_t available,
 #endif
     *ok = 0;
     GNUNET_CONNECTION_destroy (asock);
+    GNUNET_CONNECTION_destroy (csock);
   }
 }
 
@@ -142,7 +143,6 @@ make_hello (void *cls, size_t size, void *buf)
 #if VERBOSE
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Test destroys client socket\n");
 #endif
-  GNUNET_CONNECTION_destroy (csock);
   return 12;
 }
 
index 716e90d78f0148c92abdff4c41c18139cafae694..83fbdec95ce5fb89fbeec384844664d3eeda7deb 100644 (file)
@@ -41,18 +41,18 @@ static struct GNUNET_SERVICE_Context *sctx;
 
 static int ok = 1;
 
+static struct GNUNET_CLIENT_Connection *client;
+
 
 static size_t
 build_msg (void *cls, size_t size, void *buf)
 {
-  struct GNUNET_CLIENT_Connection *client = cls;
   struct GNUNET_MessageHeader *msg = buf;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Client connected, transmitting\n");
   GNUNET_assert (size >= sizeof (struct GNUNET_MessageHeader));
   msg->type = htons (MY_TYPE);
   msg->size = htons (sizeof (struct GNUNET_MessageHeader));
-  GNUNET_CLIENT_disconnect (client);
   return sizeof (struct GNUNET_MessageHeader);
 }
 
@@ -72,23 +72,24 @@ ready (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   GNUNET_CLIENT_notify_transmit_ready (client,
                                        sizeof (struct GNUNET_MessageHeader),
                                        GNUNET_TIME_UNIT_SECONDS, GNUNET_NO,
-                                       &build_msg, client);
+                                       &build_msg, NULL);
 }
 
 
 static void
 do_stop (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
+  GNUNET_CLIENT_disconnect (client);
   GNUNET_SERVICE_stop (sctx);
 }
 
 
 static void
-recv_cb (void *cls, struct GNUNET_SERVER_Client *client,
+recv_cb (void *cls, struct GNUNET_SERVER_Client *sc,
          const struct GNUNET_MessageHeader *message)
 {
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving client message...\n");
-  GNUNET_SERVER_receive_done (client, GNUNET_OK);
+  GNUNET_SERVER_receive_done (sc, GNUNET_OK);
   if (sctx != NULL)
     GNUNET_SCHEDULER_add_now (&do_stop, NULL);
   else
@@ -146,7 +147,6 @@ static void
 ready6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   const struct GNUNET_CONFIGURATION_Handle *cfg = cls;
-  struct GNUNET_CLIENT_Connection *client;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "V6 ready\n");
   GNUNET_assert (0 != (tc->reason & GNUNET_SCHEDULER_REASON_PREREQ_DONE));
@@ -156,7 +156,7 @@ ready6 (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
   GNUNET_CLIENT_notify_transmit_ready (client,
                                        sizeof (struct GNUNET_MessageHeader),
                                        GNUNET_TIME_UNIT_SECONDS, GNUNET_NO,
-                                       &build_msg, client);
+                                       &build_msg, NULL);
 }
 
 static void