+/**
+ * Disconnect from service and then reconnect.
+ *
+ * @param nsh our handle
+ */
+static void
+force_reconnect (struct GNUNET_NAMESTORE_Handle *nsh);
+
+/**
+ * Transmit messages from the message queue to the service
+ * (if there are any, and if we are not already trying).
+ *
+ * @param nsh handle to use
+ */
+static void
+do_transmit (struct GNUNET_NAMESTORE_Handle *nsh);
+
+/**
+ * We can now transmit a message to NAMESTORE. Do it.
+ *
+ * @param cls the 'struct GNUNET_NAMESTORE_Handle'
+ * @param size number of bytes we can transmit
+ * @param buf where to copy the messages
+ * @return number of bytes copied into buf
+ */
+static size_t
+transmit_message_to_namestore (void *cls, size_t size, void *buf)
+{
+ struct GNUNET_NAMESTORE_Handle *nsh = cls;
+ struct PendingMessage *p;
+ size_t ret;
+ char *cbuf;
+
+ nsh->th = NULL;
+ if ((size == 0) || (buf == NULL))
+ {
+ force_reconnect (nsh);
+ return 0;
+ }
+ ret = 0;
+ cbuf = buf;
+ while ((NULL != (p = nsh->pending_head)) && (p->size <= size))
+ {
+ memcpy (&cbuf[ret], &p[1], p->size);
+ ret += p->size;
+ size -= p->size;
+ GNUNET_CONTAINER_DLL_remove (nsh->pending_head, nsh->pending_tail, p);
+ if (GNUNET_YES == p->is_init)
+ GNUNET_CLIENT_receive (nsh->client,/* &process_namestore_message*/ NULL, nsh,
+ GNUNET_TIME_UNIT_FOREVER_REL);
+ GNUNET_free (p);
+ }
+ do_transmit (nsh);
+ return ret;
+}
+
+
+/**
+ * Transmit messages from the message queue to the service
+ * (if there are any, and if we are not already trying).
+ *
+ * @param nsh handle to use
+ */
+static void
+do_transmit (struct GNUNET_NAMESTORE_Handle *nsh)
+{
+ struct PendingMessage *p;
+
+ if (NULL != nsh->th)
+ return;
+ if (NULL == (p = nsh->pending_head))
+ return;
+ if (NULL == nsh->client)
+ return; /* currently reconnecting */
+ nsh->th = GNUNET_CLIENT_notify_transmit_ready (nsh->client, p->size,
+ GNUNET_TIME_UNIT_FOREVER_REL,
+ GNUNET_NO, &transmit_message_to_namestore,
+ nsh);
+}
+
+
+/**
+ * Try again to connect to namestore service.
+ *
+ * @param cls the handle to the namestore service
+ * @param tc scheduler context
+ */
+static void
+reconnect (struct GNUNET_NAMESTORE_Handle *nsh)
+{
+ struct PendingMessage *p;
+ struct StartMessage *init;
+
+ GNUNET_assert (NULL == nsh->client);
+ nsh->client = GNUNET_CLIENT_connect ("namestore", nsh->cfg);
+ GNUNET_assert (NULL != nsh->client);
+
+ if ((NULL == (p = nsh->pending_head)) || (GNUNET_YES != p->is_init))
+ {
+ p = GNUNET_malloc (sizeof (struct PendingMessage) +
+ sizeof (struct StartMessage));
+ p->size = sizeof (struct StartMessage);
+ p->is_init = GNUNET_YES;
+ init = (struct StartMessage *) &p[1];
+ init->header.type = htons (GNUNET_MESSAGE_TYPE_NAMESTORE_START);
+ init->header.size = htons (sizeof (struct StartMessage));
+ GNUNET_CONTAINER_DLL_insert (nsh->pending_head, nsh->pending_tail, p);
+ }
+ do_transmit (nsh);
+}
+
+/**
+ * Re-establish the connection to the service.
+ *
+ * @param cls handle to use to re-connect.
+ * @param tc scheduler context
+ */
+static void
+reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ struct GNUNET_NAMESTORE_Handle *nsh = cls;
+
+ nsh->reconnect_task = GNUNET_SCHEDULER_NO_TASK;
+ reconnect (nsh);
+}
+
+
+/**
+ * Disconnect from service and then reconnect.
+ *
+ * @param nsh our handle
+ */
+static void
+force_reconnect (struct GNUNET_NAMESTORE_Handle *nsh)
+{
+ nsh->reconnect = GNUNET_NO;
+ GNUNET_CLIENT_disconnect (nsh->client, GNUNET_NO);
+ nsh->client = NULL;
+ nsh->reconnect_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_SECONDS, &reconnect_task,
+ nsh);
+}
+
+
+