aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrey Uzunov <andrey.uzunov@gmail.com>2013-07-20 15:04:00 +0000
committerAndrey Uzunov <andrey.uzunov@gmail.com>2013-07-20 15:04:00 +0000
commit38381f24c4065b7b55d0f6d1e095df53af83f407 (patch)
tree92be21a96db2546cd96e5a75f10ac1b2cf086d0f
parent27171ab944db351385ee8395a419898474b39351 (diff)
downloadlibmicrohttpd-38381f24c4065b7b55d0f6d1e095df53af83f407.tar.gz
libmicrohttpd-38381f24c4065b7b55d0f6d1e095df53af83f407.zip
spdy2http: added timeout option for http requests
-rw-r--r--src/spdy2http/proxy.c81
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
46struct global_options 48struct 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;
142static bool call_spdy_run; 145static bool call_spdy_run;
143static bool call_curl_run; 146static bool call_curl_run;
144 147
148int debug_num_curls;
149
145 150
146struct Proxy 151struct 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;