(no commit message)
[oweals/gnunet.git] / src / transport / test_plugin_transport_http.c
index 9095e14c5b970a0b7891cbeffc01a644711b6f1c..2e540bd5406f2ede57f0af58cc012cd8b0afb1a2 100644 (file)
      Boston, MA 02111-1307, USA.
 */
 /**
- * @file transport/test_transport_api.c
- * @brief testcase for transport_api.c
- * @author Sailor Siraj
- * @author Christian Grothoff
- * @author Nathan Evans
+ * @file transport/test_plugin_transport_http.c
+ * @brief testcase for plugin_transport_http.c
+ * @author Matthias Wachs
  */
 
 #include "platform.h"
 #include "gnunet_protocols.h"
 #include "gnunet_program_lib.h"
 #include "gnunet_signatures.h"
+#include "gnunet_service_lib.h"
 #include "plugin_transport.h"
+#include "gnunet_statistics_service.h"
 #include "transport.h"
+#include <curl/curl.h>
 
-#define VERBOSE GNUNET_NO
+#define VERBOSE GNUNET_YES
+#define DEBUG GNUNET_YES
+
+#define PLUGIN libgnunet_plugin_transport_template
 
 /**
  * How long until we give up on transmitting the message?
  */
-#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
+#define TIMEOUT GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 90)
+
+/**
+ * How long until we give up on transmitting the message?
+ */
+#define STAT_INTERVALL GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 3)
+
+/**
+ * Our public key.
+ */
+/* static struct GNUNET_CRYPTO_RsaPublicKeyBinaryEncoded my_public_key; */
 
 /**
  * Our public key.
@@ -60,11 +74,18 @@ static struct GNUNET_PeerIdentity my_identity;
  */
 static struct GNUNET_CRYPTO_RsaPrivateKey *my_private_key;
 
+
 /**
  * Our scheduler.
  */
 struct GNUNET_SCHEDULER_Handle *sched;
 
+/**
+ * Our statistics handle.
+ */
+struct GNUNET_STATISTICS_Handle *stats;
+
+
 /**
  * Our configuration.
  */
@@ -78,57 +99,57 @@ static uint32_t max_connect_per_transport;
 /**
  * Environment for this plugin.
  */
-struct GNUNET_TRANSPORT_PluginEnvironment env;
+static struct GNUNET_TRANSPORT_PluginEnvironment env;
 
 /**
  *handle for the api provided by this plugin
  */
-struct GNUNET_TRANSPORT_PluginFunctions *api;
+static struct GNUNET_TRANSPORT_PluginFunctions *api;
+
+/**
+ * ID of the task controlling the testcase timeout
+ */
+static GNUNET_SCHEDULER_TaskIdentifier ti_timeout;
+
+#if 0
+static GNUNET_SCHEDULER_TaskIdentifier ti_download;
+#endif
+
+static unsigned int timeout_count;
 
 /**
  * Did the test pass or fail?
  */
-static int ok;
+static int fail;
+
+//static int done;
+
+pid_t pid;
 
 /**
  * Initialize Environment for this plugin
  */
-static void
+static struct GNUNET_TIME_Relative
 receive (void *cls,
-        const struct GNUNET_PeerIdentity * peer,
-        const struct GNUNET_MessageHeader * message,
-        uint32_t distance,
-        const char *sender_address,
-        size_t sender_address_len)
+         const struct GNUNET_PeerIdentity * peer,
+         const struct GNUNET_MessageHeader * message,
+         uint32_t distance,
+         struct Session *session,
+         const char *sender_address,
+         uint16_t sender_address_len)
 {
   /* do nothing */
+  return GNUNET_TIME_UNIT_ZERO;
 }
 
 void
 notify_address (void *cls,
                 const char *name,
                 const void *addr,
-                size_t addrlen, struct GNUNET_TIME_Relative expires)
-{
-}
-
-/**
- * Function called when the service shuts
- * down.  Unloads our plugins.
- *
- * @param cls closure
- * @param cfg configuration to use
- */
-static void
-unload_plugins (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
+                uint16_t addrlen,
+                struct GNUNET_TIME_Relative expires)
 {
-  GNUNET_assert (NULL ==
-                 GNUNET_PLUGIN_unload ("libgnunet_plugin_transport_udp",
-                                       api));
-  if (my_private_key != NULL)
-    GNUNET_CRYPTO_rsa_key_free (my_private_key);
 
-  ok = 0;
 }
 
 /**
@@ -136,33 +157,36 @@ unload_plugins (void *cls, const struct GNUNET_CONFIGURATION_Handle *cfg)
  * the check_address function of the plugin.
  */
 /* FIXME: won't work on IPv6 enabled systems where IPv4 mapping
- * isn't enabled (eg. FreeBSD > 4)
+ * isn't enabled (eg. FreeBSD > 4)[TESTING]
+WEAKRANDOM = YES
  */
 static void
