(no commit message)
[oweals/gnunet.git] / src / transport / plugin_transport_http.c
index c2f531b54d2ea234e82482906283562e828eb371..7984529343dd4381b8a54a5b311ed3c0b18eb5f6 100644 (file)
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet
-     (C) 2003, 2004, 2005, 2006, 2007, 2008 Christian Grothoff (and other contributing authors)
+     (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Christian Grothoff (and other contributing authors)
 
      GNUnet is free software; you can redistribute it and/or modify
      it under the terms of the GNU General Public License as published
 */
 
 /**
- * @file transport/plugin_transport_http.c
- * @brief Implementation of the HTTP transport service
+ * @file transport/plugin_transport_template.c
+ * @brief template for a new transport service
  * @author Christian Grothoff
  */
 
 #include "platform.h"
-#include "gnunet_util.h"
+#include "gnunet_constants.h"
 #include "gnunet_protocols.h"
-#include "gnunet_transport.h"
-#include "gnunet_stats_service.h"
-#include "gnunet_upnp_service.h"
-#include <stdint.h>
-#include <microhttpd.h>
+#include "gnunet_connection_lib.h"
+#include "gnunet_server_lib.h"
+#include "gnunet_service_lib.h"
+#include "gnunet_statistics_service.h"
+#include "gnunet_transport_service.h"
+#include "gnunet_resolver_service.h"
+#include "plugin_transport.h"
+#include "gnunet_os_lib.h"
+#include "microhttpd.h"
 #include <curl/curl.h>
-#include "ip.h"
 
+
+#define DEBUG_CURL GNUNET_CURL
 #define DEBUG_HTTP GNUNET_NO
 
 /**
- * Disable GET (for debugging only!).  Must be GNUNET_YES
- * in production use!
+ * Text of the response sent back after the last bytes of a PUT
+ * request have been received (just to formally obey the HTTP
+ * protocol).
  */
-#define DO_GET GNUNET_YES
+#define HTTP_PUT_RESPONSE "Thank you!"
 
 /**
- * After how much time of the core not being associated with a http
- * connection anymore do we close it?
- *
- * Needs to be larger than SECONDS_INACTIVE_DROP in
- * core's connection.s
+ * After how long do we expire an address that we
+ * learned from another peer if it is not reconfirmed
+ * by anyone?
  */
-#define HTTP_TIMEOUT (600 * GNUNET_CRON_SECONDS)
+#define LEARNED_ADDRESS_EXPIRATION GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_HOURS, 6)
 
 /**
- * How often do we re-issue GET requests?
+ * Page returned if request invalid
  */
-#define HTTP_GET_REFRESH (5 * GNUNET_CRON_SECONDS)
+#define HTTP_ERROR_RESPONSE "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\"><HTML><HEAD><TITLE>404 Not Found</TITLE></HEAD><BODY><H1>Not Found</H1>The requested URL was not found on this server.<P><HR><ADDRESS></ADDRESS></BODY></HTML>"
 
 /**
- * Default maximum size of the HTTP read and write buffer.
+ * Timeout for a http connect
  */
-#define HTTP_BUF_SIZE (64 * 1024)
+#define HTTP_CONNECT_TIMEOUT 30
 
 /**
- * Text of the response sent back after the last bytes of a PUT
- * request have been received (just to formally obey the HTTP
- * protocol).
+ * Timeout for a http connect
  */
-#define HTTP_PUT_RESPONSE "Thank you!"
+#define HTTP_MESSAGE_INITIAL_BUFFERSIZE GNUNET_SERVER_MAX_MESSAGE_SIZE
 
-#define MY_TRANSPORT_NAME "HTTP"
-#include "common.c"
 
 /**
- * Client-side data per PUT request.
+ * Encapsulation of all of the state of the plugin.
  */
-struct HTTPPutData
-{
-  /**
-   * This is a linked list.
-   */
-  struct HTTPPutData *next;
+struct Plugin;
 
+/**
+ * Network format for IPv4 addresses.
+ */
+struct IPv4HttpAddress
+{
   /**
-   * Handle to our CURL request.
+   * IPv4 address, in network byte order.
    */
-  CURL *curl_put;
+  uint32_t ipv4_addr;
 
   /**
-   * Last time we made progress with the PUT.
+   * Port number, in network byte order.
    */
-  GNUNET_CronTime last_activity;
+  uint16_t u_port;
 
-  /**
-   * The message we are sending.
-   */
-  char *msg;
+};
 
-  /**
-   * Size of msg.
-   */
-  unsigned int size;
 
+/**
+ * Network format for IPv6 addresses.
+ */
+struct IPv6HttpAddress
+{
   /**
-   * Current position in msg.
+   * IPv6 address.
    */
-  unsigned int pos;
+  struct in6_addr ipv6_addr;
 
   /**
-   * Are we done sending?  Set to 1 after we
-   * completed sending and started to receive
-   * a response ("Thank you!") or once the
-   * timeout has been reached.
+   * Port number, in network byte order.
    */
-  int done;
+  uint16_t u6_port;
 
 };
 
+
+
 /**
- * Server-side data per PUT request.
+ *  Message to send using http
  */
-struct MHDPutData
+struct HTTP_Message
 {
   /**
-   * This is a linked list.
-   */
-  struct MHDPutData *next;
-
-  /**
-   * MHD connection handle for this request.
-   */
-  struct MHD_Connection *session;
-
-  /**
-   * Last time we received data on this PUT
-   * connection.
+   * Next field for linked list
    */
-  GNUNET_CronTime last_activity;
+  struct HTTP_Message * next;
 
   /**
-   * Read buffer for the header (from PUT)
+   * buffer containing data to send
    */
-  char rbuff1[sizeof (GNUNET_MessageHeader)];
+  char *buf;
 
   /**
-   * The read buffer (used only receiving PUT data).
+   * amount of data already sent
    */
-  char *rbuff2;
+  size_t pos;
 
   /**
-   * Number of valid bytes in rbuff1
+   * amount of data to sent
    */
-  unsigned int rpos1;
+  size_t len;
 
-  /**
-   * Number of valid bytes in rbuff2
-   */
-  unsigned int rpos2;
-
-
-  /**
-   * Size of the rbuff2 buffer.
-   */
-  unsigned int rsize2;
+  char * dest_url;
 
   /**
-   * Should we sent a response for this PUT yet?
+   * Continuation function to call once the transmission buffer
+   * has again space available.  NULL if there is no
+   * continuation to call.
    */
-  int ready;
+  GNUNET_TRANSPORT_TransmitContinuation transmit_cont;
 
   /**
-   * Have we sent a response for this PUT yet?
+   * Closure for transmit_cont.
    */
-  int done;
-
+  void *transmit_cont_cls;
 };
 
+
 /**
- * Server-side data for a GET request.
+ * Session handle for connections.
  */
-struct MHDGetData
+struct Session
 {
 
   /**
-   * This is a linked list.
+   * Stored in a linked list.
    */
-  struct MHDGetData *next;
+  struct Session *next;
 
   /**
-   * MHD connection handle for this request.
+   * Pointer to the global plugin struct.
    */
-  struct MHD_Connection *session;
+  struct Plugin *plugin;
 
   /**
-   * GET session response handle
+   * To whom are we talking to (set to our identity
+   * if we are still waiting for the welcome message)
    */
-  struct MHD_Response *get;
+  struct GNUNET_PeerIdentity sender;
 
   /**
-   * My HTTP session.
+   * Sender's url
    */
-  struct HTTPSession *httpsession;
+  char * url;
 
   /**
-   * The write buffer (for sending GET response)
+   * Sender's ip address to distinguish between incoming connections
    */
-  char *wbuff;
+  char * ip;
 
   /**
-   * What was the last time we were able to
-   * transmit data using the current get handle?
+   * Sender's ip address to distinguish between incoming connections
    */
-  GNUNET_CronTime last_get_activity;
+  struct sockaddr_in * addr_inbound;
 
   /**
-   * Current write position in wbuff
+   * Sender's ip address recieved by transport
    */
-  unsigned int woff;
+  struct sockaddr_in * addr_outbound;
 
   /**
-   * Number of valid bytes in wbuff (starting at woff)
+   * Did we initiate the connection (GNUNET_YES) or the other peer (GNUNET_NO)?
    */
-  unsigned int wpos;
-
-  /**
-   * Size of the write buffer.
-   */
-  unsigned int wsize;
-
-};
-
-/**
- * Transport Session handle.
- */
-typedef struct HTTPSession
-{
+  unsigned int is_client;
 
   /**
-   * GNUNET_TSession for this session.
+   * Is the connection active (GNUNET_YES) or terminated (GNUNET_NO)?
    */
-  GNUNET_TSession *tsession;
+  unsigned int is_active;
 
   /**
-   * To whom are we talking to.
+   * At what time did we reset last_received last?
    */
-  GNUNET_PeerIdentity sender;
+  struct GNUNET_TIME_Absolute last_quota_update;
 
   /**
-   * number of users of this session
+   * How many bytes have we received since the "last_quota_update"
+   * timestamp?
    */
-  unsigned int users;
+  uint64_t last_received;
 
   /**
-   * Has this session been destroyed?
+   * Number of bytes per ms that this peer is allowed
+   * to send to us.
    */
-  int destroyed;
+  uint32_t quota;
 
   /**
-   * Are we client or server?  Determines which of the
-   * structs in the union below is being used for this
-   * connection!
+   * Is there a HTTP/PUT in progress?
    */
-  int is_client;
+  unsigned int is_put_in_progress;
 
   /**
-   * Is MHD still using this session handle?
+   * Is there a HTTP/PUT in progress?
    */
-  int is_mhd_active;
+  unsigned int is_bad_request;
 
   /**
-   * Data maintained for the http client-server connection
-   * (depends on if we are client or server).
+   * Encoded hash
    */
-  union
-  {
-
-    struct
-    {
-      /**
-       * Active PUT requests (linked list).
-       */
-      struct MHDPutData *puts;
-
-#if DO_GET
-      /**
-       * Active GET requests (linked list; most
-       * recent received GET is the head of the list).
-       */
-      struct MHDGetData *gets;
-#endif
-
-    } server;
-
-    struct
-    {
-
-      /**
-       * Address of the other peer.
-       */
-      HostAddress address;
-
-#if DO_GET
-      /**
-       * Last time the GET was active.
-       */
-      GNUNET_CronTime last_get_activity;
-
-      /**
-       * What was the last time we were able to
-       * transmit data using the current get handle?
-       */
-      GNUNET_CronTime last_get_initiated;
-
-      /**
-       * GET operation
-       */
-      CURL *get;
-
-      /**
-       * Read buffer for the header (from GET).
-       */
-      char rbuff1[sizeof (GNUNET_MessageHeader)];
-
-      /**
-       * The read buffer (used only receiving GET data).
-       */
-      char *rbuff2;
-
-      /**
-       * Number of valid bytes in rbuff1
-       */
-      unsigned int rpos1;
-
-      /**
-       * Number of valid bytes in rbuff2
-       */
-      unsigned int rpos2;
-
-      /**
-       * Current size of the read buffer rbuff2.
-       */
-      unsigned int rsize2;
-#endif
-
-      /**
-       * URL of the get and put operations.
-       */
-      char *url;
-
-      /**
-       * Linked list of PUT operations.
-       */
-      struct HTTPPutData *puts;
-
-    } client;
-
-  } cs;
-
-} HTTPSession;
-
-/* *********** globals ************* */
+  struct GNUNET_CRYPTO_HashAsciiEncoded hash;
 
-static int stat_bytesReceived;
+  struct HTTP_Message * pending_outbound_msg;;
 
-static int stat_bytesSent;
+  struct HTTP_Message * pending_inbound_msg;
 
-static int stat_bytesDropped;
-
-static int stat_get_issued;
-
-static int stat_get_received;
-
-static int stat_put_issued;
-
-static int stat_put_received;
-
-static int stat_select_calls;
-
-static int stat_send_calls;
-
-static int stat_connect_calls;
+  CURL *curl_handle;
+};
 
-static int stat_curl_send_callbacks;
+/**
+ * Encapsulation of all of the state of the plugin.
+ */
+struct Plugin
+{
+  /**
+   * Our environment.
+   */
+  struct GNUNET_TRANSPORT_PluginEnvironment *env;
 
-static int stat_curl_receive_callbacks;
+  /**
+   * Handle to the network service.
+   */
+  struct GNUNET_SERVICE_Context *service;
 
-static int stat_mhd_access_callbacks;
+  unsigned int port_inbound;
 
-static int stat_mhd_read_callbacks;
+  /**
+   * List of open sessions.
+   */
+  struct Session *sessions;
 
-static int stat_mhd_close_callbacks;
+  /**
+   * Number of active sessions
+   */
 
-static int stat_connect_calls;
+  unsigned int session_count;
+};
 
 /**
- * How many requests do we have currently pending
- * (with libcurl)?
+ * Daemon for listening for new IPv4 connections.
  */
-static unsigned int http_requests_pending;
-
-static struct GNUNET_DISK_FileHandle signal_pipe[2];
-
-static char *proxy;
+static struct MHD_Daemon *http_daemon_v4;
 
 /**
- * Daemon for listening for new connections.
+ * Daemon for listening for new IPv6connections.
  */
-static struct MHD_Daemon *mhd_daemon;
+static struct MHD_Daemon *http_daemon_v6;
 
 /**
- * Curl multi for managing client operations.
+ * Our primary task for http daemon handling IPv4 connections
  */
-static CURLM *curl_multi;
+static GNUNET_SCHEDULER_TaskIdentifier http_task_v4;
 
 /**
- * Set to GNUNET_YES while the transport is running.
+ * Our primary task for http daemon handling IPv6 connections
  */
-static int http_running;
+static GNUNET_SCHEDULER_TaskIdentifier http_task_v6;
+
 
 /**
- * Thread running libcurl activities.
+ * The task sending data
  */
-static struct GNUNET_ThreadHandle *curl_thread;
+static GNUNET_SCHEDULER_TaskIdentifier http_task_send;
+
 
 /**
- * Array of currently active HTTP sessions.
+ * Information about this plugin
  */
-static GNUNET_TSession **tsessions;
+static struct Plugin *plugin;
 
 /**
- * Number of valid entries in tsessions.
+ * cURL Multihandle
  */
-static unsigned int tsessionCount;
+static CURLM *multi_handle;
 
 /**
- * Sie of the tsessions array.
+ * Our hostname
  */
-static unsigned int tsessionArrayLength;
+static char * hostname;
 
 /**
- * Lock for concurrent access to all structures used
- * by http, including CURL.
+ * Our ASCII encoded, hashed peer identity
+ * This string is used to distinguish between connections and is added to the urls
  */
-static struct GNUNET_Mutex *lock;
+static struct GNUNET_CRYPTO_HashAsciiEncoded my_ascii_hash_ident;
 
+struct GNUNET_TIME_Relative timeout;
 
 /**
- * Signal select thread that its selector
- * set may have changed.
+ * 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 void
-signal_select ()
+static struct Session * find_session_by_pi( const struct GNUNET_PeerIdentity *peer )
 {
-  static char c;
-  GNUNET_DISK_file_write (signal_pipe[1], &c, sizeof (c));
+  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;
+    if ( 0 == GNUNET_CRYPTO_hash_cmp( &hc_peer, &hc_current))
+      return cur;
+    cur = plugin->sessions->next;
+  }
+  return NULL;
 }
 
 /**
- * Check if we are allowed to connect to the given IP.
+ * Finds a http session in our linked list using libcurl handle as a key
+ * Needed when sending data with libcurl to differentiate between sessions
+ * @param handle peeridentity
+ * @return http session corresponding to peer identity
  */
-static int
-acceptPolicyCallback (void *cls,
-                      const struct sockaddr *addr, socklen_t addr_len)
+static struct Session * find_session_by_curlhandle( CURL* handle )
 {
-  if (GNUNET_NO != is_rejected_tester (addr, addr_len))
-    return MHD_NO;
-  return MHD_YES;
+  struct Session * cur;
+
+  cur = plugin->sessions;
+  while (cur != NULL)
+  {
+    if ( handle == cur->curl_handle )
+      return cur;
+    cur = plugin->sessions->next;
+  }
+  return NULL;
 }
 
 /**
- * Disconnect from a remote node. May only be called
- * on sessions that were acquired by the caller first.
- * For the core, aquiration means to call associate or
- * connect. The number of disconnects must match the
- * number of calls to connect+associate.
+ * Create a new session
  *
- * Sessions are actually discarded in cleanup_connections.
- *
- *
- * @param tsession the session that is closed
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ * @param address address the peer is using inbound
+ * @param address address the peer is using outbound
+ * @param peer identity
+ * @return created session object
  */
-static int
-httpDisconnect (GNUNET_TSession * tsession)
+static struct Session * create_session (struct sockaddr_in *addr_in, struct sockaddr_in *addr_out, const struct GNUNET_PeerIdentity *peer)
 {
-  HTTPSession *httpsession = tsession->internal;
-  if (httpsession == NULL)
-    {
-      GNUNET_free (tsession);
-      return GNUNET_OK;
-    }
-  GNUNET_mutex_lock (lock);
-  httpsession->users--;
-  GNUNET_mutex_unlock (lock);
-  return GNUNET_OK;
-}
+  struct sockaddr_in  *addrin;
+  struct sockaddr_in6 *addrin6;
+  struct Session * ses = GNUNET_malloc ( sizeof( struct Session) );
+
+  ses->addr_outbound = GNUNET_malloc ( sizeof (struct sockaddr_in) );
 
-static void
-destroy_tsession (GNUNET_TSession * tsession)
-{
-  HTTPSession *httpsession = tsession->internal;
-  struct HTTPPutData *pos;
-  struct HTTPPutData *next;
-#if DO_GET
-  struct MHDGetData *gpos;
-  struct MHDGetData *gnext;
-#endif
-  struct MHD_Response *r;
-  int i;
 
-  GNUNET_mutex_lock (lock);
-  for (i = 0; i < tsessionCount; i++)
+  ses->next = NULL;
+  ses->plugin = plugin;
+  if (NULL != addr_in)
+  {
+    ses->addr_inbound  = GNUNET_malloc ( sizeof (struct sockaddr_in) );
+    memcpy(ses->addr_inbound, addr_in, sizeof (struct sockaddr_in));
+    if ( AF_INET == addr_in->sin_family)
     {
-      if (tsessions[i] == tsession)
-        {
-          tsessions[i] = tsessions[--tsessionCount];
-          break;
-        }
+      ses->ip = GNUNET_malloc (INET_ADDRSTRLEN);
+      addrin = addr_in;
+      inet_ntop(addrin->sin_family,&(addrin->sin_addr),ses->ip,INET_ADDRSTRLEN);
     }
-  if (httpsession->is_client)
+    if ( AF_INET6 == addr_in->sin_family)
     {
-#if DO_GET
-      curl_multi_remove_handle (curl_multi, httpsession->cs.client.get);
-      http_requests_pending--;
-      signal_select ();
-      curl_easy_cleanup (httpsession->cs.client.get);
-      GNUNET_array_grow (httpsession->cs.client.rbuff2,
-                         httpsession->cs.client.rsize2, 0);
-#endif
-      GNUNET_free_non_null (httpsession->cs.client.url);
-      pos = httpsession->cs.client.puts;
-      while (pos != NULL)
-        {
-          next = pos->next;
-          curl_multi_remove_handle (curl_multi, pos->curl_put);
-          http_requests_pending--;
-          signal_select ();
-          curl_easy_cleanup (pos->curl_put);
-          GNUNET_free (pos->msg);
-          GNUNET_free (pos);
-          pos = next;
-        }
-      GNUNET_free (httpsession);
-      GNUNET_free (tsession);
+      ses->ip = GNUNET_malloc (INET6_ADDRSTRLEN);
+      addrin6 = (struct sockaddr_in6 *) addr_in;
+      inet_ntop(addrin6->sin6_family, &(addrin6->sin6_addr) ,ses->ip,INET6_ADDRSTRLEN);
     }
+  }
   else
-    {
-      httpsession->destroyed = GNUNET_YES;
-      GNUNET_GE_BREAK (NULL, httpsession->cs.server.puts == NULL);
-#if DO_GET
-      gpos = httpsession->cs.server.gets;
-      while (gpos != NULL)
-        {
-          GNUNET_array_grow (gpos->wbuff, gpos->wsize, 0);
-          r = gpos->get;
-          gpos->get = NULL;
-          gnext = gpos->next;
-          MHD_destroy_response (r);
-          gpos = gnext;
-        }
-      httpsession->cs.server.gets = NULL;
-#endif
-      GNUNET_free (httpsession->tsession);
-      GNUNET_free (httpsession);
-    }
-  GNUNET_mutex_unlock (lock);
-}
+    ses->addr_inbound = NULL;
 
-/**
- * MHD is done handling a request.  Cleanup
- * the respective transport state.
- */
-static void
-requestCompletedCallback (void *unused,
-                          struct MHD_Connection *session,
-                          void **httpSessionCache)
-{
-  HTTPSession *httpsession = *httpSessionCache;
-  struct MHDPutData *pprev;
-  struct MHDPutData *ppos;
-#if DO_GET
-  struct MHDGetData *gprev;
-  struct MHDGetData *gpos;
-#endif
+  if (NULL != addr_out)
+  {
+    ses->addr_outbound  = GNUNET_malloc ( sizeof (struct sockaddr_in) );
+    memcpy(ses->addr_outbound, addr_out, sizeof (struct sockaddr_in));
+  }
+  else
+    ses->addr_outbound = NULL;
 
-  if (stats != NULL)
-    stats->change (stat_mhd_close_callbacks, 1);
-  if (httpsession == NULL)
-    return;                     /* oops */
-  GNUNET_GE_ASSERT (NULL, !httpsession->is_client);
-  pprev = NULL;
-  ppos = httpsession->cs.server.puts;
-  while (ppos != NULL)
-    {
-      if (ppos->session == session)
-        {
-          ppos->last_activity = 0;
-          signal_select ();
-          return;
-        }
-      pprev = ppos;
-      ppos = ppos->next;
-    }
-#if DO_GET
-  gprev = NULL;
-  gpos = httpsession->cs.server.gets;
-  while (gpos != NULL)
-    {
-      if (gpos->session == session)
-        {
-          gpos->last_get_activity = 0;
-          signal_select ();
-          return;
-        }
-      gprev = gpos;
-      gpos = gpos->next;
-    }
-#endif
-  httpsession->is_mhd_active--;
-}
+  memcpy(&ses->sender, peer, sizeof (struct GNUNET_PeerIdentity));
+  GNUNET_CRYPTO_hash_to_enc(&ses->sender.hashPubKey,&(ses->hash));
+  ses->is_active = GNUNET_NO;
+  ses->pending_inbound_msg = GNUNET_malloc( sizeof (struct HTTP_Message));
+  ses->pending_inbound_msg->buf = GNUNET_malloc(GNUNET_SERVER_MAX_MESSAGE_SIZE);
+  ses->pending_inbound_msg->len = GNUNET_SERVER_MAX_MESSAGE_SIZE;
+  ses->pending_inbound_msg->pos = 0;
 
-/**
- * A (core) Session is to be associated with a transport session. The
- * transport service may want to know in order to call back on the
- * core if the connection is being closed. Associate can also be
- * called to test if it would be possible to associate the session
- * later, in this case the argument session is NULL. This can be used
- * to test if the connection must be closed by the core or if the core
- * can assume that it is going to be self-managed (if associate
- * returns GNUNET_OK and session was NULL, the transport layer is responsible
- * for eventually freeing resources associated with the tesession). If
- * session is not NULL, the core takes responsbility for eventually
- * calling disconnect.
- *
- * @param tsession the session handle passed along
- *   from the call to receive that was made by the transport
- *   layer
- * @return GNUNET_OK if the session could be associated,
- *         GNUNET_SYSERR if not.
- */
-static int
-httpAssociate (GNUNET_TSession * tsession)
-{
-  HTTPSession *httpSession;
 
-  if (tsession == NULL)
-    {
-      GNUNET_GE_BREAK (NULL, 0);
-      return GNUNET_SYSERR;
-    }
-  httpSession = tsession->internal;
-  GNUNET_mutex_lock (lock);
-  if (httpSession->destroyed == GNUNET_YES)
-    {
-      GNUNET_mutex_unlock (lock);
-      return GNUNET_SYSERR;
-    }
-  httpSession->users++;
-  GNUNET_mutex_unlock (lock);
-  return GNUNET_OK;
+  return ses;
 }
 
 /**
- * Add a new session to the array watched by the select thread.  Grows
- * the array if needed.  If the caller wants to do anything useful
- * with the return value, it must have the lock before
- * calling.  It is ok to call this function without holding lock if
- * the return value is ignored.
+ * Callback called by MHD when a connection is terminated
  */
-static unsigned int
-addTSession (GNUNET_TSession * tsession)
+static void requestCompletedCallback (void *cls, struct MHD_Connection * connection, void **httpSessionCache)
 {
-  unsigned int i;
-
-  GNUNET_mutex_lock (lock);
-  if (tsessionCount == tsessionArrayLength)
-    GNUNET_array_grow (tsessions, tsessionArrayLength,
-                       tsessionArrayLength * 2);
-  i = tsessionCount;
-  tsessions[tsessionCount++] = tsession;
-  GNUNET_mutex_unlock (lock);
-  return i;
+  struct Session * cs;
+
+  cs = *httpSessionCache;
+  if (cs != NULL)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Connection from peer `%s' was terminated\n",GNUNET_i2s(&cs->sender));
+    /* session set to inactive */
+    cs->is_active = GNUNET_NO;
+    cs->is_put_in_progress = GNUNET_NO;
+  }
+  return;
 }
 
-#if DO_GET
 /**
- * Callback for processing GET requests if our side is the
- * MHD HTTP server.
- *
- * @param cls the HTTP session
- * @param pos read-offset in the stream
- * @param buf where to write the data
- * @param max how much data to write (at most)
- * @return number of bytes written, 0 is allowed!
+ * Check if we are allowed to connect to the given IP.
  */
 static int
-contentReaderCallback (void *cls, uint64_t pos, char *buf, int max)
+acceptPolicyCallback (void *cls,
+                      const struct sockaddr *addr, socklen_t addr_len)
 {
-  struct MHDGetData *mgd = cls;
-
-  if (stats != NULL)
-    stats->change (stat_mhd_read_callbacks, 1);
-  GNUNET_mutex_lock (lock);
-  if (mgd->wpos < max)
-    max = mgd->wpos;
-  memcpy (buf, &mgd->wbuff[mgd->woff], max);
-  mgd->wpos -= max;
-  mgd->woff += max;
-  if (max > 0)
-    mgd->last_get_activity = GNUNET_get_time ();
-  if (mgd->wpos == 0)
-    mgd->woff = 0;
-  GNUNET_mutex_unlock (lock);
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP returns %u bytes in MHD's GET handler.\n", max);
-#endif
-  if (stats != NULL)
-    stats->change (stat_bytesSent, max);
-  if ((max == 0) && (mgd->httpsession->cs.server.gets != mgd))
-    return -1;                  /* end of response (another GET replaces this one) */
-  return max;
+  /* Every connection is accepted, nothing more to do here */
+  return MHD_YES;
 }
-#endif
 
-#if DO_GET
-/**
- * Notification that libmicrohttpd no longer needs the
- * response object.
- */
-static void
-contentReaderFreeCallback (void *cls)
-{
-  struct MHDGetData *mgd = cls;
 
-  GNUNET_GE_ASSERT (NULL, mgd->get == NULL);
-  GNUNET_array_grow (mgd->wbuff, mgd->wsize, 0);
-  GNUNET_free (mgd);
-}
-#endif
+int serror;
 
 /**
  * Process GET or PUT request received via MHD.  For
@@ -757,1340 +475,1238 @@ accessHandlerCallback (void *cls,
                        const char *upload_data,
                        size_t * upload_data_size, void **httpSessionCache)
 {
-  GNUNET_TSession *tsession;
-  struct MHDPutData *put;
-  struct MHDGetData *get;
-  HTTPSession *httpSession;
   struct MHD_Response *response;
-  GNUNET_HashCode client;
-  int i;
-  unsigned int have;
-  GNUNET_MessageHeader *hdr;
-  GNUNET_TransportPacket *mp;
-  unsigned int cpy;
-  unsigned int poff;
-
-  if (stats != NULL)
-    stats->change (stat_mhd_access_callbacks, 1);
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/MHD receives `%s' request.\n", method);
-#endif
-  /* convert URL to sender peer id */
-  if ((strlen (url) < 2)
-      || (GNUNET_OK != GNUNET_enc_to_hash (&url[1], &client)))
+  struct Session * cs;
+  struct Session * cs_temp;
+  const union MHD_ConnectionInfo * conn_info;
+  struct sockaddr_in  *addrin;
+  struct sockaddr_in6 *addrin6;
+  char * address = NULL;
+  struct GNUNET_PeerIdentity pi_in;
+  int res = GNUNET_NO;
+  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 */
+    res = GNUNET_CRYPTO_hash_from_string ( &url[1], &(pi_in.hashPubKey));
+    if ( GNUNET_SYSERR == res )
     {
-      /* invalid request */
-      /* GNUNET_GE_BREAK_OP (NULL, 0); -- this happens a lot, most likely
-         somebody scanning for MyDoom.X-opened backdoors */
-      return MHD_NO;
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Peer has no valid ident\n");
+      response = MHD_create_response_from_data (strlen (HTTP_ERROR_RESPONSE),HTTP_ERROR_RESPONSE, MHD_NO, MHD_NO);
+      res = MHD_queue_response (session, MHD_HTTP_NOT_FOUND, response);
+      MHD_destroy_response (response);
+      return res;
     }
 
-  /* check if we already have a session for this */
-  httpSession = *httpSessionCache;
-  if (httpSession == NULL)
+    conn_info = MHD_get_connection_info(session, MHD_CONNECTION_INFO_CLIENT_ADDRESS );
+    /* Incoming IPv4 connection */
+    if ( AF_INET == conn_info->client_addr->sin_family)
     {
-      /* new http connection */
-      if (stats != NULL)
-        {
-          if (0 == strcasecmp (MHD_HTTP_METHOD_PUT, method))
-            stats->change (stat_put_received, 1);
-          else
-            stats->change (stat_get_received, 1);
-        }
-      GNUNET_mutex_lock (lock);
-      for (i = 0; i < tsessionCount; i++)
+      address = GNUNET_malloc (INET_ADDRSTRLEN);
+      addrin = conn_info->client_addr;
+      inet_ntop(addrin->sin_family, &(addrin->sin_addr),address,INET_ADDRSTRLEN);
+    }
+    /* Incoming IPv6 connection */
+    if ( AF_INET6 == conn_info->client_addr->sin_family)
+    {
+      address = GNUNET_malloc (INET6_ADDRSTRLEN);
+      addrin6 = (struct sockaddr_in6 *) conn_info->client_addr;
+      inet_ntop(addrin6->sin6_family, &(addrin6->sin6_addr),address,INET6_ADDRSTRLEN);
+    }
+    /* find existing session for address */
+    cs = NULL;
+    if (plugin->session_count > 0)
+    {
+      cs = plugin->sessions;
+      while ( NULL != cs)
+      {
+
+        /* Comparison based on ip address */
+        // res = (0 == memcmp(&(conn_info->client_addr->sin_addr),&(cs->addr->sin_addr), sizeof (struct in_addr))) ? GNUNET_YES : GNUNET_NO;
+
+        /* Comparison based on ip address, port number and address family */
+        // res = (0 == memcmp((conn_info->client_addr),(cs->addr), sizeof (struct sockaddr_in))) ? GNUNET_YES : GNUNET_NO;
+
+        /* Comparison based on PeerIdentity */
+        res = (0 == memcmp(&pi_in,&(cs->sender), sizeof (struct GNUNET_PeerIdentity))) ? GNUNET_YES : GNUNET_NO;
+
+        if ( GNUNET_YES  == res)
         {
-          tsession = tsessions[i];
-          httpSession = tsession->internal;
-          if ((0 ==
-               memcmp (&httpSession->sender, &client,
-                       sizeof (GNUNET_HashCode)))
-              && (httpSession->is_client == GNUNET_NO))
-            break;
-          tsession = NULL;
-          httpSession = NULL;
+          /* existing session for this address found */
+          GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Session `%s' found\n",address);
+          break;
         }
-      GNUNET_mutex_unlock (lock);
+        cs = cs->next;
+      }
     }
-  /* create new session if necessary */
-  if (httpSession == NULL)
+    /* no existing session, create a new one*/
+    if (cs == NULL )
     {
-#if DEBUG_HTTP
-      GNUNET_GE_LOG (coreAPI->ectx,
-                     GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                     "HTTP/MHD creates new session for request from `%s'.\n",
-                     &url[1]);
-#endif
-      httpSession = GNUNET_malloc (sizeof (HTTPSession));
-      memset (httpSession, 0, sizeof (HTTPSession));
-      httpSession->sender.hashPubKey = client;
-      httpSession->users = 0;   /* MHD */
-      tsession = GNUNET_malloc (sizeof (GNUNET_TSession));
-      memset (tsession, 0, sizeof (GNUNET_TSession));
-      tsession->ttype = GNUNET_TRANSPORT_PROTOCOL_NUMBER_HTTP;
-      tsession->internal = httpSession;
-      tsession->peer.hashPubKey = client;
-      httpSession->tsession = tsession;
-      addTSession (tsession);
+      /* create new session object */
+      cs = create_session(conn_info->client_addr, NULL, &pi_in);
+
+      /* Insert session into linked list */
+      if ( plugin->sessions == NULL)
+      {
+        plugin->sessions = cs;
+        plugin->session_count = 1;
+      }
+      cs_temp = plugin->sessions;
+      while ( cs_temp->next != NULL )
+      {
+        cs_temp = cs_temp->next;
+      }
+      if (cs_temp != cs )
+      {
+        cs_temp->next = cs;
+        plugin->session_count++;
+      }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"New Session `%s' inserted, count %u \n", address, plugin->session_count);
+    }
+    /* Set closure */
+    if (*httpSessionCache == NULL)
+    {
+      *httpSessionCache = cs;
     }
-  if (*httpSessionCache == NULL)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Daemon has new an incoming `%s' request from peer `%s' (`[%s]:%u')\n",method, GNUNET_i2s(&cs->sender),cs->ip,cs->addr_inbound->sin_port);
+  }
+  else
+  {
+    cs = *httpSessionCache;
+  }
+  /* Is it a PUT or a GET request */
+  if ( 0 == strcmp (MHD_HTTP_METHOD_PUT, method) )
+  {
+    /* New  */
+    if ((*upload_data_size == 0) && (cs->is_put_in_progress == GNUNET_NO))
     {
-      httpSession->is_mhd_active++;
-      *httpSessionCache = httpSession;
+      if (cs->pending_inbound_msg->pos !=0 )
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                    _("Incoming message from peer `%s', while existing message with %u bytes was not forwarded to transport'\n"),
+                    GNUNET_i2s(&cs->sender), cs->pending_inbound_msg->pos);
+        cs->pending_inbound_msg->pos = 0;
+      }
+      /* not yet ready */
+      cs->is_put_in_progress = GNUNET_YES;
+      cs->is_bad_request = GNUNET_NO;
+      cs->is_active = GNUNET_YES;
+      return MHD_YES;
     }
