gnunet-svn
[Top][All Lists]
Advanced

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

[GNUnet-SVN] r28187 - in libmicrohttpd/src: examples microhttpd microspd


From: gnunet
Subject: [GNUnet-SVN] r28187 - in libmicrohttpd/src: examples microhttpd microspdy
Date: Fri, 19 Jul 2013 11:19:48 +0200

Author: grothoff
Date: 2013-07-19 11:19:48 +0200 (Fri, 19 Jul 2013)
New Revision: 28187

Added:
   libmicrohttpd/src/examples/mhd2spdy.c
   libmicrohttpd/src/examples/mhd2spdy_http.c
   libmicrohttpd/src/examples/mhd2spdy_http.h
   libmicrohttpd/src/examples/mhd2spdy_spdy.c
   libmicrohttpd/src/examples/mhd2spdy_spdy.h
   libmicrohttpd/src/examples/mhd2spdy_structures.c
   libmicrohttpd/src/examples/mhd2spdy_structures.h
Modified:
   libmicrohttpd/src/examples/Makefile.am
   libmicrohttpd/src/microhttpd/connection.c
   libmicrohttpd/src/microspdy/io_raw.c
Log:
-importing Andrey Uzunov's mhd2spdy code

Modified: libmicrohttpd/src/examples/Makefile.am
===================================================================
--- libmicrohttpd/src/examples/Makefile.am      2013-07-19 09:09:57 UTC (rev 
28186)
+++ libmicrohttpd/src/examples/Makefile.am      2013-07-19 09:19:48 UTC (rev 
28187)
@@ -19,8 +19,12 @@
 spdyex = \
   spdy_event_loop \
   spdy_fileserver \
-  spdy_response_with_callback
+  spdy_response_with_callback 
+
+if HAVE_SPDYLAY
+spdyex += mhd2spdy
 endif
+endif
 
 
 # example programs
@@ -74,6 +78,15 @@
  $(top_builddir)/src/microhttpd/libmicrohttpd.la  \
  -lmagic
 
+mhd2spdy_SOURCES = \
+ mhd2spdy.c \
+ mhd2spdy_spdy.c mhd2spdy_spdy.h \
+ mhd2spdy_http.c mhd2spdy_http.h \
+ mhd2spdy_structures.c mhd2spdy_structures.h
+mhd2spdy_LDADD = \
+ $(top_builddir)/src/microhttpd/libmicrohttpd.la  \
+ -lssl -lcrypto -lspdylay
+
 benchmark_SOURCES = \
  benchmark.c 
 benchmark_LDADD = \

