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.c127
1 files changed, 78 insertions, 49 deletions
diff --git a/src/spdy2http/proxy.c b/src/spdy2http/proxy.c
index 018896ee..0c303823 100644
--- a/src/spdy2http/proxy.c
+++ b/src/spdy2http/proxy.c
@@ -20,9 +20,6 @@
20 * @file proxy.c 20 * @file proxy.c
21 * @brief Translates incoming SPDY requests to http server on localhost. 21 * @brief Translates incoming SPDY requests to http server on localhost.
22 * Uses libcurl. 22 * Uses libcurl.
23 * BUGS:
24 * Now the proxy works only when the HTTP server issues
25 * "Content-Length" header. Will brake on chunhed response.
26 * No error handling for curl requests. 23 * No error handling for curl requests.
27 * @author Andrey Uzunov 24 * @author Andrey Uzunov
28 */ 25 */
@@ -86,8 +83,9 @@ struct Proxy
86 char *status_msg; 83 char *status_msg;
87 void *http_body; 84 void *http_body;
88 size_t http_body_size; 85 size_t http_body_size;
89 ssize_t length; 86 //ssize_t length;
90 int status; 87 int status;
88 bool done;
91}; 89};
92 90
93 91
@@ -102,12 +100,14 @@ response_callback (void *cls,
102 void *newbody; 100 void *newbody;
103 101
104 //printf("response_callback\n"); 102 //printf("response_callback\n");
103
104 *more = true;
105 105
106 assert(0 != proxy->length);
107
108 *more = true;
109 if(!proxy->http_body_size)//nothing to write now 106 if(!proxy->http_body_size)//nothing to write now
107 {
108 if(proxy->done) *more = false;
110 return 0; 109 return 0;
110 }
111 111
112 if(max >= proxy->http_body_size) 112 if(max >= proxy->http_body_size)
113 { 113 {
@@ -129,17 +129,7 @@ response_callback (void *cls,
129 proxy->http_body = newbody; 129 proxy->http_body = newbody;
130 proxy->http_body_size -= ret; 130 proxy->http_body_size -= ret;
131 131
132 if(proxy->length >= 0) 132 if(proxy->done && 0 == proxy->http_body_size) *more = false;
133 {
134 proxy->length -= ret;
135 //printf("pr len %i", proxy->length);
136 if(proxy->length <= 0)
137 {
138 *more = false;
139 //last frame
140 proxy->length = 0;
141 }
142 }
143 133
144 return ret; 134 return ret;
145} 135}
@@ -188,11 +178,17 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
188 char *name; 178 char *name;
189 char *value; 179 char *value;
190 char *status; 180 char *status;
191 const char *const*length;
192 int i; 181 int i;
193 int pos; 182 int pos;
183 int ret;
184 int num_values;
185 const char * const * values;
186 bool abort_it;
194 187
195 //printf("curl_header_cb\n"); 188 //printf("curl_header_cb %s\n", line);
189
190 //trailer
191 if(NULL != proxy->response) return 0;
196 192
197 if('\r' == line[0]) 193 if('\r' == line[0])
198 { 194 {
@@ -208,12 +204,7 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
208 PRINT_INFO("no response"); 204 PRINT_INFO("no response");
209 abort(); 205 abort();
210 } 206 }
211 if(NULL != (length = SPDY_name_value_lookup(proxy->headers, 207
212 SPDY_HTTP_HEADER_CONTENT_LENGTH,
213 &i)))
214 proxy->length = atoi(length[0]);
215 else
216 proxy->length = -1;
217 SPDY_name_value_destroy(proxy->headers); 208 SPDY_name_value_destroy(proxy->headers);
218 free(proxy->status_msg); 209 free(proxy->status_msg);
219 free(proxy->version); 210 free(proxy->version);
@@ -228,7 +219,6 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
228 PRINT_INFO("no queue"); 219 PRINT_INFO("no queue");
229 abort(); 220 abort();
230 } 221 }
231 //printf("spdy headers queued %i\n");
232 222
233 return realsize; 223 return realsize;
234 } 224 }
@@ -310,10 +300,23 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp)
310 PRINT_INFO("no memory"); 300 PRINT_INFO("no memory");
311 abort(); 301 abort();
312 } 302 }
313 if(SPDY_YES != SPDY_name_value_add(proxy->headers, name, value)) 303 if(SPDY_YES != (ret = SPDY_name_value_add(proxy->headers, name, value)))
314 { 304 {
315 PRINT_INFO("SPDY_name_value_add failed"); 305 abort_it=true;
316 abort(); 306 if(NULL != (values = SPDY_name_value_lookup(proxy->headers, name, &num_values)))
307 for(i=0; i<num_values; ++i)
308 if(0 == strcasecmp(value, values[i]))
309 {
310 abort_it=false;
311 PRINT_INFO2("header appears more than once with same value '%s: %s'", name, value);
312 break;
313 }
314
315 if(abort_it)
316 {
317 PRINT_INFO2("SPDY_name_value_add failed (%i) for '%s'", ret, name);
318 abort();
319 }
317 } 320 }
318 free(name); 321 free(name);
319 free(value); 322 free(value);
@@ -329,7 +332,7 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp)
329 struct Proxy *proxy = (struct Proxy *)userp; 332 struct Proxy *proxy = (struct Proxy *)userp;
330 333
331 //printf("curl_write_cb %i\n", realsize); 334 //printf("curl_write_cb %i\n", realsize);
332 335
333 if(NULL == proxy->http_body) 336 if(NULL == proxy->http_body)
334 proxy->http_body = malloc(realsize); 337 proxy->http_body = malloc(realsize);
335 else 338 else
@@ -351,13 +354,13 @@ int
351iterate_cb (void *cls, const char *name, const char * const * value, int num_values) 354iterate_cb (void *cls, const char *name, const char * const * value, int num_values)
352{ 355{
353 struct Proxy *proxy = (struct Proxy *)cls; 356 struct Proxy *proxy = (struct Proxy *)cls;
354 struct curl_slist **curl_headers = (&(proxy->curl_headers)); 357 struct curl_slist **curl_headers = (&(proxy->curl_headers));
355 char *line; 358 char *line;
356 int line_len = strlen(name) + 3; //+ ": \0" 359 int line_len = strlen(name) + 3; //+ ": \0"
357 int i; 360 int i;
358 361
359 for(i=0; i<num_values; ++i) 362 for(i=0; i<num_values; ++i)
360 { 363 {
361 if(i) line_len += 2; //", " 364 if(i) line_len += 2; //", "
362 line_len += strlen(value[i]); 365 line_len += strlen(value[i]);
363 } 366 }
@@ -394,14 +397,14 @@ iterate_cb (void *cls, const char *name, const char * const * value, int num_val
394 397
395void 398void
396standard_request_handler(void *cls, 399standard_request_handler(void *cls,
397 struct SPDY_Request * request, 400 struct SPDY_Request * request,
398 uint8_t priority, 401 uint8_t priority,
399 const char *method, 402 const char *method,
400 const char *path, 403 const char *path,
401 const char *version, 404 const char *version,
402 const char *host, 405 const char *host,
403 const char *scheme, 406 const char *scheme,
404 struct SPDY_NameValue * headers) 407 struct SPDY_NameValue * headers)
405{ 408{
406 (void)cls; 409 (void)cls;
407 (void)priority; 410 (void)priority;
@@ -426,6 +429,7 @@ standard_request_handler(void *cls,
426 abort(); 429 abort();
427 } 430 }
428 431
432 //TODO add https
429 if(0 == strcmp(http_host, "any")) 433 if(0 == strcmp(http_host, "any"))
430 ret = asprintf(&url,"%s%s%s","http://", host, path); 434 ret = asprintf(&url,"%s%s%s","http://", host, path);
431 else 435 else
@@ -460,9 +464,10 @@ standard_request_handler(void *cls,
460 CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy); 464 CURL_SETOPT(proxy->curl_handle, CURLOPT_WRITEDATA, proxy);
461 CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERFUNCTION, curl_header_cb); 465 CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERFUNCTION, curl_header_cb);
462 CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy); 466 CURL_SETOPT(proxy->curl_handle, CURLOPT_HEADERDATA, proxy);
467 CURL_SETOPT(proxy->curl_handle, CURLOPT_PRIVATE, proxy);
463 CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers); 468 CURL_SETOPT(proxy->curl_handle, CURLOPT_HTTPHEADER, proxy->curl_headers);
464 CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L); 469 CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYPEER, 0L);
465 CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L); 470 CURL_SETOPT(proxy->curl_handle, CURLOPT_SSL_VERIFYHOST, 0L);
466 471
467 if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle))) 472 if(CURLM_OK != (ret = curl_multi_add_handle(multi_handle, proxy->curl_handle)))
468 { 473 {
@@ -482,7 +487,7 @@ int
482main (int argc, char *const *argv) 487main (int argc, char *const *argv)
483{ 488{
484 unsigned long long timeoutlong=0; 489 unsigned long long timeoutlong=0;
485 long curl_timeo = -1; 490 long curl_timeo = -1;
486 struct timeval timeout; 491 struct timeval timeout;
487 int ret; 492 int ret;
488 fd_set rs; 493 fd_set rs;
@@ -493,14 +498,17 @@ main (int argc, char *const *argv)
493 fd_set curl_es; 498 fd_set curl_es;
494 int maxfd = -1; 499 int maxfd = -1;
495 struct SPDY_Daemon *daemon; 500 struct SPDY_Daemon *daemon;
496 501 CURLMsg *msg;
497 //signal(SIGPIPE, SIG_IGN); 502 int msgs_left;
503 struct Proxy *proxy;
504
505 signal(SIGPIPE, SIG_IGN);
498 506
499 if(argc != 6) 507 if(argc != 6)
500 { 508 {
501 printf("Usage: %s cert-file key-file host port http/1.0(yes/no)\n\ 509 printf("Usage: %s cert-file key-file host port http/1.0(yes/no)\n\
502\n\ 510\n\
503Example for forward proxy (':host' header is used to know which HTTP server to connect):\n\ 511Example for transparent proxy (':host' header is used to know which HTTP server to connect):\n\
504%s cert.pem key.pem any 8080 no\n", argv[0], argv[0]); 512%s cert.pem key.pem any 8080 no\n", argv[0], argv[0]);
505 return 1; 513 return 1;
506 } 514 }
@@ -623,8 +631,29 @@ Example for forward proxy (':host' header is used to know which HTTP server to c
623 } 631 }
624 break; 632 break;
625 } 633 }
626 } 634
627 while(run); 635 while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
636 if (msg->msg == CURLMSG_DONE) {
637 if(CURLE_OK == msg->data.result)
638 {
639 if(CURLE_OK != (ret = curl_easy_getinfo(msg->easy_handle, CURLINFO_PRIVATE, &proxy)))
640 {
641 PRINT_INFO2("err %i",ret);
642 abort();
643 }
644
645 proxy->done = true;
646 }
647 else
648 {
649 //TODO handle error
650 PRINT_INFO("bad curl result");
651 }
652 }
653 else PRINT_INFO("shouldn't happen");
654 }
655 }
656 while(run);
628 657
629 curl_multi_cleanup(multi_handle); 658 curl_multi_cleanup(multi_handle);
630 659