(no commit message)
[oweals/gnunet.git] / src / transport / plugin_transport_http.c
index 79ede78d14eeb4278c8757c407091562e6469c0a..f04929af9abeaaccb35ab267b2445d78d001fb32 100644 (file)
  */
 struct Plugin;
 
+struct CBC
+{
+  char *buf;
+  size_t pos;
+  size_t size;
+  size_t len;
+};
+
 
 /**
  * Session handle for connections.
@@ -151,6 +159,14 @@ struct Session
    */
   unsigned int is_put_in_progress;
 
+  /**
+   * Encoded hash
+   */
+  struct GNUNET_CRYPTO_HashAsciiEncoded hash;
+
+  struct CBC cbc;
+
+  CURL *curl_handle;
 };
 
 /**
@@ -163,6 +179,11 @@ struct Plugin
    */
   struct GNUNET_TRANSPORT_PluginEnvironment *env;
 
+  /**
+   * Handle to the network service.
+   */
+  struct GNUNET_SERVICE_Context *service;
+
   /**
    * List of open sessions.
    */
@@ -173,7 +194,6 @@ struct Plugin
    */
 
   unsigned int session_count;
-
 };
 
 /**
@@ -197,6 +217,12 @@ static GNUNET_SCHEDULER_TaskIdentifier http_task_v4;
 static GNUNET_SCHEDULER_TaskIdentifier http_task_v6;
 
 
+/**
+ * Our primary task for http daemon handling IPv6 connections
+ */
+static GNUNET_SCHEDULER_TaskIdentifier http_task_send;
+
+
 /**
  * Information about this plugin
  */
@@ -218,42 +244,39 @@ static char * hostname;
  */
 static struct GNUNET_CRYPTO_HashAsciiEncoded my_ascii_hash_ident;
 
+static char buf[2048];
+static char test[2048] = "HEEEELLLO";
 
 /**
- * Finds a http session in our linked list using peer identity as a key
- * @param peer peeridentity
- * @return http session corresponding to peer identity
+ * Message-Packet header.
  */
-static struct Session * find_session_by_pi( const struct GNUNET_PeerIdentity *peer )
+struct HTTPMessage
 {
-  struct Session * cur;
-  GNUNET_HashCode hc_peer;
-  GNUNET_HashCode hc_current;
+  /**
+   * size of the message, in bytes, including this header.
+   */
+  struct GNUNET_MessageHeader header;
 
-  cur = plugin->sessions;
-  hc_peer = peer->hashPubKey;
-  while (cur != NULL)
-  {
-    hc_current = cur->sender.hashPubKey;
-    if ( 0 == GNUNET_CRYPTO_hash_cmp( &hc_peer, &hc_current))
-      return cur;
-    cur = plugin->sessions->next;
-  }
-  return NULL;
-}
+  /**
+   * What is the identity of the sender (GNUNET_hash of public key)
+   */
+  struct GNUNET_PeerIdentity sender;
+
+};
 
-#if 0
 /**
  * Finds a http session in our linked list using peer identity as a key
  * @param peer peeridentity
  * @return http session corresponding to peer identity
  */
-static struct Session * find_session_by_ip( char * ip )
+static struct Session * find_session_by_pi( const struct GNUNET_PeerIdentity *peer )
 {
-  /*
   struct Session * cur;
+  GNUNET_HashCode hc_peer;
+  GNUNET_HashCode hc_current;
 
   cur = plugin->sessions;
+  hc_peer = peer->hashPubKey;
   while (cur != NULL)
   {
     hc_current = cur->sender.hashPubKey;
@@ -261,39 +284,47 @@ static struct Session * find_session_by_ip( char * ip )
       return cur;
     cur = plugin->sessions->next;
   }
-  */
   return NULL;
 }
-#endif
 
-#if 0
 /**
- * Creates a http session in our linked list by ip address
- * Only ip is set here, all other fields have to be set by calling method
- * @param peer peeridentity
- * @return created http session
+ * Create a new session
+ *
+ * @param address address the peer is using
+ * @peer  peer identity
+ * @return created session object
  */