Added: libmicrohttpd/src/examples/mhd2spdy.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy.c                               (rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy.c       2013-07-19 09:19:48 UTC (rev 
28187)
@@ -0,0 +1,323 @@
+/*
+    Copyright (C) 2013 Andrey Uzunov
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file structures.h
+ * @author Andrey Uzunov
+ */
+ 
+ /*
+  * TODOs
+  * non blocking SSL connect
+  * check certificate
+  * 
+  * 
+  * 
+  * 
+  
+  
+  */
+ 
+#include "mhd2spdy_structures.h"
+#include "mhd2spdy_spdy.h"
+#include "mhd2spdy_http.h"
+
+static int run = 1;
+//static int spdy_close = 0;
+
+static void catch_signal(int signal)
+{
+  //spdy_close = 1;
+  run = 0;
+}
+
+int
+run_everything ()
+{      
+  unsigned long long timeoutlong=0;
+  struct timeval timeout;
+  int ret;
+  fd_set rs;
+  fd_set ws;
+  fd_set es;
+  int maxfd = -1;
+  int maxfd_s = -1;
+  struct MHD_Daemon *daemon;
+  nfds_t spdy_npollfds = 1;
+  //struct pollfd spdy_pollfds[MAX_SPDY_CONNECTIONS];
+  struct URI * spdy2http_uri = NULL;
+  //int spdy_nfds;
+  //int spdylay_timeout = 0;
+  struct SPDY_Connection *connection;
+  struct SPDY_Connection *connections[MAX_SPDY_CONNECTIONS];
+  struct SPDY_Connection *connection_for_delete;
+
+  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
+    PRINT_INFO("signal failed");
+    
+  if (signal(SIGINT, catch_signal) == SIG_ERR)
+    PRINT_INFO("signal failed");
+
+  //spdy2http_url = argv[2];
+  glob_opt.streams_opened = 0;
+  glob_opt.responses_pending = 0;
+  glob_opt.global_memory = 0;
+  //spdy_proto_version = 0;
+
+  srand(time(NULL));
+  
+  if(init_parse_uri(&glob_opt.uri_preg))
+    DIE("Regexp compilation failed");
+    
+    
+  if(NULL != glob_opt.spdy2http_str)
+  {
+    ret = parse_uri(&glob_opt.uri_preg, glob_opt.spdy2http_str, 
&spdy2http_uri);
+    if(ret != 0)
+      DIE("spdy_parse_uri failed");
+  }
+
+  SSL_load_error_strings();
+  SSL_library_init();
+  glob_opt.ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+  if(glob_opt.ssl_ctx == NULL) {
+    PRINT_INFO2("SSL_CTX_new %s", ERR_error_string(ERR_get_error(), NULL));
+    abort();
+  }
+  spdy_ssl_init_ssl_ctx(glob_opt.ssl_ctx, &glob_opt.spdy_proto_version);
+
+  daemon = MHD_start_daemon ( 
+          MHD_SUPPRESS_DATE_NO_CLOCK,
+          glob_opt.listen_port,
+          NULL, NULL, &http_cb_request, NULL,
+          MHD_OPTION_URI_LOG_CALLBACK, &http_log_cb, NULL,
+          MHD_OPTION_END);
+  if(NULL==daemon)
+    DIE("MHD_start_daemon failed");
+
+
+  do
+  {
+
+  timeout.tv_sec = 0;
+  timeout.tv_usec = 0;
+  
+    if(NULL == glob_opt.spdy_connection && NULL != glob_opt.spdy2http_str)
+    {
+      glob_opt.spdy_connection = spdy_connect(spdy2http_uri, 
spdy2http_uri->port, strcmp("https", spdy2http_uri->scheme)==0);
+      if(NULL == glob_opt.spdy_connection && glob_opt.only_proxy)
+        PRINT_INFO("cannot connect to the proxy");
+    }
+  
+    //PRINT_INFO("while1");
+    FD_ZERO(&rs);
+    FD_ZERO(&ws);
+    FD_ZERO(&es);
+    
+    /*if(glob_opt.spdy_data_received)
+        {
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 0;
+  glob_opt.spdy_data_received = false;
+}
+else{*/
+    /*if(glob_opt.responses_pending || glob_opt.streams_opened)// TODO only 
streams_opened true?
+      timeout.tv_usec = 0; //return immediately
+    else
+    {*/
+      ret = MHD_get_timeout(daemon, &timeoutlong);
+      if(MHD_NO == ret || timeoutlong > 5000)
+        timeout.tv_sec = 5;
+      else
+      {
+        timeout.tv_sec = timeoutlong / 1000;
+        timeout.tv_usec = (timeoutlong % 1000) * 1000;
+      }
+    //}
+//}
+    if(MHD_NO == MHD_get_fdset (daemon,
+                                  &rs,
+                                  &ws, 
+                                  &es,
+                                  &maxfd))
+    {
+      PRINT_INFO("MHD_get_fdset error");
+    }
+    assert(-1 != maxfd);
+    
+    maxfd_s = spdy_get_selectfdset(
+                                  &rs,
+                                  &ws, 
+                                  &es,
+                                  connections, MAX_SPDY_CONNECTIONS, 
&spdy_npollfds);
+    if(maxfd_s > maxfd) maxfd = maxfd_s;
+ 
+    PRINT_INFO2("MHD timeout %i %i", timeout.tv_sec, timeout.tv_usec);
+    //TODO
+    //timeout.tv_sec = 0;
+    //timeout.tv_usec = 0;
+
+    glob_opt.spdy_data_received = false;
+      
+    ret = select(maxfd+1, &rs, &ws, &es, &timeout);
+    PRINT_INFO2("timeout now %i %i", timeout.tv_sec, timeout.tv_usec);
+
+    switch(ret) {
+      case -1:
+        PRINT_INFO2("select error: %i", errno);
+        break;
+      case 0:
+        break;
+      default:
+      PRINT_INFO("run");
+        MHD_run_from_select(daemon,&rs, &ws, &es);
+        spdy_run_select(&rs, &ws, &es, connections, spdy_npollfds);
+        if(glob_opt.spdy_data_received)
+        {
+          PRINT_INFO("MHD run again");
+          MHD_run_from_select(daemon,&rs, &ws, &es);
+        }
+        break;
+    }
+    
+    /*
+    //if(glob_opt.streams_opened) spdylay_timeout = 500;
+    //if(glob_opt.responses_pending || glob_opt.streams_opened) 
spdylay_timeout = 0;
+    //else spdylay_timeout = 0;
+    //else spdylay_timeout = 0;
+    
+    spdy_get_pollfdset(spdy_pollfds, connections, MAX_SPDY_CONNECTIONS, 
&spdy_npollfds);
+    
+    //TODO
+    //spdylay_timeout = 0;
+    
+    PRINT_INFO2("spdylay timeout %i", spdylay_timeout);
+    ret = poll(spdy_pollfds, spdy_npollfds, spdylay_timeout);
+    if(ret == -1)
+      DIE("poll");
+    if(ret > 0){
+      PRINT_INFO("spdy_run");
+    spdy_run(spdy_pollfds, connections, spdy_npollfds); 
+    }*/   
+  }
+  while(run);
+  
+  //TODO exit from loop and clean
+
+  MHD_stop_daemon (daemon);
+  
+  //TODO SSL_free brakes
+  spdy_free_connection(glob_opt.spdy_connection);
+  
+  connection = glob_opt.spdy_connections_head;
+  while(NULL != connection)
+  {    
+    connection_for_delete = connection;
+    connection = connection_for_delete->next;
+    glob_opt.streams_opened -= connection_for_delete->streams_opened;
+    DLL_remove(glob_opt.spdy_connections_head, glob_opt.spdy_connections_tail, 
connection_for_delete);
+    spdy_free_connection(connection_for_delete);
+  }
+  
+  free_uri(spdy2http_uri);
+  
+  deinit_parse_uri(&glob_opt.uri_preg);
+  
+  SSL_CTX_free(glob_opt.ssl_ctx);
+  ERR_free_strings();
+  EVP_cleanup();
+    
+  PRINT_INFO2("spdy streams: %i; http requests: %i", glob_opt.streams_opened, 
glob_opt.responses_pending);
+  PRINT_INFO2("memory allocated %zu bytes", glob_opt.global_memory);
+
+  return 0;
+}
+
+void
+display_usage()
+{
+  printf(
+    "Usage: http2spdy [-vo] [-b <SPDY2HTTP-PROXY>] -p <PORT>\n"
+    "TODO\n"
+  );
+}
+
+
+int
+main (int argc,
+      char *const *argv)
+{   
+  int getopt_ret;
+  int option_index;
+  struct option long_options[] = {
+    {"port",  required_argument, 0, 'p'},
+    {"backend-proxy",  required_argument, 0, 'b'},
+    {"verbose",  no_argument, 0, 'v'},
+    {"only-proxy",  no_argument, 0, 'o'},
+    {0, 0, 0, 0}
+  };
+  
+  while (1)
+  {
+    getopt_ret = getopt_long( argc, argv, "p:b:vo", long_options, 
&option_index);
+    if (getopt_ret == -1)
+      break;
+
+    switch(getopt_ret)
+    {
+      case 'p':
+        glob_opt.listen_port = atoi(optarg);
+        break;
+        
+      case 'b':
+        glob_opt.spdy2http_str = strdup(optarg);
+        if(NULL == glob_opt.spdy2http_str)
+          return 1;
+        break;
+        
+      case 'v':
+        glob_opt.verbose = true;
+        break;
+        
+      case 'o':
+        glob_opt.only_proxy = true;
+        break;
+        
+      case 0:
+        PRINT_INFO("0 from getopt");
+        break;
+        
+      case '?':
+        display_usage();
+        return 1;
+        
+      default:
+        DIE("default from getopt");
+    }
+  }
+  
+  if(
+    0 == glob_opt.listen_port
+    || (glob_opt.only_proxy && NULL == glob_opt.spdy2http_str)
+    )
+  {
+    display_usage();
+    return 1;
+  }
+    
+  return run_everything();
+}

Added: libmicrohttpd/src/examples/mhd2spdy_http.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_http.c                          (rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy_http.c  2013-07-19 09:19:48 UTC (rev 
28187)
@@ -0,0 +1,450 @@
+/*
+    Copyright (C) 2013 Andrey Uzunov
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file structures.h
+ * @author Andrey Uzunov
+ */
+ 
+#include "mhd2spdy_structures.h"
+#include "mhd2spdy_http.h"
+#include "mhd2spdy_spdy.h"
+
+
+void * http_log_cb(void * cls, const char * uri)
+{
+  struct HTTP_URI * http_uri;
+  
+  PRINT_INFO2("log uri '%s'\n", uri);
+  
+  if(NULL == (http_uri = au_malloc(sizeof(struct HTTP_URI ))))
+    DIE("no memory");
+  //memset(http_uri, 0 , sizeof(struct HTTP_URI));
+  http_uri->uri = strdup(uri);
+  return http_uri;
+}
+
+
+/*
+static int
+http_query_iterate_cb(void *cls,
+                           enum MHD_ValueKind kind,
+                           const char *name, const char *value)
+{
+
+}*/
+
+
+static int
+http_iterate_cb(void *cls,
+                           enum MHD_ValueKind kind,
+                           const char *name, const char *value)
+{
+  static char * const forbidden[] = {"Transfer-Encoding",
+    "Proxy-Connection",
+    "Keep-Alive",
+    "Connection"};
+  static int forbidden_size = 4;
+  int i;
+       struct SPDY_Headers *spdy_headers = (struct SPDY_Headers *)cls;
+       
+       if(0 == strcasecmp(name, "Host"))
+    spdy_headers->nv[9] = (char *)value;
+  else
+  {
+    for(i=0; i<forbidden_size; ++i)
+      if(0 == strcasecmp(forbidden[i], name))
+        return MHD_YES;
+    spdy_headers->nv[spdy_headers->cnt++] = (char *)name;
+    spdy_headers->nv[spdy_headers->cnt++] = (char *)value;
+  }
+       
+       return MHD_YES;
+}
+
+
+static ssize_t
+http_response_callback (void *cls,
+                               uint64_t pos,
+                               char *buffer,
+                               size_t max)
+{
+       int ret;
+       struct Proxy *proxy = (struct Proxy *)cls;
+       void *newbody;
+  const union MHD_ConnectionInfo *info;
+  int val = 1;
+       
+  //max=16;
+       
+       //PRINT_INFO2("response_callback, pos: %i, max is %i, len is 
%i",pos,max,proxy->length);
+       
+       //assert(0 != proxy->length);
+       
+       //if(MHD_CONTENT_READER_END_OF_STREAM == proxy->length)
+       //      return MHD_CONTENT_READER_END_OF_STREAM;
+  
+  PRINT_INFO2("http_response_callback for %s", proxy->url);
+  
+       if(0 == proxy->http_body_size &&( proxy->done || !proxy->spdy_active)){
+    PRINT_INFO("sent end of stream");
+    return MHD_CONTENT_READER_END_OF_STREAM;
+  }
+       
+       //*more = true;
+       if(!proxy->http_body_size)//nothing to write now
+  {
+    //flush data
+    info = MHD_get_connection_info (proxy->http_connection,
+         MHD_CONNECTION_INFO_CONNECTION_FD);
+    ret = setsockopt(info->connect_fd, IPPROTO_TCP, TCP_NODELAY, &val, 
(socklen_t)sizeof(val));
+    if(ret == -1) {
+      DIE("setsockopt");
+    }
+    
+    PRINT_INFO("FLUSH data");
+               return 0;
+  }
+       
+       if(max >= proxy->http_body_size)
+       {
+               ret = proxy->http_body_size;
+               newbody = NULL;
+       }
+       else
+       {
+               ret = max;
+               if(NULL == (newbody = au_malloc(proxy->http_body_size - max)))
+               {
+                       PRINT_INFO("no memory");
+                       return -2;
+               }
+               memcpy(newbody, proxy->http_body + max, proxy->http_body_size - 
max);
+       }
+       memcpy(buffer, proxy->http_body, ret);
+       free(proxy->http_body);
+       proxy->http_body = newbody;
+       proxy->http_body_size -= ret;
+       
+       if(proxy->length >= 0)
+       {
+               proxy->length -= ret;
+               //printf("pr len %i", proxy->length);
+               /*if(proxy->length <= 0)
+               {
+               //      *more = false;
+                       //last frame
+                       proxy->length = MHD_CONTENT_READER_END_OF_STREAM;
+               }*/
+       }
+       
+       PRINT_INFO2("response_callback, size: %i",ret);
+       
+       return ret;
+}
+
+
+static void
+http_response_done_callback(void *cls)
+{
+       struct Proxy *proxy = (struct Proxy *)cls;
+  
+  PRINT_INFO2("http_response_done_callback for %s", proxy->url);
+       //int ret;
+       
+       //printf("response_done_callback\n");
+       
+       //printf("answer for %s was sent\n", (char *)cls);
+       
+       /*if(SPDY_RESPONSE_RESULT_SUCCESS != status)
+       {
+               printf("answer was NOT sent, %i\n",status);
+       }*/
+       /*if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, 
proxy->curl_handle)))
+       {
+               PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret);
+       }
+       curl_slist_free_all(proxy->curl_headers);
+       curl_easy_cleanup(proxy->curl_handle);
+       */
+       //SPDY_destroy_request(request);
+       //SPDY_destroy_response(response);
+      MHD_destroy_response (proxy->http_response);
+       //if(!strcmp("/close",proxy->path)) run = 0;
+       //free(proxy->path);
+  if(proxy->spdy_active)
+    proxy->http_active = false;
+  else
+    free_proxy(proxy);
+
+  --glob_opt.responses_pending;
+}
+
+int
+http_cb_request (void *cls,
+                struct MHD_Connection *connection,
+                const char *url,
+                const char *method,
+                const char *version,
+                const char *upload_data,
+                size_t *upload_data_size,
+                void **ptr)
+{
+  //struct MHD_Response *response;
+  int ret;
+  struct Proxy *proxy;
+  //struct URI *spdy_uri;
+  //char **nv;
+  //int num_headers;
+  struct SPDY_Headers spdy_headers;
+  
+  //PRINT_INFO2("request cb %i; %s", *ptr,url);
+
+  if (NULL == *ptr)
+    DIE("ptr is null");
+  struct HTTP_URI *http_uri = (struct HTTP_URI *)*ptr;
+    
+  if(NULL == http_uri->proxy)
+  {  
+    if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+    {
+      free(http_uri->uri);
+      free(http_uri);
+      PRINT_INFO2("unexpected method %s", method);
+      return MHD_NO;              /* unexpected method */
+    }
+  
+    if(NULL == (proxy = au_malloc(sizeof(struct Proxy))))
+    {
+      PRINT_INFO("No memory");
+      return MHD_NO; 
+    }
+    
+    ++glob_opt.responses_pending;
+    //memset(proxy, 0, sizeof(struct Proxy));
+    proxy->id = rand();
+    proxy->http_active = true;
+    //PRINT_INFO2("proxy obj with id %i created (%i)", proxy->id, proxy);
+    proxy->http_connection = connection;
+    http_uri->proxy = proxy;
+    return MHD_YES;
+  }
+  
+  proxy = http_uri->proxy;
+  //*ptr = NULL;                  /* reset when done */
+
+  if(proxy->spdy_active)
+  {
+    //already handled
+    PRINT_INFO("unnecessary call to http_cb_request");
+    return MHD_YES;
+  }
+
+  PRINT_INFO2("received request for '%s %s %s'\n", method, http_uri->uri, 
version);
+  /*
+  proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
+                         8096,
+                         &http_response_callback,
+                         proxy,
+                         &http_response_done_callback);
+  
+  if (proxy->http_response == NULL)
+    DIE("no response");
+    */ 
+
+  proxy->url = http_uri->uri;
+  //if(NULL == (proxy->url = strdup(http_uri->uri)))
+  //  DIE("no memory");
+
+//TODO HTTP headers
+  /*MHD_get_connection_values (connection,
+                       MHD_HEADER_KIND,
+                       &http_iterate_cb,
+                       proxy);
+  */                     
+  //proxy->url = strdup(url);
+  //if(NULL ==  (spdy_uri = au_malloc(sizeof(struct URI))))
+  //  DIE("no memory");
+    
+  ret = parse_uri(&glob_opt.uri_preg, proxy->url, &proxy->uri);
+  if(ret != 0)
+    DIE("parse_uri failed");
+  //proxy->uri = spdy_uri;
+  proxy->http_uri = http_uri;
+  proxy->spdy_active = true;
+
+  //proxy->spdy_request = au_malloc(sizeof(struct SPDY_Request));
+  //if(NULL == proxy->spdy_request)
+  //  DIE("no memory");
+  //memset(proxy->spdy_request,0,sizeof(struct SPDY_Request));
+  //spdy_request_init(proxy->spdy_request, &spdy_uri);
+  //spdy_submit_request(spdy_connection, proxy);
+
+  spdy_headers.num = MHD_get_connection_values (connection,
+                       MHD_HEADER_KIND,
+                       NULL,
+                       NULL);
+  if(NULL == (spdy_headers.nv = au_malloc(((spdy_headers.num + 5) * 2 + 1) * 
sizeof(char *))))
+    DIE("no memory");
+  spdy_headers.nv[0] = ":method";     spdy_headers.nv[1] = "GET";
+  spdy_headers.nv[2] = ":path";       spdy_headers.nv[3] = 
proxy->uri->path_and_more;
+  spdy_headers.nv[4] = ":version";    spdy_headers.nv[5] = (char *)version;
+  spdy_headers.nv[6] = ":scheme";     spdy_headers.nv[7] = proxy->uri->scheme;
+  spdy_headers.nv[8] = ":host";       spdy_headers.nv[9] = NULL;
+  //nv[14] = NULL;
+  spdy_headers.cnt = 10;
+  MHD_get_connection_values (connection,
+                       MHD_HEADER_KIND,
+                       &http_iterate_cb,
+                       &spdy_headers);
+                       
+  spdy_headers.nv[spdy_headers.cnt] = NULL;
+  if(NULL == spdy_headers.nv[9])
+    spdy_headers.nv[9] = proxy->uri->host_and_port;
+
+  /*int i;
+  for(i=0; i<spdy_headers.cnt; i+=2)
+    printf("%s: %s\n", spdy_headers.nv[i], spdy_headers.nv[i+1]);
+  */
+  if(0 != spdy_request(spdy_headers.nv, proxy))
+  {
+    //--glob_opt.responses_pending;
+    free(spdy_headers.nv);
+    //MHD_destroy_response (proxy->http_response);
+    free_proxy(proxy);//TODO call it here or in done_callback
+    
+    return MHD_NO;
+  }
+  free(spdy_headers.nv);
+  
+  proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
+                         4096,
+                         &http_response_callback,
+                         proxy,
+                         &http_response_done_callback);
+
+  if (proxy->http_response == NULL)
+    DIE("no response");
+  
+  if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                 "Proxy-Connection", "keep-alive"))
+    PRINT_INFO("SPDY_name_value_add failed: ");
+  if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                 "Connection", "Keep-Alive"))
+    PRINT_INFO("SPDY_name_value_add failed: ");
+  if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                 "Keep-Alive", "timeout=5, max=100"))
+    PRINT_INFO("SPDY_name_value_add failed: ");
+    
+    /*
+  const  union MHD_ConnectionInfo *info;
+  info = MHD_get_connection_info (connection,
+                        MHD_CONNECTION_INFO_CONNECTION_FD);
+  int val = 1;
+  int rv;
+  rv = setsockopt(info->connect_fd, IPPROTO_TCP, TCP_NODELAY, &val, 
(socklen_t)sizeof(val));
+  if(rv == -1) {
+    DIE("setsockopt");
+  }*/
+  return MHD_YES;
+}
+
+void
+http_create_response(struct Proxy* proxy, char **nv)
+{
+  size_t i;
+  //uint64_t response_size=MHD_SIZE_UNKNOWN;
+
+  /*for(i = 0; nv[i]; i += 2) {
+    if(0 == strcmp("content-length", nv[i]))
+    {
+      response_size = atoi(nv[i+1]);
+      break;
+    }
+  }*/
+    /*
+  proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
+                         4096,
+                         &http_response_callback,
+                         proxy,
+                         &http_response_done_callback);
+
+  if (proxy->http_response == NULL)
+    DIE("no response");
+  
+  if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                 "Proxy-Connection", "keep-alive"))
+    PRINT_INFO("SPDY_name_value_add failed: ");
+  if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                 "Connection", "Keep-Alive"))
+    PRINT_INFO("SPDY_name_value_add failed: ");
+  if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                 "Keep-Alive", "timeout=5, max=100"))
+    PRINT_INFO("SPDY_name_value_add failed: ");
+    */
+  for(i = 0; nv[i]; i += 2) {
+    //printf("       %s: %s\n", nv[i], nv[i+1]);
+    //int j;
+
+    if(0 == strcmp(":status", nv[i]))
+    {
+      //raise(SIGINT);
+      //proxy->status_msg = nv[i+1];
+      char tmp[4];
+      memcpy(&tmp,nv[i+1],3);
+      tmp[3]=0;
+      proxy->status = atoi(tmp);
+      continue;
+    }
+    else if(0 == strcmp(":version", nv[i]))
+    {
+      proxy->version = nv[i+1];
+      continue;
+    }
+    else if(0 == strcmp("content-length", nv[i]))
+    {
+      //proxy->length = atoi(nv[i+1]);
+      //response_size = atoi(nv[i+1]);
+      continue;
+    }
+
+    //for(j=0; j<strlen(nv[i]) && ':'==nv[i][j]; ++j);
+
+    char *header = *(nv+i);
+    //header[0] = toupper(header[0]);
+    if(MHD_NO == MHD_add_response_header (proxy->http_response,
+                   header, nv[i+1]))
+    {
+      PRINT_INFO2("SPDY_name_value_add failed: '%s' '%s'", header, nv[i+1]);
+      //abort();
+    }
+    PRINT_INFO2("adding '%s: %s'",header, nv[i+1]);
+  }
+  
+  //PRINT_INFO2("%i", MHD_get_response_headers(proxy->http_response, NULL, 
NULL));
+  //PRINT_INFO2("state before %i", proxy->http_connection->state);
+  //PRINT_INFO2("loop before %i", proxy->http_connection->event_loop_info);
+  if(MHD_NO == MHD_queue_response (proxy->http_connection, proxy->status, 
proxy->http_response)){
+    PRINT_INFO("No queue");
+    abort();
+  }
+  //PRINT_INFO2("state after %i", proxy->http_connection->state);
+  //PRINT_INFO2("loop after %i", proxy->http_connection->event_loop_info);
+  //MHD_destroy_response (proxy->http_response);
+  //PRINT_INFO2("state after %i", proxy->http_connection->state);
+  //PRINT_INFO2("loop after %i", proxy->http_connection->event_loop_info);
+}

