asserts
[oweals/gnunet.git] / src / util / server.c
index 5fda7ae818567cd83e55500e3526259e9ca98668..131c7c5c1fdc01daead809e0b12426b7ac2061b6 100644 (file)
@@ -269,6 +269,13 @@ struct GNUNET_SERVER_Client
    * Are we currently trying to receive?
    */
   int receive_pending;
+
+  /**
+   * Persist the file handle for this client no matter what happens,
+   * force the OS to close once the process actually dies.  Should only
+   * be used in special cases!
+   */
+  int persist;
 };
 
 
@@ -379,11 +386,20 @@ open_listen_socket (const struct sockaddr *serverAddr, socklen_t socklen)
       errno = 0;
       return NULL;
     }
-  if ((port != 0) &&
-      (GNUNET_NETWORK_socket_setsockopt
-       (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK))
-    GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
-                         "setsockopt");
+  if (port != 0) 
+    {
+      if (GNUNET_NETWORK_socket_setsockopt
+         (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) != GNUNET_OK)
+       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                            "setsockopt");
+#ifdef IPV6_V6ONLY
+      if ( (serverAddr->sa_family == AF_INET6) &&
+          (GNUNET_NETWORK_socket_setsockopt
+           (sock, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)) != GNUNET_OK) )
+       GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
+                            "setsockopt");
+#endif
+    }
   /* bind the socket */
   if (GNUNET_NETWORK_socket_bind (sock, serverAddr, socklen) != GNUNET_OK)
     {
@@ -473,7 +489,7 @@ GNUNET_SERVER_create (struct GNUNET_SCHEDULER_Handle *sched,
       if (j == 0)
         {
           if (errno != 0)
-            GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");
+           GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "bind");          
           GNUNET_free (lsocks);
           lsocks = NULL;
         }
@@ -933,11 +949,16 @@ sock_check (void *cls)
  * Destroy this socket (free resources).
  *
  * @param cls the socket
+ * @param persist set the socket to be persisted
  */
 static void
-sock_destroy (void *cls)
+sock_destroy (void *cls, int persist)
 {
-  GNUNET_CONNECTION_destroy (cls, GNUNET_NO);
+  struct GNUNET_CONNECTION_Handle *sock = cls;
+  if (persist == GNUNET_YES)
+    GNUNET_CONNECTION_persist_ (sock);
+
+  GNUNET_CONNECTION_destroy (sock, GNUNET_NO);
 }
 
 
@@ -1168,6 +1189,7 @@ GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
       client->receive_cancel (client->client_closure);
       client->receive_pending = GNUNET_NO;
     }
+
   rc = client->reference_count;  
   if (client->server != NULL)
     {
@@ -1198,9 +1220,9 @@ GNUNET_SERVER_client_disconnect (struct GNUNET_SERVER_Client *client)
     }
   if (rc > 0)
     return;
-  if (client->in_process_client_buffer)
+  if (client->in_process_client_buffer == GNUNET_YES)
     return;
-  client->destroy (client->client_closure);
+  client->destroy (client->client_closure, client->persist);
   GNUNET_free (client);  
 }
 
@@ -1232,6 +1254,17 @@ GNUNET_SERVER_notify_transmit_ready (struct GNUNET_SERVER_Client *client,
                                         timeout, callback, callback_cls);
 }
 
+/**
+ * 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.
+ *
+ * @param client the client to set the persistent flag on
+ */
+void
+GNUNET_SERVER_client_persist_ (struct GNUNET_SERVER_Client *client)
+{
+  client->persist = GNUNET_YES;
+}
 
 /**
  * Resume receiving from this client, we are done processing the
@@ -1274,6 +1307,11 @@ GNUNET_SERVER_receive_done (struct GNUNET_SERVER_Client *client, int success)
       GNUNET_free (sb);
       return;
     }
+  if (client->server == NULL)
+    {
+      GNUNET_SERVER_client_disconnect (client);
+      return;
+    }
   client->restart_task = GNUNET_SCHEDULER_add_now (client->server->sched,
                                                   &restart_processing,
                                                   client);