tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / util / service.c
index ee140f88e6fa2e9c097c303addda53122854ff13..4fd16f93d8386b1624f80e763167c8b1c642ee9b 100644 (file)
@@ -213,12 +213,6 @@ struct GNUNET_SERVICE_Handle
    */
   int match_gid;
 
-  /**
-   * Set to #GNUNET_YES if we got a shutdown signal and terminate
-   * the service if #have_non_monitor_clients() returns #GNUNET_YES.
-   */
-  int got_shutdown;
-
   /**
    * Are we suspended, and if so, why?
    */
@@ -378,6 +372,32 @@ have_non_monitor_clients (struct GNUNET_SERVICE_Handle *sh)
 }
 
 
+/**
+ * Suspend accepting connections from the listen socket temporarily.
+ * Resume activity using #do_resume.
+ *
+ * @param sh service to stop accepting connections.
+ * @param sr reason for suspending accepting connections
+ */
+static void
+do_suspend (struct GNUNET_SERVICE_Handle *sh,
+            enum SuspendReason sr)
+{
+  struct ServiceListenContext *slc;
+
+  GNUNET_assert (0 == (sh->suspend_state & sr));
+  sh->suspend_state |= sr;
+  for (slc = sh->slc_head; NULL != slc; slc = slc->next)
+  {
+    if (NULL != slc->listen_task)
+    {
+      GNUNET_SCHEDULER_cancel (slc->listen_task);
+      slc->listen_task = NULL;
+    }
+  }
+}
+
+
 /**
  * Shutdown task triggered when a service should be terminated.
  * This considers active clients and the service options to see
@@ -402,8 +422,9 @@ service_shutdown (void *cls)
     GNUNET_assert (0);
     break;
   case GNUNET_SERVICE_OPTION_SOFT_SHUTDOWN:
-    sh->got_shutdown = GNUNET_YES;
-    GNUNET_SERVICE_suspend (sh);
+    if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
+      do_suspend (sh,
+                  SUSPEND_STATE_SHUTDOWN);
     if (GNUNET_NO == have_non_monitor_clients (sh))
       GNUNET_SERVICE_shutdown (sh);
     break;
@@ -452,18 +473,12 @@ check_ipv6_listed (const struct GNUNET_STRINGS_IPv6NetworkPolicy *list,
 {
   unsigned int i;
   unsigned int j;
-  struct in6_addr zero;
 
   if (NULL == list)
     return GNUNET_NO;
-  memset (&zero,
-         0,
-         sizeof (struct in6_addr));
   i = 0;
 NEXT:
-  while (0 != memcmp (&zero,
-                     &list[i].network,
-                     sizeof (struct in6_addr)))
+  while (0 != GNUNET_is_zero (&list[i].network))
   {
     for (j = 0; j < sizeof (struct in6_addr) / sizeof (int); j++)
       if (((((int *) ip)[j] & ((int *) &list[i].netmask)[j])) !=
@@ -478,32 +493,6 @@ NEXT:
 }
 
 
-/**
- * Suspend accepting connections from the listen socket temporarily.
- * Resume activity using #do_resume.
- *
- * @param sh service to stop accepting connections.
- * @param sr reason for suspending accepting connections
- */
-static void
-do_suspend (struct GNUNET_SERVICE_Handle *sh,
-            enum SuspendReason sr)
-{
-  struct ServiceListenContext *slc;
-
-  GNUNET_assert (0 == (sh->suspend_state & sr));
-  sh->suspend_state |= sr;
-  for (slc = sh->slc_head; NULL != slc; slc = slc->next)
-  {
-    if (NULL != slc->listen_task)
-    {
-      GNUNET_SCHEDULER_cancel (slc->listen_task);
-      slc->listen_task = NULL;
-    }
-  }
-}
-
-
 /**
  * Task run when we are ready to transmit data to the
  * client.
@@ -519,7 +508,7 @@ do_send (void *cls)
   const char *buf;
 
   LOG (GNUNET_ERROR_TYPE_DEBUG,
-       "service: sending message with type %u",
+       "service: sending message with type %u\n",
        ntohs(client->msg->type));
 
 
@@ -838,7 +827,7 @@ accept_client (void *cls)
       if (EMFILE == errno)
         do_suspend (sh,
                     SUSPEND_STATE_EMFILE);
-      else
+      else if (EAGAIN != errno)
         GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
                              "accept");
       break;
@@ -893,6 +882,8 @@ accept_client (void *cls)
     start_client (slc->sh,
                  sock);
   }
+  if (0 != sh->suspend_state)
+    return;
   slc->listen_task
     = GNUNET_SCHEDULER_add_read_net (GNUNET_TIME_UNIT_FOREVER_REL,
                                     slc->listen_socket,
@@ -1135,50 +1126,14 @@ get_server_addresses (const char *service_name,
   *addrs = NULL;
   *addr_lens = NULL;
   desc = NULL;
-  if (GNUNET_CONFIGURATION_have_value (cfg,
-                                      service_name,
-                                      "DISABLEV6"))
-  {
-    if (GNUNET_SYSERR ==
-        (disablev6 =
-         GNUNET_CONFIGURATION_get_value_yesno (cfg,
-                                              service_name,
-                                              "DISABLEV6")))
-      return GNUNET_SYSERR;
-  }
-  else
-    disablev6 = GNUNET_NO;
-
-  if (! disablev6)
-  {
-    /* probe IPv6 support */
-    desc = GNUNET_NETWORK_socket_create (PF_INET6,
-                                        SOCK_STREAM,
-                                        0);
-    if (NULL == desc)
-    {
-      if ( (ENOBUFS == errno) ||
-          (ENOMEM == errno) ||
-          (ENFILE == errno) ||
-          (EACCES == errno) )
-      {
-        LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR,
-                     "socket");
-        return GNUNET_SYSERR;
-      }
-      LOG (GNUNET_ERROR_TYPE_INFO,
-           _("Disabling IPv6 support for service `%s', failed to create IPv6 socket: %s\n"),
-           service_name,
-          STRERROR (errno));
-      disablev6 = GNUNET_YES;
-    }
-    else
-    {
-      GNUNET_break (GNUNET_OK ==
-                   GNUNET_NETWORK_socket_close (desc));
-      desc = NULL;
-    }
-  }
+  disablev6 = GNUNET_NO;
+  if ( (GNUNET_NO ==
+       GNUNET_NETWORK_test_pf (PF_INET6)) ||
+       (GNUNET_YES ==
+       GNUNET_CONFIGURATION_get_value_yesno (cfg,
+                                             service_name,
+                                             "DISABLEV6") ) )
+    disablev6 = GNUNET_YES;
 
   port = 0;
   if (GNUNET_CONFIGURATION_have_value (cfg,
@@ -2633,7 +2588,8 @@ finish_client_drop (void *cls)
   {
     GNUNET_break (GNUNET_OK ==
                  GNUNET_NETWORK_socket_close (c->sock));
-    if (0 != (SUSPEND_STATE_EMFILE & sh->suspend_state))
+    if ( (0 != (SUSPEND_STATE_EMFILE & sh->suspend_state)) &&
+         (0 == (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) )
       do_resume (sh,
                  SUSPEND_STATE_EMFILE);
   }
@@ -2642,7 +2598,7 @@ finish_client_drop (void *cls)
     GNUNET_NETWORK_socket_free_memory_only_ (c->sock);
   }
   GNUNET_free (c);
-  if ( (GNUNET_YES == sh->got_shutdown) &&
+  if ( (0 != (SUSPEND_STATE_SHUTDOWN & sh->suspend_state)) &&
        (GNUNET_NO == have_non_monitor_clients (sh)) )
     GNUNET_SERVICE_shutdown (sh);
 }
@@ -2724,9 +2680,9 @@ GNUNET_SERVICE_shutdown (struct GNUNET_SERVICE_Handle *sh)
 {
   struct GNUNET_SERVICE_Client *client;
 
-  do_suspend (sh,
-              SUSPEND_STATE_SHUTDOWN);
-  sh->got_shutdown = GNUNET_NO;
+  if (0 == (sh->suspend_state & SUSPEND_STATE_SHUTDOWN))
+    do_suspend (sh,
+                SUSPEND_STATE_SHUTDOWN);
   while (NULL != (client = sh->clients_head))
     GNUNET_SERVICE_client_drop (client);
 }
@@ -2748,8 +2704,8 @@ void
 GNUNET_SERVICE_client_mark_monitor (struct GNUNET_SERVICE_Client *c)
 {
   c->is_monitor = GNUNET_YES;
-  if ( (GNUNET_YES == c->sh->got_shutdown) &&
-       (GNUNET_NO == have_non_monitor_clients (c->sh)) )
+  if ( (0 != (SUSPEND_STATE_SHUTDOWN & c->sh->suspend_state) &&
+        (GNUNET_NO == have_non_monitor_clients (c->sh)) ) )
     GNUNET_SERVICE_shutdown (c->sh);
 }