Added: libmicrohttpd/src/examples/mhd2spdy_http.h
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_http.h                          (rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy_http.h  2013-07-19 09:19:48 UTC (rev 
28187)
@@ -0,0 +1,43 @@
+/*
+    Copyright (C) 2013 Andrey Uzunov
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file structures.h
+ * @author Andrey Uzunov
+ */
+ 
+#ifndef HTTP_H
+#define HTTP_H
+
+#include "mhd2spdy_structures.h"
+
+int
+http_cb_request (void *cls,
+                struct MHD_Connection *connection,
+                const char *url,
+                const char *method,
+                const char *version,
+                const char *upload_data,
+                size_t *upload_data_size,
+                void **ptr);
+                
+void * http_log_cb(void * cls, const char * uri);
+         
+void
+http_create_response(struct Proxy* proxy, char **nv);
+       
+#endif

Added: libmicrohttpd/src/examples/mhd2spdy_spdy.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_spdy.c                          (rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy_spdy.c  2013-07-19 09:19:48 UTC (rev 
28187)
@@ -0,0 +1,908 @@
+/*
+ * Spdylay - SPDY Library
+ *
+ * Copyright (c) 2012 Tatsuhiro Tsujikawa
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sublicense, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+/**
+ * @file spdy.c
+ * @author Tatsuhiro Tsujikawa
+ * @author Andrey Uzunov
+ */
+
+#include "mhd2spdy_structures.h"
+#include "mhd2spdy_spdy.h"
+#include "mhd2spdy_http.h"
+
+enum
+{
+  IO_NONE,
+  WANT_READ,
+  WANT_WRITE
+};
+
+
+/*
+ * Prints error containing the function name |func| and message |msg|
+ * and exit.
+ */
+static void spdy_dief(const char *func, const char *msg)
+{
+  fprintf(stderr, "FATAL: %s: %s\n", func, msg);
+  exit(EXIT_FAILURE);
+}
+
+/*
+ * Prints error containing the function name |func| and error code
+ * |error_code| and exit.
+ */
+void spdy_diec(const char *func, int error_code)
+{
+  fprintf(stderr, "FATAL: %s: error_code=%d, msg=%s\n", func, error_code,
+          spdylay_strerror(error_code));
+  exit(EXIT_FAILURE);
+}
+
+
+/*
+ * The implementation of spdylay_send_callback type. Here we write
+ * |data| with size |length| to the network and return the number of
+ * bytes actually written. See the documentation of
+ * spdylay_send_callback for the details.
+ */
+static ssize_t spdy_cb_send(spdylay_session *session,
+                             const uint8_t *data, size_t length, int flags,
+                             void *user_data)
+{
+  //PRINT_INFO("spdy_cb_send called");
+  struct SPDY_Connection *connection;
+  ssize_t rv;
+  connection = (struct SPDY_Connection*)user_data;
+  connection->want_io = IO_NONE;
+  if(connection->is_tls)
+  {
+    ERR_clear_error();
+    rv = SSL_write(connection->ssl, data, length);
+    if(rv < 0) {
+      int err = SSL_get_error(connection->ssl, rv);
+      if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+        connection->want_io = (err == SSL_ERROR_WANT_READ ?
+                               WANT_READ : WANT_WRITE);
+        rv = SPDYLAY_ERR_WOULDBLOCK;
+      } else {
+        rv = SPDYLAY_ERR_CALLBACK_FAILURE;
+      }
+    }
+  }
+  else
+  {
+    rv = write(connection->fd, 
+            data,
+            length);
+            
+    if (rv < 0)
+    {
+      switch(errno)
+      {                                
+        case EAGAIN:
+  #if EAGAIN != EWOULDBLOCK
+        case EWOULDBLOCK:
+  #endif
+          connection->want_io = WANT_WRITE;
+          rv = SPDYLAY_ERR_WOULDBLOCK;
+          break;
+          
+        default:
+          rv = SPDYLAY_ERR_CALLBACK_FAILURE;
+      }
+    }
+  }
+  return rv;
+}
+
+/*
+ * The implementation of spdylay_recv_callback type. Here we read data
+ * from the network and write them in |buf|. The capacity of |buf| is
+ * |length| bytes. Returns the number of bytes stored in |buf|. See
+ * the documentation of spdylay_recv_callback for the details.
+ */
+static ssize_t spdy_cb_recv(spdylay_session *session,
+                             uint8_t *buf, size_t length, int flags,
+                             void *user_data)
+{
+  struct SPDY_Connection *connection;
+  ssize_t rv;
+  
+  connection = (struct SPDY_Connection*)user_data;
+  //prevent monopolizing everything
+  if(!(++connection->counter % 10)) return SPDYLAY_ERR_WOULDBLOCK;
+  connection->want_io = IO_NONE;
+  if(connection->is_tls)
+  {
+    ERR_clear_error();
+    rv = SSL_read(connection->ssl, buf, length);
+    if(rv < 0) {
+      int err = SSL_get_error(connection->ssl, rv);
+      if(err == SSL_ERROR_WANT_WRITE || err == SSL_ERROR_WANT_READ) {
+        connection->want_io = (err == SSL_ERROR_WANT_READ ?
+                               WANT_READ : WANT_WRITE);
+        rv = SPDYLAY_ERR_WOULDBLOCK;
+      } else {
+        rv = SPDYLAY_ERR_CALLBACK_FAILURE;
+      }
+    } else if(rv == 0) {
+      rv = SPDYLAY_ERR_EOF;
+    }
+  }
+  else
+  {
+    rv = read(connection->fd, 
+            buf,
+            length);
+            
+    if (rv < 0)
+    {
+      switch(errno)
+      {                                
+        case EAGAIN:
+  #if EAGAIN != EWOULDBLOCK
+        case EWOULDBLOCK:
+  #endif
+          connection->want_io = WANT_READ;
+          rv = SPDYLAY_ERR_WOULDBLOCK;
+          break;
+          
+        default:
+          rv = SPDYLAY_ERR_CALLBACK_FAILURE;
+      }
+    }
+    else if(rv == 0)
+      rv = SPDYLAY_ERR_EOF;
+  }
+  return rv;
+}
+
+/*
+ * The implementation of spdylay_before_ctrl_send_callback type.  We
+ * use this function to get stream ID of the request. This is because
+ * stream ID is not known when we submit the request
+ * (spdylay_spdy_submit_request).
+ */
+/*static void spdy_cb_before_ctrl_send(spdylay_session *session,
+                                      spdylay_frame_type type,
+                                      spdylay_frame *frame,
+                                      void *user_data)
+{
+}*/
+
+
+static void spdy_cb_on_ctrl_send(spdylay_session *session,
+                                  spdylay_frame_type type,
+                                  spdylay_frame *frame, void *user_data)
+{
+  //char **nv;
+  //const char *name = NULL;
+  int32_t stream_id;
+  //size_t i;
+  struct Proxy *proxy;
+  
+  switch(type) {
+  case SPDYLAY_SYN_STREAM:
+    //nv = frame->syn_stream.nv;
+    //name = "SYN_STREAM";
+    stream_id = frame->syn_stream.stream_id;
+    proxy = spdylay_session_get_stream_user_data(session, stream_id);
+    ++glob_opt.streams_opened;
+    ++proxy->spdy_connection->streams_opened;
+  PRINT_INFO2("opening stream: str open %i; %s", glob_opt.streams_opened, 
proxy->url);
+    break;
+  default:
+    break;
+  }
+}
+
+void spdy_cb_on_ctrl_recv(spdylay_session *session,
+                                  spdylay_frame_type type,
+                                  spdylay_frame *frame, void *user_data)
+{
+  //struct SPDY_Request *req;
+  char **nv;
+  //const char *name = NULL;
+  int32_t stream_id;
+  struct Proxy * proxy;
+
+  switch(type) {
+    case SPDYLAY_SYN_REPLY:
+      nv = frame->syn_reply.nv;
+      //name = "SYN_REPLY";
+      stream_id = frame->syn_reply.stream_id;
+    break;
+    case SPDYLAY_HEADERS:
+      nv = frame->headers.nv;
+      //name = "HEADERS";
+      stream_id = frame->headers.stream_id;
+    break;
+    default:
+      return;
+    break;
+  }
+
+  proxy = spdylay_session_get_stream_user_data(session, stream_id);
+  PRINT_INFO2("received headers for %s", proxy->url);
+
+  http_create_response(proxy, nv);
+  glob_opt.spdy_data_received = true;
+}
+
+/*
+ * The implementation of spdylay_on_stream_close_callback type. We use
+ * this function to know the response is fully received. Since we just
+ * fetch 1 resource in this program, after reception of the response,
+ * we submit GOAWAY and close the session.
+ */
+static void spdy_cb_on_stream_close(spdylay_session *session,
+                                     int32_t stream_id,
+                                     spdylay_status_code status_code,
+                                     void *user_data)
+{
+  struct Proxy * proxy = spdylay_session_get_stream_user_data(session, 
stream_id);
+  
+  assert(NULL != proxy);
+  
+  --glob_opt.streams_opened;
+  --proxy->spdy_connection->streams_opened;
+  PRINT_INFO2("closing stream: str opened %i", glob_opt.streams_opened);
+  
+  DLL_remove(proxy->spdy_connection->proxies_head, 
proxy->spdy_connection->proxies_tail, proxy);
+  
+  if(proxy->http_active)
+    proxy->spdy_active = false;
+  else
+    free_proxy(proxy);
+  return;
+}
+
+#define SPDY_MAX_OUTLEN 4096
+
+/*
+ * The implementation of spdylay_on_data_chunk_recv_callback type. We
+ * use this function to print the received response body.
+ */
+static void spdy_cb_on_data_chunk_recv(spdylay_session *session, uint8_t flags,
+                                        int32_t stream_id,
+                                        const uint8_t *data, size_t len,
+                                        void *user_data)
+{
+  //struct SPDY_Request *req;
+  struct Proxy *proxy;
+  proxy = spdylay_session_get_stream_user_data(session, stream_id);
+       
+       if(NULL == proxy->http_body)
+               proxy->http_body = au_malloc(len);
+  else
+               proxy->http_body = realloc(proxy->http_body, 
proxy->http_body_size + len);
+       if(NULL == proxy->http_body)
+       {
+               PRINT_INFO("not enough memory (realloc returned NULL)");
+               return ;
+       }
+
+       memcpy(proxy->http_body + proxy->http_body_size, data, len);
+       proxy->http_body_size += len;
+    PRINT_INFO2("received data for %s; %zu bytes", proxy->url, len);
+  glob_opt.spdy_data_received = true;
+}
+
+static void spdy_cb_on_data_recv(spdylay_session *session,
+               uint8_t flags, int32_t stream_id, int32_t length, void 
*user_data)
+{
+       if(flags & SPDYLAY_DATA_FLAG_FIN)
+       {
+    struct Proxy *proxy;
+    proxy = spdylay_session_get_stream_user_data(session, stream_id);
+    proxy->done = true;
+    PRINT_INFO2("last data frame received for %s", proxy->url);
+       }
+}
+
+/*
+ * Setup callback functions. Spdylay API offers many callback
+ * functions, but most of them are optional. The send_callback is
+ * always required. Since we use spdylay_session_recv(), the
+ * recv_callback is also required.
+ */
+static void spdy_setup_spdylay_callbacks(spdylay_session_callbacks *callbacks)
+{
+  memset(callbacks, 0, sizeof(spdylay_session_callbacks));
+  callbacks->send_callback = spdy_cb_send;
+  callbacks->recv_callback = spdy_cb_recv;
+  //callbacks->before_ctrl_send_callback = spdy_cb_before_ctrl_send;
+  callbacks->on_ctrl_send_callback = spdy_cb_on_ctrl_send;
+  callbacks->on_ctrl_recv_callback = spdy_cb_on_ctrl_recv;
+  callbacks->on_stream_close_callback = spdy_cb_on_stream_close;
+  callbacks->on_data_chunk_recv_callback = spdy_cb_on_data_chunk_recv;
+  callbacks->on_data_recv_callback = spdy_cb_on_data_recv;
+}
+
+/*
+ * Callback function for SSL/TLS NPN. Since this program only supports
+ * SPDY protocol, if server does not offer SPDY protocol the Spdylay
+ * library supports, we terminate program.
+ */
+static int spdy_cb_ssl_select_next_proto(SSL* ssl,
+                                unsigned char **out, unsigned char *outlen,
+                                const unsigned char *in, unsigned int inlen,
+                                void *arg)
+{
+    //PRINT_INFO("spdy_cb_ssl_select_next_proto");
+  int rv;
+  uint16_t *spdy_proto_version;
+  /* spdylay_select_next_protocol() selects SPDY protocol version the
+     Spdylay library supports. */
+  rv = spdylay_select_next_protocol(out, outlen, in, inlen);
+  if(rv <= 0) {
+    PRINT_INFO("Server did not advertise spdy/2 or spdy/3 protocol.");
+    return rv;
+  }
+  spdy_proto_version = (uint16_t*)arg;
+  *spdy_proto_version = rv;
+  return SSL_TLSEXT_ERR_OK;
+}
+
+/*
+ * Setup SSL context. We pass |spdy_proto_version| to get negotiated
+ * SPDY protocol version in NPN callback.
+ */
+void spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx, uint16_t *spdy_proto_version)
+{
+  /* Disable SSLv2 and enable all workarounds for buggy servers */
+  SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL|SSL_OP_NO_SSLv2 | 
SSL_OP_NO_COMPRESSION);
+  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_AUTO_RETRY);
+  SSL_CTX_set_mode(ssl_ctx, SSL_MODE_RELEASE_BUFFERS);
+  /* Set NPN callback */
+  SSL_CTX_set_next_proto_select_cb(ssl_ctx, spdy_cb_ssl_select_next_proto,
+                                   spdy_proto_version);
+}
+
+static int spdy_ssl_handshake(SSL *ssl, int fd)
+{
+  int rv;
+  if(SSL_set_fd(ssl, fd) == 0) {
+    spdy_dief("SSL_set_fd", ERR_error_string(ERR_get_error(), NULL));
+  }
+  ERR_clear_error();
+  rv = SSL_connect(ssl);
+  if(rv <= 0) {
+    PRINT_INFO2("SSL_connect %s", ERR_error_string(ERR_get_error(), NULL));
+  }
+  
+  return rv;
+}
+
+/*
+ * Connects to the host |host| and port |port|.  This function returns
+ * the file descriptor of the client socket.
+ */
+static int spdy_socket_connect_to(const char *host, uint16_t port)
+{
+  struct addrinfo hints;
+  int fd = -1;
+  int rv;
+  char service[NI_MAXSERV];
+  struct addrinfo *res, *rp;
+  snprintf(service, sizeof(service), "%u", port);
+  memset(&hints, 0, sizeof(struct addrinfo));
+  hints.ai_family = AF_UNSPEC;
+  hints.ai_socktype = SOCK_STREAM;
+  rv = getaddrinfo(host, service, &hints, &res);
+  if(rv != 0) {
+         printf("%s\n",host);
+    spdy_dief("getaddrinfo", gai_strerror(rv));
+  }
+  for(rp = res; rp; rp = rp->ai_next) {
+    fd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
+    if(fd == -1) {
+      continue;
+    }
+    while((rv = connect(fd, rp->ai_addr, rp->ai_addrlen)) == -1 &&
+          errno == EINTR);
+    if(rv == 0) {
+      break;
+    }
+    close(fd);
+    fd = -1;
+  }
+  freeaddrinfo(res);
+  return fd;
+}
+
+static void spdy_socket_make_non_block(int fd)
+{
+  int flags, rv;
+  while((flags = fcntl(fd, F_GETFL, 0)) == -1 && errno == EINTR);
+  if(flags == -1) {
+    spdy_dief("fcntl", strerror(errno));
+  }
+  while((rv = fcntl(fd, F_SETFL, flags | O_NONBLOCK)) == -1 && errno == EINTR);
+  if(rv == -1) {
+    spdy_dief("fcntl", strerror(errno));
+  }
+}
+
+/*
+ * Setting TCP_NODELAY is not mandatory for the SPDY protocol.
+ */
+static void spdy_socket_set_tcp_nodelay(int fd)
+{
+  int val = 1;
+  int rv;
+  rv = setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
+  if(rv == -1) {
+    spdy_dief("setsockopt", strerror(errno));
+  }
+}
+
+/*
+ * Update |pollfd| based on the state of |connection|.
+ */
+void spdy_ctl_poll(struct pollfd *pollfd, struct SPDY_Connection *connection)
+{
+  pollfd->events = 0;
+  if(spdylay_session_want_read(connection->session) ||
+     connection->want_io == WANT_READ) {
+    pollfd->events |= POLLIN;
+  }
+  if(spdylay_session_want_write(connection->session) ||
+     connection->want_io == WANT_WRITE) {
+    pollfd->events |= POLLOUT;
+  }
+}
+
+/*
+ * Update |selectfd| based on the state of |connection|.
+ */
+bool spdy_ctl_select(fd_set * read_fd_set,
+                               fd_set * write_fd_set, 
+                               fd_set * except_fd_set,
+         struct SPDY_Connection *connection)
+{
+  bool ret = false;
+  
+  if(spdylay_session_want_read(connection->session) ||
+     connection->want_io == WANT_READ) {
+    FD_SET(connection->fd, read_fd_set);
+    ret = true;
+  }
+  if(spdylay_session_want_write(connection->session) ||
+     connection->want_io == WANT_WRITE) {
+    FD_SET(connection->fd, write_fd_set);
+    ret = true;
+  }
+  return ret;
+}
+
+/*
+ * Performs the network I/O.
+ */
+int  spdy_exec_io(struct SPDY_Connection *connection)
+{
+  int rv;
+  rv = spdylay_session_recv(connection->session);
+  if(rv != 0) {
+    PRINT_INFO2("spdylay_session_recv %i", rv);
+    return rv;
+  }
+  rv = spdylay_session_send(connection->session);
+  if(rv != 0) {
+    PRINT_INFO2("spdylay_session_send %i", rv);
+  }
+  return rv;
+}
+
+/*
+ * Fetches the resource denoted by |uri|.
+ */
+struct SPDY_Connection * spdy_connect(const struct URI *uri, uint16_t port, 
bool is_tls)
+{
+  spdylay_session_callbacks callbacks;
+  int fd;
+  //SSL_CTX *ssl_ctx;
+  SSL *ssl=NULL;
+  //struct SPDY_Request req;
+  struct SPDY_Connection * connection;
+  int rv;
+
+  spdy_setup_spdylay_callbacks(&callbacks);
+
+  /* Establish connection and setup SSL */
+  PRINT_INFO2("connecting to %s:%i", uri->host, port);
+  fd = spdy_socket_connect_to(uri->host, port);
+  if(fd == -1) {
+    PRINT_INFO("Could not open file descriptor");
+    return NULL;//glob_opt.spdy_connection;
+  }
+  
+  if(is_tls)
+  {
+    /*ssl_ctx = SSL_CTX_new(SSLv23_client_method());
+    if(ssl_ctx == NULL) {
+      spdy_dief("SSL_CTX_new", ERR_error_string(ERR_get_error(), NULL));
+    }
+    spdy_ssl_init_ssl_ctx(ssl_ctx, &spdy_proto_version);
+    */
+    ssl = SSL_new(glob_opt.ssl_ctx);
+    if(ssl == NULL) {
+      spdy_dief("SSL_new", ERR_error_string(ERR_get_error(), NULL));
+    }
+    
+    //TODO non-blocking
+    /* To simplify the program, we perform SSL/TLS handshake in blocking
+       I/O. */
+    glob_opt.spdy_proto_version = 0;
+    rv = spdy_ssl_handshake(ssl, fd);
+    if(rv <= 0 || (glob_opt.spdy_proto_version != 3 && 
glob_opt.spdy_proto_version != 2))
+    {
+      PRINT_INFO("Closing SSL");
+      //no spdy on the other side
+      SSL_shutdown(ssl);
+      close(fd);
+      SSL_free(ssl);
+      
+      return NULL;
+    }
+  }
+  else
+  {
+    glob_opt.spdy_proto_version = 3;
+  }
+
+  if(NULL == (connection = au_malloc(sizeof(struct SPDY_Connection))))
+    return NULL;
+  //memset(connection, 0 , sizeof(struct SPDY_Connection));
+  
+  connection->is_tls = is_tls;
+  connection->ssl = ssl;
+  connection->want_io = IO_NONE;
+  connection->host = strdup(uri->host);
+
+  /* Here make file descriptor non-block */
+  spdy_socket_make_non_block(fd);
+  spdy_socket_set_tcp_nodelay(fd);
+
+  PRINT_INFO2("[INFO] SPDY protocol version = %d\n", 
glob_opt.spdy_proto_version);
+  rv = spdylay_session_client_new(&(connection->session), 
glob_opt.spdy_proto_version,
+                                  &callbacks, connection);
+  if(rv != 0) {
+    spdy_diec("spdylay_session_client_new", rv);
+  }
+  
+  connection->fd = fd;
+
+       return connection;
+}
+
+void
+spdy_free_connection(struct SPDY_Connection * connection)
+{
+  if(NULL != connection)
+  {
+    spdylay_session_del(connection->session);
+    SSL_free(connection->ssl);
+    free(connection->host);
+    free(connection);
+  }
+}
+
+int
+spdy_request(const char **nv, struct Proxy *proxy)
+{
+  int ret;
+  uint16_t port;
+  struct SPDY_Connection *connection;
+  
+  if(glob_opt.only_proxy)
+  {
+    connection = glob_opt.spdy_connection;
+  }
+  else
+  {
+    connection = glob_opt.spdy_connections_head;
+    while(NULL != connection)
+    {
+      if(0 == strcasecmp(proxy->uri->host, connection->host))
+        break;
+      connection = connection->next;
+    }
+  
+    if(NULL == connection)
+    {
+      //connect to host
+      port = proxy->uri->port;
+      if(0 == port) port = 443;
+      connection = spdy_connect(proxy->uri, port, true);
+      if(NULL != connection)
+      {
+        DLL_insert(glob_opt.spdy_connections_head, 
glob_opt.spdy_connections_tail, connection);
+        glob_opt.total_spdy_connections++;
+      }
+      else
+        connection = glob_opt.spdy_connection;
+    }
+  }
+  
+  if(NULL == connection)
+  {
+    PRINT_INFO("there is no proxy!");
+    return -1;
+  }
+  
+  proxy->spdy_connection = connection;
+  ret = spdylay_submit_request(connection->session, 0, nv, NULL, proxy);
+  if(ret != 0) {
+    spdy_diec("spdylay_spdy_submit_request", ret);
+  }
+  DLL_insert(connection->proxies_head, connection->proxies_tail, proxy);
+  
+  return ret;
+}
+
+
+void
+spdy_get_pollfdset(struct pollfd fds[], struct SPDY_Connection *connections[], 
int max_size, nfds_t *real_size)
+{
+  struct SPDY_Connection *connection;
+  struct Proxy *proxy;
+  
+  *real_size = 0;
+  if(max_size<1) return;
+  if(NULL != glob_opt.spdy_connection)
+  {
+    spdy_ctl_poll(&(fds[*real_size]), glob_opt.spdy_connection);
+    if(!fds[*real_size].events)
+    {
+      //PRINT_INFO("TODO drop connection");
+      glob_opt.streams_opened -= glob_opt.spdy_connection->streams_opened;
+      
+      for(proxy = glob_opt.spdy_connection->proxies_head; NULL != proxy; 
proxy=proxy->next)
+      {
+        DLL_remove(glob_opt.spdy_connection->proxies_head, 
glob_opt.spdy_connection->proxies_tail, proxy);
+        proxy->spdy_active = false;
+      }
+      spdy_free_connection(glob_opt.spdy_connection);
+      glob_opt.spdy_connection = NULL;
+    }
+    else
+    {
+      fds[*real_size].fd = glob_opt.spdy_connection->fd;
+      connections[*real_size] = glob_opt.spdy_connection;
+      ++(*real_size);
+    }
+  }
+  
+  connection = glob_opt.spdy_connections_head;
+  
+  while(NULL != connection && *real_size < max_size)
+  {
+    assert(!glob_opt.only_proxy);
+    spdy_ctl_poll(&(fds[*real_size]), connection);
+    if(!fds[*real_size].events)
+    {
+      //PRINT_INFO("TODO drop connection");
+      glob_opt.streams_opened -= connection->streams_opened;
+      DLL_remove(glob_opt.spdy_connections_head, 
glob_opt.spdy_connections_tail, connection);
+      glob_opt.total_spdy_connections--;
+      
+      for(proxy = connection->proxies_head; NULL != proxy; proxy=proxy->next)
+      {
+        DLL_remove(connection->proxies_head, connection->proxies_tail, proxy);
+        proxy->spdy_active = false;
+      }
+      spdy_free_connection(connection);
+    }
+    else
+    {
+      fds[*real_size].fd = connection->fd;
+      connections[*real_size] = connection;
+      ++(*real_size);
+    }
+    connection = connection->next;
+  }
+  
+  //, "TODO max num of conn reached; close something"
+  assert(NULL == connection);
+}
+
+
+int
+spdy_get_selectfdset(fd_set * read_fd_set,
+                               fd_set * write_fd_set, 
+                               fd_set * except_fd_set,
+        struct SPDY_Connection *connections[], int max_size, nfds_t *real_size)
+{
+  struct SPDY_Connection *connection;
+  struct Proxy *proxy;
+  bool ret;
+  int maxfd = 0;
+  
+  *real_size = 0;
+  if(max_size<1) return 0;
+  if(NULL != glob_opt.spdy_connection)
+  {
+    ret = spdy_ctl_select(read_fd_set,
+                                write_fd_set, 
+                                except_fd_set, glob_opt.spdy_connection);
+    if(!ret)
+    {
+      //PRINT_INFO("TODO drop connection");
+      glob_opt.streams_opened -= glob_opt.spdy_connection->streams_opened;
+      
+      for(proxy = glob_opt.spdy_connection->proxies_head; NULL != proxy; 
proxy=proxy->next)
+      {
+        DLL_remove(glob_opt.spdy_connection->proxies_head, 
glob_opt.spdy_connection->proxies_tail, proxy);
+        proxy->spdy_active = false;
+      }
+      spdy_free_connection(glob_opt.spdy_connection);
+      glob_opt.spdy_connection = NULL;
+    }
+    else
+    {
+      connections[*real_size] = glob_opt.spdy_connection;
+      ++(*real_size);
+      if(maxfd < glob_opt.spdy_connection->fd) maxfd = 
glob_opt.spdy_connection->fd;
+    }
+  }
+  
+  connection = glob_opt.spdy_connections_head;
+  
+  while(NULL != connection && *real_size < max_size)
+  {
+    assert(!glob_opt.only_proxy);
+    ret = spdy_ctl_select(read_fd_set,
+                                write_fd_set, 
+                                except_fd_set, connection);
+    if(!ret)
+    {
+      //PRINT_INFO("TODO drop connection");
+      glob_opt.streams_opened -= connection->streams_opened;
+      DLL_remove(glob_opt.spdy_connections_head, 
glob_opt.spdy_connections_tail, connection);
+      glob_opt.total_spdy_connections--;
+      
+      for(proxy = connection->proxies_head; NULL != proxy; proxy=proxy->next)
+      {
+        DLL_remove(connection->proxies_head, connection->proxies_tail, proxy);
+        proxy->spdy_active = false;
+      }
+      spdy_free_connection(connection);
+    }
+    else
+    {
+      connections[*real_size] = connection;
+      ++(*real_size);
+      if(maxfd < connection->fd) maxfd = connection->fd;
+    }
+    connection = connection->next;
+  }
+  
+  //, "TODO max num of conn reached; close something"
+  assert(NULL == connection);
+  
+  return maxfd;
+}
+
+
+void
+spdy_run(struct pollfd fds[], struct SPDY_Connection *connections[], int size)
+{
+  int i;
+  int ret;
+  struct Proxy *proxy;
+  //PRINT_INFO2("size is %i", size);
+  
+  for(i=0; i<size; ++i)
+  {
+    //  PRINT_INFO2("exec about to be called for %s", connections[i]->host);
+    if(fds[i].revents & (POLLIN | POLLOUT))
+    {
+      ret = spdy_exec_io(connections[i]);
+      //PRINT_INFO2("%i",ret);
+      //if((spdy_pollfds[i].revents & POLLHUP) || (spdy_pollfds[0].revents & 
POLLERR))
+      //  PRINT_INFO("SPDY SPDY_Connection error");
+      
+      //TODO POLLRDHUP
+      // always close on ret != 0?
+        
+      if(0 != ret)
+      {
+        glob_opt.streams_opened -= connections[i]->streams_opened;
+        if(connections[i] == glob_opt.spdy_connection)
+        {
+          glob_opt.spdy_connection = NULL;
+        }
+        else
+        {
+          DLL_remove(glob_opt.spdy_connections_head, 
glob_opt.spdy_connections_tail, connections[i]);
+          glob_opt.total_spdy_connections--;
+        }
+        for(proxy = connections[i]->proxies_head; NULL != proxy; 
proxy=proxy->next)
+        {
+          DLL_remove(connections[i]->proxies_head, 
connections[i]->proxies_tail, proxy);
+          proxy->spdy_active = false;
+        }
+        spdy_free_connection(connections[i]);
+      }
+    }
+    else
+    {
+      PRINT_INFO("not called");
+    }
+  }
+}
+
+void
+spdy_run_select(fd_set * read_fd_set,
+                               fd_set * write_fd_set, 
+                               fd_set * except_fd_set, struct SPDY_Connection 
*connections[], int size)
+{
+  int i;
+  int ret;
+  struct Proxy *proxy;
+  //PRINT_INFO2("size is %i", size);
+  
+  for(i=0; i<size; ++i)
+  {
+    //  PRINT_INFO2("exec about to be called for %s", connections[i]->host);
+    if(FD_ISSET(connections[i]->fd, read_fd_set) || 
FD_ISSET(connections[i]->fd, write_fd_set) || FD_ISSET(connections[i]->fd, 
except_fd_set))
+    {
+      ret = spdy_exec_io(connections[i]);
+      //PRINT_INFO2("%i",ret);
+      //if((spdy_pollfds[i].revents & POLLHUP) || (spdy_pollfds[0].revents & 
POLLERR))
+      //  PRINT_INFO("SPDY SPDY_Connection error");
+      
+      //TODO POLLRDHUP
+      // always close on ret != 0?
+        
+      if(0 != ret)
+      {
+        glob_opt.streams_opened -= connections[i]->streams_opened;
+        if(connections[i] == glob_opt.spdy_connection)
+        {
+          glob_opt.spdy_connection = NULL;
+        }
+        else
+        {
+          DLL_remove(glob_opt.spdy_connections_head, 
glob_opt.spdy_connections_tail, connections[i]);
+          glob_opt.total_spdy_connections--;
+        }
+        for(proxy = connections[i]->proxies_head; NULL != proxy; 
proxy=proxy->next)
+        {
+          DLL_remove(connections[i]->proxies_head, 
connections[i]->proxies_tail, proxy);
+          proxy->spdy_active = false;
+        }
+        spdy_free_connection(connections[i]);
+      }
+    }
+    else
+    {
+      PRINT_INFO("not called");
+    }
+  }
+}

