Extending the testcases to use bluetooth
[oweals/gnunet.git] / src / transport / plugin_transport_http_server.c
index 3ccdf4c94556e0366dec96f4b58611c954735425..19833521a06342c00b48d6f30f5f636cdc1d1327 100644 (file)
 #include "plugin_transport_http_common.h"
 #include <microhttpd.h>
 
+
+
 #if BUILD_HTTPS
+#define PLUGIN_NAME "https_server"
 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_https_server_init
 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_https_server_done
 #else
+#define PLUGIN_NAME "http_server"
 #define LIBGNUNET_PLUGIN_TRANSPORT_INIT libgnunet_plugin_transport_http_server_init
 #define LIBGNUNET_PLUGIN_TRANSPORT_DONE libgnunet_plugin_transport_http_server_done
 #endif
@@ -55,7 +59,6 @@
  */
 struct Plugin;
 
-
 /**
  * Session handle for connections.
  */
@@ -208,6 +211,11 @@ struct HTTP_Server_Plugin
    */
   char *protocol;
 
+  /**
+   * My options to be included in the address
+   */
+  uint32_t options;
+
   /**
    * External address
    */
@@ -245,7 +253,7 @@ struct HTTP_Server_Plugin
    * External hostname the plugin can be connected to, can be different to
    * the host's FQDN, used e.g. for reverse proxying
    */
-  char *ext_addr;
+  struct HttpAddress *ext_addr;
 
   /**
    * Notify transport only about external address
@@ -377,7 +385,7 @@ struct HttpAddressWrapper
    */
   struct HttpAddressWrapper *prev;
 
-  void *addr;
+  struct HttpAddress *address;
 
   size_t addrlen;
 };
@@ -646,23 +654,29 @@ static int
 http_server_plugin_address_suggested (void *cls, const void *addr,
                size_t addrlen)
 {
-  struct HTTP_Server_Plugin *plugin = cls;
   struct HttpAddressWrapper *next;
   struct HttpAddressWrapper *pos;
+       struct HttpAddress *h_addr;
+       h_addr = (struct HttpAddress *) addr;
 
-
-  if ((NULL != plugin->ext_addr) &&
+  if ((NULL != p->ext_addr) &&
           GNUNET_YES == (http_common_cmp_addresses (addr, addrlen,
-                                          plugin->ext_addr, plugin->ext_addr_len)))
-    return GNUNET_OK;
+                                          p->ext_addr, p->ext_addr_len)))
+  {
+       /* Checking HTTP_OPTIONS_VERIFY_CERTIFICATE option for external hostname */
+       if ((ntohl(h_addr->options) & HTTP_OPTIONS_VERIFY_CERTIFICATE) !=
+                       (p->options & HTTP_OPTIONS_VERIFY_CERTIFICATE))
+                       return GNUNET_NO; /* VERIFY option not set as required! */
+       return GNUNET_OK;
+  }
 
-  next  = plugin->addr_head;
+  next  = p->addr_head;
   while (NULL != (pos = next))
   {
     next = pos->next;
     if (GNUNET_YES == (http_common_cmp_addresses(addr,
                                                  addrlen,
-                                                 pos->addr,
+                                                 pos->address,
                                                  pos->addrlen)))
       return GNUNET_OK;
 
@@ -1021,7 +1035,7 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin,
   const union MHD_ConnectionInfo *conn_info;
   struct GNUNET_ATS_Information ats;
 
-  char *addr;
+  struct HttpAddress *addr;
   size_t addr_len;
 
   struct GNUNET_PeerIdentity target;
@@ -1105,13 +1119,11 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin,
       ats = plugin->env->get_address_type (plugin->env->cls, conn_info->client_addr, sizeof (struct sockaddr_in6));
       break;
     default:
-      GNUNET_break (0);
+       /* external host name */
+      ats.type = htonl (GNUNET_ATS_NETWORK_TYPE);
+      ats.type = htonl (GNUNET_ATS_NET_WAN);
       return NULL;
     }
