diff options
author | Andrey Uzunov <andrey.uzunov@gmail.com> | 2013-07-20 15:04:00 +0000 |
---|---|---|
committer | Andrey Uzunov <andrey.uzunov@gmail.com> | 2013-07-20 15:04:00 +0000 |
commit | 38381f24c4065b7b55d0f6d1e095df53af83f407 (patch) | |
tree | 92be21a96db2546cd96e5a75f10ac1b2cf086d0f | |
parent | 27171ab944db351385ee8395a419898474b39351 (diff) | |
download | libmicrohttpd-38381f24c4065b7b55d0f6d1e095df53af83f407.tar.gz libmicrohttpd-38381f24c4065b7b55d0f6d1e095df53af83f407.zip |
spdy2http: added timeout option for http requests
-rw-r--r-- | src/spdy2http/proxy.c | 81 |
1 files changed, 69 insertions, 12 deletions
diff --git a/src/spdy2http/proxy.c b/src/spdy2http/proxy.c index 3d592f94..c5457977 100644 --- a/src/spdy2http/proxy.c +++ b/src/spdy2http/proxy.c | |||
@@ -42,6 +42,8 @@ | |||
42 | #include <getopt.h> | 42 | #include <getopt.h> |
43 | #include <regex.h> | 43 | #include <regex.h> |
44 | 44 | ||
45 | #define ERROR_RESPONSE "502 Bad Gateway" | ||
46 | |||
45 | 47 | ||
46 | struct global_options | 48 | struct global_options |
47 | { | 49 | { |
@@ -49,6 +51,7 @@ struct global_options | |||
49 | char *cert; | 51 | char *cert; |
50 | char *cert_key; | 52 | char *cert_key; |
51 | char *listen_host; | 53 | char *listen_host; |
54 | unsigned int timeout; | ||
52 | uint16_t listen_port; | 55 | uint16_t listen_port; |
53 | bool verbose; | 56 | bool verbose; |
54 | bool curl_verbose; | 57 | bool curl_verbose; |
@@ -142,6 +145,8 @@ static regex_t uri_preg; | |||
142 | static bool call_spdy_run; | 145 | static bool call_spdy_run; |
143 | static bool call_curl_run; | 146 | static bool call_curl_run; |
144 | 147 | ||
148 | int debug_num_curls; | ||
149 | |||
145 | 150 | ||
146 | struct Proxy | 151 | struct Proxy |
147 | { | 152 | { |
@@ -158,6 +163,7 @@ struct Proxy | |||
158 | //ssize_t length; | 163 | //ssize_t length; |
159 | int status; | 164 | int status; |
160 | bool done; | 165 | bool done; |
166 | bool error; | ||
161 | bool *session_alive; | 167 | bool *session_alive; |
162 | }; | 168 | }; |
163 | 169 | ||
@@ -318,6 +324,12 @@ response_callback (void *cls, | |||
318 | //printf("response_callback\n"); | 324 | //printf("response_callback\n"); |
319 | 325 | ||
320 | *more = true; | 326 | *more = true; |
327 | |||
328 | if(proxy->error) | ||
329 | { | ||
330 | PRINT_VERBOSE("tell spdy about the error"); | ||
331 | return -1; | ||
332 | } | ||
321 | 333 | ||
322 | if(!proxy->http_body_size)//nothing to write now | 334 | if(!proxy->http_body_size)//nothing to write now |
323 | { | 335 | { |
@@ -367,11 +379,14 @@ response_done_callback(void *cls, | |||
367 | if(SPDY_RESPONSE_RESULT_SUCCESS != status) | 379 | if(SPDY_RESPONSE_RESULT_SUCCESS != status) |
368 | { | 380 | { |
369 | printf("answer was NOT sent, %i\n",status); | 381 | printf("answer was NOT sent, %i\n",status); |
382 | free(proxy->http_body); | ||
383 | proxy->http_body = NULL; | ||
370 | } | 384 | } |
371 | if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle))) | 385 | if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle))) |
372 | { | 386 | { |
373 | PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret); | 387 | PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret); |
374 | } | 388 | } |
389 | debug_num_curls--; | ||
375 | curl_slist_free_all(proxy->curl_headers); | 390 | curl_slist_free_all(proxy->curl_headers); |
376 | curl_easy_cleanup(proxy->curl_handle); | 391 | curl_easy_cleanup(proxy->curl_handle); |
377 | 392 | ||
@@ -675,6 +690,8 @@ standard_request_handler(void *cls, | |||
675 | 690 | ||
676 | if(glob_opt.curl_verbose) | 691 | if(glob_opt.curl_verbose) |
677 | CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); | 692 | CURL_SETOPT(proxy->curl_handle, CURLOPT_VERBOSE, 1); |
693 | if(glob_opt.timeout) | ||
694 | CURL_SETOPT(proxy->curl_handle, CURLOPT_TIMEOUT, glob_opt.timeout); | ||
678 | CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url); | 695 | CURL_SETOPT(proxy->curl_handle, CURLOPT_URL, proxy->url); |
679 | if(glob_opt.http10) | 696 | if(glob_opt.http10) |
680 | CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); | 697 | CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); |
@@ -684,7 +701,7 @@ standard_request_handler(void *cls, | |||
684 | CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy); | 701 | CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy); |
685 | CURL_SETOPT(proxy->curl_handle, CURLOPT_PRIVATE, proxy); | 702 | CURL_SETOPT(proxy->curl_handle, CURLOPT_PRIVATE, proxy); |
686 | CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers); | 703 | CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers); |
687 | CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); | 704 | CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);//TODO |
688 | CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L); | 705 | CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L); |
689 | if(glob_opt.ipv4 && !glob_opt.ipv6) | 706 | if(glob_opt.ipv4 && !glob_opt.ipv6) |
690 | CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); | 707 | CURL_SETOPT(proxy->curl_handle, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4); |
@@ -696,6 +713,7 @@ standard_request_handler(void *cls, | |||
696 | PRINT_INFO2("curl_multi_add_handle failed (%i)", ret); | 713 | PRINT_INFO2("curl_multi_add_handle failed (%i)", ret); |
697 | abort(); | 714 | abort(); |
698 | } | 715 | } |
716 | debug_num_curls++; | ||
699 | 717 | ||
700 | //~5ms additional latency for calling this | 718 | //~5ms additional latency for calling this |
701 | if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running)) | 719 | if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running)) |
@@ -734,6 +752,7 @@ run () | |||
734 | struct addrinfo *gai; | 752 | struct addrinfo *gai; |
735 | enum SPDY_IO_SUBSYSTEM io = glob_opt.notls ? SPDY_IO_SUBSYSTEM_RAW : SPDY_IO_SUBSYSTEM_OPENSSL; | 753 | enum SPDY_IO_SUBSYSTEM io = glob_opt.notls ? SPDY_IO_SUBSYSTEM_RAW : SPDY_IO_SUBSYSTEM_OPENSSL; |
736 | enum SPDY_DAEMON_FLAG flags = SPDY_DAEMON_FLAG_NO; | 754 | enum SPDY_DAEMON_FLAG flags = SPDY_DAEMON_FLAG_NO; |
755 | struct SPDY_Response *error_response; | ||
737 | 756 | ||
738 | signal(SIGPIPE, SIG_IGN); | 757 | signal(SIGPIPE, SIG_IGN); |
739 | 758 | ||
@@ -816,6 +835,8 @@ run () | |||
816 | FD_ZERO(&ws); | 835 | FD_ZERO(&ws); |
817 | FD_ZERO(&es); | 836 | FD_ZERO(&es); |
818 | 837 | ||
838 | PRINT_INFO2("num curls %i", debug_num_curls); | ||
839 | |||
819 | ret_spdy = SPDY_get_timeout(daemon, &timeout_spdy); | 840 | ret_spdy = SPDY_get_timeout(daemon, &timeout_spdy); |
820 | if(SPDY_NO == ret_spdy || timeout_spdy > 5000) | 841 | if(SPDY_NO == ret_spdy || timeout_spdy > 5000) |
821 | timeoutlong = 5000; | 842 | timeoutlong = 5000; |
@@ -873,7 +894,7 @@ run () | |||
873 | call_spdy_run = false; | 894 | call_spdy_run = false; |
874 | } | 895 | } |
875 | 896 | ||
876 | if(ret > 0 || (CURLM_OK == ret_curl && 0 == timeout_curl) || call_curl_run) | 897 | //if(ret > 0 || (CURLM_OK == ret_curl && 0 == timeout_curl) || call_curl_run) |
877 | { | 898 | { |
878 | PRINT_VERBOSE("run curl"); | 899 | PRINT_VERBOSE("run curl"); |
879 | if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running)) | 900 | if(CURLM_OK != (ret = curl_multi_perform(multi_handle, &still_running)) |
@@ -889,21 +910,45 @@ run () | |||
889 | 910 | ||
890 | while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { | 911 | while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) { |
891 | if (msg->msg == CURLMSG_DONE) { | 912 | if (msg->msg == CURLMSG_DONE) { |
913 | if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &proxy))) | ||
914 | { | ||
915 | PRINT_INFO2("err %i",ret); | ||
916 | abort(); | ||
917 | } | ||
892 | if(CURLE_OK == msg->data.result) | 918 | if(CURLE_OK == msg->data.result) |
893 | { | 919 | { |
894 | if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &proxy))) | ||
895 | { | ||
896 | PRINT_INFO2("err %i",ret); | ||
897 | abort(); | ||
898 | } | ||
899 | |||
900 | proxy->done = true; | 920 | proxy->done = true; |
901 | call_spdy_run = true; | 921 | call_spdy_run = true; |
902 | } | 922 | } |
903 | else | 923 | else |
904 | { | 924 | { |
905 | PRINT_VERBOSE2("bad curl result for '%s'", proxy->url); | 925 | PRINT_VERBOSE2("bad curl result (%i) for '%s'", msg->data.result, proxy->url); |
906 | proxy->done = true; | 926 | if(NULL == proxy->response) |
927 | { | ||
928 | SPDY_name_value_destroy(proxy->headers); | ||
929 | if(NULL == (error_response = SPDY_build_response(SPDY_HTTP_BAD_GATEWAY, | ||
930 | NULL, | ||
931 | SPDY_HTTP_VERSION_1_1, | ||
932 | NULL, | ||
933 | ERROR_RESPONSE, | ||
934 | strlen(ERROR_RESPONSE)))) | ||
935 | DIE("no response"); | ||
936 | if(SPDY_YES != SPDY_queue_response(proxy->request, | ||
937 | error_response, | ||
938 | true, | ||
939 | false, | ||
940 | &response_done_callback, | ||
941 | proxy)) | ||
942 | { | ||
943 | //clean and forget | ||
944 | //TODO | ||
945 | DIE("no queue"); | ||
946 | } | ||
947 | } | ||
948 | else | ||
949 | { | ||
950 | proxy->error = true; | ||
951 | } | ||
907 | call_spdy_run = true; | 952 | call_spdy_run = true; |
908 | //TODO spdy should be notified to send RST_STREAM | 953 | //TODO spdy should be notified to send RST_STREAM |
909 | } | 954 | } |
@@ -945,7 +990,7 @@ display_usage() | |||
945 | { | 990 | { |
946 | printf( | 991 | printf( |
947 | "Usage: microspdy2http -p <PORT> [-c <CERTIFICATE>] [-k <CERT-KEY>]\n" | 992 | "Usage: microspdy2http -p <PORT> [-c <CERTIFICATE>] [-k <CERT-KEY>]\n" |
948 | " [-rvh0Dt] [-b <HTTP-SERVER>] [-l <HOST>]\n\n" | 993 | " [-rvh0DtT] [-b <HTTP-SERVER>] [-l <HOST>]\n\n" |
949 | "OPTIONS:\n" | 994 | "OPTIONS:\n" |
950 | " -p, --port Listening port.\n" | 995 | " -p, --port Listening port.\n" |
951 | " -l, --host Listening host. If not set, will listen on [::]\n" | 996 | " -l, --host Listening host. If not set, will listen on [::]\n" |
@@ -966,6 +1011,8 @@ display_usage() | |||
966 | " -6, --curl-ipv6 Curl may use IPv6 to connect to the final destination.\n" | 1011 | " -6, --curl-ipv6 Curl may use IPv6 to connect to the final destination.\n" |
967 | " If neither --curl-ipv4 nor --curl-ipv6 is set,\n" | 1012 | " If neither --curl-ipv4 nor --curl-ipv6 is set,\n" |
968 | " both will be used by default.\n" | 1013 | " both will be used by default.\n" |
1014 | " -T, --timeout Maximum time in seconds for each HTTP transfer.\n" | ||
1015 | " Use 0 for no timeout; this is the default value.\n" | ||
969 | " -t, --transparent If set, the proxy will fetch an URL which\n" | 1016 | " -t, --transparent If set, the proxy will fetch an URL which\n" |
970 | " is based on 'Host:' header and requested path.\n" | 1017 | " is based on 'Host:' header and requested path.\n" |
971 | " Otherwise, full URL in the requested path is required.\n\n" | 1018 | " Otherwise, full URL in the requested path is required.\n\n" |
@@ -993,12 +1040,13 @@ main (int argc, char *const *argv) | |||
993 | {"transparent", no_argument, 0, 't'}, | 1040 | {"transparent", no_argument, 0, 't'}, |
994 | {"curl-ipv4", no_argument, 0, '4'}, | 1041 | {"curl-ipv4", no_argument, 0, '4'}, |
995 | {"curl-ipv6", no_argument, 0, '6'}, | 1042 | {"curl-ipv6", no_argument, 0, '6'}, |
1043 | {"timeout", required_argument, 0, 'T'}, | ||
996 | {0, 0, 0, 0} | 1044 | {0, 0, 0, 0} |
997 | }; | 1045 | }; |
998 | 1046 | ||
999 | while (1) | 1047 | while (1) |
1000 | { | 1048 | { |
1001 | getopt_ret = getopt_long( argc, argv, "p:l:c:k:b:rv0Dth46", long_options, &option_index); | 1049 | getopt_ret = getopt_long( argc, argv, "p:l:c:k:b:rv0Dth46T:", long_options, &option_index); |
1002 | if (getopt_ret == -1) | 1050 | if (getopt_ret == -1) |
1003 | break; | 1051 | break; |
1004 | 1052 | ||
@@ -1060,6 +1108,15 @@ main (int argc, char *const *argv) | |||
1060 | glob_opt.ipv6 = true; | 1108 | glob_opt.ipv6 = true; |
1061 | break; | 1109 | break; |
1062 | 1110 | ||
1111 | case 'T': | ||
1112 | glob_opt.timeout = atoi(optarg); | ||
1113 | if(glob_opt.timeout < 0) | ||
1114 | { | ||
1115 | display_usage(); | ||
1116 | return 1; | ||
1117 | } | ||
1118 | break; | ||
1119 | |||
1063 | case 0: | 1120 | case 0: |
1064 | PRINT_INFO("0 from getopt"); | 1121 | PRINT_INFO("0 from getopt"); |
1065 | break; | 1122 | break; |