Added: libmicrohttpd/src/examples/mhd2spdy_spdy.h
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_spdy.h                          (rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy_spdy.h  2013-07-19 09:19:48 UTC (rev 
28187)
@@ -0,0 +1,67 @@
+/*
+    Copyright (C) 2013 Andrey Uzunov
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file spdy.h
+ * @author Andrey Uzunov
+ */
+ 
+#ifndef SPDY_H
+#define SPDY_H
+
+#include "mhd2spdy_structures.h"
+
+struct SPDY_Connection * spdy_connect(const struct URI *uri, uint16_t port, 
bool is_tls);
+
+void spdy_ctl_poll(struct pollfd *pollfd, struct SPDY_Connection *connection);
+
+bool spdy_ctl_select(fd_set * read_fd_set,
+                               fd_set * write_fd_set, 
+                               fd_set * except_fd_set,
+         struct SPDY_Connection *connection);
+
+int spdy_exec_io(struct SPDY_Connection *connection);
+
+void spdy_diec(const char *func, int error_code);
+
+int 
+spdy_request(const char **nv, struct Proxy *proxy);
+
+void spdy_ssl_init_ssl_ctx(SSL_CTX *ssl_ctx, uint16_t *spdy_proto_version);
+
+void
+spdy_free_connection(struct SPDY_Connection * connection);
+
+void
+spdy_get_pollfdset(struct pollfd fds[], struct SPDY_Connection *connections[], 
int max_size, nfds_t *real_size);
+
+
+int
+spdy_get_selectfdset(fd_set * read_fd_set,
+                               fd_set * write_fd_set, 
+                               fd_set * except_fd_set,
+        struct SPDY_Connection *connections[], int max_size, nfds_t 
*real_size);
+        
+void
+spdy_run(struct pollfd fds[], struct SPDY_Connection *connections[], int size);
+
+void
+spdy_run_select(fd_set * read_fd_set,
+                               fd_set * write_fd_set, 
+                               fd_set * except_fd_set, struct SPDY_Connection 
*connections[], int size);
+        
+#endif

Added: libmicrohttpd/src/examples/mhd2spdy_structures.c
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_structures.c                            
(rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy_structures.c    2013-07-19 09:19:48 UTC 
(rev 28187)
@@ -0,0 +1,149 @@
+/*
+    Copyright (C) 2013 Andrey Uzunov
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file structures.h
+ * @author Andrey Uzunov
+ */
+ 
+#include "mhd2spdy_structures.h"
+
+
+void
+free_uri(struct URI * uri)
+{
+  if(NULL != uri)
+  {
+    free(uri->full_uri);
+    free(uri->scheme);
+    free(uri->host_and_port);
+    //free(uri->host_and_port_for_connecting);
+    free(uri->host);
+    free(uri->path);
+    free(uri->path_and_more);
+    free(uri->query);
+    free(uri->fragment);
+    uri->port = 0;
+    free(uri);
+  }
+}
+
+int
+init_parse_uri(regex_t * preg)
+{
+  // RFC 2396
+  // ^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?
+      /*
+        scheme    = $2
+      authority = $4
+      path      = $5
+      query     = $7
+      fragment  = $9
+      */
+  
+  return regcomp(preg, 
"^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?", REG_EXTENDED);
+}
+
+void
+deinit_parse_uri(regex_t * preg)
+{
+  regfree(preg);
+}
+  
+int
+parse_uri(regex_t * preg, char * full_uri, struct URI ** uri)
+{
+  int ret;
+  char *colon;
+  long long port;
+  size_t nmatch = 10;
+  regmatch_t pmatch[10];
+
+  if (0 != (ret = regexec(preg, full_uri, nmatch, pmatch, 0)))
+    return ret;
+    
+  *uri = au_malloc(sizeof(struct URI));
+  if(NULL == *uri)
+    return -200;
+    
+  (*uri)->full_uri = strdup(full_uri);
+  
+  asprintf(&((*uri)->scheme), "%.*s",pmatch[2].rm_eo - pmatch[2].rm_so, 
&full_uri[pmatch[2].rm_so]);
+  asprintf(&((*uri)->host_and_port), "%.*s",pmatch[4].rm_eo - pmatch[4].rm_so, 
&full_uri[pmatch[4].rm_so]);
+  asprintf(&((*uri)->path), "%.*s",pmatch[5].rm_eo - pmatch[5].rm_so, 
&full_uri[pmatch[5].rm_so]);
+  asprintf(&((*uri)->path_and_more), "%.*s",pmatch[9].rm_eo - pmatch[5].rm_so, 
&full_uri[pmatch[5].rm_so]);
+  asprintf(&((*uri)->query), "%.*s",pmatch[7].rm_eo - pmatch[7].rm_so, 
&full_uri[pmatch[7].rm_so]);
+  asprintf(&((*uri)->fragment), "%.*s",pmatch[9].rm_eo - pmatch[9].rm_so, 
&full_uri[pmatch[9].rm_so]);
+  
+  colon = strrchr((*uri)->host_and_port, ':');
+  if(NULL == colon)
+  {
+    (*uri)->host = strdup((*uri)->host_and_port);
+    /*if(0 == strcasecmp("http", uri->scheme))
+    {
+      uri->port = 80;
+      asprintf(&(uri->host_and_port_for_connecting), "%s:80", 
uri->host_and_port);
+    }
+    else if(0 == strcasecmp("https", uri->scheme))
+    {
+      uri->port = 443;
+      asprintf(&(uri->host_and_port_for_connecting), "%s:443", 
uri->host_and_port);
+    }
+    else
+    {
+      PRINT_INFO("no standard scheme!");
+      */(*uri)->port = 0;
+      /*uri->host_and_port_for_connecting = strdup(uri->host_and_port);
+    }*/
+    return 0;
+  }
+  
+  port = atoi(colon  + 1);
+  if(port<1 || port >= 256 * 256)
+  {
+    free_uri(*uri);
+    return -100;
+  }
+  (*uri)->port = port;
+  asprintf(&((*uri)->host), "%.*s", (int)(colon - (*uri)->host_and_port), 
(*uri)->host_and_port);
+  
+  return 0;
+}
+
+void
+free_proxy(struct Proxy *proxy)
+{
+  //PRINT_INFO("free proxy called");
+  free(proxy->http_body);
+  free_uri(proxy->uri);
+       free(proxy->url);
+       free(proxy->http_uri);
+       free(proxy);
+}
+
+void *au_malloc(size_t size)
+{
+  void *new_memory;
+  
+  new_memory = malloc(size);
+  if(NULL != new_memory)
+  {
+    glob_opt.global_memory += size;
+    memset(new_memory, 0, size);
+  }
+  return new_memory;
+}

Added: libmicrohttpd/src/examples/mhd2spdy_structures.h
===================================================================
--- libmicrohttpd/src/examples/mhd2spdy_structures.h                            
(rev 0)
+++ libmicrohttpd/src/examples/mhd2spdy_structures.h    2013-07-19 09:19:48 UTC 
(rev 28187)
@@ -0,0 +1,265 @@
+/*
+    Copyright (C) 2013 Andrey Uzunov
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/**
+ * @file structures.h
+ * @author Andrey Uzunov
+ */
+#ifndef STRUCTURES_H
+#define STRUCTURES_H
+
+#define _GNU_SOURCE
+ 
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <assert.h>
+#include <microhttpd.h>
+#include <signal.h>
+#include <poll.h>
+#include <fcntl.h>
+#include <regex.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#include <spdylay/spdylay.h>
+#include <getopt.h>
+
+struct Proxy;
+
+struct SPDY_Connection {
+  SSL *ssl;
+  //SSL_CTX *ssl_ctx;
+  spdylay_session *session;
+  struct SPDY_Connection *prev;
+  struct SPDY_Connection *next;
+  struct Proxy *proxies_head;
+  struct Proxy *proxies_tail;
+  char *host;
+  /* WANT_READ if SSL connection needs more input; or WANT_WRITE if it
+     needs more output; or IO_NONE. This is necessary because SSL/TLS
+     re-negotiation is possible at any time. Spdylay API offers
+     similar functions like spdylay_session_want_read() and
+     spdylay_session_want_write() but they do not take into account
+     SSL connection. */
+  int fd;
+  int want_io;
+  uint counter;
+  uint streams_opened;
+  bool is_tls;
+};
+
+
+struct URI
+{
+  char * full_uri;
+  char * scheme;
+  char * host_and_port;
+  //char * host_and_port_for_connecting;
+  char * host;
+  char * path;
+  char * path_and_more;
+  char * query;
+  char * fragment;
+  uint16_t port;
+};
+
+struct HTTP_URI;
+
+struct Proxy
+{
+       struct MHD_Connection *http_connection;
+       struct MHD_Response *http_response;
+       struct URI *uri;
+  struct HTTP_URI *http_uri; //TODO remove me
+  struct SPDY_Connection *spdy_connection;
+  struct Proxy *next;
+  struct Proxy *prev;
+       //char *path;
+       char *url;
+       //struct SPDY_Request *request;
+       //struct SPDY_Response *response;
+       //CURL *curl_handle;
+       //struct curl_slist *curl_headers;
+       //struct SPDY_NameValue *headers;
+       char *version;
+       //char *status_msg;
+       void *http_body;
+       size_t http_body_size;
+       ssize_t length;
+       int status;
+       int id;
+       bool done;
+  bool http_active;
+  bool spdy_active;
+};
+
+struct HTTP_URI
+{
+  char * uri;
+  struct Proxy * proxy;
+};
+
+struct SPDY_Headers
+{
+  const char **nv;
+  int num;
+  int cnt;
+};
+
+struct global_options
+{
+  char *spdy2http_str;
+  struct SPDY_Connection *spdy_connection;
+  struct SPDY_Connection *spdy_connections_head;
+  struct SPDY_Connection *spdy_connections_tail;
+  int streams_opened;
+  int responses_pending;
+  regex_t uri_preg;
+  size_t global_memory;
+  SSL_CTX *ssl_ctx;
+  uint32_t total_spdy_connections;
+  uint16_t spdy_proto_version;
+  uint16_t listen_port;
+  bool verbose;
+  bool only_proxy;
+  bool spdy_data_received;
+} glob_opt;
+
+/*
+
+#define SOCK_ADDR_IN_PTR(sa)   ((struct sockaddr_in *)(sa))
+#define SOCK_ADDR_IN_FAMILY(sa)        SOCK_ADDR_IN_PTR(sa)->sin_family
+#define SOCK_ADDR_IN_PORT(sa)  SOCK_ADDR_IN_PTR(sa)->sin_port
+#define SOCK_ADDR_IN_ADDR(sa)  SOCK_ADDR_IN_PTR(sa)->sin_addr
+
+#ifdef HAS_IPV6
+
+#define SOCK_ADDR_IN6_PTR(sa)  ((struct sockaddr_in6 *)(sa))
+#define SOCK_ADDR_IN6_FAMILY(sa) SOCK_ADDR_IN6_PTR(sa)->sin6_family
+#define SOCK_ADDR_IN6_PORT(sa) SOCK_ADDR_IN6_PTR(sa)->sin6_port
+#define SOCK_ADDR_IN6_ADDR(sa) SOCK_ADDR_IN6_PTR(sa)->sin6_addr
+
+#endif
+*/
+
+//forbidden headers
+#define SPDY_HTTP_HEADER_TRANSFER_ENCODING "transfer-encoding"
+#define SPDY_HTTP_HEADER_PROXY_CONNECTION "proxy-connection"
+#define SPDY_HTTP_HEADER_KEEP_ALIVE "keep-alive"
+#define SPDY_HTTP_HEADER_CONNECTION "connection"
+
+#define MAX_SPDY_CONNECTIONS 100
+
+
+/**
+ * Insert an element at the head of a DLL. Assumes that head, tail and
+ * element are structs with prev and next fields.
+ *
+ * @param head pointer to the head of the DLL (struct ? *)
+ * @param tail pointer to the tail of the DLL (struct ? *)
+ * @param element element to insert (struct ? *)
+ */
+#define DLL_insert(head,tail,element) do { \
+       (element)->next = (head); \
+       (element)->prev = NULL; \
+       if ((tail) == NULL) \
+               (tail) = element; \
+       else \
+               (head)->prev = element; \
+       (head) = (element); } while (0)
+
+
+/**
+ * Remove an element from a DLL. Assumes
+ * that head, tail and element are structs
+ * with prev and next fields.
+ *
+ * @param head pointer to the head of the DLL (struct ? *)
+ * @param tail pointer to the tail of the DLL (struct ? *)
+ * @param element element to remove (struct ? *)
+ */
+#define DLL_remove(head,tail,element) do { \
+       if ((element)->prev == NULL) \
+               (head) = (element)->next;  \
+       else \
+               (element)->prev->next = (element)->next; \
+       if ((element)->next == NULL) \
+               (tail) = (element)->prev;  \
+       else \
+               (element)->next->prev = (element)->prev; \
+       (element)->next = NULL; \
+       (element)->prev = NULL; } while (0)
+
+
+#define PRINT_INFO(msg) do{\
+  if(glob_opt.verbose){\
+       printf("%i:%s\n", __LINE__, msg);\
+       fflush(stdout);\
+       }\
+  }\
+       while(0)
+
+
+#define PRINT_INFO2(fmt, ...) do{\
+  if(glob_opt.verbose){\
+       printf("%i\n", __LINE__);\
+       printf(fmt,##__VA_ARGS__);\
+       printf("\n");\
+       fflush(stdout);\
+       }\
+       }\
+       while(0)
+  
+
+#define DIE(msg) do{\
+       printf("FATAL ERROR (line %i): %s\n", __LINE__, msg);\
+       fflush(stdout);\
+  exit(EXIT_FAILURE);\
+       }\
+       while(0)
+  
+  
+
+
+void
+free_uri(struct URI * uri);
+
+int
+init_parse_uri(regex_t * preg);
+
+void
+deinit_parse_uri(regex_t * preg);
+  
+int
+parse_uri(regex_t * preg, char * full_uri, struct URI ** uri);
+
+void
+free_proxy(struct Proxy *proxy);
+
+void *au_malloc(size_t size);
+
+#endif