-    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
-                     "Creating new session for peer `%s' connecting from `%s'\n",
-                     GNUNET_i2s (&target),
-                     http_common_plugin_address_to_string (NULL, addr, addr_len));
 
     s = GNUNET_malloc (sizeof (struct Session));
     memcpy (&s->target, &target, sizeof (struct GNUNET_PeerIdentity));
@@ -1128,6 +1140,11 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin,
     s->connect_in_progress = GNUNET_YES;
     server_start_session_timeout(s);
     GNUNET_CONTAINER_DLL_insert (plugin->head, plugin->tail, s);
+
+    GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+                     "Creating new session %p for peer `%s' connecting from `%s'\n",
+                     s, GNUNET_i2s (&target),
+                     http_common_plugin_address_to_string (NULL, p->protocol, addr, addr_len));
   }
   sc = GNUNET_malloc (sizeof (struct ServerConnection));
   if (conn_info->client_addr->sa_family == AF_INET)
@@ -1144,7 +1161,10 @@ server_lookup_connection (struct HTTP_Server_Plugin *plugin,
     s->server_recv = sc;
 
   if ((NULL != s->server_send) && (NULL != s->server_recv))
+  {
     s->connect_in_progress = GNUNET_NO; /* PUT and GET are connected */
+    plugin->env->session_start (NULL, &s->target, PLUGIN_NAME, NULL, 0 ,s, NULL, 0);
+  }
 
 #if MHD_VERSION >= 0x00090E00
   if ((NULL == s->server_recv) || (NULL == s->server_send))
@@ -1292,14 +1312,11 @@ server_receive_mst_cb (void *cls, void *client,
   delay = plugin->env->receive (plugin->env->cls,
                                 &s->target,
                                 message,
-                                s, s->addr, s->addrlen);
+                                s, NULL, 0);
 
   plugin->env->update_address_metrics (plugin->env->cls,
                                       &s->target,
-                                      s->addr,
-                                      s->addrlen,
-                                      s,
-                                      &atsi, 1);
+                                      NULL, 0, s, &atsi, 1);
 
   GNUNET_asprintf (&stat_txt, "# bytes received via %s_server", plugin->protocol);
   GNUNET_STATISTICS_update (plugin->env->stats,
@@ -1313,7 +1330,7 @@ server_receive_mst_cb (void *cls, void *client,
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                      "Peer `%s' address `%s' next read delayed for %llu ms\n",
                      GNUNET_i2s (&s->target),
-                     http_common_plugin_address_to_string (NULL, s->addr, s->addrlen),
+                     http_common_plugin_address_to_string (NULL,  p->protocol, s->addr, s->addrlen),
                      delay);
   }
   server_reschedule_session_timeout (s);
@@ -1420,6 +1437,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
                        s, sc,
                        GNUNET_i2s (&s->target),
                        http_common_plugin_address_to_string (NULL,
+                                                                                                                                                                   p->protocol,
                                                              s->addr,
                                                              s->addrlen));
       sc->connected = GNUNET_YES;
@@ -1433,6 +1451,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
                        s, sc,
                        GNUNET_i2s (&s->target),
                        http_common_plugin_address_to_string (NULL,
+                                                                                                                                                                         p->protocol,
                                                              s->addr,
                                                              s->addrlen));
       sc->connected = GNUNET_NO;
@@ -1452,6 +1471,7 @@ server_access_cb (void *cls, struct MHD_Connection *mhd_connection,
                        s, sc,
                        GNUNET_i2s (&s->target),
                        http_common_plugin_address_to_string (NULL,
+                                                                                                                                                                   p->protocol,
                                                              s->addr,
                                                              s->addrlen),
                        *upload_data_size);
@@ -1532,7 +1552,7 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                      "Peer `%s' connection  %p, GET on address `%s' disconnected\n",
                      GNUNET_i2s (&s->target), s->server_send,
