diff options
Diffstat (limited to 'src/spdy2http/proxy.c')
-rw-r--r-- | src/spdy2http/proxy.c | 78 |
1 files changed, 56 insertions, 22 deletions
diff --git a/src/spdy2http/proxy.c b/src/spdy2http/proxy.c index 56c7d929..69a502f4 100644 --- a/src/spdy2http/proxy.c +++ b/src/spdy2http/proxy.c | |||
@@ -24,14 +24,14 @@ | |||
24 | * TODO: | 24 | * TODO: |
25 | * - test all options! | 25 | * - test all options! |
26 | * - don't abort on lack of memory | 26 | * - don't abort on lack of memory |
27 | * - Memory leak: in rare cases the proxy object is not freed (and there | ||
28 | * is a lot of data pointed from it) | ||
29 | * - Correct recapitalizetion of header names before giving the headers | 27 | * - Correct recapitalizetion of header names before giving the headers |
30 | * to curl. | 28 | * to curl. |
31 | * - curl does not close sockets when connection is closed and no | 29 | * - curl does not close sockets when connection is closed and no |
32 | * new sockets are opened (they stay in CLOSE_WAIT) | 30 | * new sockets are opened (they stay in CLOSE_WAIT) |
33 | * - add '/' when a user requests http://example.com . Now this is a bad | 31 | * - add '/' when a user requests http://example.com . Now this is a bad |
34 | * request | 32 | * request |
33 | * - curl returns 0 or 1 ms for timeout even when nothing will be done; | ||
34 | * thus the loop uses CPU for nothing | ||
35 | * @author Andrey Uzunov | 35 | * @author Andrey Uzunov |
36 | */ | 36 | */ |
37 | 37 | ||
@@ -173,11 +173,15 @@ struct Proxy | |||
173 | size_t received_body_size; | 173 | size_t received_body_size; |
174 | //ssize_t length; | 174 | //ssize_t length; |
175 | int status; | 175 | int status; |
176 | bool done; | 176 | //bool done; |
177 | bool receiving_done; | 177 | bool receiving_done; |
178 | bool is_curl_read_paused; | 178 | bool is_curl_read_paused; |
179 | bool is_with_body_data; | 179 | bool is_with_body_data; |
180 | bool error; | 180 | //bool error; |
181 | bool curl_done; | ||
182 | bool curl_error; | ||
183 | bool spdy_done; | ||
184 | bool spdy_error; | ||
181 | }; | 185 | }; |
182 | 186 | ||
183 | 187 | ||
@@ -444,7 +448,9 @@ response_callback (void *cls, | |||
444 | 448 | ||
445 | *more = true; | 449 | *more = true; |
446 | 450 | ||
447 | if(proxy->error) | 451 | assert(!proxy->spdy_error); |
452 | |||
453 | if(proxy->curl_error) | ||
448 | { | 454 | { |
449 | PRINT_VERBOSE("tell spdy about the error"); | 455 | PRINT_VERBOSE("tell spdy about the error"); |
450 | return -1; | 456 | return -1; |
@@ -452,8 +458,8 @@ response_callback (void *cls, | |||
452 | 458 | ||
453 | if(!proxy->http_body_size)//nothing to write now | 459 | if(!proxy->http_body_size)//nothing to write now |
454 | { | 460 | { |
455 | PRINT_VERBOSE2("nothing to write now? %i", proxy->done); | 461 | PRINT_VERBOSE("nothing to write now"); |
456 | if(proxy->done) *more = false; | 462 | if(proxy->curl_done || proxy->curl_error) *more = false; |
457 | return 0; | 463 | return 0; |
458 | } | 464 | } |
459 | 465 | ||
@@ -461,10 +467,11 @@ response_callback (void *cls, | |||
461 | if(ret < 0) | 467 | if(ret < 0) |
462 | { | 468 | { |
463 | PRINT_INFO("no memory"); | 469 | PRINT_INFO("no memory"); |
470 | //TODO error? | ||
464 | return -1; | 471 | return -1; |
465 | } | 472 | } |
466 | 473 | ||
467 | if(proxy->done && 0 == proxy->http_body_size) *more = false; | 474 | if((proxy->curl_done || proxy->curl_error) && 0 == proxy->http_body_size) *more = false; |
468 | 475 | ||
469 | PRINT_VERBOSE2("given bytes to microspdy: %zd", ret); | 476 | PRINT_VERBOSE2("given bytes to microspdy: %zd", ret); |
470 | 477 | ||
@@ -482,8 +489,11 @@ cleanup(struct Proxy *proxy) | |||
482 | if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle))) | 489 | if(CURLM_OK != (ret = curl_multi_remove_handle(multi_handle, proxy->curl_handle))) |
483 | { | 490 | { |
484 | PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret); | 491 | PRINT_INFO2("curl_multi_remove_handle failed (%i)", ret); |
492 | DIE("bug in cleanup"); | ||
485 | } | 493 | } |
486 | debug_num_curls--; | 494 | debug_num_curls--; |
495 | //TODO bug on ku6.com or amazon.cn | ||
496 | // after curl_multi_remove_handle returned CURLM_BAD_EASY_HANDLE | ||
487 | curl_slist_free_all(proxy->curl_headers); | 497 | curl_slist_free_all(proxy->curl_headers); |
488 | curl_easy_cleanup(proxy->curl_handle); | 498 | curl_easy_cleanup(proxy->curl_handle); |
489 | 499 | ||
@@ -506,6 +516,7 @@ response_done_callback(void *cls, | |||
506 | { | 516 | { |
507 | free(proxy->http_body); | 517 | free(proxy->http_body); |
508 | proxy->http_body = NULL; | 518 | proxy->http_body = NULL; |
519 | proxy->spdy_error = true; | ||
509 | } | 520 | } |
510 | cleanup(proxy); | 521 | cleanup(proxy); |
511 | SPDY_destroy_request(request); | 522 | SPDY_destroy_request(request); |
@@ -533,7 +544,8 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) | |||
533 | if(!*(proxy->session_alive)) | 544 | if(!*(proxy->session_alive)) |
534 | { | 545 | { |
535 | PRINT_VERBOSE("headers received, but session is dead"); | 546 | PRINT_VERBOSE("headers received, but session is dead"); |
536 | proxy->error = true; | 547 | proxy->spdy_error = true; |
548 | proxy->curl_error = true; | ||
537 | return 0; | 549 | return 0; |
538 | } | 550 | } |
539 | 551 | ||
@@ -554,8 +566,11 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) | |||
554 | DIE("no response"); | 566 | DIE("no response"); |
555 | 567 | ||
556 | SPDY_name_value_destroy(proxy->headers); | 568 | SPDY_name_value_destroy(proxy->headers); |
569 | proxy->headers = NULL; | ||
557 | free(proxy->status_msg); | 570 | free(proxy->status_msg); |
571 | proxy->status_msg = NULL; | ||
558 | free(proxy->version); | 572 | free(proxy->version); |
573 | proxy->version = NULL; | ||
559 | 574 | ||
560 | if(SPDY_YES != SPDY_queue_response(proxy->request, | 575 | if(SPDY_YES != SPDY_queue_response(proxy->request, |
561 | proxy->response, | 576 | proxy->response, |
@@ -566,8 +581,11 @@ curl_header_cb(void *ptr, size_t size, size_t nmemb, void *userp) | |||
566 | { | 581 | { |
567 | //DIE("no queue"); | 582 | //DIE("no queue"); |
568 | //TODO right? | 583 | //TODO right? |
569 | proxy->error = true; | 584 | proxy->spdy_error = true; |
570 | PRINT_VERBOSE2("erorr in curl_header_cb for %s", proxy->url); | 585 | proxy->curl_error = true; |
586 | PRINT_VERBOSE2("no queue in curl_header_cb for %s", proxy->url); | ||
587 | SPDY_destroy_response(proxy->response); | ||
588 | proxy->response = NULL; | ||
571 | return 0; | 589 | return 0; |
572 | } | 590 | } |
573 | 591 | ||
@@ -671,12 +689,15 @@ curl_write_cb(void *contents, size_t size, size_t nmemb, void *userp) | |||
671 | if(!*(proxy->session_alive)) | 689 | if(!*(proxy->session_alive)) |
672 | { | 690 | { |
673 | PRINT_VERBOSE("data received, but session is dead"); | 691 | PRINT_VERBOSE("data received, but session is dead"); |
692 | proxy->spdy_error = true; | ||
693 | proxy->curl_error = true; | ||
674 | return 0; | 694 | return 0; |
675 | } | 695 | } |
676 | 696 | ||
677 | if(!store_in_buffer(contents, realsize, &proxy->http_body, &proxy->http_body_size)) | 697 | if(!store_in_buffer(contents, realsize, &proxy->http_body, &proxy->http_body_size)) |
678 | { | 698 | { |
679 | PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); | 699 | PRINT_INFO("not enough memory (malloc/realloc returned NULL)"); |
700 | proxy->curl_error = true; | ||
680 | return 0; | 701 | return 0; |
681 | } | 702 | } |
682 | /* | 703 | /* |
@@ -1143,7 +1164,7 @@ run () | |||
1143 | proxy = (struct Proxy *)curl_private; | 1164 | proxy = (struct Proxy *)curl_private; |
1144 | if(CURLE_OK == msg->data.result) | 1165 | if(CURLE_OK == msg->data.result) |
1145 | { | 1166 | { |
1146 | proxy->done = true; | 1167 | proxy->curl_done = true; |
1147 | call_spdy_run = true; | 1168 | call_spdy_run = true; |
1148 | //TODO what happens with proxy when the client resets a stream | 1169 | //TODO what happens with proxy when the client resets a stream |
1149 | //and response_done is not yet set for the last frame? is it | 1170 | //and response_done is not yet set for the last frame? is it |
@@ -1152,27 +1173,40 @@ run () | |||
1152 | else | 1173 | else |
1153 | { | 1174 | { |
1154 | PRINT_VERBOSE2("bad curl result (%i) for '%s'", msg->data.result, proxy->url); | 1175 | PRINT_VERBOSE2("bad curl result (%i) for '%s'", msg->data.result, proxy->url); |
1155 | if(NULL == proxy->response) | 1176 | if(proxy->spdy_done || proxy->spdy_error || NULL == proxy->response) |
1177 | { | ||
1178 | PRINT_VERBOSE("cleaning"); | ||
1179 | SPDY_name_value_destroy(proxy->headers); | ||
1180 | SPDY_destroy_request(proxy->request); | ||
1181 | SPDY_destroy_response(proxy->response); | ||
1182 | cleanup(proxy); | ||
1183 | } | ||
1184 | else | ||
1185 | { | ||
1186 | proxy->curl_error = true; | ||
1187 | } | ||
1188 | /*if(NULL == proxy->response) | ||
1156 | { | 1189 | { |
1157 | SPDY_name_value_destroy(proxy->headers); | 1190 | SPDY_name_value_destroy(proxy->headers); |
1158 | /*if(!*(proxy->session_alive)) | 1191 | *//*if(!*(proxy->session_alive)) |
1159 | { | 1192 | { |
1160 | free(proxy->http_body); | 1193 | free(proxy->http_body); |
1161 | proxy->http_body = NULL; | 1194 | proxy->http_body = NULL; |
1162 | */ | 1195 | *//* |
1163 | SPDY_destroy_request(proxy->request); | 1196 | SPDY_destroy_request(proxy->request); |
1164 | cleanup(proxy); | 1197 | cleanup(proxy); |
1165 | /*} | 1198 | *//*} |
1166 | else | 1199 | else |
1167 | proxy->error = true;*/ | 1200 | proxy->error = true;*/ |
1168 | } | 1201 | /* } |
1169 | else | 1202 | else |
1170 | { | 1203 | { |
1171 | //proxy->error = true; | 1204 | //TODO too early to clean them |
1172 | SPDY_destroy_request(proxy->request); | 1205 | proxy->error = true; |
1173 | SPDY_destroy_response(proxy->response); | 1206 | //SPDY_destroy_request(proxy->request); |
1174 | cleanup(proxy); | 1207 | //SPDY_destroy_response(proxy->response); |
1175 | } | 1208 | //cleanup(proxy); |
1209 | }*/ | ||
1176 | call_spdy_run = true; | 1210 | call_spdy_run = true; |
1177 | //TODO spdy should be notified to send RST_STREAM | 1211 | //TODO spdy should be notified to send RST_STREAM |
1178 | } | 1212 | } |