-test_validation ()
+shutdown_clean ()
 {
-  struct sockaddr_in soaddr;
-
-  memset (&soaddr, 0, sizeof (soaddr));
-#if HAVE_SOCKADDR_IN_SIN_LEN
-  soaddr.sin_len = sizeof (soaddr);
-#endif
-  soaddr.sin_family = AF_INET;
-  soaddr.sin_port = htons (2368 /* FIXME: get from config! */ );
-  soaddr.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
-
-  api->check_address(api->cls,
-      &soaddr, sizeof (soaddr));
-
-  unload_plugins(env.cls, env.cfg);
+/*  if (stat_get_handle != NULL)
+  {
+    GNUNET_STATISTICS_get_cancel(stat_get_handle);
+  }*/
+
+  /* if ( NULL!=stats )GNUNET_STATISTICS_destroy (stats, GNUNET_YES); */
+  if (ti_timeout != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_SCHEDULER_cancel(sched,ti_timeout);
+  ti_timeout = GNUNET_SCHEDULER_NO_TASK;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unloading http plugin\n");
+  GNUNET_assert (NULL == GNUNET_PLUGIN_unload ("libgnunet_plugin_transport_http", api));
+  
+  GNUNET_SCHEDULER_shutdown(sched);
+  /* FIXME: */ fail = GNUNET_NO;
+  return;
 }
 
-
 static void
 setup_plugin_environment ()
 {
   env.cfg = cfg;
   env.sched = sched;
+  env.stats = stats;
   env.my_identity = &my_identity;
   env.cls = &env;
   env.receive = &receive;
@@ -170,6 +194,271 @@ setup_plugin_environment ()
   env.max_connections = max_connect_per_transport;
 }
 
+#if 0
+static int
+process_stat (void *cls,
+              const char *subsystem,
+              const char *name,
+              uint64_t value,
+              int is_persistent)
+{
+  stat_get_handle = NULL;
+  if (value==1)
+    {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown, plugin failed \n");
+    fail = GNUNET_YES;
+    shutdown_clean();
+    return GNUNET_YES;
+    }
+  if (value==2)
+    {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Shutdown, plugin not failed \n");
+    shutdown_clean();
+    return GNUNET_YES;
+    }
+  return GNUNET_YES;
+}
+#endif
+
+#if 0
+static void
+cont_func (void *cls, int success)
+{
+  stat_get_handle = NULL;
+}
+#endif
+
+/**
+ * Task that checks if we should try to download a hostlist.
+ * If so, we initiate the download, otherwise we schedule
+ * this task again for a later time.
+ */
+static void
+task_timeout (void *cls,
+            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  ti_timeout = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  if ( timeout_count > 15 )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Testcase timeout\n",  timeout_count);
+    fail = GNUNET_YES;
+    shutdown_clean();
+    return;
+  }
+  timeout_count++;
+
+/*  stat_get_handle = GNUNET_STATISTICS_get (stats,
+                                           "http-transport",
+                                           gettext_noop("shutdown"),
+                                           GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 2),
+                                           &cont_func,
+                                           &process_stat,
+                                           NULL);*/
+
+  ti_timeout = GNUNET_SCHEDULER_add_delayed (sched, STAT_INTERVALL, &task_timeout, NULL);
+  return;
+}
+
+#if 0
+static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
+{
+  size_t retcode;
+
+  /* in real-world cases, this would probably get this data differently
+     as this fread() stuff is exactly what the library already would do
+     by default internally */
+  retcode = fread(ptr, size, nmemb, stream);
+
+  fprintf(stderr, "*** We read %d bytes from file\n", (int) retcode);
+
+  return retcode;
+}
+#endif
+
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+};
+
+#if 0
+static size_t
+putBuffer (void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  size_t len;
+
+  struct CBC  * cbc = ptr;
+
+  len = strlen(cbc->buf);
+
+  if (( cbc->pos == len) && (len < (size * nmemb)))
+    return 0;
+  memcpy(stream, cbc->buf, len+1);
+  cbc->pos = len;
+  return len;
+}
+#endif
+
+#if 0
+static int execute (char * url)
+{
+  done = 0;
+  CURLM *multi_handle;
+  CURL *curl_handle;
+  CURLMsg *msg;
+  int msgs_left;
+  FILE * hd_src ;
+  int hd ;
+  struct stat file_info;
+  int still_running;
+  char buf[2048];
+  struct CBC cbc;
+
+  char *file = "curl.c";
+
+  cbc.buf = buf;
+  cbc.size = 2048;
+  cbc.pos = 0;
+
+  const char * txt = "Hello World!";
+  memcpy(cbc.buf,txt,strlen(txt)+1);
+  //fprintf(stderr,"%s %u\n",src,strlen(src));
+
+  /* get the file size of the local file */
+  hd = open(file, O_RDONLY) ;
+  fstat(hd, &file_info);
+  close(hd) ;
+
+  /* get a FILE * of the same file, could also be made with
+     fdopen() from the previous descriptor, but hey this is just
+     an example! */
+  hd_src = fopen(file, "rb");
+  //printf("size: %u \n", (curl_off_t) file_info.st_size);
+
+  /* get a curl handle */
+  curl_handle = curl_easy_init();
+  if( NULL == curl_handle)
+  {
+    printf("easy_init failed \n");
+    return 0;
+  }
+  curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
+  //curl_easy_setopt (curl_handle, CURLOPT_WRITEFUNCTION, &copyBuffer);
+  //curl_easy_setopt (curl_handle, CURLOPT_WRITEDATA, &cbc);
+  curl_easy_setopt (curl_handle, CURLOPT_READFUNCTION, &putBuffer);
+  curl_easy_setopt (curl_handle, CURLOPT_READDATA, &cbc);
+  curl_easy_setopt(curl_handle, CURLOPT_UPLOAD, 1L);
+  curl_easy_setopt(curl_handle, CURLOPT_PUT, 1L);
+  curl_easy_setopt(curl_handle, CURLOPT_URL, url);
+  curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) strlen(txt));
+
+  //curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t)file_info.st_size);
+
+  multi_handle = curl_multi_init();
+  curl_multi_add_handle(multi_handle, curl_handle);
+
+  while(CURLM_CALL_MULTI_PERFORM ==
+        curl_multi_perform(multi_handle, &still_running));
+
+  while(still_running)
+  {
+      struct timeval timeout;
+      int rc; /* select() return code */
+
+      fd_set fdread;
+      fd_set fdwrite;
+      fd_set fdexcep;
+      int maxfd = -1;
+
+      FD_ZERO(&fdread);
+      FD_ZERO(&fdwrite);
+      FD_ZERO(&fdexcep);
+
+      /* set a suitable timeout to play around with */
+      timeout.tv_sec = 1;
+      timeout.tv_usec = 0;
+
+      /* get file descriptors from the transfers */
+      curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+      /* In a real-world program you OF COURSE check the return code of the
+         function calls.  On success, the value of maxfd is guaranteed to be
+         greater or equal than -1.  We call select(maxfd + 1, ...), specially in
+         case of (maxfd == -1), we call select(0, ...), which is basically equal
+         to sleep. */
+
+      rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+      switch(rc)
+      {
+      case -1:
+        /* select error */
+        break;
+      case 0:
+        /* timeout, do something else */
+        break;
+      default:
+        /* one or more of curl's file descriptors say there's data to read
+           or write */
+        while(CURLM_CALL_MULTI_PERFORM ==
+              curl_multi_perform(multi_handle, &still_running));
+        break;
+      }
+  }
+
+  /* See how the transfers went */
+  while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
+    if (msg->msg == CURLMSG_DONE) {
+      int idx, found = 0;
+
+      /* Find out which handle this message is about */
+      for (idx=0; idx<1; idx++) {
+        found = (msg->easy_handle == curl_handle);
+        if(found)
+          break;
+      }
+
+      switch (idx) {
+      case 0:
+        printf("HTTP transfer completed with status %d\n", msg->data.result);
+        break;
+      }
+    }
+  }
+
+  curl_multi_cleanup(multi_handle);
+
+  curl_easy_cleanup(curl_handle);
+
+  fclose(hd_src); /* close the local file */
+  return 0;
+}
+#endif
+
+#if 0
+/**
+ * Task that checks if we should try to download a hostlist.
+ * If so, we initiate the download, otherwise we schedule
+ * this task again for a later time.
+ */
+static void
+task_download (void *cls,
+            const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  ti_download = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  execute ("http://localhost:12389/Q7BO0ELEHAT8JNENQ90112G0TACH2H2HIR4IJ2JQ28U6FV14CK44EVP26FVAEALO7HIRJFLFE6709RP6IITM64B0FU7J4RA8KPNDKN8");
+
+  return;
+}
+#endif
+
 /**
  * Runs the test.
  *
@@ -183,12 +472,23 @@ run (void *cls,
      char *const *args,
      const char *cfgfile, const struct GNUNET_CONFIGURATION_Handle *c)
 {
-  unsigned long long tneigh;
-  char *keyfile;
-  char *libname;
-
+  char * libname;
   sched = s;
   cfg = c;
+  char *keyfile;
+  unsigned long long tneigh;
+
+  /* settings up statistics */
+/*  stats = GNUNET_STATISTICS_create (sched, "http-transport", cfg);
+  if (NULL == stats)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to retrieve statistics handle\n"));
+    fail = GNUNET_YES;
+    shutdown_clean();
+    return ;
+  }*/
+
   /* parse configuration */
   if ((GNUNET_OK !=
        GNUNET_CONFIGURATION_get_value_number (c,
@@ -223,19 +523,23 @@ run (void *cls,
 
   /* load plugins... */
   setup_plugin_environment ();
-  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading udp transport plugin\n"));
-  GNUNET_asprintf (&libname, "libgnunet_plugin_transport_udp");
-
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, _("Loading HTTP transport plugin `%s'\n"),"libgnunet_plugin_transport_http");
+  GNUNET_asprintf (&libname, "libgnunet_plugin_transport_http");
   api = GNUNET_PLUGIN_load (libname, &env);
   GNUNET_free (libname);
   if (api == NULL)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                  _("Failed to load transport plugin for udp\n"));
-      /* FIXME: set some error code for main */
-      return;
-    }
-  test_validation ();
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("Failed to load transport plugin for http\n"));
+    fail = GNUNET_YES;
+    return;
+  }
+
+  ti_timeout = GNUNET_SCHEDULER_add_now (sched, &task_timeout, NULL);
+  //ti_download = GNUNET_SCHEDULER_add_now (sched, &task_download, NULL);
+
+  return;
+
 }
 
 