-                     http_common_plugin_address_to_string (NULL, s->addr, s->addrlen));
+                     http_common_plugin_address_to_string (NULL,  p->protocol, s->addr, s->addrlen));
     s->server_send = NULL;
     if (NULL != (s->server_recv))
     {
@@ -1550,7 +1570,7 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                      "Peer `%s' connection %p PUT on address `%s' disconnected\n",
                      GNUNET_i2s (&s->target), s->server_recv,
-                     http_common_plugin_address_to_string (NULL, s->addr, s->addrlen));
+                     http_common_plugin_address_to_string (NULL,  p->protocol, s->addr, s->addrlen));
     s->server_recv = NULL;
     /* Do not terminate session when PUT disconnects
     if (NULL != (s->server_send))
@@ -1578,7 +1598,7 @@ server_disconnect_cb (void *cls, struct MHD_Connection *connection,
     GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                      "Peer `%s' on address `%s' disconnected\n",
                      GNUNET_i2s (&s->target),
-                     http_common_plugin_address_to_string (NULL, s->addr, s->addrlen));
+                     http_common_plugin_address_to_string (NULL,  p->protocol, s->addr, s->addrlen));
 
     if ((GNUNET_YES == s->session_passed) && (GNUNET_NO == s->session_ended))
     {
@@ -2152,22 +2172,22 @@ server_add_address (void *cls, int add_remove, const struct sockaddr *addr,
   struct HttpAddressWrapper *w = NULL;
 
   w = GNUNET_malloc (sizeof (struct HttpAddressWrapper));
-  w->addr = http_common_address_from_socket (plugin->protocol, addr, addrlen);
-  if (NULL == w->addr)
+  w->address = http_common_address_from_socket (plugin->protocol, addr, addrlen);
+  if (NULL == w->address)
   {
     GNUNET_free (w);
     return;
   }
-  w->addrlen = http_common_address_get_size (w->addr);
+  w->addrlen = http_common_address_get_size (w->address);
 
   GNUNET_CONTAINER_DLL_insert(plugin->addr_head, plugin->addr_tail, w);
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                    "Notifying transport to add address `%s'\n",
-                   http_common_plugin_address_to_string(NULL, w->addr, w->addrlen));
+                   http_common_plugin_address_to_string (NULL,  p->protocol, w->address, w->addrlen));
 #if BUILD_HTTPS
-  plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, w->addrlen, "https_client");
+  plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "https_client");
 #else
-  plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, w->addrlen, "http_client");
+  plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "http_client");
 #endif
 }
 
@@ -2194,7 +2214,7 @@ server_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
 
   while (NULL != w)
   {
-      if (GNUNET_YES == http_common_cmp_addresses(w->addr, w->addrlen, saddr, saddr_len))
+      if (GNUNET_YES == http_common_cmp_addresses(w->address, w->addrlen, saddr, saddr_len))
         break;
       w = w->next;
   }
@@ -2205,14 +2225,14 @@ server_remove_address (void *cls, int add_remove, const struct sockaddr *addr,
 
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                    "Notifying transport to remove address `%s'\n",
-                   http_common_plugin_address_to_string (NULL, w->addr, w->addrlen));
+                   http_common_plugin_address_to_string (NULL,  p->protocol, w->address, w->addrlen));
   GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
 #if BUILD_HTTPS
-  plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, w->addrlen, "https_client");
+  plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "https_client");
 #else
-  plugin->env->notify_address (plugin->env->cls, add_remove, w->addr, w->addrlen, "http_client");
+  plugin->env->notify_address (plugin->env->cls, add_remove, w->address, w->addrlen, "http_client");
 #endif
-  GNUNET_free (w->addr);
+  GNUNET_free (w->address);
   GNUNET_free (w);
 }
 
@@ -2533,7 +2553,7 @@ server_stop_report_addresses (struct HTTP_Server_Plugin *plugin)
   {
     w = plugin->addr_head;
     GNUNET_CONTAINER_DLL_remove (plugin->addr_head, plugin->addr_tail, w);
-    GNUNET_free (w->addr);
+    GNUNET_free (w->address);
     GNUNET_free (w);
   }
 }
@@ -2588,30 +2608,29 @@ static void
 server_notify_external_hostname (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
   struct HTTP_Server_Plugin *plugin = cls;
+  unsigned int urlen;
+  char *url;
 
   plugin->notify_ext_task = GNUNET_SCHEDULER_NO_TASK;
-
   if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
     return;
 
+  GNUNET_asprintf(&url, "%s://%s", plugin->protocol, plugin->external_hostname);
 
-#if BUILD_HTTPS
-  GNUNET_asprintf(&plugin->ext_addr, "%s%s://%s", plugin->protocol,
-               (GNUNET_YES == plugin->verify_external_hostname) ? "+" : "",
-               plugin->external_hostname);
-#else
-  GNUNET_asprintf(&plugin->ext_addr, "%s://%s", plugin->protocol,
-               plugin->external_hostname);
-#endif
-
-  plugin->ext_addr_len = strlen (plugin->ext_addr) + 1;
+  urlen = strlen (url) + 1;
+  plugin->ext_addr = GNUNET_malloc (sizeof (struct HttpAddress) + urlen);
+  plugin->ext_addr->options = htonl(plugin->options);
+  plugin->ext_addr->urlen = htonl (urlen);
+  plugin->ext_addr_len = sizeof (struct HttpAddress) + urlen;
+  memcpy (&plugin->ext_addr[1], url, urlen);
+  GNUNET_free (url);
   GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
-                   "Notifying transport about external hostname address `%s'\n", plugin->ext_addr);
+                   "Notifying transport about external hostname address `%s'\n", plugin->external_hostname);
 
 #if BUILD_HTTPS
   if (GNUNET_YES == plugin->verify_external_hostname)
     GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
-                     "Enabling SSL verification for external hostname address `%s'\n", plugin->ext_addr);
+                     "Enabling SSL verification for external hostname address `%s'\n", plugin->external_hostname);
   plugin->env->notify_address (plugin->env->cls, GNUNET_YES,
                                plugin->ext_addr, plugin->ext_addr_len,
                                "https_client");
@@ -2636,6 +2655,8 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin)
   unsigned long long max_connections;
   char *bind4_address = NULL;
   char *bind6_address = NULL;
+  char *eh_tmp = NULL;
+  int external_hostname_use_port;
 
   /* Use IPv4? */
   if (GNUNET_CONFIGURATION_have_value
@@ -2686,7 +2707,7 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin)
   }
   plugin->port = port;
 