Modified: libmicrohttpd/src/microhttpd/connection.c
===================================================================
--- libmicrohttpd/src/microhttpd/connection.c   2013-07-19 09:09:57 UTC (rev 
28186)
+++ libmicrohttpd/src/microhttpd/connection.c   2013-07-19 09:19:48 UTC (rev 
28187)
@@ -2312,7 +2312,7 @@
         case MHD_CONNECTION_FOOTERS_SENT:
 #if HAVE_DECL_TCP_CORK
           /* done sending, uncork */
-          {
+          if (0) {
             const int val = 0;
             setsockopt (connection->socket_fd, IPPROTO_TCP, TCP_CORK, &val,
                         sizeof (val));

Modified: libmicrohttpd/src/microspdy/io_raw.c
===================================================================
--- libmicrohttpd/src/microspdy/io_raw.c        2013-07-19 09:09:57 UTC (rev 
28186)
+++ libmicrohttpd/src/microspdy/io_raw.c        2013-07-19 09:19:48 UTC (rev 
28187)
@@ -159,6 +159,7 @@
 int
 SPDYF_raw_before_write(struct SPDY_Session *session)
 {
+#if HAVE_DECL_TCP_CORK
   if(0 == (SPDY_DAEMON_FLAG_NO_DELAY & session->daemon->flags))
   {
     int val = 1;
@@ -168,6 +169,7 @@
     if(-1 == ret)
       SPDYF_DEBUG("WARNING: Couldn't set the new connection to TCP_CORK");
   }
+#endif
   
        return SPDY_YES;
 }
@@ -176,6 +178,7 @@
 int
 SPDYF_raw_after_write(struct SPDY_Session *session, int was_written)
 {
+#if HAVE_DECL_TCP_CORK
   if(SPDY_YES == was_written && 0 == (SPDY_DAEMON_FLAG_NO_DELAY & 
session->daemon->flags))
   {
     int val = 0;
@@ -186,5 +189,6 @@
       SPDYF_DEBUG("WARNING: Couldn't unset the new connection to TCP_CORK");
   }
   
+#endif
        return was_written;
 }




reply via email to

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