@@ -249,14 +553,15 @@ run (void *cls,
 int
 main (int argc, char *const *argv)
 {
+
   static struct GNUNET_GETOPT_CommandLineOption options[] = {
     GNUNET_GETOPT_OPTION_END
   };
   int ret;
   char *const argv_prog[] = {
-    "test_plugin_transport",
+    "test_plugin_transport_http",
     "-c",
-    "test_plugin_transport_data_udp.conf",
+    "test_plugin_transport_data_http.conf",
     "-L",
 #if VERBOSE
     "DEBUG",
@@ -265,23 +570,45 @@ main (int argc, char *const *argv)
 #endif
     NULL
   };
-  GNUNET_log_setup ("test-plugin-transport",
+  GNUNET_log_setup ("test_plugin_transport_http",
 #if VERBOSE
                     "DEBUG",
 #else
                     "WARNING",
 #endif
                     NULL);
-  ok = 1;                       /* set to fail */
+/*  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Starting statistics service\n");
+  pid = GNUNET_OS_start_process (NULL, NULL, "gnunet-service-statistics",
+                                 "gnunet-service-statistics",
+                                 "-L", "DEBUG",
+                                 "-c", "test_plugin_transport_data_http.conf", NULL);
+
+  fail = GNUNET_NO;
+  if (pid==-1 )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Failed to start statistics service\n");
+    fail = GNUNET_YES;
+    return fail;
+  }*/
+
   ret = (GNUNET_OK ==
          GNUNET_PROGRAM_run (5,
                              argv_prog,
-                             "test-plugin-transport",
-                             "testcase", options, &run, NULL)) ? ok : 1;
-  GNUNET_DISK_directory_remove ("/tmp/test-gnunetd-plugin-transport");
-  /* FIXME: return correct value */
-  /* return ret; */
-  return GNUNET_NO;
+                             "test_plugin_transport_http",
+                             "testcase", options, &run, NULL)) ? GNUNET_NO : GNUNET_YES;
+
+    GNUNET_DISK_directory_remove ("/tmp/test_plugin_transport_http");
+
+
+/*  if (0 != PLIBC_KILL (pid, SIGTERM))
+  {
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "Failed to kill statistics service");
+    fail = GNUNET_YES;
+  }
+  if (GNUNET_OS_process_wait(pid) != GNUNET_OK)
+    GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "waitpid");
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Killed statistics service\n");*/
+  return fail;
 }
 
-/* end of test_plugin_transport_udp.c */
+/* end of test_plugin_transport_http.c */