-  GNUNET_mutex_lock (lock);
-#if DO_GET
-  if (0 == strcasecmp (MHD_HTTP_METHOD_GET, method))
+
+    if ((*upload_data_size > 0) && (cs->is_bad_request != GNUNET_YES))
     {
-#if DEBUG_HTTP
-      GNUNET_GE_LOG (coreAPI->ectx,
-                     GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                     "HTTP/MHD receives GET request from `%s'.\n", &url[1]);
-#endif
+      if ((*upload_data_size + cs->pending_inbound_msg->pos < cs->pending_inbound_msg->len) && (*upload_data_size + cs->pending_inbound_msg->pos <= GNUNET_SERVER_MAX_MESSAGE_SIZE))
+      {
+        /* copy uploaded data to buffer */
+        memcpy(&cs->pending_inbound_msg->buf[cs->pending_inbound_msg->pos],upload_data,*upload_data_size);
+        cs->pending_inbound_msg->pos += *upload_data_size;
+        *upload_data_size = 0;
+        return MHD_YES;
+      }
+      else
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"%u bytes not added to message of %u bytes, message to big\n",*upload_data_size, cs->pending_inbound_msg->pos);
+        cs->is_bad_request = GNUNET_YES;
+        /* (*upload_data_size) bytes not processed */
+        return MHD_YES;
+      }
+    }
 
