aboutsummaryrefslogtreecommitdiff
path: root/src/spdy2http/proxy.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/spdy2http/proxy.c')
-rw-r--r--src/spdy2http/proxy.c245
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)
219static int 224static int
220parse_uri(regex_t * preg, const char * full_uri, struct URI ** uri) 225parse_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
280static void catch_signal(int signal) 286static bool
287store_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
306static ssize_t
307get_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
333static void
334catch_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
378static int
379spdy_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
324ssize_t 429ssize_t
325response_callback (void *cls, 430response_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
410static size_t 524static size_t
411curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) 525curl_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
705static size_t
706curl_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
584static int 768static int
585iterate_cb (void *cls, const char *name, const char * const * value, int num_values) 769iterate_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;