diff options
Diffstat (limited to 'src/examples/mhd2spdy.c')
-rw-r--r-- | src/examples/mhd2spdy.c | 323 |
1 files changed, 323 insertions, 0 deletions
diff --git a/src/examples/mhd2spdy.c b/src/examples/mhd2spdy.c new file mode 100644 index 00000000..507641c2 --- /dev/null +++ b/src/examples/mhd2spdy.c | |||
@@ -0,0 +1,323 @@ | |||
1 | /* | ||
2 | Copyright (C) 2013 Andrey Uzunov | ||
3 | |||
4 | This program is free software: you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation, either version 3 of the License, or | ||
7 | (at your option) any later version. | ||
8 | |||
9 | This program is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
16 | */ | ||
17 | |||
18 | /** | ||
19 | * @file structures.h | ||
20 | * @author Andrey Uzunov | ||
21 | */ | ||
22 | |||
23 | /* | ||
24 | * TODOs | ||
25 | * non blocking SSL connect | ||
26 | * check certificate | ||
27 | * | ||
28 | * | ||
29 | * | ||
30 | * | ||
31 | |||
32 | |||
33 | */ | ||
34 | |||
35 | #include "mhd2spdy_structures.h" | ||
36 | #include "mhd2spdy_spdy.h" | ||
37 | #include "mhd2spdy_http.h" | ||
38 | |||
39 | static int run = 1; | ||
40 | //static int spdy_close = 0; | ||
41 | |||
42 | static void catch_signal(int signal) | ||
43 | { | ||
44 | //spdy_close = 1; | ||
45 | run = 0; | ||
46 | } | ||
47 | |||
48 | int | ||
49 | run_everything () | ||
50 | { | ||
51 | unsigned long long timeoutlong=0; | ||
52 | struct timeval timeout; | ||
53 | int ret; | ||
54 | fd_set rs; | ||
55 | fd_set ws; | ||
56 | fd_set es; | ||
57 | int maxfd = -1; | ||
58 | int maxfd_s = -1; | ||
59 | struct MHD_Daemon *daemon; | ||
60 | nfds_t spdy_npollfds = 1; | ||
61 | //struct pollfd spdy_pollfds[MAX_SPDY_CONNECTIONS]; | ||
62 | struct URI * spdy2http_uri = NULL; | ||
63 | //int spdy_nfds; | ||
64 | //int spdylay_timeout = 0; | ||
65 | struct SPDY_Connection *connection; | ||
66 | struct SPDY_Connection *connections[MAX_SPDY_CONNECTIONS]; | ||
67 | struct SPDY_Connection *connection_for_delete; | ||
68 | |||
69 | if (signal(SIGPIPE, SIG_IGN) == SIG_ERR) | ||
70 | PRINT_INFO("signal failed"); | ||
71 | |||
72 | if (signal(SIGINT, catch_signal) == SIG_ERR) | ||
73 | PRINT_INFO("signal failed"); | ||
74 | |||
75 | //spdy2http_url = argv[2]; | ||
76 | glob_opt.streams_opened = 0; | ||
77 | glob_opt.responses_pending = 0; | ||
78 | glob_opt.global_memory = 0; | ||
79 | //spdy_proto_version = 0; | ||
80 | |||
81 | srand(time(NULL)); | ||
82 | |||
83 | if(init_parse_uri(&glob_opt.uri_preg)) | ||
84 | DIE("Regexp compilation failed"); | ||
85 | |||
86 | |||
87 | if(NULL != glob_opt.spdy2http_str) | ||
88 | { | ||
89 | ret = parse_uri(&glob_opt.uri_preg, glob_opt.spdy2http_str, &spdy2http_uri); | ||
90 | if(ret != 0) | ||
91 | DIE("spdy_parse_uri failed"); | ||
92 | } | ||
93 | |||
94 | SSL_load_error_strings(); | ||
95 | SSL_library_init(); | ||
96 | glob_opt.ssl_ctx = SSL_CTX_new(SSLv23_client_method()); | ||
97 | if(glob_opt.ssl_ctx == NULL) { | ||
98 | PRINT_INFO2("SSL_CTX_new %s", ERR_error_string(ERR_get_error(), NULL)); | ||
99 | abort(); | ||
100 | } | ||
101 | spdy_ssl_init_ssl_ctx(glob_opt.ssl_ctx, &glob_opt.spdy_proto_version); | ||
102 | |||
103 | daemon = MHD_start_daemon ( | ||
104 | MHD_SUPPRESS_DATE_NO_CLOCK, | ||
105 | glob_opt.listen_port, | ||
106 | NULL, NULL, &http_cb_request, NULL, | ||
107 | MHD_OPTION_URI_LOG_CALLBACK, &http_log_cb, NULL, | ||
108 | MHD_OPTION_END); | ||
109 | if(NULL==daemon) | ||
110 | DIE("MHD_start_daemon failed"); | ||
111 | |||
112 | |||
113 | do | ||
114 | { | ||
115 | |||
116 | timeout.tv_sec = 0; | ||
117 | timeout.tv_usec = 0; | ||
118 | |||
119 | if(NULL == glob_opt.spdy_connection && NULL != glob_opt.spdy2http_str) | ||
120 | { | ||
121 | glob_opt.spdy_connection = spdy_connect(spdy2http_uri, spdy2http_uri->port, strcmp("https", spdy2http_uri->scheme)==0); | ||
122 | if(NULL == glob_opt.spdy_connection && glob_opt.only_proxy) | ||
123 | PRINT_INFO("cannot connect to the proxy"); | ||
124 | } | ||
125 | |||
126 | //PRINT_INFO("while1"); | ||
127 | FD_ZERO(&rs); | ||
128 | FD_ZERO(&ws); | ||
129 | FD_ZERO(&es); | ||
130 | |||
131 | /*if(glob_opt.spdy_data_received) | ||
132 | { | ||
133 | timeout.tv_sec = 0; | ||
134 | timeout.tv_usec = 0; | ||
135 | glob_opt.spdy_data_received = false; | ||
136 | } | ||
137 | else{*/ | ||
138 | /*if(glob_opt.responses_pending || glob_opt.streams_opened)// TODO only streams_opened true? | ||
139 | timeout.tv_usec = 0; //return immediately | ||
140 | else | ||
141 | {*/ | ||
142 | ret = MHD_get_timeout(daemon, &timeoutlong); | ||
143 | if(MHD_NO == ret || timeoutlong > 5000) | ||
144 | timeout.tv_sec = 5; | ||
145 | else | ||
146 | { | ||
147 | timeout.tv_sec = timeoutlong / 1000; | ||
148 | timeout.tv_usec = (timeoutlong % 1000) * 1000; | ||
149 | } | ||
150 | //} | ||
151 | //} | ||
152 | if(MHD_NO == MHD_get_fdset (daemon, | ||
153 | &rs, | ||
154 | &ws, | ||
155 | &es, | ||
156 | &maxfd)) | ||
157 | { | ||
158 | PRINT_INFO("MHD_get_fdset error"); | ||
159 | } | ||
160 | assert(-1 != maxfd); | ||
161 | |||
162 | maxfd_s = spdy_get_selectfdset( | ||
163 | &rs, | ||
164 | &ws, | ||
165 | &es, | ||
166 | connections, MAX_SPDY_CONNECTIONS, &spdy_npollfds); | ||
167 | if(maxfd_s > maxfd) maxfd = maxfd_s; | ||
168 | |||
169 | PRINT_INFO2("MHD timeout %i %i", timeout.tv_sec, timeout.tv_usec); | ||
170 | //TODO | ||
171 | //timeout.tv_sec = 0; | ||
172 | //timeout.tv_usec = 0; | ||
173 | |||
174 | glob_opt.spdy_data_received = false; | ||
175 | |||
176 | ret = select(maxfd+1, &rs, &ws, &es, &timeout); | ||
177 | PRINT_INFO2("timeout now %i %i", timeout.tv_sec, timeout.tv_usec); | ||
178 | |||
179 | switch(ret) { | ||
180 | case -1: | ||
181 | PRINT_INFO2("select error: %i", errno); | ||
182 | break; | ||
183 | case 0: | ||
184 | break; | ||
185 | default: | ||
186 | PRINT_INFO("run"); | ||
187 | MHD_run_from_select(daemon,&rs, &ws, &es); | ||
188 | spdy_run_select(&rs, &ws, &es, connections, spdy_npollfds); | ||
189 | if(glob_opt.spdy_data_received) | ||
190 | { | ||
191 | PRINT_INFO("MHD run again"); | ||
192 | MHD_run_from_select(daemon,&rs, &ws, &es); | ||
193 | } | ||
194 | break; | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | //if(glob_opt.streams_opened) spdylay_timeout = 500; | ||
199 | //if(glob_opt.responses_pending || glob_opt.streams_opened) spdylay_timeout = 0; | ||
200 | //else spdylay_timeout = 0; | ||
201 | //else spdylay_timeout = 0; | ||
202 | |||
203 | spdy_get_pollfdset(spdy_pollfds, connections, MAX_SPDY_CONNECTIONS, &spdy_npollfds); | ||
204 | |||
205 | //TODO | ||
206 | //spdylay_timeout = 0; | ||
207 | |||
208 | PRINT_INFO2("spdylay timeout %i", spdylay_timeout); | ||
209 | ret = poll(spdy_pollfds, spdy_npollfds, spdylay_timeout); | ||
210 | if(ret == -1) | ||
211 | DIE("poll"); | ||
212 | if(ret > 0){ | ||
213 | PRINT_INFO("spdy_run"); | ||
214 | spdy_run(spdy_pollfds, connections, spdy_npollfds); | ||
215 | }*/ | ||
216 | } | ||
217 | while(run); | ||
218 | |||
219 | //TODO exit from loop and clean | ||
220 | |||
221 | MHD_stop_daemon (daemon); | ||
222 | |||
223 | //TODO SSL_free brakes | ||
224 | spdy_free_connection(glob_opt.spdy_connection); | ||
225 | |||
226 | connection = glob_opt.spdy_connections_head; | ||
227 | while(NULL != connection) | ||
228 | { | ||
229 | connection_for_delete = connection; | ||
230 | connection = connection_for_delete->next; | ||
231 | glob_opt.streams_opened -= connection_for_delete->streams_opened; | ||
232 | DLL_remove(glob_opt.spdy_connections_head, glob_opt.spdy_connections_tail, connection_for_delete); | ||
233 | spdy_free_connection(connection_for_delete); | ||
234 | } | ||
235 | |||
236 | free_uri(spdy2http_uri); | ||
237 | |||
238 | deinit_parse_uri(&glob_opt.uri_preg); | ||
239 | |||
240 | SSL_CTX_free(glob_opt.ssl_ctx); | ||
241 | ERR_free_strings(); | ||
242 | EVP_cleanup(); | ||
243 | |||
244 | PRINT_INFO2("spdy streams: %i; http requests: %i", glob_opt.streams_opened, glob_opt.responses_pending); | ||
245 | PRINT_INFO2("memory allocated %zu bytes", glob_opt.global_memory); | ||
246 | |||
247 | return 0; | ||
248 | } | ||
249 | |||
250 | void | ||
251 | display_usage() | ||
252 | { | ||
253 | printf( | ||
254 | "Usage: http2spdy [-vo] [-b <SPDY2HTTP-PROXY>] -p <PORT>\n" | ||
255 | "TODO\n" | ||
256 | ); | ||
257 | } | ||
258 | |||
259 | |||
260 | int | ||
261 | main (int argc, | ||
262 | char *const *argv) | ||
263 | { | ||
264 | int getopt_ret; | ||
265 | int option_index; | ||
266 | struct option long_options[] = { | ||
267 | {"port", required_argument, 0, 'p'}, | ||
268 | {"backend-proxy", required_argument, 0, 'b'}, | ||
269 | {"verbose", no_argument, 0, 'v'}, | ||
270 | {"only-proxy", no_argument, 0, 'o'}, | ||
271 | {0, 0, 0, 0} | ||
272 | }; | ||
273 | |||
274 | while (1) | ||
275 | { | ||
276 | getopt_ret = getopt_long( argc, argv, "p:b:vo", long_options, &option_index); | ||
277 | if (getopt_ret == -1) | ||
278 | break; | ||
279 | |||
280 | switch(getopt_ret) | ||
281 | { | ||
282 | case 'p': | ||
283 | glob_opt.listen_port = atoi(optarg); | ||
284 | break; | ||
285 | |||
286 | case 'b': | ||
287 | glob_opt.spdy2http_str = strdup(optarg); | ||
288 | if(NULL == glob_opt.spdy2http_str) | ||
289 | return 1; | ||
290 | break; | ||
291 | |||
292 | case 'v': | ||
293 | glob_opt.verbose = true; | ||
294 | break; | ||
295 | |||
296 | case 'o': | ||
297 | glob_opt.only_proxy = true; | ||
298 | break; | ||
299 | |||
300 | case 0: | ||
301 | PRINT_INFO("0 from getopt"); | ||
302 | break; | ||
303 | |||
304 | case '?': | ||
305 | display_usage(); | ||
306 | return 1; | ||
307 | |||
308 | default: | ||
309 | DIE("default from getopt"); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | if( | ||
314 | 0 == glob_opt.listen_port | ||
315 | || (glob_opt.only_proxy && NULL == glob_opt.spdy2http_str) | ||
316 | ) | ||
317 | { | ||
318 | display_usage(); | ||
319 | return 1; | ||
320 | } | ||
321 | |||
322 | return run_everything(); | ||
323 | } | ||