aboutsummaryrefslogtreecommitdiff
path: root/src/examples/mhd2spdy_http.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/examples/mhd2spdy_http.c')
-rw-r--r--src/examples/mhd2spdy_http.c450
1 files changed, 450 insertions, 0 deletions
diff --git a/src/examples/mhd2spdy_http.c b/src/examples/mhd2spdy_http.c
new file mode 100644
index 00000000..5f788524
--- /dev/null
+++ b/src/examples/mhd2spdy_http.c
@@ -0,0 +1,450 @@
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#include "mhd2spdy_structures.h"
24#include "mhd2spdy_http.h"
25#include "mhd2spdy_spdy.h"
26
27
28void * http_log_cb(void * cls, const char * uri)
29{
30 struct HTTP_URI * http_uri;
31
32 PRINT_INFO2("log uri '%s'\n", uri);
33
34 if(NULL == (http_uri = au_malloc(sizeof(struct HTTP_URI ))))
35 DIE("no memory");
36 //memset(http_uri, 0 , sizeof(struct HTTP_URI));
37 http_uri->uri = strdup(uri);
38 return http_uri;
39}
40
41
42/*
43static int
44http_query_iterate_cb(void *cls,
45 enum MHD_ValueKind kind,
46 const char *name, const char *value)
47{
48
49}*/
50
51
52static int
53http_iterate_cb(void *cls,
54 enum MHD_ValueKind kind,
55 const char *name, const char *value)
56{
57 static char * const forbidden[] = {"Transfer-Encoding",
58 "Proxy-Connection",
59 "Keep-Alive",
60 "Connection"};
61 static int forbidden_size = 4;
62 int i;
63 struct SPDY_Headers *spdy_headers = (struct SPDY_Headers *)cls;
64
65 if(0 == strcasecmp(name, "Host"))
66 spdy_headers->nv[9] = (char *)value;
67 else
68 {
69 for(i=0; i<forbidden_size; ++i)
70 if(0 == strcasecmp(forbidden[i], name))
71 return MHD_YES;
72 spdy_headers->nv[spdy_headers->cnt++] = (char *)name;
73 spdy_headers->nv[spdy_headers->cnt++] = (char *)value;
74 }
75
76 return MHD_YES;
77}
78
79
80static ssize_t
81http_response_callback (void *cls,
82 uint64_t pos,
83 char *buffer,
84 size_t max)
85{
86 int ret;
87 struct Proxy *proxy = (struct Proxy *)cls;
88 void *newbody;
89 const union MHD_ConnectionInfo *info;
90 int val = 1;
91
92 //max=16;
93
94 //PRINT_INFO2("response_callback, pos: %i, max is %i, len is %i",pos,max,proxy->length);
95
96 //assert(0 != proxy->length);
97
98 //if(MHD_CONTENT_READER_END_OF_STREAM == proxy->length)
99 // return MHD_CONTENT_READER_END_OF_STREAM;
100
101 PRINT_INFO2("http_response_callback for %s", proxy->url);
102
103 if(0 == proxy->http_body_size &&( proxy->done || !proxy->spdy_active)){
104 PRINT_INFO("sent end of stream");
105 return MHD_CONTENT_READER_END_OF_STREAM;
106 }
107
108 //*more = true;
109 if(!proxy->http_body_size)//nothing to write now
110 {
111 //flush data
112 info = MHD_get_connection_info (proxy->http_connection,
113 MHD_CONNECTION_INFO_CONNECTION_FD);
114 ret = setsockopt(info->connect_fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
115 if(ret == -1) {
116 DIE("setsockopt");
117 }
118
119 PRINT_INFO("FLUSH data");
120 return 0;
121 }
122
123 if(max >= proxy->http_body_size)
124 {
125 ret = proxy->http_body_size;
126 newbody = NULL;
127 }
128 else
129 {
130 ret = max;
131 if(NULL == (newbody = au_malloc(proxy->http_body_size - max)))
132 {
133 PRINT_INFO("no memory");
134 return -2;
135 }
136 memcpy(newbody, proxy->http_body + max, proxy->http_body_size - max);
137 }
138 memcpy(buffer, proxy->http_body, ret);
139 free(proxy->http_body);
140 proxy->http_body = newbody;
141 proxy->http_body_size -= ret;
142
143 if(proxy->length >= 0)
144 {
145 proxy->length -= ret;
146 //printf("pr len %i", proxy->length);
147 /*if(proxy->length <= 0)
148 {
149 // *more = false;
150 //last frame
151 proxy->length = MHD_CONTENT_READER_END_OF_STREAM;
152 }*/
153 }
154
155 PRINT_INFO2("response_callback, size: %i",ret);
156
157 return ret;
158}
159
160
161static void
162http_response_done_callback(void *cls)
163{
164 struct Proxy *proxy = (struct Proxy *)cls;
165
166 PRINT_INFO2("http_response_done_callback for %s", proxy->url);
167 //int ret;
168
169 //printf("response_done_callback\n");
170
171 //printf("answer for %s was sent\n", (char *)cls);
172
173 /*if(SPDY_RESPONSE_RESULT_SUCCESS != status)
174 {
175 printf("answer was NOT sent, %i\n",status);
176 }*/
177 /*if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle)))
178 {
179 PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret);
180 }
181 curl_slist_free_all(proxy->curl_headers);
182 curl_easy_cleanup(proxy->curl_handle);
183 */
184 //SPDY_destroy_request(request);
185 //SPDY_destroy_response(response);
186 MHD_destroy_response (proxy->http_response);
187 //if(!strcmp("/close",proxy->path)) run = 0;
188 //free(proxy->path);
189 if(proxy->spdy_active)
190 proxy->http_active = false;
191 else
192 free_proxy(proxy);
193
194 --glob_opt.responses_pending;
195}
196
197int
198http_cb_request (void *cls,
199 struct MHD_Connection *connection,
200 const char *url,
201 const char *method,
202 const char *version,
203 const char *upload_data,
204 size_t *upload_data_size,
205 void **ptr)
206{
207 //struct MHD_Response *response;
208 int ret;
209 struct Proxy *proxy;
210 //struct URI *spdy_uri;
211 //char **nv;
212 //int num_headers;
213 struct SPDY_Headers spdy_headers;
214
215 //PRINT_INFO2("request cb %i; %s", *ptr,url);
216
217 if (NULL == *ptr)
218 DIE("ptr is null");
219 struct HTTP_URI *http_uri = (struct HTTP_URI *)*ptr;
220
221 if(NULL == http_uri->proxy)
222 {
223 if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
224 {
225 free(http_uri->uri);
226 free(http_uri);
227 PRINT_INFO2("unexpected method %s", method);
228 return MHD_NO; /* unexpected method */
229 }
230
231 if(NULL == (proxy = au_malloc(sizeof(struct Proxy))))
232 {
233 PRINT_INFO("No memory");
234 return MHD_NO;
235 }
236
237 ++glob_opt.responses_pending;
238 //memset(proxy, 0, sizeof(struct Proxy));
239 proxy->id = rand();
240 proxy->http_active = true;
241 //PRINT_INFO2("proxy obj with id %i created (%i)", proxy->id, proxy);
242 proxy->http_connection = connection;
243 http_uri->proxy = proxy;
244 return MHD_YES;
245 }
246
247 proxy = http_uri->proxy;
248 //*ptr = NULL; /* reset when done */
249
250 if(proxy->spdy_active)
251 {
252 //already handled
253 PRINT_INFO("unnecessary call to http_cb_request");
254 return MHD_YES;
255 }
256
257 PRINT_INFO2("received request for '%s %s %s'\n", method, http_uri->uri, version);
258 /*
259 proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
260 8096,
261 &http_response_callback,
262 proxy,
263 &http_response_done_callback);
264
265 if (proxy->http_response == NULL)
266 DIE("no response");
267 */
268
269 proxy->url = http_uri->uri;
270 //if(NULL == (proxy->url = strdup(http_uri->uri)))
271 // DIE("no memory");
272
273//TODO HTTP headers
274 /*MHD_get_connection_values (connection,
275 MHD_HEADER_KIND,
276 &http_iterate_cb,
277 proxy);
278 */
279 //proxy->url = strdup(url);
280 //if(NULL == (spdy_uri = au_malloc(sizeof(struct URI))))
281 // DIE("no memory");
282
283 ret = parse_uri(&glob_opt.uri_preg, proxy->url, &proxy->uri);
284 if(ret != 0)
285 DIE("parse_uri failed");
286 //proxy->uri = spdy_uri;
287 proxy->http_uri = http_uri;
288 proxy->spdy_active = true;
289
290 //proxy->spdy_request = au_malloc(sizeof(struct SPDY_Request));
291 //if(NULL == proxy->spdy_request)
292 // DIE("no memory");
293 //memset(proxy->spdy_request,0,sizeof(struct SPDY_Request));
294 //spdy_request_init(proxy->spdy_request, &spdy_uri);
295 //spdy_submit_request(spdy_connection, proxy);
296
297 spdy_headers.num = MHD_get_connection_values (connection,
298 MHD_HEADER_KIND,
299 NULL,
300 NULL);
301 if(NULL == (spdy_headers.nv = au_malloc(((spdy_headers.num + 5) * 2 + 1) * sizeof(char *))))
302 DIE("no memory");
303 spdy_headers.nv[0] = ":method"; spdy_headers.nv[1] = "GET";
304 spdy_headers.nv[2] = ":path"; spdy_headers.nv[3] = proxy->uri->path_and_more;
305 spdy_headers.nv[4] = ":version"; spdy_headers.nv[5] = (char *)version;
306 spdy_headers.nv[6] = ":scheme"; spdy_headers.nv[7] = proxy->uri->scheme;
307 spdy_headers.nv[8] = ":host"; spdy_headers.nv[9] = NULL;
308 //nv[14] = NULL;
309 spdy_headers.cnt = 10;
310 MHD_get_connection_values (connection,
311 MHD_HEADER_KIND,
312 &http_iterate_cb,
313 &spdy_headers);
314
315 spdy_headers.nv[spdy_headers.cnt] = NULL;
316 if(NULL == spdy_headers.nv[9])
317 spdy_headers.nv[9] = proxy->uri->host_and_port;
318
319 /*int i;
320 for(i=0; i<spdy_headers.cnt; i+=2)
321 printf("%s: %s\n", spdy_headers.nv[i], spdy_headers.nv[i+1]);
322 */
323 if(0 != spdy_request(spdy_headers.nv, proxy))
324 {
325 //--glob_opt.responses_pending;
326 free(spdy_headers.nv);
327 //MHD_destroy_response (proxy->http_response);
328 free_proxy(proxy);//TODO call it here or in done_callback
329
330 return MHD_NO;
331 }
332 free(spdy_headers.nv);
333
334 proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
335 4096,
336 &http_response_callback,
337 proxy,
338 &http_response_done_callback);
339
340 if (proxy->http_response == NULL)
341 DIE("no response");
342
343 if(MHD_NO == MHD_add_response_header (proxy->http_response,
344 "Proxy-Connection", "keep-alive"))
345 PRINT_INFO("SPDY_name_value_add failed: ");
346 if(MHD_NO == MHD_add_response_header (proxy->http_response,
347 "Connection", "Keep-Alive"))
348 PRINT_INFO("SPDY_name_value_add failed: ");
349 if(MHD_NO == MHD_add_response_header (proxy->http_response,
350 "Keep-Alive", "timeout=5, max=100"))
351 PRINT_INFO("SPDY_name_value_add failed: ");
352
353 /*
354 const union MHD_ConnectionInfo *info;
355 info = MHD_get_connection_info (connection,
356 MHD_CONNECTION_INFO_CONNECTION_FD);
357 int val = 1;
358 int rv;
359 rv = setsockopt(info->connect_fd, IPPROTO_TCP, TCP_NODELAY, &val, (socklen_t)sizeof(val));
360 if(rv == -1) {
361 DIE("setsockopt");
362 }*/
363 return MHD_YES;
364}
365
366void
367http_create_response(struct Proxy* proxy, char **nv)
368{
369 size_t i;
370 //uint64_t response_size=MHD_SIZE_UNKNOWN;
371
372 /*for(i = 0; nv[i]; i += 2) {
373 if(0 == strcmp("content-length", nv[i]))
374 {
375 response_size = atoi(nv[i+1]);
376 break;
377 }
378 }*/
379 /*
380 proxy->http_response = MHD_create_response_from_callback (MHD_SIZE_UNKNOWN,
381 4096,
382 &http_response_callback,
383 proxy,
384 &http_response_done_callback);
385
386 if (proxy->http_response == NULL)
387 DIE("no response");
388
389 if(MHD_NO == MHD_add_response_header (proxy->http_response,
390 "Proxy-Connection", "keep-alive"))
391 PRINT_INFO("SPDY_name_value_add failed: ");
392 if(MHD_NO == MHD_add_response_header (proxy->http_response,
393 "Connection", "Keep-Alive"))
394 PRINT_INFO("SPDY_name_value_add failed: ");
395 if(MHD_NO == MHD_add_response_header (proxy->http_response,
396 "Keep-Alive", "timeout=5, max=100"))
397 PRINT_INFO("SPDY_name_value_add failed: ");
398 */
399 for(i = 0; nv[i]; i += 2) {
400 //printf(" %s: %s\n", nv[i], nv[i+1]);
401 //int j;
402
403 if(0 == strcmp(":status", nv[i]))
404 {
405 //raise(SIGINT);
406 //proxy->status_msg = nv[i+1];
407 char tmp[4];
408 memcpy(&tmp,nv[i+1],3);
409 tmp[3]=0;
410 proxy->status = atoi(tmp);
411 continue;
412 }
413 else if(0 == strcmp(":version", nv[i]))
414 {
415 proxy->version = nv[i+1];
416 continue;
417 }
418 else if(0 == strcmp("content-length", nv[i]))
419 {
420 //proxy->length = atoi(nv[i+1]);
421 //response_size = atoi(nv[i+1]);
422 continue;
423 }
424
425 //for(j=0; j<strlen(nv[i]) && ':'==nv[i][j]; ++j);
426
427 char *header = *(nv+i);
428 //header[0] = toupper(header[0]);
429 if(MHD_NO == MHD_add_response_header (proxy->http_response,
430 header, nv[i+1]))
431 {
432 PRINT_INFO2("SPDY_name_value_add failed: '%s' '%s'", header, nv[i+1]);
433 //abort();
434 }
435 PRINT_INFO2("adding '%s: %s'",header, nv[i+1]);
436 }
437
438 //PRINT_INFO2("%i", MHD_get_response_headers(proxy->http_response, NULL, NULL));
439 //PRINT_INFO2("state before %i", proxy->http_connection->state);
440 //PRINT_INFO2("loop before %i", proxy->http_connection->event_loop_info);
441 if(MHD_NO == MHD_queue_response (proxy->http_connection, proxy->status, proxy->http_response)){
442 PRINT_INFO("No queue");
443 abort();
444 }
445 //PRINT_INFO2("state after %i", proxy->http_connection->state);
446 //PRINT_INFO2("loop after %i", proxy->http_connection->event_loop_info);
447 //MHD_destroy_response (proxy->http_response);
448 //PRINT_INFO2("state after %i", proxy->http_connection->state);
449 //PRINT_INFO2("loop after %i", proxy->http_connection->event_loop_info);
450}