-static struct Session * create_session_by_ip ( struct sockaddr_in * addr )
+
+static struct Session * create_session (struct sockaddr_in *address, const struct GNUNET_PeerIdentity *peer)
 {
-  struct Session * cur;
-  struct Session * last_in_list;
-  /* Create a new session object */
-  cur = GNUNET_malloc (sizeof (struct Session));
-  // FIXME: memcpy( &(cur->ip), , sizeof( struct GNUNET_PeerIdentity ) );
+  struct sockaddr_in  *addrin;
+  struct sockaddr_in6 *addrin6;
 
-  cur->next = NULL;
+  struct Session * ses = GNUNET_malloc ( sizeof( struct Session) );
+  ses->addr = GNUNET_malloc ( sizeof (struct sockaddr_in) );
 
-  /* Insert into linked list */
-  last_in_list = plugin->sessions;
-  while (last_in_list->next != NULL)
+  ses->next = NULL;
+  ses->plugin = plugin;
+
+  memcpy(ses->addr, address, sizeof (struct sockaddr_in));
+  if ( AF_INET == address->sin_family)
+  {
+    ses->ip = GNUNET_malloc (INET_ADDRSTRLEN);
+    addrin = address;
+    inet_ntop(addrin->sin_family,&(addrin->sin_addr),ses->ip,INET_ADDRSTRLEN);
+  }
+  if ( AF_INET6 == address->sin_family)
   {
-    last_in_list = last_in_list->next;
+    ses->ip = GNUNET_malloc (INET6_ADDRSTRLEN);
+    addrin6 = (struct sockaddr_in6 *) address;
+    inet_ntop(addrin6->sin6_family, &(addrin6->sin6_addr) ,ses->ip,INET6_ADDRSTRLEN);
   }
-  last_in_list->next = cur;
+  memcpy(&ses->sender, peer, sizeof (struct GNUNET_PeerIdentity));
+  GNUNET_CRYPTO_hash_to_enc(&ses->sender.hashPubKey,&(ses->hash));
+  ses->is_active = GNUNET_NO;
 
-  return cur;
+  return ses;
 }
-#endif
 
 /**
  * Callback called by MHD when a connection is terminated
@@ -321,10 +352,12 @@ acceptPolicyCallback (void *cls,
                       const struct sockaddr *addr, socklen_t addr_len)
 {
   /* Every connection is accepted, nothing more to do here */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connect!\n");
   return MHD_YES;
 }
 
 
+
 /**
  * Process GET or PUT request received via MHD.  For
  * GET, queue response that will send back our pending
@@ -350,7 +383,12 @@ accessHandlerCallback (void *cls,
   char * address = NULL;
   struct GNUNET_PeerIdentity pi_in;
   int res = GNUNET_NO;
+  size_t bytes_recv;
+  struct GNUNET_MessageHeader *gn_msg;
+  int send_error_to_client;
 
+  gn_msg = NULL;
+  send_error_to_client = GNUNET_NO;
   if ( NULL == *httpSessionCache)
   {
     /* check url for peer identity */
@@ -363,6 +401,7 @@ accessHandlerCallback (void *cls,
       MHD_destroy_response (response);
       return res;
     }
+
     conn_info = MHD_get_connection_info(session, MHD_CONNECTION_INFO_CLIENT_ADDRESS );
     /* Incoming IPv4 connection */
     if ( AF_INET == conn_info->client_addr->sin_family)