-  GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+  GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
                    _("Using port %u\n"), plugin->port);
 
   if ((plugin->use_ipv4 == GNUNET_YES) &&
@@ -2756,20 +2777,45 @@ server_configure_plugin (struct HTTP_Server_Plugin *plugin)
                                                                                                                                                                "VERIFY_EXTERNAL_HOSTNAME");
   if (GNUNET_SYSERR == plugin->verify_external_hostname)
        plugin->verify_external_hostname = GNUNET_NO;
+  if (GNUNET_YES == plugin->verify_external_hostname)
+       plugin->options |= HTTP_OPTIONS_VERIFY_CERTIFICATE;
 #endif
+  external_hostname_use_port = GNUNET_CONFIGURATION_get_value_yesno (plugin->env->cfg, plugin->name,
+                                                                                                                                                               "EXTERNAL_HOSTNAME_USE_PORT");
+  if (GNUNET_SYSERR == external_hostname_use_port)
+       external_hostname_use_port = GNUNET_NO;
+
 
   if (GNUNET_YES == GNUNET_CONFIGURATION_get_value_string (plugin->env->cfg, plugin->name,
-                                              "EXTERNAL_HOSTNAME", &plugin->external_hostname))
+                                              "EXTERNAL_HOSTNAME", &eh_tmp))
   {
       char * tmp = NULL;
-      if (NULL != strstr(plugin->external_hostname, "://"))
+      char * pos = NULL;
+      char * pos_url = NULL;
+
+      if (NULL != strstr(eh_tmp, "://"))
       {
-          tmp = strdup(&strstr(plugin->external_hostname, "://")[3]);
-          GNUNET_free (plugin->external_hostname);
-          plugin->external_hostname = tmp;
+          tmp = &strstr(eh_tmp, "://")[3];
+      }
+      else
+               tmp = eh_tmp;
 
+      if (GNUNET_YES == external_hostname_use_port)
+      {
+        if ( (strlen (tmp) > 1) && (NULL != (pos = strchr(tmp, '/'))) )
+        {
+               pos_url = pos + 1;
+               pos[0] = '\0';
+               GNUNET_asprintf (&plugin->external_hostname, "%s:%u/%s", tmp, (uint16_t) port, (NULL == pos_url) ? "" : pos_url);
+        }
+        else
+               GNUNET_asprintf (&plugin->external_hostname, "%s:%u", tmp, (uint16_t) port);
       }
-      GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
+      else
+       plugin->external_hostname = GNUNET_strdup (tmp);
+      GNUNET_free (eh_tmp);
+
+      GNUNET_log_from (GNUNET_ERROR_TYPE_INFO, plugin->name,
                        _("Using external hostname `%s'\n"), plugin->external_hostname);
       plugin->notify_ext_task = GNUNET_SCHEDULER_add_now (&server_notify_external_hostname, plugin);
 
@@ -2908,6 +2954,7 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
       GNUNET_log_from (GNUNET_ERROR_TYPE_DEBUG, plugin->name,
                        "Notifying transport to remove address `%s'\n",
                        http_common_plugin_address_to_string (NULL,
+                                 p->protocol,
                            plugin->ext_addr,
                            plugin->ext_addr_len));
 #if BUILD_HTTPS
@@ -2961,6 +3008,34 @@ LIBGNUNET_PLUGIN_TRANSPORT_DONE (void *cls)
   return NULL;
 }
 
