types
[oweals/gnunet.git] / src / hostlist / hostlist-server.c
index a2bbe2dec1375292e264810757cb2627583de637..03e3c5d69dd85df8cbb09ebf2de6a9896add1e04 100644 (file)
@@ -43,13 +43,18 @@ static struct MHD_Daemon *daemon_handle;
 /**
  * Our configuration.
  */
-static struct GNUNET_CONFIGURATION_Handle *cfg;
+static const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 /**
  * Our scheduler.
  */
 static struct GNUNET_SCHEDULER_Handle *sched;
 
+/**
+ * Our primary task.
+ */
+static GNUNET_SCHEDULER_TaskIdentifier hostlist_task;
+
 /**
  * Our canonical response.
  */
@@ -60,7 +65,7 @@ static struct MHD_Response *response;
  */
 struct HostSet
 {
-  size_t size;
+  unsigned int size;
 
   char *data;
 };
@@ -89,7 +94,7 @@ finish_response (struct HostSet *results)
   GNUNET_SCHEDULER_add_delayed (sched,
                                GNUNET_NO,
                                GNUNET_SCHEDULER_PRIORITY_IDLE,
-                               GNUNET_SCHEDULER_NO_PREREQUISITE_TASK,
+                               GNUNET_SCHEDULER_NO_TASK,
                                RESPONSE_UPDATE_FREQUENCY,
                                &update_response,
                                NULL);
@@ -111,7 +116,10 @@ host_processor (void *cls,
   size_t s;
   
   if (peer == NULL)
-    finish_response (results);
+    {
+      finish_response (results);
+      return;
+    }
   old = results->size;
   s = GNUNET_HELLO_size(hello);
   if (old + s >= GNUNET_MAX_MALLOC_CHECKED)
@@ -142,7 +150,9 @@ update_response (void *cls,
 }
 
 
-
+/**
+ * Hostlist access policy (very permissive, allows everything).
+ */
 static int
 accept_policy_callback (void *cls,
                         const struct sockaddr *addr, socklen_t addrlen)
@@ -151,6 +161,9 @@ accept_policy_callback (void *cls,
 }
 
 
+/**
+ * Main request handler.
+ */
 static int
 access_handler_callback (void *cls,
                          struct MHD_Connection *connection,
@@ -158,7 +171,7 @@ access_handler_callback (void *cls,
                          const char *method,
                          const char *version,
                          const char *upload_data,
-                         unsigned int *upload_data_size, void **con_cls)
+                         size_t*upload_data_size, void **con_cls)
 {
   static int dummy;
   
@@ -177,13 +190,90 @@ access_handler_callback (void *cls,
 }
 
 
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ */
+static void 
+prepare_daemon (void);
+
+
+/**
+ * Call MHD to process pending requests and then go back
+ * and schedule the next run.
+ */
+static void
+run_daemon (void *cls,
+           const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
+  prepare_daemon ();
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ */
+static void 
+prepare_daemon ()
+{
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  struct GNUNET_NETWORK_FDSet *wrs;
+  struct GNUNET_NETWORK_FDSet *wws;
+  struct GNUNET_NETWORK_FDSet *wes;
+  int max;
+  unsigned long long timeout;
+  int haveto;
+  struct GNUNET_TIME_Relative tv;
+  
+  FD_ZERO(&rs);
+  FD_ZERO(&ws);
+  FD_ZERO(&es);
+  wrs = GNUNET_NETWORK_fdset_create ();
+  wes = GNUNET_NETWORK_fdset_create ();
+  wws = GNUNET_NETWORK_fdset_create ();
+  max = -1;
+  GNUNET_assert (MHD_YES ==
+                MHD_get_fdset (daemon_handle,
+                               &rs,
+                               &ws,
+                               &es,
+                               &max));
+  haveto = MHD_get_timeout (daemon_handle, &timeout);
+  if (haveto == MHD_YES)
+    tv.value = (uint64_t) timeout;
+  else
+    tv = GNUNET_TIME_UNIT_FOREVER_REL;
+  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max);
+  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max);
+  GNUNET_NETWORK_fdset_copy_native (wes, &es, max);
+  hostlist_task 
+    = GNUNET_SCHEDULER_add_select (sched,
+                                  GNUNET_NO,
+                                  GNUNET_SCHEDULER_PRIORITY_HIGH,
+                                  GNUNET_SCHEDULER_NO_TASK,
+                                  tv,
+                                  wrs,
+                                  wws,
+                                  &run_daemon,
+                                  NULL);
+  GNUNET_NETWORK_fdset_destroy (wrs);
+  GNUNET_NETWORK_fdset_destroy (wws);
+  GNUNET_NETWORK_fdset_destroy (wes);
+}
+
+
+
 /**
  * Start server offering our hostlist.
  *
  * @return GNUNET_OK on success
  */
 int
-GNUNET_HOSTLIST_server_start (struct GNUNET_CONFIGURATION_Handle *c,
+GNUNET_HOSTLIST_server_start (const struct GNUNET_CONFIGURATION_Handle *c,
                              struct GNUNET_SCHEDULER_Handle *s,
                              struct GNUNET_STATISTICS_Handle *st)
 {
@@ -193,12 +283,10 @@ GNUNET_HOSTLIST_server_start (struct GNUNET_CONFIGURATION_Handle *c,
   cfg = c;
   if (-1 == GNUNET_CONFIGURATION_get_value_number (cfg,
                                                   "HOSTLIST",
-                                                  "PORT", 
+                                                  "HTTPPORT", 
                                                   &port))
     return GNUNET_SYSERR;
-  /* FIXME: must use *external* SELECT mode since our
-     code is NOT thread safe!  Integrate with scheduler! */
-  daemon_handle = MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_IPv6,
+  daemon_handle = MHD_start_daemon (MHD_USE_IPv6,
                                     (unsigned short) port,
                                     &accept_policy_callback,
                                     NULL,
@@ -216,6 +304,7 @@ GNUNET_HOSTLIST_server_start (struct GNUNET_CONFIGURATION_Handle *c,
                  (unsigned short) port);
       return GNUNET_SYSERR;    
     }
+  prepare_daemon ();
   return GNUNET_OK;
 }
 
@@ -225,6 +314,8 @@ GNUNET_HOSTLIST_server_start (struct GNUNET_CONFIGURATION_Handle *c,
 void
 GNUNET_HOSTLIST_server_stop ()
 {
+  GNUNET_SCHEDULER_cancel (sched, hostlist_task);
+  hostlist_task = GNUNET_SCHEDULER_NO_TASK;
   MHD_stop_daemon (daemon_handle);
   daemon_handle = NULL;
 }