@@ -408,14 +447,7 @@ accessHandlerCallback (void *cls,
     if (cs == NULL )
     {
       /* create new session object */
-      cs = GNUNET_malloc ( sizeof( struct Session) );
-      cs->addr = GNUNET_malloc ( sizeof (struct sockaddr_in) );
-
-      cs->ip = address;
-      memcpy(cs->addr, conn_info->client_addr, sizeof (struct sockaddr_in));
-      memcpy(&cs->sender, &pi_in, sizeof (struct GNUNET_PeerIdentity));
-      cs->next = NULL;
-      cs->is_active = GNUNET_YES;
+      cs = create_session(conn_info->client_addr, &pi_in);
 
       /* Insert session into linked list */
       if ( plugin->sessions == NULL)
@@ -446,7 +478,6 @@ accessHandlerCallback (void *cls,
   {
     cs = *httpSessionCache;
   }
-
   /* Is it a PUT or a GET request */
   if ( 0 == strcmp (MHD_HTTP_METHOD_PUT, method) )
   {
@@ -455,6 +486,7 @@ accessHandlerCallback (void *cls,
     {
       /* not yet ready */
       cs->is_put_in_progress = GNUNET_YES;
+      cs->is_active = GNUNET_YES;
       return MHD_YES;
     }
     if ( *upload_data_size > 0 )
@@ -462,8 +494,45 @@ accessHandlerCallback (void *cls,
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"PUT URL: `%s'\n",url);
       GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"PUT Request: %lu bytes: `%s' \n", (*upload_data_size), upload_data);
       /* No data left */
+      bytes_recv = *upload_data_size ;
       *upload_data_size = 0;
-      /* do something with the data */
+
+      /* checking size */
+      if (bytes_recv < sizeof (struct GNUNET_MessageHeader))
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message too small, is %u bytes, has to be at least %u '\n",bytes_recv, sizeof(struct GNUNET_MessageHeader));
+        send_error_to_client = GNUNET_YES;
+      }
+
+      if ( bytes_recv > GNUNET_SERVER_MAX_MESSAGE_SIZE)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message too big, is %u bytes, maximum %u '\n",bytes_recv, GNUNET_SERVER_MAX_MESSAGE_SIZE);
+        send_error_to_client = GNUNET_YES;
+      }
+
+      struct GNUNET_MessageHeader * gn_msg = GNUNET_malloc (bytes_recv);
+      memcpy (gn_msg,upload_data,bytes_recv);
+
+      if ( ntohs(gn_msg->size) != bytes_recv )
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Message has incorrect size, is %u bytes vs %u recieved'\n",ntohs(gn_msg->size) , bytes_recv);
+        GNUNET_free (gn_msg);
+        send_error_to_client = GNUNET_YES;
+      }
+
+      if ( GNUNET_YES == send_error_to_client)
+      {
+        response = MHD_create_response_from_data (strlen (HTTP_PUT_RESPONSE),HTTP_PUT_RESPONSE, MHD_NO, MHD_NO);
+        res = MHD_queue_response (session, MHD_HTTP_BAD_REQUEST, response);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Sent HTTP/1.1: 400 BAD REQUEST as PUT Response\n",HTTP_PUT_RESPONSE, strlen (HTTP_PUT_RESPONSE), res );
+        MHD_destroy_response (response);
+        return MHD_NO;
+      }
+
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Recieved GNUnet message type %u size %u and payload %u \n",ntohs (gn_msg->type), ntohs (gn_msg->size), ntohs (gn_msg->size)-sizeof(struct GNUNET_MessageHeader));
+
+      /* forwarding message to transport */
+      plugin->env->receive(plugin->env, &(cs->sender), gn_msg, 1, cs , cs->ip, strlen(cs->ip) );
       return MHD_YES;
     }
     if ((*upload_data_size == 0) && (cs->is_put_in_progress == GNUNET_YES))
@@ -578,17 +647,139 @@ http_daemon_run (void *cls,
   return;
 }
 