-      /* handle get; create response object if we do not
-         have one already */
-      get = GNUNET_malloc (sizeof (struct MHDGetData));
-      memset (get, 0, sizeof (struct MHDGetData));
-      get->next = httpSession->cs.server.gets;
-      httpSession->cs.server.gets = get;
-      get->session = session;
-      get->httpsession = httpSession;
-      get->last_get_activity = GNUNET_get_time ();
-      get->get = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
-                                                    64 * 1024,
-                                                    contentReaderCallback,
-                                                    get,
-                                                    contentReaderFreeCallback);
-      MHD_queue_response (session, MHD_HTTP_OK, get->get);
-      GNUNET_mutex_unlock (lock);
+    if ((cs->is_put_in_progress == GNUNET_YES) && (cs->is_bad_request == GNUNET_YES))
+    {
+      *upload_data_size = 0;
+      response = MHD_create_response_from_data (strlen (HTTP_PUT_RESPONSE),HTTP_PUT_RESPONSE, MHD_NO, MHD_NO);
+      res = MHD_queue_response (session, MHD_HTTP_REQUEST_ENTITY_TOO_LARGE, response);
+      if (res == MHD_YES)
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Sent HTTP/1.1: 413 ENTITY TOO LARGE as PUT Response\n");
+        cs->is_bad_request = GNUNET_NO;
+        cs->is_put_in_progress =GNUNET_NO;
+      }
+      MHD_destroy_response (response);
       return MHD_YES;
     }
-#endif
-  if (0 == strcasecmp (MHD_HTTP_METHOD_PUT, method))
+
+    if ((*upload_data_size == 0) && (cs->is_put_in_progress == GNUNET_YES) && (cs->is_bad_request == GNUNET_NO))
     {
-#if DEBUG_HTTP
-      GNUNET_GE_LOG (coreAPI->ectx,
-                     GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                     "HTTP/MHD receives PUT request from `%s' with %u bytes.\n",
-                     &url[1], *upload_data_size);
-#endif
-      put = httpSession->cs.server.puts;
-      while ((put != NULL) && (put->session != session))
-        put = put->next;
-      if (put == NULL)
-        {
-          put = GNUNET_malloc (sizeof (struct MHDPutData));
-          memset (put, 0, sizeof (struct MHDPutData));
-          put->next = httpSession->cs.server.puts;
-          httpSession->cs.server.puts = put;
-          put->session = session;
-        }
-      put->last_activity = GNUNET_get_time ();
-
-      /* handle put (upload_data!) */
-      poff = 0;
-      have = *upload_data_size;
-      if (stats != NULL)
-        stats->change (stat_bytesReceived, have);
-      *upload_data_size = 0;    /* we will always process everything */
-      if ((have == 0) && (put->done == GNUNET_NO)
-          && (put->ready == GNUNET_YES))
-        {
-          put->done = GNUNET_YES;
-          /* end of upload, send response! */
-#if DEBUG_HTTP
-          GNUNET_GE_LOG (coreAPI->ectx,
-                         GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                         "HTTP/MHD queues dummy response to completed PUT request.\n");
-#endif
-          response =
-            MHD_create_response_from_data (strlen (HTTP_PUT_RESPONSE),
-                                           HTTP_PUT_RESPONSE, MHD_NO, MHD_NO);
-          MHD_queue_response (session, MHD_HTTP_OK, response);
-          MHD_destroy_response (response);
-          GNUNET_mutex_unlock (lock);
-          return MHD_YES;
-        }
-      while (have > 0)
+      send_error_to_client = GNUNET_YES;
+      struct GNUNET_MessageHeader * gn_msg = NULL;
+      /*check message and forward here */
+      /* checking size */
+      if (cs->pending_inbound_msg->pos >= sizeof (struct GNUNET_MessageHeader))
+      {
+        gn_msg = GNUNET_malloc (cs->pending_inbound_msg->pos);
+        memcpy (gn_msg,cs->pending_inbound_msg->buf,cs->pending_inbound_msg->pos);
+
+        if ((ntohs(gn_msg->size) == cs->pending_inbound_msg->pos))
         {
-          put->ready = GNUNET_NO;
-          if (put->rpos1 < sizeof (GNUNET_MessageHeader))
-            {
-              cpy = sizeof (GNUNET_MessageHeader) - put->rpos1;
-              if (cpy > have)
-                cpy = have;
-              memcpy (&put->rbuff1[put->rpos1], &upload_data[poff], cpy);
-              put->rpos1 += cpy;
-              have -= cpy;
-              poff += cpy;
-              put->rpos2 = 0;
-            }
-          if (put->rpos1 < sizeof (GNUNET_MessageHeader))
-            break;
-          hdr = (GNUNET_MessageHeader *) put->rbuff1;
-          GNUNET_array_grow (put->rbuff2,
-                             put->rsize2,
-                             ntohs (hdr->size) -
-                             sizeof (GNUNET_MessageHeader));
-          if (put->rpos2 < ntohs (hdr->size) - sizeof (GNUNET_MessageHeader))
-            {
-              cpy =
-                ntohs (hdr->size) - sizeof (GNUNET_MessageHeader) -
-                put->rpos2;
-              if (cpy > have)
-                cpy = have;
-              memcpy (&put->rbuff2[put->rpos2], &upload_data[poff], cpy);
-              have -= cpy;
-              poff += cpy;
-              put->rpos2 += cpy;
-            }
-          if (put->rpos2 < ntohs (hdr->size) - sizeof (GNUNET_MessageHeader))
-            break;
-          mp = GNUNET_malloc (sizeof (GNUNET_TransportPacket));
-          mp->msg = put->rbuff2;
-          mp->sender = httpSession->sender;
-          mp->tsession = httpSession->tsession;
-          mp->size = ntohs (hdr->size) - sizeof (GNUNET_MessageHeader);
-#if DEBUG_HTTP
-          GNUNET_GE_LOG (coreAPI->ectx,
-                         GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                         "HTTP/MHD passes %u bytes to core (received via PUT request).\n",
-                         mp->size);
-#endif
-          coreAPI->receive (mp);
-          put->rbuff2 = NULL;
-          put->rpos2 = 0;
-          put->rsize2 = 0;
-          put->rpos1 = 0;
-          put->ready = GNUNET_YES;
+          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) );
+          send_error_to_client = GNUNET_NO;
         }
