gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r23357 - gnunet/src/transport


From: gnunet
Subject: [GNUnet-SVN] r23357 - gnunet/src/transport
Date: Wed, 22 Aug 2012 14:14:22 +0200

Author: wachs
Date: 2012-08-22 14:14:22 +0200 (Wed, 22 Aug 2012)
New Revision: 23357

Modified:
   gnunet/src/transport/plugin_transport_http_server.c
Log:
fix for https


Modified: gnunet/src/transport/plugin_transport_http_server.c
===================================================================
--- gnunet/src/transport/plugin_transport_http_server.c 2012-08-22 12:03:47 UTC 
(rev 23356)
+++ gnunet/src/transport/plugin_transport_http_server.c 2012-08-22 12:14:22 UTC 
(rev 23357)
@@ -45,18 +45,9 @@
 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE 
libgnunet_plugin_transport_http_server_done
 #endif
 
+#define HTTP_NOT_VALIDATED_TIMEOUT GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_SECONDS, 15)
 
-#define DEBUG_TEMPLATE GNUNET_EXTRA_LOGGING
-
 /**
- * After how long do we expire an address that we
- * learned from another peer if it is not reconfirmed
- * by anyone?
- */
-#define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply 
(GNUNET_TIME_UNIT_HOURS, 6)
-
-
-/**
  * Encapsulation of all of the state of the plugin.
  */
 struct Plugin;
@@ -71,7 +62,7 @@
    * To whom are we talking to (set to our identity
    * if we are still waiting for the welcome message)
    */
-  struct GNUNET_PeerIdentity sender;
+  struct GNUNET_PeerIdentity target;
 
   /**
    * Stored in a linked list.
@@ -79,6 +70,11 @@
   struct Session *next;
 
   /**
+   * Stored in a linked list.
+   */
+  struct Session *prev;
+
+  /**
    * Pointer to the global plugin struct.
    */
   struct HTTP_Server_Plugin *plugin;
@@ -117,6 +113,45 @@
    */
   uint32_t quota;
 
+  /**
+   * next pointer for double linked list
+   */
+  struct HTTP_Message *msg_head;
+
+  /**
+   * previous pointer for double linked list
+   */
+  struct HTTP_Message *msg_tail;
+
+  /**
+   * Message stream tokenizer for incoming data
+   */
+  struct GNUNET_SERVER_MessageStreamTokenizer *msg_tk;
+
+  /**
+   * Server handles
+   */
+
+  /**
+   * Client send handle
+   */
+  struct ServerConnection *server_recv;
+
+  /**
+   * Client send handle
+   */
+  struct ServerConnection *server_send;
+
+  /**
+   * Address
+   */
+  void *addr;
+
+  /**
+   * Address length
+   */
+  size_t addrlen;
+
 };
 
 /**
@@ -130,21 +165,53 @@
   struct GNUNET_TRANSPORT_PluginEnvironment *env;
 
   /**
-   * List of open sessions.
+   * Linked list of open sessions.
    */
-  struct Session *sessions;
 
+  struct Session *head;
+
+  struct Session *tail;
+
+
   char *name;
   char *protocol;
   char *external_hostname;
 
   /**
+   * libCurl TLS crypto init string, can be set to enhance performance
+   *
+   * Example:
+   *
+   * Use RC4-128 instead of AES:
+   * NONE:+VERS-TLS1.0:+ARCFOUR-128:+SHA1:+RSA:+COMP-NULL
+   *
+   */
+  char *crypto_init;
+
+  /**
+   * TLS key
+   */
+  char *key;
+
+  /**
+   * TLS certificate
+   */
+  char *cert;
+
+
+  /**
    * Maximum number of sockets the plugin can use
    * Each http inbound /outbound connections are two connections
    */
   unsigned int max_connections;
 
   /**
+   * Current number of sockets the plugin can use
+   * Each http inbound /outbound connections are two connections
+   */
+  unsigned int cur_connections;
+
+  /**
    * External hostname the plugin can be connected to, can be different to
    * the host's FQDN, used e.g. for reverse proxying
    */