-static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
+static size_t send_read_callback(void *stream, size_t size, size_t nmemb, void *ptr)
 {
-  size_t retcode;
-  /*
-  fprintf(stdout, "*** Read callback: size %u, size nmemb: %u \n", size, nmemb);
-  retcode = fread(ptr, size, nmemb, stream);
-   */
-  retcode = 0;
-  return retcode;
+  struct Session  * ses = ptr;
+  struct CBC * cbc = &(ses->cbc);
+
+  if (cbc->len > (size * nmemb))
+    return CURL_READFUNC_ABORT;
+
+  if (( cbc->pos == cbc->len) && (cbc->len < (size * nmemb)))
+    return 0;
+  memcpy(stream, cbc->buf, cbc->len);
+  cbc->pos = cbc->len;
+  return cbc->len;
+}
+
+
+static size_t send_prepare(struct Session* session );
+
+static void send_execute (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int running;
+  struct CURLMsg *msg;
+  CURLMcode mret;
+  char * current_url= "test";
+
+ // GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"send_execute\n");
+
+  http_task_send = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  do
+    {
+      running = 0;
+      mret = curl_multi_perform (multi_handle, &running);
+      //GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"send_execute %u\n", running);
+      if (running == 0)
+        {
+          do
+            {
+
+              msg = curl_multi_info_read (multi_handle, &running);
+              GNUNET_break (msg != NULL);
+              if (msg == NULL)
+                break;
+              switch (msg->msg)
+                {
+                case CURLMSG_DONE:
+                  if ( (msg->data.result != CURLE_OK) &&
+                       (msg->data.result != CURLE_GOT_NOTHING) )
+                    GNUNET_log(GNUNET_ERROR_TYPE_INFO,
+                               _("%s failed for `%s' at %s:%d: `%s'\n"),
+                               "curl_multi_perform",
+                               current_url,
+                               __FILE__,
+                               __LINE__,
+                               curl_easy_strerror (msg->data.result));
+                  else
+                    {
+                    GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+                                _("Download of hostlist `%s' completed.\n"),
+                                current_url);
+                    }
+                  return;
+                default:
+                  break;
+                }
+
+            }
+          while ( (running > 0) );
+        }
+    }
+  while (mret == CURLM_CALL_MULTI_PERFORM);
+  send_prepare(cls);
+}
+
+
+static size_t send_prepare(struct Session* session )
+{
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int max;
+  struct GNUNET_NETWORK_FDSet *grs;
+  struct GNUNET_NETWORK_FDSet *gws;
+  long to;
+  CURLMcode mret;
+
+//  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"send_prepare\n");
+  max = -1;
+  FD_ZERO (&rs);
+  FD_ZERO (&ws);
+  FD_ZERO (&es);
+  mret = curl_multi_fdset (multi_handle, &rs, &ws, &es, &max);
+  if (mret != CURLM_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("%s failed at %s:%d: `%s'\n"),
+                  "curl_multi_fdset", __FILE__, __LINE__,
+                  curl_multi_strerror (mret));
+      return -1;
+    }
+  mret = curl_multi_timeout (multi_handle, &to);
+  if (mret != CURLM_OK)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("%s failed at %s:%d: `%s'\n"),
+                  "curl_multi_timeout", __FILE__, __LINE__,
+                  curl_multi_strerror (mret));
+      return -1;
+    }
+
+  grs = GNUNET_NETWORK_fdset_create ();
+  gws = GNUNET_NETWORK_fdset_create ();
+  GNUNET_NETWORK_fdset_copy_native (grs, &rs, max + 1);
+  GNUNET_NETWORK_fdset_copy_native (gws, &ws, max + 1);
+  http_task_send = GNUNET_SCHEDULER_add_select (plugin->env->sched,
+                                   GNUNET_SCHEDULER_PRIORITY_DEFAULT,
+                                   GNUNET_SCHEDULER_NO_TASK,
+                                   GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 0),
+                                   grs,
+                                   gws,
+                                   &send_execute,
+                                   session);
+  GNUNET_NETWORK_fdset_destroy (gws);
+  GNUNET_NETWORK_fdset_destroy (grs);
+
+  /* FIXME: return bytes REALLY sent */
+  return 0;
 }
 
