1/* Copyright (C) 2007-2008 The Android Open Source Project 2** 3** This software is licensed under the terms of the GNU General Public 4** License version 2, as published by the Free Software Foundation, and 5** may be copied, distributed, and modified under those terms. 6** 7** This program is distributed in the hope that it will be useful, 8** but WITHOUT ANY WARRANTY; without even the implied warranty of 9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10** GNU General Public License for more details. 11*/ 12#include "proxy_http_int.h" 13#include <stdio.h> 14#include <string.h> 15#include "qemu-common.h" 16#include "android/utils/system.h" /* strsep */ 17 18/* this implements a transparent HTTP rewriting proxy 19 * 20 * this is needed because the HTTP spec mandates that 21 * any query made to a proxy uses an absolute URI as 22 * in: 23 * 24 * GET http://www.example.com/index.html HTTP/1.1 25 * 26 * while the Android browser will think it's talking to 27 * a normal web server and will issue a: 28 * 29 * GET /index.html HTTP/1.1 30 * Host: www.example.com 31 * 32 * what we do here is thus the following: 33 * 34 * - read the request header 35 * - rewrite the request's URI to use absolute URI 36 * - send the rewritten header to the proxy 37 * - then read the rest of the request, and tunnel it to the 38 * proxy as well 39 * - read the answer as-is and send it back to the system 40 * 41 * this sounds all easy, but the rules for computing the 42 * sizes of HTTP Message Bodies makes the implementation 43 * a *bit* funky. 44 */ 45 46/* define D_ACTIVE to 1 to dump additionnal debugging 47 * info when -debug-proxy is used. These are only needed 48 * when debugging the proxy code. 49 */ 50#define D_ACTIVE 1 51 52#if D_ACTIVE 53# define D(...) PROXY_LOG(__VA_ARGS__) 54#else 55# define D(...) ((void)0) 56#endif 57 58 59/** ************************************************************* 60 ** 61 ** HTTP HEADERS 62 ** 63 **/ 64 65/* HttpHeader is a simple structure used to hold a (key,value) 66 * pair in a linked list. 67 */ 68typedef struct HttpHeader { 69 struct HttpHeader* next; 70 const char* key; 71 const char* value; 72} HttpHeader; 73 74static void 75http_header_free( HttpHeader* h ) 76{ 77 if (h) { 78 qemu_free((char*)h->value); 79 qemu_free(h); 80 } 81} 82 83static int 84http_header_append( HttpHeader* h, const char* value ) 85{ 86 int old = strlen(h->value); 87 int new = strlen(value); 88 char* s = realloc((char*)h->value, old+new+1); 89 if (s == NULL) 90 return -1; 91 memcpy(s + old, value, new+1); 92 h->value = (const char*)s; 93 return 0; 94} 95 96static HttpHeader* 97http_header_alloc( const char* key, const char* value ) 98{ 99 int len = strlen(key)+1; 100 HttpHeader* h = malloc(sizeof(*h) + len+1); 101 if (h) { 102 h->next = NULL; 103 h->key = (const char*)(h+1); 104 memcpy( (char*)h->key, key, len ); 105 h->value = qemu_strdup(value); 106 } 107 return h; 108} 109 110/** ************************************************************* 111 ** 112 ** HTTP HEADERS LIST 113 ** 114 **/ 115 116typedef struct { 117 HttpHeader* first; 118 HttpHeader* last; 119} HttpHeaderList; 120 121static void 122http_header_list_init( HttpHeaderList* l ) 123{ 124 l->first = l->last = NULL; 125} 126 127static void 128http_header_list_done( HttpHeaderList* l ) 129{ 130 while (l->first) { 131 HttpHeader* h = l->first; 132 l->first = h->next; 133 http_header_free(h); 134 } 135 l->last = NULL; 136} 137 138static void 139http_header_list_add( HttpHeaderList* l, 140 HttpHeader* h ) 141{ 142 if (!l->first) { 143 l->first = h; 144 } else { 145 l->last->next = h; 146 } 147 h->next = NULL; 148 l->last = h; 149} 150 151static const char* 152http_header_list_find( HttpHeaderList* l, 153 const char* key ) 154{ 155 HttpHeader* h; 156 for (h = l->first; h; h = h->next) 157 if (!strcasecmp(h->key, key)) 158 return h->value; 159 160 return NULL; 161} 162 163/** ************************************************************* 164 ** 165 ** HTTP REQUEST AND REPLY 166 ** 167 **/ 168 169typedef enum { 170 HTTP_REQUEST_UNSUPPORTED = 0, 171 HTTP_REQUEST_GET, 172 HTTP_REQUEST_HEAD, 173 HTTP_REQUEST_POST, 174 HTTP_REQUEST_PUT, 175 HTTP_REQUEST_DELETE, 176} HttpRequestType; 177 178/* HttpRequest is used both to store information about a specific 179 * request and the corresponding reply 180 */ 181typedef struct { 182 HttpRequestType req_type; /* request type */ 183 char* req_method; /* "GET", "POST", "HEAD", etc... */ 184 char* req_uri; /* the request URI */ 185 char* req_version; /* "HTTP/1.0" or "HTTP/1.1" */ 186 char* rep_version; /* reply version string */ 187 int rep_code; /* reply code as decimal */ 188 char* rep_readable; /* human-friendly reply/error message */ 189 HttpHeaderList headers[1]; /* headers */ 190} HttpRequest; 191 192 193static HttpRequest* 194http_request_alloc( const char* method, 195 const char* uri, 196 const char* version ) 197{ 198 HttpRequest* r = malloc(sizeof(*r)); 199 200 r->req_method = qemu_strdup(method); 201 r->req_uri = qemu_strdup(uri); 202 r->req_version = qemu_strdup(version); 203 r->rep_version = NULL; 204 r->rep_code = -1; 205 r->rep_readable = NULL; 206 207 if (!strcmp(method,"GET")) { 208 r->req_type = HTTP_REQUEST_GET; 209 } else if (!strcmp(method,"POST")) { 210 r->req_type = HTTP_REQUEST_POST; 211 } else if (!strcmp(method,"HEAD")) { 212 r->req_type = HTTP_REQUEST_HEAD; 213 } else if (!strcmp(method,"PUT")) { 214 r->req_type = HTTP_REQUEST_PUT; 215 } else if (!strcmp(method,"DELETE")) { 216 r->req_type = HTTP_REQUEST_DELETE; 217 } else 218 r->req_type = HTTP_REQUEST_UNSUPPORTED; 219 220 http_header_list_init(r->headers); 221 return r; 222} 223 224static void 225http_request_replace_uri( HttpRequest* r, 226 const char* uri ) 227{ 228 const char* old = r->req_uri; 229 r->req_uri = qemu_strdup(uri); 230 qemu_free((char*)old); 231} 232 233static void 234http_request_free( HttpRequest* r ) 235{ 236 if (r) { 237 http_header_list_done(r->headers); 238 239 qemu_free(r->req_method); 240 qemu_free(r->req_uri); 241 qemu_free(r->req_version); 242 qemu_free(r->rep_version); 243 qemu_free(r->rep_readable); 244 qemu_free(r); 245 } 246} 247 248static char* 249http_request_find_header( HttpRequest* r, 250 const char* key ) 251{ 252 return (char*)http_header_list_find(r->headers, key); 253} 254 255 256static int 257http_request_add_header( HttpRequest* r, 258 const char* key, 259 const char* value ) 260{ 261 HttpHeader* h = http_header_alloc(key,value); 262 if (h) { 263 http_header_list_add(r->headers, h); 264 return 0; 265 } 266 return -1; 267} 268 269static int 270http_request_add_to_last_header( HttpRequest* r, 271 const char* line ) 272{ 273 if (r->headers->last) { 274 return http_header_append( r->headers->last, line ); 275 } else { 276 return -1; 277 } 278} 279 280static int 281http_request_set_reply( HttpRequest* r, 282 const char* version, 283 const char* code, 284 const char* readable ) 285{ 286 if (strcmp(version,"HTTP/1.0") && strcmp(version,"HTTP/1.1")) { 287 PROXY_LOG("%s: bad reply protocol: %s", __FUNCTION__, version); 288 return -1; 289 } 290 r->rep_code = atoi(code); 291 if (r->rep_code == 0) { 292 PROXY_LOG("%s: bad reply code: %d", __FUNCTION__, code); 293 return -1; 294 } 295 296 r->rep_version = qemu_strdup(version); 297 r->rep_readable = qemu_strdup(readable); 298 299 /* reset the list of headers */ 300 http_header_list_done(r->headers); 301 return 0; 302} 303 304/** ************************************************************* 305 ** 306 ** REWRITER CONNECTION 307 ** 308 **/ 309 310typedef enum { 311 STATE_CONNECTING = 0, 312 STATE_CREATE_SOCKET_PAIR, 313 STATE_REQUEST_FIRST_LINE, 314 STATE_REQUEST_HEADERS, 315 STATE_REQUEST_SEND, 316 STATE_REQUEST_BODY, 317 STATE_REPLY_FIRST_LINE, 318 STATE_REPLY_HEADERS, 319 STATE_REPLY_SEND, 320 STATE_REPLY_BODY, 321} ConnectionState; 322 323/* root->socket is connected to the proxy server. while 324 * slirp_fd is connected to the slirp code through a 325 * socket_pair() we created for this specific purpose. 326 */ 327 328typedef enum { 329 BODY_NONE = 0, 330 BODY_KNOWN_LENGTH, 331 BODY_UNTIL_CLOSE, 332 BODY_CHUNKED, 333 BODY_MODE_MAX 334} BodyMode; 335 336static const char* const body_mode_str[BODY_MODE_MAX] = { 337 "NONE", "KNOWN_LENGTH", "UNTIL_CLOSE", "CHUNKED" 338}; 339 340enum { 341 CHUNK_HEADER, // Waiting for a chunk header + CR LF 342 CHUNK_DATA, // Waiting for chunk data 343 CHUNK_DATA_END, // Waiting for the CR LF after the chunk data 344 CHUNK_TRAILER // Waiting for the chunk trailer + CR LF 345}; 346 347typedef struct { 348 ProxyConnection root[1]; 349 int slirp_fd; 350 ConnectionState state; 351 HttpRequest* request; 352 BodyMode body_mode; 353 int64_t body_length; 354 int64_t body_total; 355 int64_t body_sent; 356 int64_t chunk_length; 357 int64_t chunk_total; 358 int chunk_state; 359 char body_has_data; 360 char body_is_full; 361 char body_is_closed; 362 char parse_chunk_header; 363 char parse_chunk_trailer; 364} RewriteConnection; 365 366 367static void 368rewrite_connection_free( ProxyConnection* root ) 369{ 370 RewriteConnection* conn = (RewriteConnection*)root; 371 372 if (conn->slirp_fd >= 0) { 373 socket_close(conn->slirp_fd); 374 conn->slirp_fd = -1; 375 } 376 http_request_free(conn->request); 377 proxy_connection_done(root); 378 qemu_free(conn); 379} 380 381 382static int 383rewrite_connection_init( RewriteConnection* conn ) 384{ 385 HttpService* service = (HttpService*) conn->root->service; 386 ProxyConnection* root = conn->root; 387 388 conn->slirp_fd = -1; 389 conn->state = STATE_CONNECTING; 390 391 if (socket_connect( root->socket, &service->server_addr ) < 0) { 392 if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) { 393 PROXY_LOG("%s: connecting", conn->root->name); 394 } 395 else { 396 PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str); 397 return -1; 398 } 399 } 400 else { 401 PROXY_LOG("%s: immediate connection", root->name); 402 conn->state = STATE_CREATE_SOCKET_PAIR; 403 } 404 return 0; 405} 406 407static int 408rewrite_connection_create_sockets( RewriteConnection* conn ) 409{ 410 /* immediate connection to the proxy. now create a socket 411 * pair and send a 'success' event to slirp */ 412 int slirp_1; 413 ProxyConnection* root = conn->root; 414 415 if (socket_pair( &slirp_1, &conn->slirp_fd ) < 0) { 416 PROXY_LOG("%s: coult not create socket pair: %s", 417 root->name, errno_str); 418 return -1; 419 } 420 421 root->ev_func( root->ev_opaque, slirp_1, PROXY_EVENT_CONNECTED ); 422 conn->state = STATE_REQUEST_FIRST_LINE; 423 return 0; 424} 425 426 427/* read the first line of a given HTTP request. returns -1/0/+1 */ 428static DataStatus 429rewrite_connection_read_request( RewriteConnection* conn ) 430{ 431 ProxyConnection* root = conn->root; 432 DataStatus ret; 433 434 ret = proxy_connection_receive_line(root, conn->slirp_fd); 435 if (ret == DATA_COMPLETED) { 436 /* now parse the first line to see if we can handle it */ 437 char* line = root->str->s; 438 char* method; 439 char* uri; 440 char* version; 441 char* p = line; 442 443 method = strsep(&p, " "); 444 if (p == NULL) { 445 PROXY_LOG("%s: can't parse method in '%'", 446 root->name, line); 447 return DATA_ERROR; 448 } 449 uri = strsep(&p, " "); 450 if (p == NULL) { 451 PROXY_LOG( "%s: can't parse URI in '%s'", 452 root->name, line); 453 return DATA_ERROR; 454 } 455 version = strsep(&p, " "); 456 if (p != NULL) { 457 PROXY_LOG( "%s: extra data after version in '%s'", 458 root->name, line); 459 return DATA_ERROR; 460 } 461 if (conn->request) 462 http_request_free(conn->request); 463 464 conn->request = http_request_alloc( method, uri, version ); 465 if (!conn->request) 466 return DATA_ERROR; 467 468 proxy_connection_rewind(root); 469 } 470 return ret; 471} 472 473 474static DataStatus 475rewrite_connection_read_reply( RewriteConnection* conn ) 476{ 477 ProxyConnection* root = conn->root; 478 DataStatus ret; 479 480 ret = proxy_connection_receive_line( root, root->socket ); 481 if (ret == DATA_COMPLETED) { 482 HttpRequest* request = conn->request; 483 484 char* line = stralloc_cstr( root->str ); 485 char* p = line; 486 char* protocol; 487 char* number; 488 char* readable; 489 490 protocol = strsep(&p, " "); 491 if (p == NULL) { 492 PROXY_LOG("%s: can't parse response protocol: '%s'", 493 root->name, line); 494 return DATA_ERROR; 495 } 496 number = strsep(&p, " "); 497 if (p == NULL) { 498 PROXY_LOG("%s: can't parse response number: '%s'", 499 root->name, line); 500 return DATA_ERROR; 501 } 502 readable = p; 503 504 if (http_request_set_reply(request, protocol, number, readable) < 0) 505 return DATA_ERROR; 506 507 proxy_connection_rewind(root); 508 } 509 return ret; 510} 511 512 513static DataStatus 514rewrite_connection_read_headers( RewriteConnection* conn, 515 int fd ) 516{ 517 int ret; 518 ProxyConnection* root = conn->root; 519 520 for (;;) { 521 char* line; 522 stralloc_t* str = root->str; 523 524 ret = proxy_connection_receive_line(root, fd); 525 if (ret != DATA_COMPLETED) 526 break; 527 528 str->n = 0; 529 line = str->s; 530 531 if (line[0] == 0) { 532 /* an empty line means the end of headers */ 533 ret = 1; 534 break; 535 } 536 537 /* it this a continuation ? */ 538 if (line[0] == ' ' || line[0] == '\t') { 539 ret = http_request_add_to_last_header( conn->request, line ); 540 } 541 else { 542 char* key; 543 char* value; 544 545 value = line; 546 key = strsep(&value, ":"); 547 if (value == NULL) { 548 PROXY_LOG("%s: can't parse header '%s'", root->name, line); 549 ret = -1; 550 break; 551 } 552 value += strspn(value, " "); 553 if (http_request_add_header(conn->request, key, value) < 0) 554 ret = -1; 555 } 556 if (ret == DATA_ERROR) 557 break; 558 } 559 return ret; 560} 561 562static int 563rewrite_connection_rewrite_request( RewriteConnection* conn ) 564{ 565 ProxyConnection* root = conn->root; 566 HttpService* service = (HttpService*) root->service; 567 HttpRequest* r = conn->request; 568 stralloc_t* str = root->str; 569 HttpHeader* h; 570 571 proxy_connection_rewind(conn->root); 572 573 /* only rewrite the URI if it is not absolute */ 574 if (r->req_uri[0] == '/') { 575 char* host = http_request_find_header(r, "Host"); 576 if (host == NULL) { 577 PROXY_LOG("%s: uh oh, not Host: in request ?", root->name); 578 } else { 579 /* now create new URI */ 580 stralloc_add_str(str, "http://"); 581 stralloc_add_str(str, host); 582 stralloc_add_str(str, r->req_uri); 583 http_request_replace_uri(r, stralloc_cstr(str)); 584 proxy_connection_rewind(root); 585 } 586 } 587 588 stralloc_format( str, "%s %s %s\r\n", r->req_method, r->req_uri, r->req_version ); 589 for (h = r->headers->first; h; h = h->next) { 590 stralloc_add_format( str, "%s: %s\r\n", h->key, h->value ); 591 } 592 /* add the service's footer - includes final \r\n */ 593 stralloc_add_bytes( str, service->footer, service->footer_len ); 594 595 return 0; 596} 597 598static int 599rewrite_connection_rewrite_reply( RewriteConnection* conn ) 600{ 601 HttpRequest* r = conn->request; 602 ProxyConnection* root = conn->root; 603 stralloc_t* str = root->str; 604 HttpHeader* h; 605 606 proxy_connection_rewind(root); 607 stralloc_format(str, "%s %d %s\r\n", r->rep_version, r->rep_code, r->rep_readable); 608 for (h = r->headers->first; h; h = h->next) { 609 stralloc_add_format(str, "%s: %s\r\n", h->key, h->value); 610 } 611 stralloc_add_str(str, "\r\n"); 612 613 return 0; 614} 615 616 617static int 618rewrite_connection_get_body_length( RewriteConnection* conn, 619 int is_request ) 620{ 621 HttpRequest* r = conn->request; 622 ProxyConnection* root = conn->root; 623 char* content_length; 624 char* transfer_encoding; 625 626 conn->body_mode = BODY_NONE; 627 conn->body_length = 0; 628 conn->body_total = 0; 629 conn->body_sent = 0; 630 conn->body_is_closed = 0; 631 conn->body_is_full = 0; 632 conn->body_has_data = 0; 633 634 proxy_connection_rewind(root); 635 636 if (is_request) { 637 /* only POST and PUT should have a body */ 638 if (r->req_type != HTTP_REQUEST_POST && 639 r->req_type != HTTP_REQUEST_PUT) 640 { 641 return 0; 642 } 643 } else { 644 /* HTTP 1.1 Section 4.3 Message Body states that HEAD requests must not have 645 * a message body, as well as any 1xx, 204 and 304 replies */ 646 if (r->req_type == HTTP_REQUEST_HEAD || r->rep_code/100 == 1 || 647 r->rep_code == 204 || r->rep_code == 304) 648 return 0; 649 } 650 651 content_length = http_request_find_header(r, "Content-Length"); 652 if (content_length != NULL) { 653 char* end; 654 int64_t body_len = strtoll( content_length, &end, 10 ); 655 if (*end != '\0' || *content_length == '\0' || body_len < 0) { 656 PROXY_LOG("%s: bad content length: %s", root->name, content_length); 657 return DATA_ERROR; 658 } 659 if (body_len > 0) { 660 conn->body_mode = BODY_KNOWN_LENGTH; 661 conn->body_length = body_len; 662 } 663 } else { 664 transfer_encoding = http_request_find_header(r, "Transfer-Encoding"); 665 if (transfer_encoding && !strcasecmp(transfer_encoding, "Chunked")) { 666 conn->body_mode = BODY_CHUNKED; 667 conn->parse_chunk_header = 0; 668 conn->parse_chunk_trailer = 0; 669 conn->chunk_length = -1; 670 conn->chunk_total = 0; 671 conn->chunk_state = CHUNK_HEADER; 672 } 673 } 674 if (conn->body_mode == BODY_NONE) { 675 char* connection = http_request_find_header(r, "Proxy-Connection"); 676 677 if (!connection) 678 connection = http_request_find_header(r, "Connection"); 679 680 if (!connection || strcasecmp(connection, "Close")) { 681 /* hum, we can't support this at all */ 682 PROXY_LOG("%s: can't determine content length, and client wants" 683 " to keep connection opened", 684 root->name); 685 return -1; 686 } 687 /* a negative value means that the data ends when the client 688 * disconnects the connection. 689 */ 690 conn->body_mode = BODY_UNTIL_CLOSE; 691 } 692 D("%s: body_length=%lld body_mode=%s", 693 root->name, conn->body_length, 694 body_mode_str[conn->body_mode]); 695 696 proxy_connection_rewind(root); 697 return 0; 698} 699 700#define MAX_BODY_BUFFER 65536 701 702static DataStatus 703rewrite_connection_read_body( RewriteConnection* conn, int fd ) 704{ 705 ProxyConnection* root = conn->root; 706 stralloc_t* str = root->str; 707 int wanted = 0, current, avail; 708 DataStatus ret; 709 710 if (conn->body_is_closed) { 711 return DATA_NEED_MORE; 712 } 713 714 /* first, determine how many bytes we want to read. */ 715 switch (conn->body_mode) { 716 case BODY_NONE: 717 D("%s: INTERNAL ERROR: SHOULDN'T BE THERE", root->name); 718 return DATA_COMPLETED; 719 720 case BODY_KNOWN_LENGTH: 721 { 722 if (conn->body_length == 0) 723 return DATA_COMPLETED; 724 725 if (conn->body_length > MAX_BODY_BUFFER) 726 wanted = MAX_BODY_BUFFER; 727 else 728 wanted = (int)conn->body_length; 729 } 730 break; 731 732 case BODY_UNTIL_CLOSE: 733 wanted = MAX_BODY_BUFFER; 734 break; 735 736 case BODY_CHUNKED: 737 if (conn->chunk_state == CHUNK_DATA_END) { 738 /* We're waiting for the CR LF after the chunk data */ 739 ret = proxy_connection_receive_line(root, fd); 740 if (ret != DATA_COMPLETED) 741 return ret; 742 743 if (str->s[0] != 0) { /* this should be an empty line */ 744 PROXY_LOG("%s: invalid chunk data end: '%s'", 745 root->name, str->s); 746 return DATA_ERROR; 747 } 748 /* proxy_connection_receive_line() did remove the 749 * trailing \r\n, but we must preserve it when we 750 * send the chunk size end to the proxy. 751 */ 752 stralloc_add_str(root->str, "\r\n"); 753 conn->chunk_state = CHUNK_HEADER; 754 /* fall-through */ 755 } 756 757 if (conn->chunk_state == CHUNK_HEADER) { 758 char* line; 759 char* end; 760 long long length; 761 /* Ensure that the previous chunk was flushed before 762 * accepting a new header */ 763 if (!conn->parse_chunk_header) { 764 if (conn->body_has_data) 765 return DATA_NEED_MORE; 766 D("%s: waiting chunk header", root->name); 767 conn->parse_chunk_header = 1; 768 } 769 ret = proxy_connection_receive_line(root, fd); 770 if (ret != DATA_COMPLETED) { 771 return ret; 772 } 773 conn->parse_chunk_header = 0; 774 775 line = str->s; 776 length = strtoll(line, &end, 16); 777 if (line[0] == ' ' || (end[0] != '\0' && end[0] != ';')) { 778 PROXY_LOG("%s: invalid chunk header: %s", 779 root->name, line); 780 return DATA_ERROR; 781 } 782 if (length < 0) { 783 PROXY_LOG("%s: invalid chunk length %lld", 784 root->name, length); 785 return DATA_ERROR; 786 } 787 /* proxy_connection_receive_line() did remove the 788 * trailing \r\n, but we must preserve it when we 789 * send the chunk size to the proxy. 790 */ 791 stralloc_add_str(root->str, "\r\n"); 792 793 conn->chunk_length = length; 794 conn->chunk_total = 0; 795 conn->chunk_state = CHUNK_DATA; 796 if (length == 0) { 797 /* the last chunk, no we need to add the trailer */ 798 conn->chunk_state = CHUNK_TRAILER; 799 conn->parse_chunk_trailer = 0; 800 } 801 } 802 803 if (conn->chunk_state == CHUNK_TRAILER) { 804 /* ensure that 'str' is flushed before reading the trailer */ 805 if (!conn->parse_chunk_trailer) { 806 if (conn->body_has_data) 807 return DATA_NEED_MORE; 808 conn->parse_chunk_trailer = 1; 809 } 810 ret = rewrite_connection_read_headers(conn, fd); 811 if (ret == DATA_COMPLETED) { 812 conn->body_is_closed = 1; 813 } 814 return ret; 815 } 816 817 /* if we get here, body_length > 0 */ 818 if (conn->chunk_length > MAX_BODY_BUFFER) 819 wanted = MAX_BODY_BUFFER; 820 else 821 wanted = (int)conn->chunk_length; 822 break; 823 824 default: 825 ; 826 } 827 828 /* we don't want more than MAX_BODY_BUFFER bytes in the 829 * buffer we used to pass the body */ 830 current = str->n; 831 avail = MAX_BODY_BUFFER - current; 832 if (avail <= 0) { 833 /* wait for some flush */ 834 conn->body_is_full = 1; 835 D("%s: waiting to flush %d bytes", 836 root->name, current); 837 return DATA_NEED_MORE; 838 } 839 840 if (wanted > avail) 841 wanted = avail; 842 843 ret = proxy_connection_receive(root, fd, wanted); 844 conn->body_has_data = (str->n > 0); 845 conn->body_is_full = (str->n == MAX_BODY_BUFFER); 846 847 if (ret == DATA_ERROR) { 848 if (conn->body_mode == BODY_UNTIL_CLOSE) { 849 /* a disconnection here is normal and signals the 850 * end of the body */ 851 conn->body_total += root->str_recv; 852 D("%s: body completed by close (%lld bytes)", 853 root->name, conn->body_total); 854 conn->body_is_closed = 1; 855 ret = DATA_COMPLETED; 856 } 857 } else { 858 avail = root->str_recv; 859 ret = DATA_NEED_MORE; /* we're not really done yet */ 860 861 switch (conn->body_mode) { 862 case BODY_CHUNKED: 863 conn->chunk_total += avail; 864 conn->chunk_length -= avail; 865 866 if (conn->chunk_length == 0) { 867 D("%s: chunk completed (%lld bytes)", 868 root->name, conn->chunk_total); 869 conn->body_total += conn->chunk_total; 870 conn->chunk_total = 0; 871 conn->chunk_length = -1; 872 conn->chunk_state = CHUNK_DATA; 873 } 874 break; 875 876 case BODY_KNOWN_LENGTH: 877 conn->body_length -= avail; 878 conn->body_total += avail; 879 880 if (conn->body_length == 0) { 881 D("%s: body completed (%lld bytes)", 882 root->name, conn->body_total); 883 conn->body_is_closed = 1; 884 ret = DATA_COMPLETED; 885 } 886 break; 887 888 case BODY_UNTIL_CLOSE: 889 conn->body_total += avail; 890 break; 891 892 default: 893 ; 894 } 895 } 896 return ret; 897} 898 899static DataStatus 900rewrite_connection_send_body( RewriteConnection* conn, int fd ) 901{ 902 ProxyConnection* root = conn->root; 903 stralloc_t* str = root->str; 904 DataStatus ret = DATA_NEED_MORE; 905 906 if (conn->body_has_data) { 907 ret = proxy_connection_send(root, fd); 908 if (ret != DATA_ERROR) { 909 int pos = root->str_pos; 910 911 memmove(str->s, str->s+pos, str->n-pos); 912 str->n -= pos; 913 root->str_pos = 0; 914 conn->body_is_full = (str->n == MAX_BODY_BUFFER); 915 conn->body_has_data = (str->n > 0); 916 conn->body_sent += root->str_sent; 917 918 /* ensure that we return DATA_COMPLETED only when 919 * we have sent everything, and there is no more 920 * body pieces to read */ 921 if (ret == DATA_COMPLETED) { 922 if (!conn->body_is_closed || conn->body_has_data) 923 ret = DATA_NEED_MORE; 924 else { 925 D("%s: sent all body (%lld bytes)", 926 root->name, conn->body_sent); 927 } 928 } 929 D("%s: sent closed=%d data=%d n=%d ret=%d", 930 root->name, conn->body_is_closed, 931 conn->body_has_data, str->n, 932 ret); 933 } 934 } 935 return ret; 936} 937 938 939static void 940rewrite_connection_select( ProxyConnection* root, 941 ProxySelect* sel ) 942{ 943 RewriteConnection* conn = (RewriteConnection*)root; 944 int slirp = conn->slirp_fd; 945 int proxy = root->socket; 946 947 switch (conn->state) { 948 case STATE_CONNECTING: 949 case STATE_CREATE_SOCKET_PAIR: 950 /* try to connect to the proxy server */ 951 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 952 break; 953 954 case STATE_REQUEST_FIRST_LINE: 955 case STATE_REQUEST_HEADERS: 956 proxy_select_set( sel, slirp, PROXY_SELECT_READ ); 957 break; 958 959 case STATE_REQUEST_SEND: 960 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 961 break; 962 963 case STATE_REQUEST_BODY: 964 if (!conn->body_is_closed && !conn->body_is_full) 965 proxy_select_set( sel, slirp, PROXY_SELECT_READ ); 966 967 if (conn->body_has_data) 968 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 969 break; 970 971 case STATE_REPLY_FIRST_LINE: 972 case STATE_REPLY_HEADERS: 973 proxy_select_set( sel, proxy, PROXY_SELECT_READ ); 974 break; 975 976 case STATE_REPLY_SEND: 977 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE ); 978 break; 979 980 case STATE_REPLY_BODY: 981 if (conn->body_has_data) 982 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE ); 983 984 if (!conn->body_is_closed && !conn->body_is_full) 985 proxy_select_set( sel, proxy, PROXY_SELECT_READ ); 986 break; 987 default: 988 ; 989 }; 990} 991 992static void 993rewrite_connection_poll( ProxyConnection* root, 994 ProxySelect* sel ) 995{ 996 RewriteConnection* conn = (RewriteConnection*)root; 997 998 int slirp = conn->slirp_fd; 999 int proxy = root->socket; 1000 int has_slirp = proxy_select_poll(sel, slirp); 1001 int has_proxy = proxy_select_poll(sel, proxy); 1002 DataStatus ret = DATA_NEED_MORE; 1003 1004 switch (conn->state) { 1005 case STATE_CONNECTING: 1006 if (has_proxy) { 1007 PROXY_LOG("%s: connected to proxy", root->name); 1008 conn->state = STATE_CREATE_SOCKET_PAIR; 1009 } 1010 break; 1011 1012 case STATE_CREATE_SOCKET_PAIR: 1013 if (has_proxy) { 1014 if (rewrite_connection_create_sockets(conn) < 0) { 1015 ret = DATA_ERROR; 1016 } else { 1017 D("%s: socket pair created", root->name); 1018 conn->state = STATE_REQUEST_FIRST_LINE; 1019 } 1020 } 1021 break; 1022 1023 case STATE_REQUEST_FIRST_LINE: 1024 if (has_slirp) { 1025 ret = rewrite_connection_read_request(conn); 1026 if (ret == DATA_COMPLETED) { 1027 PROXY_LOG("%s: request first line ok", root->name); 1028 conn->state = STATE_REQUEST_HEADERS; 1029 } 1030 } 1031 break; 1032 1033 case STATE_REQUEST_HEADERS: 1034 if (has_slirp) { 1035 ret = rewrite_connection_read_headers(conn, slirp); 1036 if (ret == DATA_COMPLETED) { 1037 PROXY_LOG("%s: request headers ok", root->name); 1038 if (rewrite_connection_rewrite_request(conn) < 0) 1039 ret = DATA_ERROR; 1040 else 1041 conn->state = STATE_REQUEST_SEND; 1042 } 1043 } 1044 break; 1045 1046 case STATE_REQUEST_SEND: 1047 if (has_proxy) { 1048 ret = proxy_connection_send(root, proxy); 1049 if (ret == DATA_COMPLETED) { 1050 if (rewrite_connection_get_body_length(conn, 1) < 0) { 1051 ret = DATA_ERROR; 1052 } else if (conn->body_mode != BODY_NONE) { 1053 PROXY_LOG("%s: request sent, waiting for body", 1054 root->name); 1055 conn->state = STATE_REQUEST_BODY; 1056 } else { 1057 PROXY_LOG("%s: request sent, waiting for reply", 1058 root->name); 1059 conn->state = STATE_REPLY_FIRST_LINE; 1060 } 1061 } 1062 } 1063 break; 1064 1065 case STATE_REQUEST_BODY: 1066 if (has_slirp) { 1067 ret = rewrite_connection_read_body(conn, slirp); 1068 } 1069 if (ret != DATA_ERROR && has_proxy) { 1070 ret = rewrite_connection_send_body(conn, proxy); 1071 if (ret == DATA_COMPLETED) { 1072 PROXY_LOG("%s: request body ok, waiting for reply", 1073 root->name); 1074 conn->state = STATE_REPLY_FIRST_LINE; 1075 } 1076 } 1077 break; 1078 1079 case STATE_REPLY_FIRST_LINE: 1080 if (has_proxy) { 1081 ret = rewrite_connection_read_reply(conn); 1082 if (ret == DATA_COMPLETED) { 1083 PROXY_LOG("%s: reply first line ok", root->name); 1084 conn->state = STATE_REPLY_HEADERS; 1085 } 1086 } 1087 break; 1088 1089 case STATE_REPLY_HEADERS: 1090 if (has_proxy) { 1091 ret = rewrite_connection_read_headers(conn, proxy); 1092 if (ret == DATA_COMPLETED) { 1093 PROXY_LOG("%s: reply headers ok", root->name); 1094 if (rewrite_connection_rewrite_reply(conn) < 0) 1095 ret = DATA_ERROR; 1096 else 1097 conn->state = STATE_REPLY_SEND; 1098 } 1099 } 1100 break; 1101 1102 case STATE_REPLY_SEND: 1103 if (has_slirp) { 1104 ret = proxy_connection_send(conn->root, slirp); 1105 if (ret == DATA_COMPLETED) { 1106 if (rewrite_connection_get_body_length(conn, 0) < 0) { 1107 ret = DATA_ERROR; 1108 } else if (conn->body_mode != BODY_NONE) { 1109 PROXY_LOG("%s: reply sent, waiting for body", 1110 root->name); 1111 conn->state = STATE_REPLY_BODY; 1112 } else { 1113 PROXY_LOG("%s: reply sent, looping to waiting request", 1114 root->name); 1115 conn->state = STATE_REQUEST_FIRST_LINE; 1116 } 1117 } 1118 } 1119 break; 1120 1121 case STATE_REPLY_BODY: 1122 if (has_proxy) { 1123 ret = rewrite_connection_read_body(conn, proxy); 1124 } 1125 if (ret != DATA_ERROR && has_slirp) { 1126 ret = rewrite_connection_send_body(conn, slirp); 1127 if (ret == DATA_COMPLETED) { 1128 if (conn->body_mode == BODY_UNTIL_CLOSE) { 1129 PROXY_LOG("%s: closing connection", root->name); 1130 ret = DATA_ERROR; 1131 } else { 1132 PROXY_LOG("%s: reply body ok, looping to waiting request", 1133 root->name); 1134 conn->state = STATE_REQUEST_FIRST_LINE; 1135 } 1136 } 1137 } 1138 break; 1139 1140 default: 1141 ; 1142 } 1143 if (ret == DATA_ERROR) 1144 proxy_connection_free(root, 0, PROXY_EVENT_NONE); 1145 1146 return; 1147} 1148 1149 1150ProxyConnection* 1151http_rewriter_connect( HttpService* service, 1152 SockAddress* address ) 1153{ 1154 RewriteConnection* conn; 1155 int s; 1156 1157 s = socket_create(address->family, SOCKET_STREAM ); 1158 if (s < 0) 1159 return NULL; 1160 1161 conn = qemu_mallocz(sizeof(*conn)); 1162 if (conn == NULL) { 1163 socket_close(s); 1164 return NULL; 1165 } 1166 1167 proxy_connection_init( conn->root, s, address, service->root, 1168 rewrite_connection_free, 1169 rewrite_connection_select, 1170 rewrite_connection_poll ); 1171 1172 if ( rewrite_connection_init( conn ) < 0 ) { 1173 rewrite_connection_free( conn->root ); 1174 return NULL; 1175 } 1176 1177 return conn->root; 1178} 1179