@@ -204,8 +271,38 @@
    */
   struct sockaddr_in6 *server_addr_v6;
 
+  /**
+   * MHD IPv4 task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier server_v4_task;
 
   /**
+   * MHD IPv6 task
+   */
+  GNUNET_SCHEDULER_TaskIdentifier server_v6_task;
+
+  /**
+   * The IPv4 server is scheduled to run asap
+   */
+  int server_v4_immediately;
+
+  /**
+   * The IPv6 server is scheduled to run asap
+   */
+  int server_v6_immediately;
+
+
+  /**
+   * Server semi connections
+   * A full session consists of 2 semi-connections: send and receive
+   * If not both directions are established the server keeps this sessions here
+   */
+  struct Session *server_semi_head;
+
+  struct Session *server_semi_tail;
+
+
+  /**
    * MHD IPv4 daemon
    */
   struct MHD_Daemon *server_v4;
@@ -253,7 +350,53 @@
   struct HttpAddress *addr;
 };
 
+/**
+ *  Message to send using http
+ */
+struct HTTP_Message
+{
+  /**
+   * next pointer for double linked list
+   */
+  struct HTTP_Message *next;
 
+  /**
+   * previous pointer for double linked list
+   */
+  struct HTTP_Message *prev;
+
+  /**
+   * buffer containing data to send
+   */
+  char *buf;
+
+  /**
+   * amount of data already sent
+   */
+  size_t pos;
+
+  /**
+   * buffer length
+   */
+  size_t size;
+
+  /**
+   * Continuation function to call once the transmission buffer
+   * has again space available.  NULL if there is no
+   * continuation to call.
+   */
+  GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
+
+  /**
+   * Closure for transmit_cont.
+   */
+  void *transmit_cont_cls;
+};
+
+
+static struct Plugin * p;
+
+
 /**
  * Function that can be used by the transport service to transmit
  * a message using the plugin.   Note that in the case of a
@@ -386,6 +529,46 @@
 }
 
 
+/**
+ * Deleting the session
+ * Must not be used afterwards
+ */
+
+void
+server_delete_session (struct Session *s)
+{
+  struct HTTP_Server_Plugin *plugin = s->plugin;
+  stop_session_timeout(s);
+
+  GNUNET_CONTAINER_DLL_remove (plugin->head, plugin->tail, s);
+  struct HTTP_Message *msg = s->msg_head;
+  struct HTTP_Message *tmp = NULL;
+
+  while (msg != NULL)
+  {
+    tmp = msg->next;
+
+    GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
+    if (msg->transmit_cont != NULL)
+    {
+      msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
+    }
+    GNUNET_free (msg);
+    msg = tmp;
+  }
+
+  if (s->msg_tk != NULL)
+  {
+    GNUNET_SERVER_mst_destroy (s->msg_tk);
+    s->msg_tk = NULL;
+  }
+  GNUNET_free (s->addr);
+  GNUNET_free_non_null (s->server_recv);
+  GNUNET_free_non_null (s->server_send);
+  GNUNET_free (s);
+}
+
+
 static void *
 server_find_address (struct HTTP_Server_Plugin *plugin, const struct sockaddr 
*addr, socklen_t addrlen)
 {
@@ -405,7 +588,606 @@
   return w;
 }
 
+static int
+server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
+                  const char *url, const char *method, const char *version,
+                  const char *upload_data, size_t * upload_data_size,
+                  void **httpSessionCache)
+{
+  GNUNET_break (0);
+  return MHD_NO;
+}
+
 static void
