1748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/*
2748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    Copyright Copyright (C) 2013 Andrey Uzunov
3748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
4748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    This program is free software: you can redistribute it and/or modify
5748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    it under the terms of the GNU General Public License as published by
6748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    the Free Software Foundation, either version 3 of the License, or
7748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    (at your option) any later version.
8748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
9748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    This program is distributed in the hope that it will be useful,
10748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    but WITHOUT ANY WARRANTY; without even the implied warranty of
11748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    GNU General Public License for more details.
13748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
14748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    You should have received a copy of the GNU General Public License
15748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    along with this program.  If not, see <http://www.gnu.org/licenses/>.
16748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat*/
17748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
18748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat/**
19748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @file mhd2spdy.c
20748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @brief  The main file of the HTTP-to-SPDY proxy with the 'main' function
21748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         and event loop. No threads are used.
22748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         Currently only GET is supported.
23748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         TODOs:
24748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         - non blocking SSL connect
25748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         - check certificate
26748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat *         - on closing spdy session, close sockets for all requests
27748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat * @author Andrey Uzunov
28748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat */
29748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
30748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
31748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "mhd2spdy_structures.h"
32748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "mhd2spdy_spdy.h"
33748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat#include "mhd2spdy_http.h"
34748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
35748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
36748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic int run = 1;
37748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat//static int spdy_close = 0;
38748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
39748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
40748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratstatic void
41748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratcatch_signal(int signal)
42748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
43748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  (void)signal;
44748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //spdy_close = 1;
45748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  run = 0;
46748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
47748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
48748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
49748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid
50748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratprint_stat()
51748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
52748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if(!glob_opt.statistics)
53748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return;
54748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
55748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  printf("--------------------------\n");
56748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  printf("Statistics (TLS overhead is ignored when used):\n");
57748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //printf("HTTP bytes received: %lld\n", glob_stat.http_bytes_received);
58748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //printf("HTTP bytes sent: %lld\n", glob_stat.http_bytes_sent);
59748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  printf("SPDY bytes sent: %lld\n", glob_stat.spdy_bytes_sent);
60748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  printf("SPDY bytes received: %lld\n", glob_stat.spdy_bytes_received);
61748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  printf("SPDY bytes received and dropped: %lld\n", glob_stat.spdy_bytes_received_and_dropped);
62748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
63748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
64748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
65748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
66748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratrun_everything ()
67748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
68748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  unsigned long long timeoutlong=0;
69748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct timeval timeout;
70748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int ret;
71748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set rs;
72748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set ws;
73748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  fd_set es;
74748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int maxfd = -1;
75748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int maxfd_s = -1;
76748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct MHD_Daemon *daemon;
77748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  nfds_t spdy_npollfds = 1;
78748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct URI * spdy2http_uri = NULL;
79748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct SPDY_Connection *connection;
80748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct SPDY_Connection *connections[MAX_SPDY_CONNECTIONS];
81748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct SPDY_Connection *connection_for_delete;
82748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
83748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (signal(SIGPIPE, SIG_IGN) == SIG_ERR)
84748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    PRINT_INFO("signal failed");
85748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
86748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if (signal(SIGINT, catch_signal) == SIG_ERR)
87748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    PRINT_INFO("signal failed");
88748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
89748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  glob_opt.streams_opened = 0;
90748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  glob_opt.responses_pending = 0;
91748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //glob_opt.global_memory = 0;
92748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
93748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  srand(time(NULL));
94748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
95748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if(init_parse_uri(&glob_opt.uri_preg))
96748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    DIE("Regexp compilation failed");
97748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
98748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if(NULL != glob_opt.spdy2http_str)
99748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  {
100748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    ret = parse_uri(&glob_opt.uri_preg, glob_opt.spdy2http_str, &spdy2http_uri);
101748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if(ret != 0)
102748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      DIE("spdy_parse_uri failed");
103748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
104748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
105748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  SSL_load_error_strings();
106748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  SSL_library_init();
107748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  glob_opt.ssl_ctx = SSL_CTX_new(SSLv23_client_method());
108748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if(glob_opt.ssl_ctx == NULL) {
109748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    PRINT_INFO2("SSL_CTX_new %s", ERR_error_string(ERR_get_error(), NULL));
110748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    abort();
111748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
112748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  spdy_ssl_init_ssl_ctx(glob_opt.ssl_ctx, &glob_opt.spdy_proto_version);
113748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
114748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  daemon = MHD_start_daemon (
115748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_SUPPRESS_DATE_NO_CLOCK,
116748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          glob_opt.listen_port,
117748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          NULL, NULL, &http_cb_request, NULL,
118748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_OPTION_URI_LOG_CALLBACK, &http_cb_log, NULL,
119748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_OPTION_NOTIFY_COMPLETED, &http_cb_request_completed, NULL,
120748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_OPTION_END);
121748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if(NULL==daemon)
122748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    DIE("MHD_start_daemon failed");
123748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
124748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  do
125748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  {
126748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    timeout.tv_sec = 0;
127748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    timeout.tv_usec = 0;
128748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
129748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if(NULL == glob_opt.spdy_connection && NULL != glob_opt.spdy2http_str)
130748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
131748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      glob_opt.spdy_connection = spdy_connect(spdy2http_uri, spdy2http_uri->port, strcmp("https", spdy2http_uri->scheme)==0);
132748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      if(NULL == glob_opt.spdy_connection && glob_opt.only_proxy)
133748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        PRINT_INFO("cannot connect to the proxy");
134748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
135748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
136748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    FD_ZERO(&rs);
137748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    FD_ZERO(&ws);
138748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    FD_ZERO(&es);
139748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
140748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    ret = MHD_get_timeout(daemon, &timeoutlong);
141748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if(MHD_NO == ret || timeoutlong > 5000)
142748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      timeout.tv_sec = 5;
143748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    else
144748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
145748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      timeout.tv_sec = timeoutlong / 1000;
146748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      timeout.tv_usec = (timeoutlong % 1000) * 1000;
147748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
148748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
149748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if(MHD_NO == MHD_get_fdset (daemon,
150748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &rs,
151748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &ws,
152748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &es,
153748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &maxfd))
154748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
155748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      PRINT_INFO("MHD_get_fdset error");
156748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
157748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    assert(-1 != maxfd);
158748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
159748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    maxfd_s = spdy_get_selectfdset(
160748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &rs,
161748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &ws,
162748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  &es,
163748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat                                  connections, MAX_SPDY_CONNECTIONS, &spdy_npollfds);
164748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if(maxfd_s > maxfd)
165748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      maxfd = maxfd_s;
166748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
167748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    PRINT_INFO2("MHD timeout %lld %lld", (unsigned long long)timeout.tv_sec, (unsigned long long)timeout.tv_usec);
168748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
169748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    glob_opt.spdy_data_received = false;
170748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
171748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    ret = select(maxfd+1, &rs, &ws, &es, &timeout);
172748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    PRINT_INFO2("timeout now %lld %lld ret is %i", (unsigned long long)timeout.tv_sec, (unsigned long long)timeout.tv_usec, ret);
173748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
174748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    switch(ret)
175748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
176748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case -1:
177748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        PRINT_INFO2("select error: %i", errno);
178748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
179748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 0:
180748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        //break;
181748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      default:
182748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      PRINT_INFO("run");
183748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        //MHD_run_from_select(daemon,&rs, &ws, &es); //not closing FDs at some time in past
184748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        MHD_run(daemon);
185748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        spdy_run_select(&rs, &ws, &es, connections, spdy_npollfds);
186748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        if(glob_opt.spdy_data_received)
187748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        {
188748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          PRINT_INFO("MHD run again");
189748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          //MHD_run_from_select(daemon,&rs, &ws, &es); //not closing FDs at some time in past
190748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          MHD_run(daemon);
191748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        }
192748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
193748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
194748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
195748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while(run);
196748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
197748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  MHD_stop_daemon (daemon);
198748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
199748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //TODO SSL_free brakes
200748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  spdy_free_connection(glob_opt.spdy_connection);
201748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
202748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  connection = glob_opt.spdy_connections_head;
203748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while(NULL != connection)
204748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  {
205748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    connection_for_delete = connection;
206748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    connection = connection_for_delete->next;
207748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    glob_opt.streams_opened -= connection_for_delete->streams_opened;
208748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    DLL_remove(glob_opt.spdy_connections_head, glob_opt.spdy_connections_tail, connection_for_delete);
209748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    spdy_free_connection(connection_for_delete);
210748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
211748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
212748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  free_uri(spdy2http_uri);
213748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
214748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  deinit_parse_uri(&glob_opt.uri_preg);
215748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
216748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  SSL_CTX_free(glob_opt.ssl_ctx);
217748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  ERR_free_strings();
218748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  EVP_cleanup();
219748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
220748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  PRINT_INFO2("spdy streams: %i; http requests: %i", glob_opt.streams_opened, glob_opt.responses_pending);
221748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  //PRINT_INFO2("memory allocated %zu bytes", glob_opt.global_memory);
222748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
223748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  print_stat();
224748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
225748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return 0;
226748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
227748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
228748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
229748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratvoid
230748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratdisplay_usage()
231748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
232748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  printf(
233748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "Usage: mhd2spdy [-ovs] [-b <SPDY2HTTP-PROXY>] -p <PORT>\n\n"
234748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "OPTIONS:\n"
235748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "    -p, --port            Listening port.\n"
236748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "    -b, --backend-proxy   If set, he proxy will send requests to\n"
237748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          that SPDY server or proxy. Set the address\n"
238748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          in the form 'http://host:port'. Use 'https'\n"
239748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          for SPDY over TLS, or 'http' for plain SPDY\n"
240748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          communication with the backend.\n"
241748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "    -o, --only-proxy      If set, the proxy will always forward the\n"
242748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          requests to the backend proxy. If not set,\n"
243748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          the proxy will first try to establsh SPDY\n"
244748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          connection to the requested server. If the\n"
245748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          server does not support SPDY and TLS, the\n"
246748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "                          backend proxy will be used for the request.\n"
247748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "    -v, --verbose         Print debug information.\n"
248748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    "    -s, --statistics      Print simple statistics on exit.\n\n"
249748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
250748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  );
251748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
252748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
253748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
254748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratint
255748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Eratmain (int argc,
256748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      char *const *argv)
257748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat{
258748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int getopt_ret;
259748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  int option_index;
260748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  struct option long_options[] = {
261748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {"port",  required_argument, 0, 'p'},
262748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {"backend-proxy",  required_argument, 0, 'b'},
263748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {"verbose",  no_argument, 0, 'v'},
264748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {"only-proxy",  no_argument, 0, 'o'},
265748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {"statistics",  no_argument, 0, 's'},
266748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {0, 0, 0, 0}
267748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  };
268748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
269748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  while (1)
270748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  {
271748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    getopt_ret = getopt_long( argc, argv, "p:b:vos", long_options, &option_index);
272748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    if (getopt_ret == -1)
273748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      break;
274748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
275748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    switch(getopt_ret)
276748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    {
277748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 'p':
278748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        glob_opt.listen_port = atoi(optarg);
279748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
280748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
281748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 'b':
282748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        glob_opt.spdy2http_str = strdup(optarg);
283748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        if(NULL == glob_opt.spdy2http_str)
284748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat          return 1;
285748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
286748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
287748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 'v':
288748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        glob_opt.verbose = true;
289748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
290748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
291748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 'o':
292748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        glob_opt.only_proxy = true;
293748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
294748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
295748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 's':
296748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        glob_opt.statistics = true;
297748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
298748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
299748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case 0:
300748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        PRINT_INFO("0 from getopt");
301748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        break;
302748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
303748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      case '?':
304748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        display_usage();
305748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        return 1;
306748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
307748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat      default:
308748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat        DIE("default from getopt");
309748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    }
310748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
311748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
312748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  if(
313748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    0 == glob_opt.listen_port
314748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    || (glob_opt.only_proxy && NULL == glob_opt.spdy2http_str)
315748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    )
316748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  {
317748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    display_usage();
318748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat    return 1;
319748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  }
320748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat
321748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat  return run_everything();
322748945ec6f1c67b7efc934ab0808e1d32f2fb98dDaniel Erat}
323