diff options
Diffstat (limited to 'src/spdy2http/proxy.c')
-rw-r--r-- | src/spdy2http/proxy.c | 245 |
1 files changed, 234 insertions, 11 deletions
diff --git a/src/spdy2http/proxy.c b/src/spdy2http/proxy.c index 19cb26f6..e896bbc4 100644 --- a/src/spdy2http/proxy.c +++ b/src/spdy2http/proxy.c | |||
@@ -163,11 +163,16 @@ struct Proxy | |||
163 | char *version; | 163 | char *version; |
164 | char *status_msg; | 164 | char *status_msg; |
165 | void *http_body; | 165 | void *http_body; |
166 | void *received_body; | ||
166 | bool *session_alive; | 167 | bool *session_alive; |
167 | size_t http_body_size; | 168 | size_t http_body_size; |
169 | size_t received_body_size; | ||
168 | //ssize_t length; | 170 | //ssize_t length; |
169 | int status; | 171 | int status; |
170 | bool done; | 172 | bool done; |
173 | bool receiving_done; | ||
174 | bool is_curl_read_paused; | ||
175 | bool is_with_body_data; | ||
171 | bool error; | 176 | bool error; |
172 | }; | 177 | }; |
173 | 178 | ||
@@ -219,6 +224,7 @@ deinit_parse_uri(regex_t * preg) | |||
219 | static int | 224 | static int |
220 | parse_uri(regex_t * preg, const char * full_uri, struct URI ** uri) | 225 | parse_uri(regex_t * preg, const char * full_uri, struct URI ** uri) |
221 | { | 226 | { |
227 | //TODO memeory checks | ||
222 | int ret; | 228 | int ret; |
223 | char *colon; | 229 | char *colon; |
224 | long long port; | 230 | long long port; |
@@ -277,7 +283,55 @@ parse_uri(regex_t * preg, const char * full_uri, struct URI ** uri) | |||
277 | } | 283 | } |
278 | 284 | ||
279 | 285 | ||
280 | static void catch_signal(int signal) | 286 | static bool |
287 | store_in_buffer(const void *src, size_t src_size, void **dst, size_t *dst_size) | ||
288 | { | ||
289 | if(0 == src_size) | ||
290 | return true; | ||
291 | |||
292 | if(NULL == *dst) | ||
293 | *dst = malloc(src_size); | ||
294 | else | ||
295 | *dst = realloc(*dst, src_size + *dst_size); | ||
296 | if(NULL == *dst) | ||
297 | return false; | ||
298 | |||
299 | memcpy(*dst + *dst_size, src, src_size); | ||
300 | *dst_size += src_size; | ||
301 | |||
302 | return true; | ||
303 | } | ||
304 | |||
305 | |||
306 | static ssize_t | ||
307 | get_from_buffer(void **src, size_t *src_size, void *dst, size_t max_size) | ||
308 | { | ||
309 | size_t ret; | ||
310 | void *newbody; | ||
311 | |||
312 | if(max_size >= *src_size) | ||
313 | { | ||
314 | ret = *src_size; | ||
315 | newbody = NULL; | ||
316 | } | ||
317 | else | ||
318 | { | ||
319 | ret = max_size; | ||
320 | if(NULL == (newbody = malloc(*src_size - max_size))) | ||
321 | return -1; | ||
322 | memcpy(newbody, *src + ret, *src_size - ret); | ||
323 | } | ||
324 | memcpy(dst, *src, ret); | ||
325 | free(*src); | ||
326 | *src = newbody; | ||
327 | *src_size -= ret; | ||
328 | |||
329 | return ret; | ||
330 | } | ||
331 | |||
332 | |||
333 | static void | ||
334 | catch_signal(int signal) | ||
281 | { | 335 | { |
282 | (void)signal; | 336 | (void)signal; |
283 | 337 | ||
@@ -319,7 +373,58 @@ session_closed_cb (void * cls, | |||
319 | 373 | ||
320 | *session_alive = false; | 374 | *session_alive = false; |
321 | } | 375 | } |
322 | 376 | ||
377 | |||
378 | static int | ||
379 | spdy_post_data_cb (void * cls, | ||
380 | struct SPDY_Request *request, | ||
381 | const void * buf, | ||
382 | size_t size, | ||
383 | bool more) | ||
384 | { | ||
385 | (void)cls; | ||
386 | int ret; | ||
387 | struct Proxy *proxy = (struct Proxy *)SPDY_get_cls_from_request(request); | ||
388 | |||
389 | if(!store_in_buffer(buf, size, &proxy->received_body, &proxy->received_body_size)) | ||
390 | { | ||
391 | PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); | ||
392 | return 0; | ||
393 | } | ||
394 | /* | ||
395 | if(NULL == proxy->received_body) | ||
396 | proxy->received_body = malloc(size); | ||
397 | else | ||
398 | proxy->received_body = realloc(proxy->received_body, proxy->received_body_size + size); | ||
399 | if(NULL == proxy->received_body) | ||
400 | { | ||
401 | PRINT_INFO("not enough memory (realloc returned NULL)"); | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | memcpy(proxy->received_body + proxy->received_body_size, buf, size); | ||
406 | proxy->received_body_size += size; | ||
407 | */ | ||
408 | |||
409 | proxy->receiving_done = !more; | ||
410 | |||
411 | PRINT_VERBOSE2("POST bytes from SPDY: %zu", size); | ||
412 | |||
413 | call_curl_run = true; | ||
414 | |||
415 | if(proxy->is_curl_read_paused) | ||
416 | { | ||
417 | if(CURLE_OK != (ret = curl_easy_pause(proxy->curl_handle, CURLPAUSE_CONT))) | ||
418 | { | ||
419 | PRINT_INFO2("curl_easy_pause returned %i", ret); | ||
420 | abort(); | ||
421 | } | ||
422 | PRINT_VERBOSE("curl_read_cb pause resumed"); | ||
423 | } | ||
424 | |||
425 | return SPDY_YES; | ||
426 | } | ||
427 | |||
323 | 428 | ||
324 | ssize_t | 429 | ssize_t |
325 | response_callback (void *cls, | 430 | response_callback (void *cls, |
@@ -329,7 +434,7 @@ response_callback (void *cls, | |||
329 | { | 434 | { |
330 | ssize_t ret; | 435 | ssize_t ret; |
331 | struct Proxy *proxy = (struct Proxy *)cls; | 436 | struct Proxy *proxy = (struct Proxy *)cls; |
332 | void *newbody; | 437 | //void *newbody; |
333 | 438 | ||
334 | //printf("response_callback\n"); | 439 | //printf("response_callback\n"); |
335 | 440 | ||
@@ -347,6 +452,14 @@ response_callback (void *cls, | |||
347 | return 0; | 452 | return 0; |
348 | } | 453 | } |
349 | 454 | ||
455 | ret = get_from_buffer(&(proxy->http_body), &(proxy->http_body_size), buffer, max); | ||
456 | if(ret < 0) | ||
457 | { | ||
458 | PRINT_INFO("no memory"); | ||
459 | return -1; | ||
460 | } | ||
461 | |||
462 | /* | ||
350 | if(max >= proxy->http_body_size) | 463 | if(max >= proxy->http_body_size) |
351 | { | 464 | { |
352 | ret = proxy->http_body_size; | 465 | ret = proxy->http_body_size; |
@@ -366,7 +479,7 @@ response_callback (void *cls, | |||
366 | free(proxy->http_body); | 479 | free(proxy->http_body); |
367 | proxy->http_body = newbody; | 480 | proxy->http_body = newbody; |
368 | proxy->http_body_size -= ret; | 481 | proxy->http_body_size -= ret; |
369 | 482 | */ | |
370 | if(proxy->done && 0 == proxy->http_body_size) *more = false; | 483 | if(proxy->done && 0 == proxy->http_body_size) *more = false; |
371 | 484 | ||
372 | PRINT_VERBOSE2("given bytes to microspdy: %zd", ret); | 485 | PRINT_VERBOSE2("given bytes to microspdy: %zd", ret); |
@@ -407,6 +520,7 @@ response_done_callback(void *cls, | |||
407 | } | 520 | } |
408 | 521 | ||
409 | 522 | ||
523 | |||
410 | static size_t | 524 | static size_t |
411 | curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) | 525 | curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) |
412 | { | 526 | { |
@@ -560,6 +674,12 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) | |||
560 | return 0; | 674 | return 0; |
561 | } | 675 | } |
562 | 676 | ||
677 | if(!store_in_buffer(contents, realsize, &proxy->http_body, &proxy->http_body_size)) | ||
678 | { | ||
679 | PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); | ||
680 | return 0; | ||
681 | } | ||
682 | /* | ||
563 | if(NULL == proxy->http_body) | 683 | if(NULL == proxy->http_body) |
564 | proxy->http_body = malloc(realsize); | 684 | proxy->http_body = malloc(realsize); |
565 | else | 685 | else |
@@ -572,6 +692,7 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) | |||
572 | 692 | ||
573 | memcpy(proxy->http_body + proxy->http_body_size, contents, realsize); | 693 | memcpy(proxy->http_body + proxy->http_body_size, contents, realsize); |
574 | proxy->http_body_size += realsize; | 694 | proxy->http_body_size += realsize; |
695 | */ | ||
575 | 696 | ||
576 | PRINT_VERBOSE2("received bytes from curl: %zu", realsize); | 697 | PRINT_VERBOSE2("received bytes from curl: %zu", realsize); |
577 | 698 | ||
@@ -581,6 +702,69 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) | |||
581 | } | 702 | } |
582 | 703 | ||
583 | 704 | ||
705 | static size_t | ||
706 | curl_read_cb(void *ptr, size_t size, size_t nmemb, void *userp) | ||
707 | { | ||
708 | ssize_t ret; | ||
709 | size_t max = size * nmemb; | ||
710 | struct Proxy *proxy = (struct Proxy *)userp; | ||
711 | //void *newbody; | ||
712 | |||
713 | |||
714 | if((proxy->receiving_done && !proxy->received_body_size) || !proxy->is_with_body_data || max < 1) | ||
715 | { | ||
716 | PRINT_VERBOSE("curl_read_cb last call"); | ||
717 | return 0; | ||
718 | } | ||
719 | |||
720 | if(!*(proxy->session_alive)) | ||
721 | { | ||
722 | PRINT_VERBOSE("POST is still being sent, but session is dead"); | ||
723 | return CURL_READFUNC_ABORT; | ||
724 | } | ||
725 | |||
726 | if(!proxy->received_body_size)//nothing to write now | ||
727 | { | ||
728 | PRINT_VERBOSE("curl_read_cb called paused"); | ||
729 | proxy->is_curl_read_paused = true; | ||
730 | return CURL_READFUNC_PAUSE;//TODO curl pause should be used | ||
731 | } | ||
732 | |||
733 | ret = get_from_buffer(&(proxy->received_body), &(proxy->received_body_size), ptr, max); | ||
734 | if(ret < 0) | ||
735 | { | ||
736 | PRINT_INFO("no memory"); | ||
737 | return CURL_READFUNC_ABORT; | ||
738 | } | ||
739 | |||
740 | /* | ||
741 | if(max >= proxy->received_body_size) | ||
742 | { | ||
743 | ret = proxy->received_body_size; | ||
744 | newbody = NULL; | ||
745 | } | ||
746 | else | ||
747 | { | ||
748 | ret = max; | ||
749 | if(NULL == (newbody = malloc(proxy->received_body_size - max))) | ||
750 | { | ||
751 | PRINT_INFO("no memory"); | ||
752 | return CURL_READFUNC_ABORT; | ||
753 | } | ||
754 | memcpy(newbody, proxy->received_body + max, proxy->received_body_size - max); | ||
755 | } | ||
756 | memcpy(ptr, proxy->received_body, ret); | ||
757 | free(proxy->received_body); | ||
758 | proxy->received_body = newbody; | ||
759 | proxy->received_body_size -= ret; | ||
760 | * */ | ||
761 | |||
762 | PRINT_VERBOSE2("given POST bytes to curl: %zd", ret); | ||
763 | |||
764 | return ret; | ||
765 | } | ||
766 | |||
767 | |||
584 | static int | 768 | static int |
585 | iterate_cb (void *cls, const char *name, const char * const * value, int num_values) | 769 | iterate_cb (void *cls, const char *name, const char * const * value, int num_values) |
586 | { | 770 | { |
@@ -630,7 +814,8 @@ standard_request_handler(void *cls, | |||
630 | const char *version, | 814 | const char *version, |
631 | const char *host, | 815 | const char *host, |
632 | const char *scheme, | 816 | const char *scheme, |
633 | struct SPDY_NameValue * headers) | 817 | struct SPDY_NameValue * headers, |
818 | bool more) | ||
634 | { | 819 | { |
635 | (void)cls; | 820 | (void)cls; |
636 | (void)priority; | 821 | (void)priority; |
@@ -641,6 +826,13 @@ standard_request_handler(void *cls, | |||
641 | int ret; | 826 | int ret; |
642 | struct URI *uri; | 827 | struct URI *uri; |
643 | struct SPDY_Session *session; | 828 | struct SPDY_Session *session; |
829 | |||
830 | proxy = SPDY_get_cls_from_request(request); | ||
831 | if(NULL != proxy) | ||
832 | { | ||
833 | //ignore trailers or more headers | ||
834 | return; | ||
835 | } | ||
644 | 836 | ||
645 | PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version); | 837 | PRINT_VERBOSE2("received request for '%s %s %s'\n", method, path, version); |
646 | 838 | ||
@@ -654,7 +846,10 @@ standard_request_handler(void *cls, | |||
654 | proxy->session_alive = SPDY_get_cls_from_session(session); | 846 | proxy->session_alive = SPDY_get_cls_from_session(session); |
655 | assert(NULL != proxy->session_alive); | 847 | assert(NULL != proxy->session_alive); |
656 | 848 | ||
849 | SPDY_set_cls_to_request(request, proxy); | ||
850 | |||
657 | proxy->request = request; | 851 | proxy->request = request; |
852 | proxy->is_with_body_data = more; | ||
658 | if(NULL == (proxy->headers = SPDY_name_value_create())) | 853 | if(NULL == (proxy->headers = SPDY_name_value_create())) |
659 | DIE("No memory"); | 854 | DIE("No memory"); |
660 | 855 | ||
@@ -703,6 +898,16 @@ standard_request_handler(void *cls, | |||
703 | 898 | ||
704 | if(glob_opt.curl_verbose) | 899 | if(glob_opt.curl_verbose) |
705 | CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); | 900 | CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); |
901 | |||
902 | if(0 == strcmp(SPDY_HTTP_METHOD_POST,method)) | ||
903 | { | ||
904 | if(NULL == (proxy->curl_headers = curl_slist_append(proxy->curl_headers, "Expect:"))) | ||
905 | DIE("curl_slist_append failed"); | ||
906 | CURL_SETOPT(proxy->curl_handle, CURLOPT_POST, 1); | ||
907 | CURL_SETOPT(proxy->curl_handle, CURLOPT_READFUNCTION, curl_read_cb); | ||
908 | CURL_SETOPT(proxy->curl_handle, CURLOPT_READDATA, proxy); | ||
909 | } | ||
910 | |||
706 | if(glob_opt.timeout) | 911 | if(glob_opt.timeout) |
707 | CURL_SETOPT(proxy->curl_handle, CURLOPT_TIMEOUT, glob_opt.timeout); | 912 | CURL_SETOPT(proxy->curl_handle, CURLOPT_TIMEOUT, glob_opt.timeout); |
708 | CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url); | 913 | CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url); |
@@ -720,7 +925,7 @@ standard_request_handler(void *cls, | |||
720 | CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); | 925 | CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); |
721 | else if(glob_opt.ipv6 && !glob_opt.ipv4) | 926 | else if(glob_opt.ipv6 && !glob_opt.ipv4) |
722 | CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); | 927 | CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V6); |
723 | 928 | ||
724 | if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle))) | 929 | if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle))) |
725 | { | 930 | { |
726 | PRINT_INFO2("curl_multi_add_handle failed (%i)", ret); | 931 | PRINT_INFO2("curl_multi_add_handle failed (%i)", ret); |
@@ -765,7 +970,7 @@ run () | |||
765 | struct addrinfo *gai; | 970 | struct addrinfo *gai; |
766 | enum SPDY_IO_SUBSYSTEM io = glob_opt.notls ? SPDY_IO_SUBSYSTEM_RAW : SPDY_IO_SUBSYSTEM_OPENSSL; | 971 | enum SPDY_IO_SUBSYSTEM io = glob_opt.notls ? SPDY_IO_SUBSYSTEM_RAW : SPDY_IO_SUBSYSTEM_OPENSSL; |
767 | enum SPDY_DAEMON_FLAG flags = SPDY_DAEMON_FLAG_NO; | 972 | enum SPDY_DAEMON_FLAG flags = SPDY_DAEMON_FLAG_NO; |
768 | struct SPDY_Response *error_response; | 973 | //struct SPDY_Response *error_response; |
769 | char *curl_private; | 974 | char *curl_private; |
770 | 975 | ||
771 | signal(SIGPIPE, SIG_IGN); | 976 | signal(SIGPIPE, SIG_IGN); |
@@ -790,7 +995,7 @@ run () | |||
790 | &new_session_cb, | 995 | &new_session_cb, |
791 | &session_closed_cb, | 996 | &session_closed_cb, |
792 | &standard_request_handler, | 997 | &standard_request_handler, |
793 | NULL, | 998 | &spdy_post_data_cb, |
794 | NULL, | 999 | NULL, |
795 | SPDY_DAEMON_OPTION_SESSION_TIMEOUT, | 1000 | SPDY_DAEMON_OPTION_SESSION_TIMEOUT, |
796 | 1800, | 1001 | 1800, |
@@ -819,7 +1024,7 @@ run () | |||
819 | &new_session_cb, | 1024 | &new_session_cb, |
820 | &session_closed_cb, | 1025 | &session_closed_cb, |
821 | &standard_request_handler, | 1026 | &standard_request_handler, |
822 | NULL, | 1027 | &spdy_post_data_cb, |
823 | NULL, | 1028 | NULL, |
824 | SPDY_DAEMON_OPTION_SESSION_TIMEOUT, | 1029 | SPDY_DAEMON_OPTION_SESSION_TIMEOUT, |
825 | 1800, | 1030 | 1800, |
@@ -924,6 +1129,7 @@ run () | |||
924 | 1129 | ||
925 | while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { | 1130 | while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { |
926 | if (msg->msg == CURLMSG_DONE) { | 1131 | if (msg->msg == CURLMSG_DONE) { |
1132 | PRINT_VERBOSE("A curl handler is done"); | ||
927 | if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &curl_private))) | 1133 | if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &curl_private))) |
928 | { | 1134 | { |
929 | PRINT_INFO2("err %i",ret); | 1135 | PRINT_INFO2("err %i",ret); |
@@ -944,7 +1150,7 @@ run () | |||
944 | SPDY_name_value_destroy(proxy->headers); | 1150 | SPDY_name_value_destroy(proxy->headers); |
945 | if(!*(proxy->session_alive)) | 1151 | if(!*(proxy->session_alive)) |
946 | { | 1152 | { |
947 | if(NULL == (error_response = SPDY_build_response(SPDY_HTTP_BAD_GATEWAY, | 1153 | /*if(NULL == (error_response = SPDY_build_response(SPDY_HTTP_BAD_GATEWAY, |
948 | NULL, | 1154 | NULL, |
949 | SPDY_HTTP_VERSION_1_1, | 1155 | SPDY_HTTP_VERSION_1_1, |
950 | NULL, | 1156 | NULL, |
@@ -961,7 +1167,24 @@ run () | |||
961 | //clean and forget | 1167 | //clean and forget |
962 | //TODO | 1168 | //TODO |
963 | DIE("no queue"); | 1169 | DIE("no queue"); |
964 | } | 1170 | }*/ |
1171 | |||
1172 | free(proxy->http_body); | ||
1173 | proxy->http_body = NULL; | ||
1174 | |||
1175 | if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle))) | ||
1176 | { | ||
1177 | PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret); | ||
1178 | } | ||
1179 | debug_num_curls--; | ||
1180 | curl_slist_free_all(proxy->curl_headers); | ||
1181 | curl_easy_cleanup(proxy->curl_handle); | ||
1182 | |||
1183 | SPDY_destroy_request(proxy->request); | ||
1184 | //SPDY_destroy_response(proxy->response); | ||
1185 | free(proxy->url); | ||
1186 | free(proxy); | ||
1187 | |||
965 | } | 1188 | } |
966 | else | 1189 | else |
967 | proxy->error = true; | 1190 | proxy->error = true; |