-      GNUNET_mutex_unlock (lock);
-      return MHD_YES;
+      }
+
+      if (send_error_to_client == GNUNET_NO)
+      {
+        response = MHD_create_response_from_data (strlen (HTTP_PUT_RESPONSE),HTTP_PUT_RESPONSE, MHD_NO, MHD_NO);
+        res = MHD_queue_response (session, MHD_HTTP_OK, response);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Sent HTTP/1.1: 200 OK as PUT Response\n",HTTP_PUT_RESPONSE, strlen (HTTP_PUT_RESPONSE), res );
+        MHD_destroy_response (response);
+      }
+      else
+      {
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Recieved malformed message with %u bytes\n", cs->pending_inbound_msg->pos);
+        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);
+        MHD_destroy_response (response);
+        GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Sent HTTP/1.1: 400 BAD REQUEST as PUT Response\n");
+      }
+
+      GNUNET_free_non_null (gn_msg);
+      cs->is_put_in_progress = GNUNET_NO;
+      cs->is_bad_request = GNUNET_NO;
+      cs->pending_inbound_msg->pos = 0;
+      return res;
     }
-  GNUNET_mutex_unlock (lock);
-  GNUNET_GE_BREAK_OP (NULL, 0); /* invalid request */
+  }
+  if ( 0 == strcmp (MHD_HTTP_METHOD_GET, method) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Got GET Request\n");
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"URL: `%s'\n",url);
+    response = MHD_create_response_from_data (strlen (HTTP_PUT_RESPONSE),HTTP_PUT_RESPONSE, MHD_NO, MHD_NO);
+    res = MHD_queue_response (session, MHD_HTTP_OK, response);
+    MHD_destroy_response (response);
+    return res;
+  }
   return MHD_NO;
 }
 
-#if DO_GET
+
+/**
+ * Call MHD to process pending requests and then go back
+ * and schedule the next run.
+ */
+static void http_daemon_run (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
+
 /**
- * Process downloaded bits (from GET via CURL).
+ * Function that queries MHD's select sets and
+ * starts the task waiting for them.
  */
-static size_t
-receiveContentCallback (void *ptr, size_t size, size_t nmemb, void *ctx)
+static GNUNET_SCHEDULER_TaskIdentifier
+http_daemon_prepare (struct MHD_Daemon *daemon_handle)
 {
-  HTTPSession *httpSession = ctx;
-  const char *inbuf = ptr;
-  size_t have = size * nmemb;
-  size_t poff = 0;
-  size_t cpy;
-  GNUNET_MessageHeader *hdr;
-  GNUNET_TransportPacket *mp;
-
-  if (stats != NULL)
-    stats->change (stat_curl_receive_callbacks, 1);
-  httpSession->cs.client.last_get_activity = GNUNET_get_time ();
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/CURL receives %u bytes as response to GET.\n",
-                 size * nmemb);
-#endif
-  while (have > 0)
-    {
-      if (httpSession->cs.client.rpos1 < sizeof (GNUNET_MessageHeader))
-        {
-          cpy = sizeof (GNUNET_MessageHeader) - httpSession->cs.client.rpos1;
-          if (cpy > have)
-            cpy = have;
-          memcpy (&httpSession->cs.
-                  client.rbuff1[httpSession->cs.client.rpos1], &inbuf[poff],
-                  cpy);
-          httpSession->cs.client.rpos1 += cpy;
-          have -= cpy;
-          poff += cpy;
-          httpSession->cs.client.rpos2 = 0;
-        }
-      if (httpSession->cs.client.rpos1 < sizeof (GNUNET_MessageHeader))
-        break;
-      hdr = (GNUNET_MessageHeader *) httpSession->cs.client.rbuff1;
-      GNUNET_array_grow (httpSession->cs.client.rbuff2,
-                         httpSession->cs.client.rsize2,
-                         ntohs (hdr->size) - sizeof (GNUNET_MessageHeader));
-      if (httpSession->cs.client.rpos2 <
-          ntohs (hdr->size) - sizeof (GNUNET_MessageHeader))
-        {
-          cpy =
-            ntohs (hdr->size) - sizeof (GNUNET_MessageHeader) -
-            httpSession->cs.client.rpos2;
-          if (cpy > have)
-            cpy = have;
-          memcpy (&httpSession->cs.
-                  client.rbuff2[httpSession->cs.client.rpos2], &inbuf[poff],
-                  cpy);
-          have -= cpy;
-          poff += cpy;
-          httpSession->cs.client.rpos2 += cpy;
-        }
-      if (httpSession->cs.client.rpos2 <
-          ntohs (hdr->size) - sizeof (GNUNET_MessageHeader))
-        break;
-      mp = GNUNET_malloc (sizeof (GNUNET_TransportPacket));
-      mp->msg = httpSession->cs.client.rbuff2;
-      mp->sender = httpSession->sender;
-      mp->tsession = httpSession->tsession;
-      mp->size = ntohs (hdr->size) - sizeof (GNUNET_MessageHeader);
-      coreAPI->receive (mp);
-      httpSession->cs.client.rbuff2 = NULL;
-      httpSession->cs.client.rpos2 = 0;
-      httpSession->cs.client.rsize2 = 0;
-      httpSession->cs.client.rpos1 = 0;
-    }
-  if (stats != NULL)
-    stats->change (stat_bytesReceived, size * nmemb);
-  return size * nmemb;
+  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 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);
+  ret = GNUNET_SCHEDULER_add_select (plugin->env->sched,
+                                     GNUNET_SCHEDULER_PRIORITY_HIGH,
+                                     GNUNET_SCHEDULER_NO_TASK,
+                                     tv,
+                                     wrs,
+                                     wws,
+                                     &http_daemon_run,
+                                     daemon_handle);
+  GNUNET_NETWORK_fdset_destroy (wrs);
+  GNUNET_NETWORK_fdset_destroy (wws);
+  GNUNET_NETWORK_fdset_destroy (wes);
+  return ret;
 }
-#endif
 
 /**
- * Provide bits for upload: we're using CURL for a PUT request
- * and now need to provide data from the message we are transmitting.
+ * Call MHD to process pending requests and then go back
+ * and schedule the next run.
  */
-static size_t
-sendContentCallback (void *ptr, size_t size, size_t nmemb, void *ctx)
+static void http_daemon_run (void *cls,
+                             const struct GNUNET_SCHEDULER_TaskContext *tc)
 {
-  struct HTTPPutData *put = ctx;
-  size_t max = size * nmemb;
-
-  if (stats != NULL)
-    stats->change (stat_curl_send_callbacks, 1);
-  put->last_activity = GNUNET_get_time ();
-  if (max > put->size - put->pos)
-    max = put->size - put->pos;
-  memcpy (ptr, &put->msg[put->pos], max);
-  put->pos += max;
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/CURL sends %u bytes in PUT request.\n", max);
-#endif
-  if (stats != NULL)
-    stats->change (stat_bytesSent, max);
-  return max;
-}
+  struct MHD_Daemon *daemon_handle = cls;
 
-#define CURL_EASY_SETOPT(c, a, b) do { ret = curl_easy_setopt(c, a, b); if (ret != CURLE_OK) GNUNET_GE_LOG(coreAPI->ectx, GNUNET_GE_WARNING | GNUNET_GE_USER | GNUNET_GE_BULK, _("%s failed at %s:%d: `%s'\n"), "curl_easy_setopt", __FILE__, __LINE__, curl_easy_strerror(ret)); } while (0);
-#define IP_BUF_LEN 128
+  if (daemon_handle == http_daemon_v4)
+    http_task_v4 = GNUNET_SCHEDULER_NO_TASK;
 
-static void
-create_session_url (HTTPSession * httpSession)
-{
-  char buf[IP_BUF_LEN];
-  char *url;
-  GNUNET_EncName enc;
-  unsigned short available;
-  const char *obr;
-  const char *cbr;
-  const HostAddress *haddr =
-    (const HostAddress *) &httpSession->cs.client.address;
-
-  url = httpSession->cs.client.url;
-  if (url == NULL)
-    {
-      GNUNET_hash_to_enc (&coreAPI->my_identity->hashPubKey, &enc);
-      available = ntohs (haddr->availability) & available_protocols;
-      if (available == (VERSION_AVAILABLE_IPV4 | VERSION_AVAILABLE_IPV6))
-        {
-          if (GNUNET_random_u32 (GNUNET_RANDOM_QUALITY_WEAK, 2) == 0)
-            available = VERSION_AVAILABLE_IPV4;
-          else
-            available = VERSION_AVAILABLE_IPV6;
-        }
-      if ((available & VERSION_AVAILABLE_IPV4) > 0)
-        {
-          if (NULL == inet_ntop (AF_INET, &haddr->ipv4, buf, IP_BUF_LEN))
-            {
-              /* log? */
-              return;
-            }
-          obr = "";
-          cbr = "";
-        }
-      else if ((available & VERSION_AVAILABLE_IPV6) > 0)
-        {
-          if (NULL == inet_ntop (AF_INET6, &haddr->ipv6, buf, IP_BUF_LEN))
-            {
-              /* log? */
-              return;
-            }
-          obr = "[";
-          cbr = "]";
-        }
-      else
-        return;                 /* error */
-      url = GNUNET_malloc (64 + sizeof (GNUNET_EncName) + strlen (buf));
-      GNUNET_snprintf (url,
-                       64 + sizeof (GNUNET_EncName),
-                       "http://%s%s%s:%u/%s", obr, buf, cbr,
-                       ntohs (haddr->port), &enc);
-      httpSession->cs.client.url = url;
-    }
+  if (daemon_handle == http_daemon_v6)
+    http_task_v6 = GNUNET_SCHEDULER_NO_TASK;
+
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  GNUNET_assert (MHD_YES == MHD_run (daemon_handle));
+  if (daemon_handle == http_daemon_v4)
+    http_task_v4 = http_daemon_prepare (daemon_handle);
+  if (daemon_handle == http_daemon_v6)
+    http_task_v6 = http_daemon_prepare (daemon_handle);
+  return;
 }
 
-#if DO_GET
 /**
- * Try to do a GET on the other peer of the given
- * http session.
- *
- * @return GNUNET_OK on success, GNUNET_SYSERR on error
+ * Removes a message from the linked list of messages
+ * @param ses session to remove message from
+ * @param msg message to remove
+ * @return GNUNET_SYSERR if msg not found, GNUNET_OK on success
  */