+const char *http_plugin_address_to_string (void *cls,
+                                           const void *addr,
+                                           size_t addrlen)
+{
+#if BUILD_HTTPS
+       return http_common_plugin_address_to_string (cls, PLUGIN_NAME, addr, addrlen);
+#else
+       return http_common_plugin_address_to_string (cls, PLUGIN_NAME, addr, addrlen);
+#endif
+
+}
+
+
+/**
+ * Function obtain the network type for a session
+ *
+ * @param cls closure ('struct Plugin*')
+ * @param session the session
+ * @return the network type in HBO or GNUNET_SYSERR
+ */
+static enum GNUNET_ATS_Network_Type
+http_server_get_network (void *cls,
+                        struct Session *session)
+{
+  GNUNET_assert (NULL != session);
+  return ntohl (session->ats_address_network_type);
+}
+
 
 /**
  * Entry point for the plugin.
@@ -2985,7 +3060,7 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
        initialze the plugin or the API */
     api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
     api->cls = NULL;
-    api->address_to_string = &http_common_plugin_address_to_string;
+    api->address_to_string = &http_plugin_address_to_string;
     api->string_to_address = &http_common_plugin_string_to_address;
     api->address_pretty_printer = &http_common_plugin_address_pretty_printer;
     return api;
@@ -2998,9 +3073,10 @@ LIBGNUNET_PLUGIN_TRANSPORT_INIT (void *cls)
   api->check_address = &http_server_plugin_address_suggested;
   api->get_session = &http_server_plugin_get_session;
 
-  api->address_to_string = &http_common_plugin_address_to_string;
+  api->address_to_string = &http_plugin_address_to_string;
   api->string_to_address = &http_common_plugin_string_to_address;
   api->address_pretty_printer = &http_common_plugin_address_pretty_printer;
+  api->get_network = &http_server_get_network;
 
 #if BUILD_HTTPS
   plugin->name = "transport-https_server";