+
 /**
  * Function that can be used by the transport service to transmit
  * a message using the plugin.
@@ -617,8 +808,7 @@ static size_t read_callback(void *ptr, size_t size, size_t nmemb, void *stream)
  */
 static ssize_t
 http_plugin_send (void *cls,
-                      const struct GNUNET_PeerIdentity *
-                      target,
+                      const struct GNUNET_PeerIdentity *target,
                       const char *msgbuf,
                       size_t msgbuf_size,
                       unsigned int priority,
@@ -627,30 +817,30 @@ http_plugin_send (void *cls,
                       const void *addr,
                       size_t addrlen,
                       int force_address,
-                      GNUNET_TRANSPORT_TransmitContinuation
-                      cont, void *cont_cls)
+                      GNUNET_TRANSPORT_TransmitContinuation cont,
+                      void *cont_cls)
 {
   struct Session* ses;
   struct Session* ses_temp;
   int bytes_sent = 0;
-  unsigned int i_timeout;
-  /*  struct Plugin *plugin = cls; */
-  CURL *curl_handle;
-  /* CURLcode res; */
+
+  //FILE * hd_src ;
+
+  CURLMcode mret;
+  char * url;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Transport told plugin to send to peer `%s'\n",GNUNET_i2s(target));
 
   /* find session for peer */
   ses = find_session_by_pi (target);
-
+  if (NULL != ses )
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Existing session for peer `%s' found\n", GNUNET_i2s(target));
   if ( ses == NULL)
   {
     /* create new session object */
-    ses = GNUNET_malloc ( sizeof( struct Session) );
-    ses->addr = GNUNET_malloc ( sizeof (struct sockaddr_in) );
 
-    //ses->ip = address;
-    // memcpy(ses->addr, conn_info->client_addr, sizeof (struct sockaddr_in));
-    memcpy(&ses->sender, &target, sizeof (struct GNUNET_PeerIdentity));
-    ses->next = NULL;
+    /*FIXME: what is const void * really? Assuming struct sockaddr_in * ! */
+    ses = create_session((struct sockaddr_in *) addr, target);
     ses->is_active = GNUNET_YES;
 
     /* Insert session into linked list */
@@ -669,31 +859,46 @@ http_plugin_send (void *cls,
       ses_temp->next = ses;
       plugin->session_count++;
     }
-    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"New Session `%s' inserted, count %u \n", GNUNET_i2s(target), plugin->session_count);  }
-
-  char *url = "";
-
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"New Session `%s' inserted, count %u \n", GNUNET_i2s(target), plugin->session_count);
+  }
 
-  curl_handle = curl_easy_init();
-  if( NULL == curl_handle)
+  ses->curl_handle = curl_easy_init();
+  if( NULL == ses->curl_handle)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Getting cURL handle failed\n");
     return -1;
   }
 
-  i_timeout = ( timeout.value / 1000);
+  url = GNUNET_malloc( 7 + strlen(ses->ip) + 7 + strlen ((char *) &(ses->hash)) + 1);
+  GNUNET_asprintf(&url,"http://%s:%u/%s",ses->ip,12389, (char *) &(ses->hash));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"url: %s %u\n",url, 7 + strlen(ses->ip) + 7 + strlen ((char *) &(ses->hash)) + 1 );
+
+  (ses->cbc).len = msgbuf_size;
+  (ses->cbc).buf = buf;
+  memcpy(ses->cbc.buf,msgbuf,msgbuf_size);
 
-  curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
-  curl_easy_setopt(curl_handle, CURLOPT_READFUNCTION, read_callback);
-  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_TIMEOUT, timeout);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"msgbuf %s cbc: len %u cbc.buf `%s' test `%s'\n",msgbuf,ses->cbc.len,ses->cbc.buf,test);
+
+  curl_easy_setopt(ses->curl_handle, CURLOPT_VERBOSE, 1L);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_URL, url);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_PUT, 1L);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_READFUNCTION, send_read_callback);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_READDATA, ses);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) (ses->cbc).len);
+  curl_easy_setopt(curl_handle, CURLOPT_TIMEOUT, (timeout.value / 1000 ));
   curl_easy_setopt(curl_handle, CURLOPT_CONNECTTIMEOUT, HTTP_CONNECT_TIMEOUT);
-  curl_easy_setopt(curl_handle, CURLOPT_READDATA, msgbuf);
-  curl_easy_setopt(curl_handle, CURLOPT_INFILESIZE_LARGE,
-                  (curl_off_t)msgbuf_size);
 
+  mret = curl_multi_add_handle(multi_handle, ses->curl_handle);
+  if (mret != CURLM_OK)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _("%s failed at %s:%d: `%s'\n"),
+                "curl_multi_add_handle", __FILE__, __LINE__,
+                curl_multi_strerror (mret));
+    return -1;
+  }
+  bytes_sent = send_prepare (ses );
+  GNUNET_free ( url );
   return bytes_sent;
 }
 
@@ -711,6 +916,7 @@ static void
 http_plugin_disconnect (void *cls,
                             const struct GNUNET_PeerIdentity *target)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_disconnect\n");
   // struct Plugin *plugin = cls;
   // FIXME
 }