-static int
-create_curl_get (HTTPSession * httpSession)
+
+static int remove_http_message(struct Session * ses, struct HTTP_Message * msg)
 {
-  CURL *curl_get;
-  CURLcode ret;
-  CURLMcode mret;
-  GNUNET_CronTime now;
+  struct HTTP_Message * cur;
+  struct HTTP_Message * next;
 
-  if (httpSession->cs.client.url == NULL)
-    return GNUNET_SYSERR;
-  curl_get = httpSession->cs.client.get;
-  if (curl_get != NULL)
-    {
-      GNUNET_mutex_lock (lock);
-      curl_multi_remove_handle (curl_multi, curl_get);
-      http_requests_pending--;
-      signal_select ();
-      curl_easy_cleanup (curl_get);
-      GNUNET_mutex_unlock (lock);
-      httpSession->cs.client.get = NULL;
-    }
-  curl_get = curl_easy_init ();
-  if (curl_get == NULL)
+  cur = ses->pending_outbound_msg;
+  next = NULL;
+
+  if (cur == NULL)
     return GNUNET_SYSERR;
-  /* create GET */
-  CURL_EASY_SETOPT (curl_get, CURLOPT_FAILONERROR, 1);
-  CURL_EASY_SETOPT (curl_get, CURLOPT_URL, httpSession->cs.client.url);
-  if (strlen (proxy) > 0)
-    CURL_EASY_SETOPT (curl_get, CURLOPT_PROXY, proxy);
-  CURL_EASY_SETOPT (curl_get, CURLOPT_BUFFERSIZE, 32 * 1024);
-  if (0 == strncmp (httpSession->cs.client.url, "http", 4))
-    CURL_EASY_SETOPT (curl_get, CURLOPT_USERAGENT, "GNUnet-http");
-#if 0
-  CURL_EASY_SETOPT (curl_get, CURLOPT_VERBOSE, 1);
-#endif
-  CURL_EASY_SETOPT (curl_get, CURLOPT_CONNECTTIMEOUT, 150L);
-  /* NOTE: use of CONNECTTIMEOUT without also
-     setting NOSIGNAL results in really weird
-     crashes on my system! */
-  CURL_EASY_SETOPT (curl_get, CURLOPT_NOSIGNAL, 1);
-  CURL_EASY_SETOPT (curl_get, CURLOPT_TIMEOUT, 150L);
-  CURL_EASY_SETOPT (curl_get, CURLOPT_WRITEFUNCTION, &receiveContentCallback);
-  CURL_EASY_SETOPT (curl_get, CURLOPT_WRITEDATA, httpSession);
-  CURL_EASY_SETOPT (curl_get, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  if (ret != CURLE_OK)
-    {
-      curl_easy_cleanup (curl_get);
-      return GNUNET_SYSERR;
-    }
-  GNUNET_mutex_lock (lock);
-  mret = curl_multi_add_handle (curl_multi, curl_get);
-  http_requests_pending++;
-  GNUNET_mutex_unlock (lock);
-  if (stats != NULL)
-    stats->change (stat_get_issued, 1);
-  if (mret != CURLM_OK)
-    {
-      GNUNET_GE_LOG (coreAPI->ectx,
-                     GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
-                     GNUNET_GE_BULK, _("%s failed at %s:%d: `%s'\n"),
-                     "curl_multi_add_handle", __FILE__, __LINE__,
-                     curl_multi_strerror (mret));
-      curl_easy_cleanup (curl_get);
+
+  if (cur == msg)
+  {
+    ses->pending_outbound_msg = cur->next;
+    GNUNET_free (cur->buf);
+    GNUNET_free (cur->dest_url);
+    GNUNET_free (cur);
+    cur = NULL;
+    return GNUNET_OK;
+  }
+
+  while (cur->next!=msg)
+  {
+    if (cur->next != NULL)
+      cur = cur->next;
+    else
       return GNUNET_SYSERR;
-    }
-  signal_select ();
-  now = GNUNET_get_time ();
-  httpSession->cs.client.last_get_activity = now;
-  httpSession->cs.client.get = curl_get;
-  httpSession->cs.client.last_get_initiated = now;
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/CURL initiated GET request.\n");
-#endif
+  }
+
+  cur->next = cur->next->next;
+  GNUNET_free (cur->next->buf);
+  GNUNET_free (cur->next->dest_url);
+  GNUNET_free (cur->next);
+  cur->next = NULL;
   return GNUNET_OK;
 }
+
+
+static size_t header_function( void *ptr, size_t size, size_t nmemb, void *stream)
+{
+  char * tmp;
+  unsigned int len = size * nmemb;
+
+  tmp = GNUNET_malloc (  len+1 );
+  memcpy(tmp,ptr,len);
+  if (tmp[len-2] == 13)
+    tmp[len-2]= '\0';
+#if DEBUG_CURL
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Header: `%s'\n",tmp);
 #endif
+  /*
+  if (0==strcmp (tmp,"HTTP/1.1 100 Continue"))
+  {
+    res->http_result_code=100;
+  }
+  if (0==strcmp (tmp,"HTTP/1.1 200 OK"))
+  {
+    res->http_result_code=200;
+  }
+  if (0==strcmp (tmp,"HTTP/1.1 400 Bad Request"))
+  {
+    res->http_result_code=400;
+  }
+  if (0==strcmp (tmp,"HTTP/1.1 404 Not Found"))
+  {
+    res->http_result_code=404;
+  }
+  if (0==strcmp (tmp,"HTTP/1.1 413 Request entity too large"))
+  {
+    res->http_result_code=413;
+  }
+   */
+  GNUNET_free (tmp);
+  return size * nmemb;
+}
 
 /**
- * Establish a connection to a remote node.
- *
- * @param hello the hello-Message for the target node
- * @param tsessionPtr the session handle that is set
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ * Callback method used with libcurl
+ * Method is called when libcurl needs to read data during sending
+ * @param stream pointer where to write data
+ * @param size size of an individual element
+ * @param nmemb count of elements that can be written to the buffer
+ * @param ptr source pointer, passed to the libcurl handle
+ * @return bytes written to stream
  */
-static int
-httpConnect (const GNUNET_MessageHello * hello,
-             GNUNET_TSession ** tsessionPtr, int may_reuse)
+static size_t send_read_callback(void *stream, size_t size, size_t nmemb, void *ptr)
+{
+  struct Session * ses = ptr;
+  struct HTTP_Message * msg = ses->pending_outbound_msg;
+  unsigned int bytes_sent;
+
+  bytes_sent = 0;
+  if (msg->len > (size * nmemb))
+    return CURL_READFUNC_ABORT;
+
+  if (( msg->pos < msg->len) && (msg->len < (size * nmemb)))
+  {
+    memcpy(stream, msg->buf, msg->len);
+    msg->pos = msg->len;
+    bytes_sent = msg->len;
+  }
+
+  return bytes_sent;
+}
+
+/**
+* Callback method used with libcurl
+* Method is called when libcurl needs to write data during sending
+* @param stream pointer where to write data
+* @param size size of an individual element
+* @param nmemb count of elements that can be written to the buffer
+* @param ptr destination pointer, passed to the libcurl handle
+* @return bytes read from stream
+*/
+static size_t send_write_callback( void *stream, size_t size, size_t nmemb, void *ptr)
 {
-  const HostAddress *haddr = (const HostAddress *) &hello[1];
-  GNUNET_TSession *tsession;
-  HTTPSession *httpSession;
-  int i;
-
-  if (stats != NULL)
-    stats->change (stat_connect_calls, 1);
-  /* check if we have a session pending for this peer */
-  tsession = NULL;
-  if (may_reuse)
+  char * data = malloc(size*nmemb +1);
+
+  memcpy( data, stream, size*nmemb);
+  data[size*nmemb] = '\0';
+  /* Just a dummy print for the response recieved for the PUT message */
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Recieved %u bytes: `%s' \n", size * nmemb, data);
+  free (data);
+  return (size * nmemb);
+
+}
+
+/**
+ * Function setting up file descriptors and scheduling task to run
+ * @param session session to send data to
+ * @return bytes sent to peer
+ */
+static size_t send_prepare(struct Session* session );
+
+/**
+ * Function setting up curl handle and selecting message to send
+ * @param ses session to send data to
+ * @return bytes sent to peer
+ */
+static ssize_t send_select_init (struct Session* ses )
+{
+  int bytes_sent = 0;
+  CURLMcode mret;
+  struct HTTP_Message * msg;
+
+  if ( NULL == ses->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;
+  }
+  msg = ses->pending_outbound_msg;
+
+
+
+#if DEBUG_CURL
+  curl_easy_setopt(ses->curl_handle, CURLOPT_VERBOSE, 1L);
+#endif
+  curl_easy_setopt(ses->curl_handle, CURLOPT_URL, msg->dest_url);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_PUT, 1L);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_HEADERFUNCTION, &header_function);
+  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_WRITEFUNCTION, send_write_callback);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_READDATA, ses);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_INFILESIZE_LARGE, (curl_off_t) msg->len);
+  curl_easy_setopt(ses->curl_handle, CURLOPT_TIMEOUT, (long) (timeout.value / 1000 ));
+  curl_easy_setopt(ses->curl_handle, CURLOPT_CONNECTTIMEOUT, HTTP_CONNECT_TIMEOUT);
+
+  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 );
+  return bytes_sent;
+}
+
+static void send_execute (void *cls,
+             const struct GNUNET_SCHEDULER_TaskContext *tc)
+{
+  int running;
+  struct CURLMsg *msg;
+  CURLMcode mret;
+  struct Session * cs = NULL;
+
+  http_task_send = GNUNET_SCHEDULER_NO_TASK;
+  if (0 != (tc->reason & GNUNET_SCHEDULER_REASON_SHUTDOWN))
+    return;
+
+  do
     {
-      GNUNET_mutex_lock (lock);
-      for (i = 0; i < tsessionCount; i++)
+      running = 0;
+      mret = curl_multi_perform (multi_handle, &running);
+      if (running == 0)
         {
-          if (0 == memcmp (&hello->senderIdentity,
-                           &tsessions[i]->peer, sizeof (GNUNET_PeerIdentity)))
+          do
             {
-              tsession = tsessions[i];
-              break;
+
+              msg = curl_multi_info_read (multi_handle, &running);
+              GNUNET_break (msg != NULL);
+              if (msg == NULL)
+                break;
+              /* get session for affected curl handle */
+              GNUNET_assert ( msg->easy_handle != NULL );
+              cs = find_session_by_curlhandle (msg->easy_handle);
+              GNUNET_assert ( cs != NULL );
+              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",
+                               cs->ip,
+                               __FILE__,
+                               __LINE__,
+                               curl_easy_strerror (msg->data.result));
+                    /* sending msg failed*/
+                    if ( NULL != cs->pending_outbound_msg->transmit_cont)
+                      cs->pending_outbound_msg->transmit_cont (cs->pending_outbound_msg->transmit_cont_cls,&cs->sender,GNUNET_SYSERR);
+                    }
+                  else
+                  {
+                    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+                                "Send to %s completed.\n", cs->ip);
+                    if (GNUNET_OK != remove_http_message(cs, cs->pending_outbound_msg))
+                      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Message could not be removed from session `%s'", GNUNET_i2s(&cs->sender));
+
+                    curl_easy_cleanup(cs->curl_handle);
+                    cs->curl_handle=NULL;
+
+                    /* Calling transmit continuation  */
+                    if ( NULL != cs->pending_outbound_msg->transmit_cont)
+                      cs->pending_outbound_msg->transmit_cont (cs->pending_outbound_msg->transmit_cont_cls,&cs->sender,GNUNET_OK);
+
+
+                    /* send pending messages */
+                    if (cs->pending_outbound_msg != NULL)
+                    {
+                      send_select_init (cs);
+                    }
+                  }
+                  return;
+                default:
+                  break;
+                }
+
             }
+          while ( (running > 0) );
         }
-      if ((tsession != NULL) && (GNUNET_OK == httpAssociate (tsession)))
-        {
-          *tsessionPtr = tsession;
-          GNUNET_mutex_unlock (lock);
-          return GNUNET_OK;
-        }
-      GNUNET_mutex_unlock (lock);
-    }
-  /* no session pending, initiate a new one! */
-  httpSession = GNUNET_malloc (sizeof (HTTPSession));
-  memset (httpSession, 0, sizeof (HTTPSession));
-  httpSession->sender = hello->senderIdentity;
-  httpSession->users = 1;       /* us only, core has not seen this tsession! */
-  httpSession->is_client = GNUNET_YES;
-  httpSession->cs.client.address = *haddr;
-  tsession = GNUNET_malloc (sizeof (GNUNET_TSession));
-  memset (tsession, 0, sizeof (GNUNET_TSession));
-  httpSession->tsession = tsession;
-  tsession->ttype = GNUNET_TRANSPORT_PROTOCOL_NUMBER_HTTP;
-  tsession->internal = httpSession;
-  tsession->peer = hello->senderIdentity;
-  create_session_url (httpSession);
-#if DO_GET
-  if (GNUNET_OK != create_curl_get (httpSession))
-    {
-      GNUNET_free (tsession);
-      GNUNET_free (httpSession);
-      return GNUNET_SYSERR;
     }
-#endif
-  /* PUTs will be created as needed */
-  addTSession (tsession);
-  *tsessionPtr = tsession;
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/CURL initiated connection to `%s'.\n",
-                 httpSession->cs.client.url);
-#endif
-  return GNUNET_OK;
+  while (mret == CURLM_CALL_MULTI_PERFORM);
+  send_prepare(cls);
 }
 
-/**
- * We received the "Thank you!" response to a PUT.
- * Discard the data (not useful) and mark the PUT
- * operation as completed.
- */
-static size_t
-discardContentCallback (void *data, size_t size, size_t nmemb, void *put_cls)
-{
-  struct HTTPPutData *put = put_cls;
-  /* this condition should pretty much always be
-     true; just checking here in case the PUT
-     response comes early somehow */
-  if (put->pos == put->size)
-    put->done = GNUNET_YES;
-  return size * nmemb;
-}
 
 /**
- * Create a new PUT request for the given PUT data.
+ * Function setting up file descriptors and scheduling task to run
+ * @param ses session to send data to
+ * @return bytes sent to peer
  */
-static int
-create_curl_put (HTTPSession * httpSession, struct HTTPPutData *put)
+static size_t send_prepare(struct Session* session )
 {
-  CURL *curl_put;
-  CURLcode ret;
+  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;
-  long size;
 
-  /* we should have initiated a GET earlier,
-     so URL must not be NULL here */
-  if (httpSession->cs.client.url == NULL)
-    return GNUNET_SYSERR;
-  curl_put = curl_easy_init ();
-  if (curl_put == NULL)
-    return GNUNET_SYSERR;
-  CURL_EASY_SETOPT (curl_put, CURLOPT_FAILONERROR, 1);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_URL, httpSession->cs.client.url);
-  if (strlen (proxy) > 0)
-    CURL_EASY_SETOPT (curl_put, CURLOPT_PROXY, proxy);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_BUFFERSIZE, put->size);
-  if (0 == strncmp (httpSession->cs.client.url, "http", 4))
-    CURL_EASY_SETOPT (curl_put, CURLOPT_USERAGENT, "GNUnet-http");
-  CURL_EASY_SETOPT (curl_put, CURLOPT_UPLOAD, 1);
-#if 0
-  CURL_EASY_SETOPT (curl_put, CURLOPT_VERBOSE, 1);
-#endif
-  CURL_EASY_SETOPT (curl_put, CURLOPT_CONNECTTIMEOUT, 150L);
-  /* NOTE: use of CONNECTTIMEOUT without also
-     setting NOSIGNAL results in really weird
-     crashes on my system! */
-  CURL_EASY_SETOPT (curl_put, CURLOPT_NOSIGNAL, 1);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_TIMEOUT, 150L);
-  size = put->size;
-  CURL_EASY_SETOPT (curl_put, CURLOPT_INFILESIZE, size);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_READFUNCTION, &sendContentCallback);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_READDATA, put);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_WRITEFUNCTION, &discardContentCallback);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_WRITEDATA, put);
-  CURL_EASY_SETOPT (curl_put, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
-  if (ret != CURLE_OK)
+  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)
     {
-      curl_easy_cleanup (curl_put);
-      return GNUNET_SYSERR;
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("%s failed at %s:%d: `%s'\n"),
+                  "curl_multi_fdset", __FILE__, __LINE__,
+                  curl_multi_strerror (mret));
+      return -1;
     }
-  GNUNET_mutex_lock (lock);
-  mret = curl_multi_add_handle (curl_multi, curl_put);
-  http_requests_pending++;
-  GNUNET_mutex_unlock (lock);
-  if (stats != NULL)
-    stats->change (stat_put_issued, 1);
+  mret = curl_multi_timeout (multi_handle, &to);
   if (mret != CURLM_OK)
     {
-      GNUNET_GE_LOG (coreAPI->ectx,
-                     GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
-                     GNUNET_GE_BULK, _("%s failed at %s:%d: `%s'\n"),
-                     "curl_multi_add_handle", __FILE__, __LINE__,
-                     curl_multi_strerror (mret));
-      return GNUNET_SYSERR;
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                  _("%s failed at %s:%d: `%s'\n"),
+                  "curl_multi_timeout", __FILE__, __LINE__,
+                  curl_multi_strerror (mret));
+      return -1;
     }
