+ switch (rh->af)
+ {
+ case AF_INET:
+ rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
+ break;
+ case AF_INET6:
+ rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
+ break;
+ case AF_UNSPEC:
+ rh->addr_callback (rh->cls, (const struct sockaddr *) &v6, sizeof (v6));
+ rh->addr_callback (rh->cls, (const struct sockaddr *) &v4, sizeof (v4));
+ break;
+ default:
+ GNUNET_break (0);
+ break;
+ }
+ rh->addr_callback (rh->cls, NULL, 0);
+ GNUNET_free (rh);
+}
+
+
+/**
+ * Task executed on system shutdown.
+ */
+static void
+shutdown_task (void *cls,
+ const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ s_task = GNUNET_SCHEDULER_NO_TASK;
+ GNUNET_RESOLVER_disconnect ();
+ backoff = GNUNET_TIME_UNIT_MILLISECONDS;
+}
+
+
+/**
+ * Process pending requests to the resolver.
+ */
+static void
+process_requests ()
+{
+ struct GNUNET_RESOLVER_GetMessage *msg;
+ char buf[GNUNET_SERVER_MAX_MESSAGE_SIZE - 1] GNUNET_ALIGN;
+ struct GNUNET_RESOLVER_RequestHandle *rh;
+
+ if (NULL == client)
+ {
+ reconnect ();
+ return;
+ }
+ rh = req_head;
+ if (NULL == rh)
+ {
+ /* nothing to do, release socket really soon if there is nothing
+ * else happening... */
+ s_task =
+ GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_MILLISECONDS,
+ &shutdown_task, NULL);
+ return;
+ }
+ if (GNUNET_YES == rh->was_transmitted)
+ return; /* waiting for reply */
+ msg = (struct GNUNET_RESOLVER_GetMessage *) buf;
+ msg->header.size =
+ htons (sizeof (struct GNUNET_RESOLVER_GetMessage) + rh->data_len);
+ msg->header.type = htons (GNUNET_MESSAGE_TYPE_RESOLVER_REQUEST);
+ msg->direction = htonl (rh->direction);
+ msg->af = htonl (rh->af);
+ memcpy (&msg[1], &rh[1], rh->data_len);
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Transmitting DNS resolution request to DNS service\n");
+ if (GNUNET_OK !=
+ GNUNET_CLIENT_transmit_and_get_response (client, &msg->header,
+ GNUNET_TIME_absolute_get_remaining
+ (rh->timeout), GNUNET_YES,
+ &handle_response, rh))
+ {
+ GNUNET_CLIENT_disconnect (client);
+ client = NULL;
+ GNUNET_break (0);
+ reconnect ();
+ return;
+ }
+ rh->was_transmitted = GNUNET_YES;
+}
+
+
+/**
+ * Now try to reconnect to the resolver service.
+ *
+ * @param cls NULL
+ * @param tc scheduler context
+ */
+static void
+reconnect_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+ r_task = GNUNET_SCHEDULER_NO_TASK;
+ if (NULL == req_head)
+ return; /* no work pending */
+ if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+ return;
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to connect to DNS service\n");
+ client = GNUNET_CLIENT_connect ("resolver", resolver_cfg);
+ if (NULL == client)
+ {
+ LOG (GNUNET_ERROR_TYPE_DEBUG,
+ "Failed to connect, will try again later\n");
+ reconnect ();
+ return;
+ }
+ process_requests ();
+}
+
+
+/**
+ * Adjust exponential back-off and reconnect to the service.
+ */
+static void
+reconnect ()
+{
+ struct GNUNET_RESOLVER_RequestHandle *rh;
+
+ if (GNUNET_SCHEDULER_NO_TASK != r_task)
+ return;
+ GNUNET_assert (NULL == client);
+ if (NULL != (rh = req_head))
+ {
+ switch (rh->was_transmitted)