@@ -740,6 +946,7 @@ http_plugin_address_pretty_printer (void *cls,
                                         GNUNET_TRANSPORT_AddressStringCallback
                                         asc, void *asc_cls)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_address_pretty_printer\n");
   asc (asc_cls, NULL);
 }
 
@@ -765,6 +972,7 @@ http_plugin_address_suggested (void *cls,
 
   /* check if the address is plausible; if so,
      add it to our list! */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_address_suggested\n");
   return GNUNET_OK;
 }
 
@@ -785,6 +993,7 @@ http_plugin_address_to_string (void *cls,
                                    const void *addr,
                                    size_t addrlen)
 {
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_address_to_string\n");
   GNUNET_break (0);
   return NULL;
 }
@@ -799,6 +1008,7 @@ libgnunet_plugin_transport_http_done (void *cls)
   struct Plugin *plugin = api->cls;
   struct Session * cs;
   struct Session * cs_next;
+  CURLMcode mret;
 
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Unloading http plugin...\n");
 
@@ -814,6 +1024,12 @@ libgnunet_plugin_transport_http_done (void *cls)
     http_task_v6 = GNUNET_SCHEDULER_NO_TASK;
   }
 
+  if ( http_task_send != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel(plugin->env->sched, http_task_send);
+    http_task_send = GNUNET_SCHEDULER_NO_TASK;
+  }
+
   if (http_daemon_v4 != NULL)
   {
     MHD_stop_daemon (http_daemon_v4);
@@ -825,7 +1041,9 @@ libgnunet_plugin_transport_http_done (void *cls)
     http_daemon_v6 = NULL;
   }
 
-  curl_multi_cleanup(multi_handle);
+  mret = curl_multi_cleanup(multi_handle);
+  if ( CURLM_OK != mret)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"curl multihandle clean up failed");
 
   /* free all sessions */
   cs = plugin->sessions;
@@ -840,6 +1058,8 @@ libgnunet_plugin_transport_http_done (void *cls)
       cs = cs_next;
     }
 
+  /* GNUNET_SERVICE_stop (plugin->service); */
+
   GNUNET_free (plugin);
   GNUNET_free (api);
   return NULL;
@@ -854,13 +1074,29 @@ libgnunet_plugin_transport_http_init (void *cls)
 {
   struct GNUNET_TRANSPORT_PluginEnvironment *env = cls;
   struct GNUNET_TRANSPORT_PluginFunctions *api;
+  struct GNUNET_SERVICE_Context *service;
   unsigned int timeout;
   struct GNUNET_TIME_Relative gn_timeout;
   long long unsigned int port;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Starting http plugin...\n");
+
+  service = NULL;
+  /*
+  service = GNUNET_SERVICE_start ("transport-http", env->sched, env->cfg);
+  if (service == NULL)
+    {
+      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "", _
+                       ("Failed to start service for `%s' transport plugin.\n"),
+                       "http");
+      return NULL;
+    }
+    */
+
   plugin = GNUNET_malloc (sizeof (struct Plugin));
   plugin->env = env;
   plugin->sessions = NULL;
+  plugin->service = service;
   api = GNUNET_malloc (sizeof (struct GNUNET_TRANSPORT_PluginFunctions));
   api->cls = plugin;
   api->send = &http_plugin_send;
@@ -874,7 +1110,6 @@ libgnunet_plugin_transport_http_init (void *cls)
   /* Hashing our identity to use it in URLs */
   GNUNET_CRYPTO_hash_to_enc ( &(plugin->env->my_identity->hashPubKey), &my_ascii_hash_ident);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Starting http plugin...\n");
   /* Reading port number from config file */
   if ((GNUNET_OK !=
        GNUNET_CONFIGURATION_get_value_number (env->cfg,
@@ -931,7 +1166,15 @@ libgnunet_plugin_transport_http_init (void *cls)
 
   /* Initializing cURL */
   multi_handle = curl_multi_init();
-
+  if ( NULL == multi_handle )
+  {
+    GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+                     "http",
+                     _("Could not initialize curl multi handle, failed to start http plugin!\n"),
+                     "transport-http");
+    libgnunet_plugin_transport_http_done (api);
+    return NULL;
+  }
   return api;
 }