-  signal_select ();
-  put->curl_put = curl_put;
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/CURL initiated PUT request to `%s'.\n",
-                 httpSession->cs.client.url);
-#endif
-  return GNUNET_OK;
-}
 
+  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;
+}
 
 /**
- * Test if the transport would even try to send
- * a message of the given size and importance
- * for the given session.<br>
- * This function is used to check if the core should
- * even bother to construct (and encrypt) this kind
- * of message.
+ * Function that can be used by the transport service to transmit
+ * a message using the plugin.
  *
- * @return GNUNET_YES if the transport would try (i.e. queue
- *         the message or call the OS to send),
- *         GNUNET_NO if the transport would just drop the message,
- *         GNUNET_SYSERR if the size/session is invalid
+ * @param cls closure
+ * @param target who should receive this message
+ * @param priority how important is the message
+ * @param msgbuf the message to transmit
+ * @param msgbuf_size number of bytes in 'msgbuf'
+ * @param to when should we time out
+ * @param session which session must be used (or NULL for "any")
+ * @param addr the address to use (can be NULL if the plugin
+ *                is "on its own" (i.e. re-use existing TCP connection))
+ * @param addrlen length of the address in bytes
+ * @param force_address GNUNET_YES if the plugin MUST use the given address,
+ *                otherwise the plugin may use other addresses or
+ *                existing connections (if available)
+ * @param cont continuation to call once the message has
+ *        been transmitted (or if the transport is ready
+ *        for the next transmission call; or if the
+ *        peer disconnected...)
+ * @param cont_cls closure for cont
+ * @return number of bytes used (on the physical network, with overheads);
+ *         -1 on hard errors (i.e. address invalid); 0 is a legal value
+ *         and does NOT mean that the message was not transmitted (DV)
  */
-static int
-httpTestWouldTry (GNUNET_TSession * tsession, const unsigned int size,
-                  int important)
+static ssize_t
+http_plugin_send (void *cls,
+                      const struct GNUNET_PeerIdentity *target,
+                      const char *msgbuf,
+                      size_t msgbuf_size,
+                      unsigned int priority,
+                      struct GNUNET_TIME_Relative to,
+                      struct Session *session,
+                      const void *addr,
+                      size_t addrlen,
+                      int force_address,
+                      GNUNET_TRANSPORT_TransmitContinuation cont,
+                      void *cont_cls)
 {
-  HTTPSession *httpSession = tsession->internal;
-  struct MHDGetData *get;
-  int ret;
+  char * address;
+  struct Session* ses;
+  struct Session* ses_temp;
+  struct HTTP_Message * msg;
+  struct HTTP_Message * tmp;
+  int bytes_sent = 0;
+
+  /* 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 */
 
-  if (size >= GNUNET_MAX_BUFFER_SIZE - sizeof (GNUNET_MessageHeader))
+    /*FIXME: what is const void * really? Assuming struct sockaddr_in * ! */
+    ses = create_session(NULL, (struct sockaddr_in *) addr, target);
+    ses->is_active = GNUNET_YES;
+
+    /* Insert session into linked list */
+    if ( plugin->sessions == NULL)
     {
-      GNUNET_GE_BREAK (coreAPI->ectx, 0);
-      return GNUNET_SYSERR;
+      plugin->sessions = ses;
+      plugin->session_count = 1;
     }
-  if (size == 0)
+    ses_temp = plugin->sessions;
+    while ( ses_temp->next != NULL )
     {
-      GNUNET_GE_BREAK (coreAPI->ectx, 0);
-      return GNUNET_SYSERR;
+      ses_temp = ses_temp->next;
     }
-  if (httpSession->is_client)
+    if (ses_temp != ses )
     {
-      /* client */
-      if ((important != GNUNET_YES) && (httpSession->cs.client.puts != NULL))
-        return GNUNET_NO;
-      return GNUNET_YES;
+      ses_temp->next = ses;
+      plugin->session_count++;
     }
-  else
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"New Session `%s' inserted, count %u \n", GNUNET_i2s(target), plugin->session_count);
+  }
+
+  GNUNET_assert (addr!=NULL);
+  unsigned int port;
+
+  /* setting url to send to */
+  if (force_address == GNUNET_YES)
+  {
+    if (addrlen == (sizeof (struct IPv4HttpAddress)))
     {
-      /* server */
-      GNUNET_mutex_lock (lock);
-      get = httpSession->cs.server.gets;
-      if (get == NULL)
-        ret = GNUNET_NO;
-      else
-        {
-          if (get->wsize == 0)
-            ret = GNUNET_YES;
-          else if ((get->wpos + size > get->wsize)
-                   && (important != GNUNET_YES))
-            ret = GNUNET_NO;
-          else
-            ret = GNUNET_YES;
-        }
-      GNUNET_mutex_unlock (lock);
-      return ret;
+      address = GNUNET_malloc(INET_ADDRSTRLEN + 14 + strlen ((const char *) (&ses->hash)));
+      inet_ntop(AF_INET,&((struct IPv4HttpAddress *) addr)->ipv4_addr,address,INET_ADDRSTRLEN);
+      port = ntohs(((struct IPv4HttpAddress *) addr)->u_port);
+      GNUNET_asprintf(&address,"http://%s:%u/%s",address,port, (char *) (&ses->hash));
+    }
+    else if (addrlen == (sizeof (struct IPv6HttpAddress)))
+    {
+      address = GNUNET_malloc(INET6_ADDRSTRLEN + 14 + strlen ((const char *) (&ses->hash)));
+      inet_ntop(AF_INET6, &((struct IPv6HttpAddress *) addr)->ipv6_addr,address,INET6_ADDRSTRLEN);
+      port = ntohs(((struct IPv6HttpAddress *) addr)->u6_port);
+      GNUNET_asprintf(&address,"http://%s:%u/%s",address,port,(char *) (&ses->hash));
     }
+    else
+      {
+        GNUNET_break (0);
+        return -1;
+    }
+  }
+
+  timeout = to;
+  /* setting up message */
+  msg = GNUNET_malloc (sizeof (struct HTTP_Message));
+  msg->next = NULL;
+  msg->len = msgbuf_size;
+  msg->pos = 0;
+  msg->buf = GNUNET_malloc (msgbuf_size);
+  msg->dest_url = address;
+  msg->transmit_cont = cont;
+  msg->transmit_cont_cls = cont_cls;
+  memcpy (msg->buf,msgbuf, msgbuf_size);
+
+  /* insert created message in list of pending messages */
+  if (ses->pending_outbound_msg == NULL)
+  {
+    ses->pending_outbound_msg = msg;
+  }
+  tmp = ses->pending_outbound_msg;
+  while ( NULL != tmp->next)
+  {
+    tmp = tmp->next;
+  }
+  if ( tmp != msg)
+  {
+    tmp->next = msg;
+  }
+
+  if (msg == ses->pending_outbound_msg)
+  {
+    bytes_sent = send_select_init (ses);
+    return bytes_sent;
+  }
+  return msgbuf_size;
 }
 
 
+
 /**
- * Send a message to the specified remote node.
+ * Function that can be used to force the plugin to disconnect
+ * from the given peer and cancel all previous transmissions
+ * (and their continuationc).
  *
- * @param tsession the GNUNET_MessageHello identifying the remote node
- * @param msg the message
- * @param size the size of the message
- * @return GNUNET_SYSERR on error, GNUNET_OK on success, GNUNET_NO if queue is full
+ * @param cls closure
+ * @param target peer from which to disconnect
  */
-static int
-httpSend (GNUNET_TSession * tsession,
-          const void *msg, unsigned int size, int important)
+static void
+http_plugin_disconnect (void *cls,
+                            const struct GNUNET_PeerIdentity *target)
 {
-  HTTPSession *httpSession = tsession->internal;
-  struct HTTPPutData *putData;
-  GNUNET_MessageHeader *hdr;
-#if DO_GET
-  struct MHDGetData *getData;
-  char *tmp;
-#endif
-
-  if (stats != NULL)
-    stats->change (stat_send_calls, 1);
-  if (httpSession->is_client)
-    {
-      /* we need to do a PUT (we are the client) */
-      if (size >= GNUNET_MAX_BUFFER_SIZE)
-        return GNUNET_SYSERR;
-      if (size == 0)
-        {
-          GNUNET_GE_BREAK (NULL, 0);
-          return GNUNET_SYSERR;
-        }
-      if (important != GNUNET_YES)
-        {
-          GNUNET_mutex_lock (lock);
-          if (httpSession->cs.client.puts != NULL)
-            {
-              /* do not queue more than one unimportant PUT at a time */
-              signal_select (); /* do clean up now! */
-              GNUNET_mutex_unlock (lock);
-              if (stats != NULL)
-                stats->change (stat_bytesDropped, size);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"HTTP Plugin: http_plugin_disconnect\n");
+  // struct Plugin *plugin = cls;
+  // FIXME
+}
 
-              return GNUNET_NO;
-            }
-          GNUNET_mutex_unlock (lock);
-        }
-      putData = GNUNET_malloc (sizeof (struct HTTPPutData));
-      memset (putData, 0, sizeof (struct HTTPPutData));
-      putData->msg = GNUNET_malloc (size + sizeof (GNUNET_MessageHeader));
-      hdr = (GNUNET_MessageHeader *) putData->msg;
-      hdr->size = htons (size + sizeof (GNUNET_MessageHeader));
-      hdr->type = htons (0);
-      memcpy (&putData->msg[sizeof (GNUNET_MessageHeader)], msg, size);
-      putData->size = size + sizeof (GNUNET_MessageHeader);
-      putData->last_activity = GNUNET_get_time ();
-      if (GNUNET_OK != create_curl_put (httpSession, putData))
-        {
-          GNUNET_free (putData->msg);
-          GNUNET_free (putData);
-          return GNUNET_SYSERR;
-        }
-      GNUNET_mutex_lock (lock);
-      putData->next = httpSession->cs.client.puts;
-      httpSession->cs.client.puts = putData;
-      GNUNET_mutex_unlock (lock);
-      return GNUNET_OK;
-    }
 
-  /* httpSession->isClient == false, respond to a GET (we
-     hopefully have one or will have one soon) */
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP/MHD queues %u bytes to be sent as response to GET as soon as possible.\n",
-                 size);
-#endif
-#if DO_GET
-  GNUNET_mutex_lock (lock);
-  getData = httpSession->cs.server.gets;
-  if (getData == NULL)
+/**
+ * Convert the transports address to a nice, human-readable
+ * format.
+ *
+ * @param cls closure
+ * @param type name of the transport that generated the address
+ * @param addr one of the addresses of the host, NULL for the last address
+ *        the specific address format depends on the transport
+ * @param addrlen length of the address
+ * @param numeric should (IP) addresses be displayed in numeric form?
+ * @param timeout after how long should we give up?
+ * @param asc function to call on each string
+ * @param asc_cls closure for asc
+ */
+static void
+http_plugin_address_pretty_printer (void *cls,
+                                        const char *type,
+                                        const void *addr,
+                                        size_t addrlen,
+                                        int numeric,
+                                        struct GNUNET_TIME_Relative timeout,
+                                        GNUNET_TRANSPORT_AddressStringCallback
+                                        asc, void *asc_cls)
+{
+  const struct IPv4HttpAddress *t4;
+  const struct IPv6HttpAddress *t6;
+  struct sockaddr_in a4;
+  struct sockaddr_in6 a6;
+  char * address;
+  char * ret;
+  unsigned int port;
+
+  if (addrlen == sizeof (struct IPv6HttpAddress))
     {
-      GNUNET_mutex_unlock (lock);
-      return GNUNET_SYSERR;
+      address = GNUNET_malloc (INET6_ADDRSTRLEN);
+      t6 = addr;
+      a6.sin6_addr = t6->ipv6_addr;
+      inet_ntop(AF_INET6, &(a6.sin6_addr),address,INET6_ADDRSTRLEN);
+      port = ntohs(t6->u6_port);
     }
-  if (getData->wsize == 0)
-    GNUNET_array_grow (getData->wbuff, getData->wsize, HTTP_BUF_SIZE);
-  size += sizeof (GNUNET_MessageHeader);
-  if (getData->wpos + size > getData->wsize)
+  else if (addrlen == sizeof (struct IPv4HttpAddress))
     {
-      /* need to grow or discard */
-      if (!important)
-        {
-          GNUNET_mutex_unlock (lock);
-          return GNUNET_NO;
-        }
-      tmp = GNUNET_malloc (getData->wpos + size);
-      memcpy (tmp, &getData->wbuff[getData->woff], getData->wpos);
-      hdr = (GNUNET_MessageHeader *) & tmp[getData->wpos];
-      hdr->type = htons (0);
-      hdr->size = htons (size);
-      memcpy (&hdr[1], msg, size - sizeof (GNUNET_MessageHeader));
-      GNUNET_free (getData->wbuff);
-      getData->wbuff = tmp;
-      getData->wsize = getData->wpos + size;
-      getData->woff = 0;
-      getData->wpos = getData->wpos + size;
+      address = GNUNET_malloc (INET_ADDRSTRLEN);
+      t4 = addr;
+      a4.sin_addr.s_addr =  t4->ipv4_addr;
+      inet_ntop(AF_INET, &(a4.sin_addr),address,INET_ADDRSTRLEN);
+      port = ntohs(t4->u_port);
     }
   else
     {
-      /* fits without growing */
-      if (getData->wpos + getData->woff + size > getData->wsize)
-        {
-          /* need to compact first */
-          memmove (getData->wbuff,
-                   &getData->wbuff[getData->woff], getData->wpos);
-          getData->woff = 0;
-        }
-      /* append */
-      hdr =
-        (GNUNET_MessageHeader *) & getData->wbuff[getData->woff +
-                                                  getData->wpos];
-      hdr->size = htons (size);
-      hdr->type = htons (0);
-      memcpy (&hdr[1], msg, size - sizeof (GNUNET_MessageHeader));
-      getData->wpos += size;
+      /* invalid address */
+      GNUNET_break_op (0);
+      asc (asc_cls, NULL);
+      return;
     }
-  signal_select ();
-  GNUNET_mutex_unlock (lock);
-#endif
-  return GNUNET_OK;
+
+  ret = GNUNET_malloc(strlen(address) +14);
+  GNUNET_asprintf(&ret,"http://%s:%u/",address,port);
+  GNUNET_free (address);
+  asc (asc_cls, ret);
 }
 
+
+
 /**
- * Function called to cleanup dead connections
- * (completed PUTs, GETs that have timed out,
- * etc.).  Also re-vives GETs that have timed out
- * if we are still interested in the connection.
+ * Another peer has suggested an address for this
+ * peer and transport plugin.  Check that this could be a valid
+ * address.  If so, consider adding it to the list
+ * of addresses.
+ *
+ * @param cls closure
+ * @param addr pointer to the address
+ * @param addrlen length of addr
+ * @return GNUNET_OK if this is a plausible address for this peer
+ *         and transport
  */