+server_disconnect_cb (void *cls, struct MHD_Connection *connection,
+                      void **httpSessionCache)
+{
+  GNUNET_break (0);
+}
+
+/**
+ * Check if incoming connection is accepted.
+ * NOTE: Here every connection is accepted
+ * @param cls plugin as closure
+ * @param addr address of incoming connection
+ * @param addr_len address length of incoming connection
+ * @return MHD_YES if connection is accepted, MHD_NO if connection is rejected
+ *
+ */
+static int
+server_accept_cb (void *cls, const struct sockaddr *addr, socklen_t addr_len)
+{
+  struct HTTP_Server_Plugin *plugin = cls;
+  GNUNET_break (0);
+  if (plugin->cur_connections <= plugin->max_connections)
+    return MHD_YES;
+  else
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Server: Cannot accept new connections\n");
+    return MHD_NO;
+  }
+}
+
+static void
+server_log (void *arg, const char *fmt, va_list ap)
+{
+  char text[1024];
+
+  vsnprintf (text, sizeof (text), fmt, ap);
+  va_end (ap);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Server: %s\n", text);
+}
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ * @param plugin plugin
+ * @param daemon_handle the MHD daemon handle
+ * @return gnunet task identifier
+ */
+static GNUNET_SCHEDULER_TaskIdentifier
+server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon 
*daemon_handle,
+                 int now);
+
+/**
+ * Reschedule the execution of both IPv4 and IPv6 server
+ * @param plugin the plugin
+ * @param server which server to schedule v4 or v6?
+ * @param now GNUNET_YES to schedule execution immediately, GNUNET_NO to wait
+ * until timeout
+ */
+static void
+server_reschedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon 
*server, int now)
+{
+  if ((server == plugin->server_v4) && (plugin->server_v4 != NULL))
+  {
+    if (GNUNET_YES == plugin->server_v4_immediately)
+      return; /* No rescheduling, server will run asap */
+
+    if (GNUNET_YES == now)
+      plugin->server_v4_immediately = GNUNET_YES;
+
+    if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
+      plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+    plugin->server_v4_task = server_schedule (plugin, plugin->server_v4, now);
+  }
+
+  if ((server == plugin->server_v6) && (plugin->server_v6 != NULL))
+  {
+    if (GNUNET_YES == plugin->server_v6_immediately)
+      return; /* No rescheduling, server will run asap */
+
+    if (GNUNET_YES == now)
+      plugin->server_v6_immediately = GNUNET_YES;
+
+    if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
+      plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+    plugin->server_v6_task = server_schedule (plugin, plugin->server_v6, now);
+  }
+}
+
+/**
+ * Call MHD IPv4 to process pending requests and then go back
+ * and schedule the next run.
+ * @param cls plugin as closure
+ * @param tc task context
+ */
+static void
+server_v4_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct HTTP_Server_Plugin *plugin = cls;
+
+  GNUNET_assert (cls != NULL);
+
+  plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+#if 0
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                   "Running IPv4 server\n");
+#endif
+  plugin->server_v4_immediately = GNUNET_NO;
+  GNUNET_assert (MHD_YES == MHD_run (plugin->server_v4));
+  server_reschedule (plugin, plugin->server_v4, GNUNET_NO);
+}
+
+
+/**
+ * Call MHD IPv6 to process pending requests and then go back
+ * and schedule the next run.
+ * @param cls plugin as closure
+ * @param tc task context
+ */
+static void
+server_v6_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  struct HTTP_Server_Plugin *plugin = cls;
+
+  GNUNET_assert (cls != NULL);
+  plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+#if 0
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                   "Running IPv6 server\n");
+#endif
+  plugin->server_v6_immediately = GNUNET_NO;
+  GNUNET_assert (MHD_YES == MHD_run (plugin->server_v6));
+  server_reschedule (plugin, plugin->server_v6, GNUNET_NO);
+}
+
+
+/**
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
+ * @param plugin plugin
+ * @param daemon_handle the MHD daemon handle
+ * @return gnunet task identifier
+ */
+static GNUNET_SCHEDULER_TaskIdentifier
+server_schedule (struct HTTP_Server_Plugin *plugin, struct MHD_Daemon 
*daemon_handle,
+                 int now)
+{
+  GNUNET_SCHEDULER_TaskIdentifier ret;
+  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 MHD_LONG_LONG timeout;
+  static unsigned long long last_timeout = 0;
+  int haveto;
+
+  struct GNUNET_TIME_Relative tv;
+
+  ret = GNUNET_SCHEDULER_NO_TASK;
+  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)
+  {
+    if (timeout != last_timeout)
+    {
+#if VERBOSE_SERVER
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                       "SELECT Timeout changed from %llu to %llu\n",
+                       last_timeout, timeout);
+#endif
+      last_timeout = timeout;
+    }
+    tv.rel_value = (uint64_t) timeout;
+  }
+  else
+    tv = GNUNET_TIME_UNIT_SECONDS;
+  /* Force immediate run, since we have outbound data to send */
+  if (now == GNUNET_YES)
+    tv = GNUNET_TIME_UNIT_MILLISECONDS;
+  GNUNET_NETWORK_fdset_copy_native (wrs, &rs, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (wws, &ws, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (wes, &es, max + 1);
+
+  if (daemon_handle == plugin->server_v4)
+  {
+    if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
+      plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+#if 0
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                     "Scheduling IPv4 server task in %llu ms\n", tv);
+#endif
+    ret =
+        GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                                     tv, wrs, wws,
+                                     &server_v4_run, plugin);
+  }
+  if (daemon_handle == plugin->server_v6)
+  {
+    if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
+    {
+      GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
+      plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
+    }
+#if 0
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                     "Scheduling IPv6 server task in %llu ms\n", tv);
+#endif
+    ret =
+        GNUNET_SCHEDULER_add_select (GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                                     tv, wrs, wws,
+                                     &server_v6_run, plugin);
+  }
+  GNUNET_NETWORK_fdset_destroy (wrs);
+  GNUNET_NETWORK_fdset_destroy (wws);
+  GNUNET_NETWORK_fdset_destroy (wes);
+  return ret;
+}
+
+
+#if BUILD_HTTPS
+static char *
+server_load_file (const char *file)
+{
+  struct GNUNET_DISK_FileHandle *gn_file;
+  uint64_t fsize;
+  char *text = NULL;
+
+  if (GNUNET_OK != GNUNET_DISK_file_size (file,
+      &fsize, GNUNET_NO, GNUNET_YES))
+    return NULL;
+  text = GNUNET_malloc (fsize + 1);
+  gn_file =
+      GNUNET_DISK_file_open (file, GNUNET_DISK_OPEN_READ,
+                             GNUNET_DISK_PERM_USER_READ);
+  if (gn_file == NULL)
+  {
+    GNUNET_free (text);
+    return NULL;
+  }
+  if (GNUNET_SYSERR == GNUNET_DISK_file_read (gn_file, text, fsize))
+  {
+    GNUNET_free (text);
+    GNUNET_DISK_file_close (gn_file);
+    return NULL;
+  }
+  text[fsize] = '\0';
+  GNUNET_DISK_file_close (gn_file);
+  return text;
+}
+#endif
+
+
+#if BUILD_HTTPS
+
+static int
+server_load_certificate (struct HTTP_Server_Plugin *plugin)
+{
+  int res = GNUNET_OK;
+
+  char *key_file;
+  char *cert_file;
+
+  /* Get crypto init string from config
+   * If not present just use default values */
+
+  if (GNUNET_OK ==
+                 GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg,
+                                                        plugin->name,
+                                                        "CRYPTO_INIT",
+                                                        &plugin->crypto_init))
+      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                       "Using crypto init string `%s'\n",
+                       plugin->crypto_init);
+  else
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                     "Using default crypto init string \n");
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name,
+                                               "KEY_FILE", &key_file))
+  {
+    key_file = GNUNET_strdup ("https_key.key");
+  }
+
+  if (GNUNET_OK !=
+      GNUNET_CONFIGURATION_get_value_filename (plugin->env->cfg, plugin->name,
+                                               "CERT_FILE", &cert_file))
+  {
+    GNUNET_asprintf (&cert_file, "%s", "https_cert.crt");
+  }
+
+  /* read key & certificates from file */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Trying to loading TLS certificate from key-file `%s' 
cert-file`%s'\n",
+              key_file, cert_file);
+
+  plugin->key = server_load_file (key_file);
+  plugin->cert = server_load_file (cert_file);
+
+  if ((plugin->key == NULL) || (plugin->cert == NULL))
+  {
+    struct GNUNET_OS_Process *cert_creation;
+
+    GNUNET_free_non_null (plugin->key);
+    plugin->key = NULL;
+    GNUNET_free_non_null (plugin->cert);
+    plugin->cert = NULL;
+
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                "No usable TLS certificate found, creating certificate\n");
+    errno = 0;
+    cert_creation =
+        GNUNET_OS_start_process (GNUNET_NO, GNUNET_OS_INHERIT_STD_OUT_AND_ERR, 
NULL, NULL,
+                                 "gnunet-transport-certificate-creation",
+                                 "gnunet-transport-certificate-creation",
+                                 key_file, cert_file, NULL);
+    if (cert_creation == NULL)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+                       _
+                       ("Could not create a new TLS certificate, program 
`gnunet-transport-certificate-creation' could not be started!\n"));
+      GNUNET_free (key_file);
+      GNUNET_free (cert_file);
+
+      GNUNET_free_non_null (plugin->key);
+      plugin->key = NULL;
+      GNUNET_free_non_null (plugin->cert);
+      plugin->cert = NULL;
+      GNUNET_free_non_null (plugin->crypto_init);
+      plugin->crypto_init = NULL;
+
+      return GNUNET_SYSERR;
+    }
+    GNUNET_assert (GNUNET_OK == GNUNET_OS_process_wait (cert_creation));
+    GNUNET_OS_process_destroy (cert_creation);
+
+    plugin->key = server_load_file (key_file);
+    plugin->cert = server_load_file (cert_file);
+  }
+
+  if ((plugin->key == NULL) || (plugin->cert == NULL))
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+                     _
+                     ("No usable TLS certificate found and creating one 
failed!\n"),
+                     "transport-https");
+    GNUNET_free (key_file);
+    GNUNET_free (cert_file);
+
+    GNUNET_free_non_null (plugin->key);
+    plugin->key = NULL;
+    GNUNET_free_non_null (plugin->cert);
+    plugin->cert = NULL;
+    GNUNET_free_non_null (plugin->crypto_init);
+    plugin->crypto_init = NULL;
+
+    return GNUNET_SYSERR;
+  }
+  GNUNET_free (key_file);
+  GNUNET_free (cert_file);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "TLS certificate loaded\n");
+  return res;
+}
+#endif
+
+int
+server_start (struct HTTP_Server_Plugin *plugin)
+{
+  unsigned int timeout;
+  GNUNET_assert (NULL != plugin);
+
+#if BUILD_HTTPS
+  if (GNUNET_SYSERR == server_load_certificate (plugin))
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+                     "Could not load or create server certificate! Loading 
plugin failed!\n");
+    return GNUNET_SYSERR;
+  }
+#endif
+
+
+#if MHD_VERSION >= 0x00090E00
+  timeout = HTTP_NOT_VALIDATED_TIMEOUT.rel_value / 1000;
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                   "MHD can set timeout per connection! Default time out %u 
sec.\n",
+                   timeout);
+#else
+  timeout = GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT.rel_value / 1000;
+  GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, plugin->name,
+                   "MHD cannot set timeout per connection! Default time out %u 
sec.\n",
+                   timeout);
+#endif
+  plugin->server_v4 = NULL;
+  if (plugin->use_ipv4 == GNUNET_YES)
+  {
+    plugin->server_v4 = MHD_start_daemon (
+#if VERBOSE_SERVER
+                                           MHD_USE_DEBUG |
+#endif
+#if BUILD_HTTPS
+                                           MHD_USE_SSL |
+#endif
+                                           MHD_NO_FLAG, plugin->port,
+                                           &server_accept_cb, plugin,
+                                           &server_access_cb, plugin,
+                                           MHD_OPTION_SOCK_ADDR,
+                                           (struct sockaddr_in *)
+                                           plugin->server_addr_v4,
+                                           MHD_OPTION_CONNECTION_LIMIT,
+                                           (unsigned int)
+                                           plugin->max_connections,
+#if BUILD_HTTPS
+                                           MHD_OPTION_HTTPS_PRIORITIES,
+                                           plugin->crypto_init,
+                                           MHD_OPTION_HTTPS_MEM_KEY,
+                                           plugin->key,
+                                           MHD_OPTION_HTTPS_MEM_CERT,
+                                           plugin->cert,
+#endif
+                                           MHD_OPTION_CONNECTION_TIMEOUT,
+                                           timeout,
+                                           MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                                           (size_t) (2 *
+                                                     
GNUNET_SERVER_MAX_MESSAGE_SIZE),
+                                           MHD_OPTION_NOTIFY_COMPLETED,
+                                           &server_disconnect_cb, plugin,
+                                           MHD_OPTION_EXTERNAL_LOGGER,
+                                           server_log, NULL, MHD_OPTION_END);
+  }
+  plugin->server_v6 = NULL;
+  if (plugin->use_ipv6 == GNUNET_YES)
+  {
+    plugin->server_v6 = MHD_start_daemon (
+#if VERBOSE_SERVER
+                                           MHD_USE_DEBUG |
+#endif
+#if BUILD_HTTPS
+                                           MHD_USE_SSL |
+#endif
+                                           MHD_USE_IPv6, plugin->port,
+                                           &server_accept_cb, plugin,
+                                           &server_access_cb, plugin,
+                                           MHD_OPTION_SOCK_ADDR,
+                                           (struct sockaddr_in6 *)
+                                           plugin->server_addr_v6,
+                                           MHD_OPTION_CONNECTION_LIMIT,
+                                           (unsigned int)
+                                           plugin->max_connections,
+#if BUILD_HTTPS
+                                           MHD_OPTION_HTTPS_PRIORITIES,
+                                           plugin->crypto_init,
+                                           MHD_OPTION_HTTPS_MEM_KEY,
+                                           plugin->key,
+                                           MHD_OPTION_HTTPS_MEM_CERT,
+                                           plugin->cert,
+#endif
+                                           MHD_OPTION_CONNECTION_TIMEOUT,
+                                           timeout,
+                                           MHD_OPTION_CONNECTION_MEMORY_LIMIT,
+                                           (size_t) (2 *
+                                                     
GNUNET_SERVER_MAX_MESSAGE_SIZE),
+                                           MHD_OPTION_NOTIFY_COMPLETED,
+                                           &server_disconnect_cb, plugin,
+                                           MHD_OPTION_EXTERNAL_LOGGER,
+                                           server_log, NULL, MHD_OPTION_END);
+
+  }
+
+  if ((plugin->use_ipv4 == GNUNET_YES) && (plugin->server_v4 == NULL))
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+                     "Failed to start %s IPv4 server component on port %u\n",
+                     plugin->name, plugin->port);
+    return GNUNET_SYSERR;
+  }
+  server_reschedule (plugin, plugin->server_v4, GNUNET_NO);
+
+  if ((plugin->use_ipv6 == GNUNET_YES) && (plugin->server_v6 == NULL))
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+                     "Failed to start %s IPv6 server component on port %u\n",
+                     plugin->name, plugin->port);
+    return GNUNET_SYSERR;
+  }
+  server_reschedule (plugin, plugin->server_v6, GNUNET_NO);
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                   "%s server component started on port %u\n", plugin->name,
+                   plugin->port);
+  return GNUNET_OK;
+}
+
+
+void
+server_stop (struct HTTP_Server_Plugin *plugin)
+{
+  struct Session *s = NULL;
+  struct Session *t = NULL;
+
+  struct MHD_Daemon *server_v4_tmp = plugin->server_v4;
+  plugin->server_v4 = NULL;
+
+  struct MHD_Daemon *server_v6_tmp = plugin->server_v6;
+  plugin->server_v6 = NULL;
+
+  if (plugin->server_v4_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (plugin->server_v4_task);
+    plugin->server_v4_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  if (plugin->server_v6_task != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel (plugin->server_v6_task);
+    plugin->server_v6_task = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  if (server_v6_tmp != NULL)
+  {
+    MHD_stop_daemon (server_v4_tmp);
+  }
+  if (server_v6_tmp != NULL)
+  {
+    MHD_stop_daemon (server_v6_tmp);
+  }
+
+  /* cleaning up semi-sessions never propagated */
+  s = plugin->server_semi_head;
+  while (s != NULL)
+  {
+#if VERBOSE_SERVER
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                     "Deleting semi-sessions %p\n", s);
+#endif
+    t = s->next;
+    struct HTTP_Message *msg = s->msg_head;
+    struct HTTP_Message *tmp = NULL;
+
+    while (msg != NULL)
+    {
+      tmp = msg->next;
+
+      GNUNET_CONTAINER_DLL_remove (s->msg_head, s->msg_tail, msg);
+      if (msg->transmit_cont != NULL)
+      {
+        msg->transmit_cont (msg->transmit_cont_cls, &s->target, GNUNET_SYSERR);
+      }
+      GNUNET_free (msg);
+      msg = tmp;
+    }
+
+    server_delete_session (s);
+    s = t;
+  }
+
+  p = NULL;
+
+#if BUILD_HTTPS
+  GNUNET_free_non_null (plugin->crypto_init);
+  GNUNET_free_non_null (plugin->cert);
+  GNUNET_free_non_null (plugin->key);
+#endif
+
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                   "%s server component stopped\n", plugin->name);
+}
+
+static void
 server_add_address (void *cls, int add_remove, const struct sockaddr *addr,
                  socklen_t addrlen)
 {
@@ -425,7 +1207,7 @@
   GNUNET_free (saddr);
 
   GNUNET_CONTAINER_DLL_insert(plugin->addr_head, plugin->addr_tail, w);
-  GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                    "Notifying transport to add address `%s'\n", w->addr->addr);
 
   plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, 
haddrlen);
@@ -787,7 +1569,7 @@
   eaddr->addr_len = htonl (uri_len);
   eaddr->addr = (void *) &eaddr[1];
   memcpy (&eaddr->addr, addr, uri_len);
-  GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR, plugin->name,
+  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                    "Notifying transport about external hostname address 
`%s'\n", addr);
 
   GNUNET_free (addr);
@@ -940,7 +1722,6 @@
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                    _("Maximum number of connections is %u\n"),
                    plugin->max_connections);
-GNUNET_break(0);
   return GNUNET_OK;
 }
 
@@ -976,13 +1757,14 @@
   /* Stop to report addresses to transport service */
   server_stop_report_addresses (plugin);
 
+  server_stop (plugin);
+
   /* Clean up */
   GNUNET_free_non_null (plugin->external_hostname);
   GNUNET_free_non_null (plugin->ext_addr);
   GNUNET_free_non_null (plugin->server_addr_v4);
   GNUNET_free_non_null (plugin->server_addr_v6);
 
-
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;
@@ -1031,6 +1813,12 @@
   /* Report addresses to transport service */
   server_start_report_addresses (plugin);
 
+  if (GNUNET_SYSERR == server_start (plugin))
+  {
+      LIBGNUNET_PLUGIN_TRANSPORT_DONE (api);
+      return NULL;
+  }
+
   return api;
 }
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]