-static void
-cleanup_connections ()
+static int
+http_plugin_address_suggested (void *cls,
+                                  void *addr, size_t addrlen)
 {
-  int i;
-  HTTPSession *s;
-  struct HTTPPutData *prev;
-  struct HTTPPutData *pos;
-  struct MHDPutData *mpos;
-  struct MHDPutData *mprev;
-#if DO_GET
-  struct MHD_Response *r;
-  struct MHDGetData *gpos;
-  struct MHDGetData *gnext;
-#endif
-  GNUNET_CronTime now;
+  struct IPv4HttpAddress *v4;
+  struct IPv6HttpAddress *v6;
+  unsigned int port;
 
-  GNUNET_mutex_lock (lock);
-  now = GNUNET_get_time ();
-  for (i = 0; i < tsessionCount; i++)
+  if ((addrlen != sizeof (struct IPv4HttpAddress)) &&
+      (addrlen != sizeof (struct IPv6HttpAddress)))
     {
-      s = tsessions[i]->internal;
-      if (s->is_client)
-        {
-          if ((s->cs.client.puts == NULL) && (s->users == 0)
-#if DO_GET
-              && (s->cs.client.last_get_activity + HTTP_TIMEOUT < now)
-#endif
-            )
-            {
-#if DO_GET
-#if DEBUG_HTTP
-              GNUNET_GE_LOG (coreAPI->ectx,
-                             GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
-                             GNUNET_GE_USER,
-                             "HTTP transport destroys old (%llu ms) unused client session\n",
-                             now - s->cs.client.last_get_activity);
-#endif
-#endif
-              destroy_tsession (tsessions[i]);
-              i--;
-              continue;
-            }
+      GNUNET_break_op (0);
+      return GNUNET_SYSERR;
+    }
+  if (addrlen == sizeof (struct IPv4HttpAddress))
+    {
+      v4 = (struct IPv4HttpAddress *) addr;
 
-          prev = NULL;
-          pos = s->cs.client.puts;
-          while (pos != NULL)
-            {
-              if (pos->last_activity + HTTP_TIMEOUT < now)
-                pos->done = GNUNET_YES;
-              if (pos->done)
-                {
-                  if (prev == NULL)
-                    s->cs.client.puts = pos->next;
-                  else
-                    prev->next = pos->next;
-                  GNUNET_free (pos->msg);
-                  curl_multi_remove_handle (curl_multi, pos->curl_put);
-                  http_requests_pending--;
-                  signal_select ();
-                  curl_easy_cleanup (pos->curl_put);
-                  GNUNET_free (pos);
-                  if (prev == NULL)
-                    pos = s->cs.client.puts;
-                  else
-                    pos = prev->next;
-                  continue;
-                }
-              prev = pos;
-              pos = pos->next;
-            }
-#if DO_GET
-          if ((s->cs.client.last_get_activity + HTTP_TIMEOUT < now) &&
-              ((s->users > 0) || (s->cs.client.puts != NULL)) &&
-              ((s->cs.client.last_get_initiated + HTTP_GET_REFRESH > now) ||
-               (s->cs.client.get == NULL)) &&
-              ((s->cs.client.get == NULL) ||
-               (s->cs.client.last_get_activity + HTTP_GET_REFRESH / 2 < now)))
-            create_curl_get (s);
-#endif
-        }
-      else
+      port = ntohs (v4->u_port);
+      if (port != plugin->port_inbound)
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+    }
+  else
+    {
+      v6 = (struct IPv6HttpAddress *) addr;
+      if (IN6_IS_ADDR_LINKLOCAL (&v6->ipv6_addr))
         {
-          mpos = s->cs.server.puts;
-          mprev = NULL;
-          while (mpos != NULL)
-            {
-              if (mpos->last_activity == 0)
-                {
-                  if (mprev == NULL)
-                    s->cs.server.puts = mpos->next;
-                  else
-                    mprev->next = mpos->next;
-                  GNUNET_array_grow (mpos->rbuff2, mpos->rsize2, 0);
-                  GNUNET_free (mpos);
-                  if (mprev == NULL)
-                    mpos = s->cs.server.puts;
-                  else
-                    mpos = mprev->next;
-                  continue;
-                }
-              mprev = mpos;
-              mpos = mpos->next;
-            }
-
-          /* ! s->is_client */
-#if DO_GET
-          gpos = s->cs.server.gets;
-          while (gpos != NULL)
-            {
-              gnext = gpos->next;
-              gpos->next = NULL;
-              if ((gpos->last_get_activity + HTTP_TIMEOUT < now) ||
-                  (gpos != s->cs.server.gets))
-                {
-                  if (gpos == s->cs.server.gets)
-                    s->cs.server.gets = NULL;
-                  r = gpos->get;
-                  gpos->get = NULL;
-                  MHD_destroy_response (r);
-                }
-              gpos = gnext;
-            }
-#endif
-          if (
-#if DO_GET
-               (s->cs.server.gets == NULL) &&
-#endif
-               (s->is_mhd_active == 0) && (s->users == 0))
-            {
-#if DO_GET
-#if DEBUG_HTTP
-              GNUNET_GE_LOG (coreAPI->ectx,
-                             GNUNET_GE_DEBUG | GNUNET_GE_REQUEST |
-                             GNUNET_GE_USER,
-                             "HTTP transport destroys unused server session\n");
-#endif
-#endif
-              destroy_tsession (tsessions[i]);
-              i--;
-              continue;
-            }
+          GNUNET_break_op (0);
+          return GNUNET_SYSERR;
         }
+      port = ntohs (v6->u6_port);
+      if (port != plugin->port_inbound)
+      {
+        GNUNET_break_op (0);
+        return GNUNET_SYSERR;
+      }
+
     }
-  GNUNET_mutex_unlock (lock);
+  return GNUNET_OK;
 }
 
+
 /**
- * Thread that runs the CURL and MHD requests.
+ * Function called for a quick conversion of the binary address to
+ * a numeric address.  Note that the caller must not free the
+ * address and that the next call to this function is allowed
+ * to override the address again.
+ *
+ * @param cls closure
+ * @param addr binary address
+ * @param addrlen length of the address
+ * @return string representing the same address
  */
-static void *
-curl_runner (void *unused)
+static const char*
+http_plugin_address_to_string (void *cls,
+                                   const void *addr,
+                                   size_t addrlen)
 {
-  CURLMcode mret;
-  fd_set rs;
-  fd_set ws;
-  fd_set es;
-  struct GNUNET_NETWORK_FDSet *hrs;
-  struct GNUNET_NETWORK_FDSet *hws;
-  struct GNUNET_NETWORK_FDSet *hes;
-  int max;
-  int running;
-  unsigned long long timeout;
-  long ms;
-  int have_tv;
-  char buf[128];                /* for reading from pipe */
-  int ret;
-
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP transport select thread started\n");
-#endif
-
-  hrs = GNUNET_net_fdset_create ();
-  hws = GNUNET_net_fdset_create ();
-  hes = GNUNET_net_fdset_create ();
-
-  while (GNUNET_YES == http_running)
+  const struct IPv4HttpAddress *t4;
+  const struct IPv6HttpAddress *t6;
+  struct sockaddr_in a4;
+  struct sockaddr_in6 a6;
+  char * address;
+  char * ret;
+  unsigned int port;
+
+  if (addrlen == sizeof (struct IPv6HttpAddress))
     {
-      max = 0;
-      FD_ZERO (&rs);
-      FD_ZERO (&ws);
-      FD_ZERO (&es);
-      GNUNET_mutex_lock (lock);
-      mret = curl_multi_fdset (curl_multi, &rs, &ws, &es, &max);
-      GNUNET_mutex_unlock (lock);
-      if (mret != CURLM_OK)
-        {
-          GNUNET_GE_LOG (coreAPI->ectx,
-                         GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
-                         GNUNET_GE_BULK, _("%s failed at %s:%d: `%s'\n"),
-                         "curl_multi_fdset", __FILE__, __LINE__,
-                         curl_multi_strerror (mret));
-          break;
-        }
-      if (mhd_daemon != NULL)
-        MHD_get_fdset (mhd_daemon, &rs, &ws, &es, &max);
-      timeout = 0;
-      have_tv = MHD_NO;
-      if (mhd_daemon != NULL)
-        have_tv = MHD_get_timeout (mhd_daemon, &timeout);
-      GNUNET_mutex_lock (lock);
-      if ((CURLM_OK == curl_multi_timeout (curl_multi, &ms)) &&
-          (ms != -1) && ((ms < timeout) || (have_tv == MHD_NO)))
-        {
-          timeout = ms;
-          have_tv = MHD_YES;
-        }
-      GNUNET_mutex_unlock (lock);
-
-      GNUNET_net_fdset_zero (hws);
-      GNUNET_net_fdset_zero (hrs);
-      GNUNET_net_fdset_zero (hes);
-      GNUNET_net_fdset_copy_native (hws, ws);
-      GNUNET_net_fdset_copy_native (hrs, rs);
-      GNUNET_net_fdset_copy_native (hes, es);
-
-       GNUNET_net_fdset_handle_set (signal_pipe[0], hrs);
-      if (stats != NULL)
-        stats->change (stat_select_calls, 1);
-      ret =
-        GNUNET_net_select (hrs, hws, hes, (have_tv == MHD_YES) ? timeout : GNUNET_TIME_UNIT_FOREVER_REL);
-      if (ret == GNUNET_SYSERR)
-        {
-          GNUNET_GE_LOG_STRERROR (coreAPI->ectx,
-                                  GNUNET_GE_ERROR | GNUNET_GE_ADMIN |
-                                  GNUNET_GE_DEVELOPER, "select");
-        }
-      if (GNUNET_YES != http_running)
-        break;
-      running = 0;
-      do
-        {
-          GNUNET_mutex_lock (lock);
-          mret = curl_multi_perform (curl_multi, &running);
-          GNUNET_mutex_unlock (lock);
-        }
-      while ((mret == CURLM_CALL_MULTI_PERFORM)
-             && (http_running == GNUNET_YES));
-      if (GNUNET_net_fdset_handle_isset (signal_pipe[0], hrs))
-        GNUNET_DISK_file_read (signal_pipe[0], buf, sizeof (buf));
-      if ((mret != CURLM_OK) && (mret != CURLM_CALL_MULTI_PERFORM))
-        GNUNET_GE_LOG (coreAPI->ectx,
-                       GNUNET_GE_ERROR | GNUNET_GE_ADMIN | GNUNET_GE_USER |
-                       GNUNET_GE_BULK, _("%s failed at %s:%d: `%s'\n"),
-                       "curl_multi_perform", __FILE__, __LINE__,
-                       curl_multi_strerror (mret));
-      if (mhd_daemon != NULL)
-        MHD_run (mhd_daemon);
-      cleanup_connections ();
+      address = GNUNET_malloc (INET6_ADDRSTRLEN);
+      t6 = addr;
+      a6.sin6_addr = t6->ipv6_addr;
+      inet_ntop(AF_INET6, &(a6.sin6_addr),address,INET6_ADDRSTRLEN);
+      port = ntohs(t6->u6_port);
+    }
+  else if (addrlen == sizeof (struct IPv4HttpAddress))
+    {
+      address = GNUNET_malloc (INET_ADDRSTRLEN);
+      t4 = addr;
+      a4.sin_addr.s_addr =  t4->ipv4_addr;
+      inet_ntop(AF_INET, &(a4.sin_addr),address,INET_ADDRSTRLEN);
+      port = ntohs(t4->u_port);
+    }
+  else
+    {
+      /* invalid address */
+      return NULL;
     }
-#if DEBUG_HTTP
-  GNUNET_GE_LOG (coreAPI->ectx,
-                 GNUNET_GE_DEBUG | GNUNET_GE_REQUEST | GNUNET_GE_USER,
-                 "HTTP transport select thread exits.\n");
-#endif
-  return NULL;
-}
 
+  ret = GNUNET_malloc(strlen(address) +6);
+  GNUNET_asprintf(&ret,"%s:%u",address,port);
+  GNUNET_free (address);
+  return ret;
+}
 
 /**
- * Start the server process to receive inbound traffic.
- * @return GNUNET_OK on success, GNUNET_SYSERR if the operation failed
+ * Add the IP of our network interface to the list of
+ * our external IP addresses.
+ *
+ * @param cls the 'struct Plugin*'
+ * @param name name of the interface
+ * @param isDefault do we think this may be our default interface
+ * @param addr address of the interface
+ * @param addrlen number of bytes in addr
+ * @return GNUNET_OK to continue iterating
  */
 static int
-startTransportServer ()
+process_interfaces (void *cls,
+                    const char *name,
+                    int isDefault,
+                    const struct sockaddr *addr, socklen_t addrlen)
 {
-  unsigned short port;
+  struct IPv4HttpAddress t4;
+  struct IPv6HttpAddress t6;
+  int af;
+  void *arg;
+  uint16_t args;
 
-  if ((curl_multi != NULL) || (http_running == GNUNET_YES))
-    return GNUNET_SYSERR;
-  curl_multi = curl_multi_init ();
-  if (curl_multi == NULL)
-    return GNUNET_SYSERR;
-  port = get_port ();
-  if ((mhd_daemon == NULL) && (port != 0))
+
+
+  af = addr->sa_family;
+  if (af == AF_INET)
     {
-      if (GNUNET_YES !=
-          GNUNET_GC_get_configuration_value_yesno (cfg, "GNUNETD",
-                                                   "DISABLE-IPV6",
-                                                   GNUNET_YES))
-        {
-          mhd_daemon = MHD_start_daemon (MHD_USE_IPv6,
-                                         port,
-                                         &acceptPolicyCallback,
-                                         NULL, &accessHandlerCallback, NULL,
-                                         MHD_OPTION_CONNECTION_TIMEOUT,
-                                         (unsigned int) HTTP_TIMEOUT,
-                                         MHD_OPTION_CONNECTION_MEMORY_LIMIT,
-                                         (unsigned int) 1024 * 128,
-                                         MHD_OPTION_CONNECTION_LIMIT,
-                                         (unsigned int) 128,
-                                         MHD_OPTION_PER_IP_CONNECTION_LIMIT,
-                                         (unsigned int) 8,
-                                         MHD_OPTION_NOTIFY_COMPLETED,
-                                         &requestCompletedCallback, NULL,
-                                         MHD_OPTION_END);
-        }
-      if (mhd_daemon == NULL)
+      if (INADDR_LOOPBACK == ntohl(((struct sockaddr_in *) addr)->sin_addr.s_addr))
+      {
+        /* skip loopback addresses */
+        return GNUNET_OK;
+      }
+      t4.ipv4_addr = ((struct sockaddr_in *) addr)->sin_addr.s_addr;
+      t4.u_port = htons (plugin->port_inbound);
+      arg = &t4;
+      args = sizeof (t4);
+    }
+  else if (af == AF_INET6)
+    {
+      if (IN6_IS_ADDR_LINKLOCAL (&((struct sockaddr_in6 *) addr)->sin6_addr))
         {
-          /* try without IPv6 */
-          mhd_daemon = MHD_start_daemon (MHD_NO_FLAG,
-                                         port,
-                                         &acceptPolicyCallback,
-                                         NULL, &accessHandlerCallback, NULL,
-                                         MHD_OPTION_CONNECTION_TIMEOUT,
-                                         (unsigned int) HTTP_TIMEOUT,
-                                         MHD_OPTION_CONNECTION_MEMORY_LIMIT,
-                                         (unsigned int) 1024 * 128,
-                                         MHD_OPTION_CONNECTION_LIMIT,
-                                         (unsigned int) 128,
-                                         MHD_OPTION_PER_IP_CONNECTION_LIMIT,
-                                         (unsigned int) 8,
-                                         MHD_OPTION_NOTIFY_COMPLETED,
-                                         &requestCompletedCallback, NULL,
-                                         MHD_OPTION_END);
+          /* skip link local addresses */
+          return GNUNET_OK;
         }
-      else
+      if (IN6_IS_ADDR_LOOPBACK (&((struct sockaddr_in6 *) addr)->sin6_addr))
         {
-          available_protocols |= VERSION_AVAILABLE_IPV6;
+          /* skip loopback addresses */
+          return GNUNET_OK;
         }
-      if (mhd_daemon != NULL)
-        available_protocols |= VERSION_AVAILABLE_IPV4;
-    }
-  if (port == 0)
-    {
-      /* NAT */
-      available_protocols |= VERSION_AVAILABLE_IPV4;
-      if (GNUNET_YES !=
-          GNUNET_GC_get_configuration_value_yesno (cfg, "GNUNETD",
-                                                   "DISABLE-IPV6",
-                                                   GNUNET_YES))
-        available_protocols |= VERSION_AVAILABLE_IPV6;
+      memcpy (&t6.ipv6_addr,
+              &((struct sockaddr_in6 *) addr)->sin6_addr,
+              sizeof (struct in6_addr));
+      t6.u6_port = htons (plugin->port_inbound);
+      arg = &t6;
+      args = sizeof (t6);
     }
-  if (GNUNET_OK != GNUNET_DISK_pipe (signal_pipe, GNUNET_NO))
+  else
     {
-      MHD_stop_daemon (mhd_daemon);
-      curl_multi_cleanup (curl_multi);
-      curl_multi = NULL;
-      mhd_daemon = NULL;
-      return GNUNET_SYSERR;
+      GNUNET_break (0);
+      return GNUNET_OK;
     }
-  http_running = GNUNET_YES;
-  curl_thread = GNUNET_thread_create (&curl_runner, NULL, 32 * 1024);
-  if (curl_thread == NULL)
-    GNUNET_GE_DIE_STRERROR (coreAPI->ectx,
-                            GNUNET_GE_FATAL | GNUNET_GE_ADMIN |
-                            GNUNET_GE_IMMEDIATE, "pthread_create");
+  plugin->env->notify_address(plugin->env->cls,"http",arg, args, GNUNET_TIME_UNIT_FOREVER_REL);
+
   return GNUNET_OK;
 }
 
 /**
- * Shutdown the server process (stop receiving inbound
- * traffic). May be restarted later!
+ * Exit point from the plugin.
  */
-static int
-stopTransportServer ()
+void *
+libgnunet_plugin_transport_http_done (void *cls)
 {
-  void *unused;
-  int i;
-  HTTPSession *s;
+  struct GNUNET_TRANSPORT_PluginFunctions *api = cls;
+  struct Plugin *plugin = api->cls;
+  struct Session * cs;
+  struct Session * cs_next;
+  CURLMcode mret;
 
-  if ((http_running == GNUNET_NO) || (curl_multi == NULL))
-    return GNUNET_SYSERR;
-  http_running = GNUNET_NO;
-  signal_select ();
-  GNUNET_thread_stop_sleep (curl_thread);
-  GNUNET_thread_join (curl_thread, &unused);
-  GNUNET_DISK_close (signal_pipe[0]);
-  GNUNET_DISK_close (signal_pipe[1]);
-  if (mhd_daemon != NULL)
-    {
-      MHD_stop_daemon (mhd_daemon);
-      mhd_daemon = NULL;
-    }
-  cleanup_connections ();
-  for (i = 0; i < tsessionCount; i++)
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Unloading http plugin...\n");
+
+  if ( http_task_v4 != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel(plugin->env->sched, http_task_v4);
+    http_task_v4 = GNUNET_SCHEDULER_NO_TASK;
+  }
+
+  if ( http_task_v6 != GNUNET_SCHEDULER_NO_TASK)
+  {
+    GNUNET_SCHEDULER_cancel(plugin->env->sched, http_task_v6);
+    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);
+    http_daemon_v4 = NULL;
+  }
+  if (http_daemon_v6 != NULL)
+  {
+    MHD_stop_daemon (http_daemon_v6);
+    http_daemon_v6 = NULL;
+  }
+
+  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;
+
+  while ( NULL != cs)
     {
-      s = tsessions[i]->internal;
-      if (s->users == 0)
-        {
-          destroy_tsession (tsessions[i]);
-          i--;
-        }
+      GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Freeing session to `%s'\n",cs->ip);
+
+      cs_next = cs->next;
+      /* freeing messages */
+      struct HTTP_Message *cur;
+      struct HTTP_Message *tmp;
+      cur = cs->pending_outbound_msg;
+
+      while (cur != NULL)
+      {
+         tmp = cur->next;
+         if (NULL != cur->buf)
+           GNUNET_free (cur->buf);
+         GNUNET_free (cur);
+         cur = tmp;
+      }
+      GNUNET_free (cs->pending_inbound_msg->buf);
+      GNUNET_free (cs->pending_inbound_msg);
+      GNUNET_free (cs->ip);
+      GNUNET_free (cs->addr_inbound);
+      GNUNET_free_non_null (cs->addr_outbound);
+      GNUNET_free (cs);
+      plugin->session_count--;
+      cs = cs_next;
+
     }
-  curl_multi_cleanup (curl_multi);
-  curl_multi = NULL;
-  return GNUNET_OK;
+
+  /* GNUNET_SERVICE_stop (plugin->service); */
+  GNUNET_free (hostname);
+  GNUNET_free (plugin);
+  GNUNET_free (api);
+  return NULL;
 }
 
-/* ******************** public API ******************** */
 
 /**
- * The exported method. Makes the core api available
- * via a global and returns the udp transport API.
+ * Entry point for the plugin.
  */
-GNUNET_TransportAPI *
-inittransport_http (GNUNET_CoreAPIForTransport * core)
+void *
+libgnunet_plugin_transport_http_init (void *cls)
 {
-  GNUNET_GE_ASSERT (coreAPI->ectx, sizeof (HostAddress) == 24);
-  coreAPI = core;
-  cfg = coreAPI->cfg;
-  lock = GNUNET_mutex_create (GNUNET_YES);
-  if (0 != GNUNET_GC_attach_change_listener (coreAPI->cfg,
-                                             &reload_configuration, NULL))
+  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_mutex_destroy (lock);
-      lock = NULL;
+      GNUNET_log_from (GNUNET_ERROR_TYPE_WARNING, "", _
+                       ("Failed to start service for `%s' transport plugin.\n"),
+                       "http");
       return NULL;
     }
-  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
+    */
+
+  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;
+  api->disconnect = &http_plugin_disconnect;
+  api->address_pretty_printer = &http_plugin_address_pretty_printer;
+  api->check_address = &http_plugin_address_suggested;
+  api->address_to_string = &http_plugin_address_to_string;
+
+  hostname = GNUNET_RESOLVER_local_fqdn_get ();
+
+  /* Hashing our identity to use it in URLs */
+  GNUNET_CRYPTO_hash_to_enc ( &(plugin->env->my_identity->hashPubKey), &my_ascii_hash_ident);
+
+  /* Reading port number from config file */
+  if ((GNUNET_OK !=
+       GNUNET_CONFIGURATION_get_value_number (env->cfg,
+                                              "transport-http",
+                                              "PORT",
+                                              &port)) ||
+      (port > 65535) )
     {
-      GNUNET_GE_BREAK (NULL, 0);
-      GNUNET_GC_detach_change_listener (coreAPI->cfg, &reload_configuration,
-                                        NULL);
-      GNUNET_mutex_destroy (lock);
-      lock = NULL;
+      GNUNET_log_from (GNUNET_ERROR_TYPE_ERROR,
+                       "http",
+                       _
+                       ("Require valid port number for transport plugin `%s' in configuration!\n"),
+                       "transport-http");
+      libgnunet_plugin_transport_http_done (api);
       return NULL;
     }
-  tsessionCount = 0;
-  tsessionArrayLength = 0;
-  GNUNET_array_grow (tsessions, tsessionArrayLength, 32);
-  if (GNUNET_GC_get_configuration_value_yesno (coreAPI->cfg,
-                                               "HTTP", "UPNP",
-                                               GNUNET_YES) == GNUNET_YES)
+  plugin->port_inbound = port;
+  gn_timeout = GNUNET_CONSTANTS_IDLE_CONNECTION_TIMEOUT;
+  timeout = ( gn_timeout.value / 1000);
+  if ((http_daemon_v4 == NULL) && (http_daemon_v6 == NULL) && (port != 0))
     {
-      upnp = coreAPI->service_request ("upnp");
-
-      if (upnp == NULL)
-        {
-          GNUNET_GE_LOG (coreAPI->ectx,
-                         GNUNET_GE_ERROR | GNUNET_GE_USER |
-                         GNUNET_GE_IMMEDIATE,
-                         _
-                         ("The UPnP service could not be loaded. To disable UPnP, set the "
-                          "configuration option \"UPNP\" in section \"%s\" to \"NO\"\n"),
-                         "HTTP");
-        }
+    http_daemon_v6 = MHD_start_daemon (MHD_USE_IPv6,
+                                       port,
+                                       &acceptPolicyCallback,
+                                       NULL , &accessHandlerCallback, NULL,
+                                       MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 16,
+                                       MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1,
+                                       MHD_OPTION_CONNECTION_TIMEOUT, timeout,
+                                       /* FIXME: set correct limit */
+                                       MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024),
+                                       MHD_OPTION_NOTIFY_COMPLETED, &requestCompletedCallback, NULL,
+                                       MHD_OPTION_END);
+    http_daemon_v4 = MHD_start_daemon (MHD_NO_FLAG,
+                                       port,
+                                       &acceptPolicyCallback,
+                                       NULL , &accessHandlerCallback, NULL,
+                                       MHD_OPTION_CONNECTION_LIMIT, (unsigned int) 16,
+                                       MHD_OPTION_PER_IP_CONNECTION_LIMIT, (unsigned int) 1,
+                                       MHD_OPTION_CONNECTION_TIMEOUT, timeout,
+                                       /* FIXME: set correct limit */
+                                       MHD_OPTION_CONNECTION_MEMORY_LIMIT, (size_t) (16 * 1024),
+                                       MHD_OPTION_NOTIFY_COMPLETED, &requestCompletedCallback, NULL,
+                                       MHD_OPTION_END);
     }
-  stats = coreAPI->service_request ("stats");
-  if (stats != NULL)
-    {
-      stat_bytesReceived
-        = stats->create (gettext_noop ("# bytes received via HTTP"));
-      stat_bytesSent = stats->create (gettext_noop ("# bytes sent via HTTP"));
-      stat_bytesDropped
-        = stats->create (gettext_noop ("# bytes dropped by HTTP (outgoing)"));
-      stat_get_issued = stats->create (gettext_noop ("# HTTP GET issued"));
-      stat_get_received
-        = stats->create (gettext_noop ("# HTTP GET received"));
-      stat_put_issued = stats->create (gettext_noop ("# HTTP PUT issued"));
-      stat_put_received
-        = stats->create (gettext_noop ("# HTTP PUT received"));
-      stat_select_calls
-        = stats->create (gettext_noop ("# HTTP select calls"));
-
-      stat_send_calls = stats->create (gettext_noop ("# HTTP send calls"));
-
-      stat_curl_send_callbacks
-        = stats->create (gettext_noop ("# HTTP curl send callbacks"));
-      stat_curl_receive_callbacks
-        = stats->create (gettext_noop ("# HTTP curl receive callbacks"));
-      stat_mhd_access_callbacks
-        = stats->create (gettext_noop ("# HTTP mhd access callbacks"));
-      stat_mhd_read_callbacks
-        = stats->create (gettext_noop ("# HTTP mhd read callbacks"));
-      stat_mhd_close_callbacks
-        = stats->create (gettext_noop ("# HTTP mhd close callbacks"));
-      stat_connect_calls
-        = stats->create (gettext_noop ("# HTTP connect calls"));
-    }
-  GNUNET_GC_get_configuration_value_string (coreAPI->cfg,
-                                            "GNUNETD", "HTTP-PROXY", "",
-                                            &proxy);
-
-  myAPI.protocol_number = GNUNET_TRANSPORT_PROTOCOL_NUMBER_HTTP;
-  myAPI.mtu = 0;
-  myAPI.cost = 20000;           /* about equal to udp */
-  myAPI.hello_verify = &verify_hello;
-  myAPI.hello_create = &create_hello;
-  myAPI.connect = &httpConnect;
-  myAPI.associate = &httpAssociate;
-  myAPI.send = &httpSend;
-  myAPI.disconnect = &httpDisconnect;
-  myAPI.server_start = &startTransportServer;
-  myAPI.server_stop = &stopTransportServer;
-  myAPI.hello_to_address = &hello_to_address;
-  myAPI.send_now_test = &httpTestWouldTry;
-
-  return &myAPI;
-}
+  if (http_daemon_v4 != NULL)
+    http_task_v4 = http_daemon_prepare (http_daemon_v4);
+  if (http_daemon_v6 != NULL)
+    http_task_v6 = http_daemon_prepare (http_daemon_v6);
 
-void
-donetransport_http ()
-{
-  curl_global_cleanup ();
-  GNUNET_free_non_null (proxy);
-  proxy = NULL;
-  GNUNET_array_grow (tsessions, tsessionArrayLength, 0);
-  do_shutdown ();
+  if (http_task_v4 != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Starting MHD with IPv4 on port %u\n",port);
+  if (http_task_v6 != GNUNET_SCHEDULER_NO_TASK)
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,"Starting MHD with IPv4 and IPv6 on port %u\n",port);
+
+
+  /* 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;
+  }
+
+  GNUNET_OS_network_interfaces_list (&process_interfaces, plugin);
+
+  return api;
 }
 
-/* end of http.c */
+/* end of plugin_transport_template.c */