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 */ 68 typedef struct HttpHeader { 69 struct HttpHeader* next; 70 const char* key; 71 const char* value; 72 } HttpHeader; 73 74 static void 75 http_header_free( HttpHeader* h ) 76 { 77 if (h) { 78 qemu_free((char*)h->value); 79 qemu_free(h); 80 } 81 } 82 83 static int 84 http_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 96 static HttpHeader* 97 http_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 116 typedef struct { 117 HttpHeader* first; 118 HttpHeader* last; 119 } HttpHeaderList; 120 121 static void 122 http_header_list_init( HttpHeaderList* l ) 123 { 124 l->first = l->last = NULL; 125 } 126 127 static void 128 http_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 138 static void 139 http_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 151 static const char* 152 http_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 169 typedef 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 */ 181 typedef 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 193 static HttpRequest* 194 http_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 224 static void 225 http_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 233 static void 234 http_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 248 static char* 249 http_request_find_header( HttpRequest* r, 250 const char* key ) 251 { 252 return (char*)http_header_list_find(r->headers, key); 253 } 254 255 256 static int 257 http_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 269 static int 270 http_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 280 static int 281 http_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 310 typedef 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 328 typedef enum { 329 BODY_NONE = 0, 330 BODY_KNOWN_LENGTH, 331 BODY_UNTIL_CLOSE, 332 BODY_CHUNKED, 333 BODY_MODE_MAX 334 } BodyMode; 335 336 static const char* const body_mode_str[BODY_MODE_MAX] = { 337 "NONE", "KNOWN_LENGTH", "UNTIL_CLOSE", "CHUNKED" 338 }; 339 340 typedef struct { 341 ProxyConnection root[1]; 342 int slirp_fd; 343 ConnectionState state; 344 HttpRequest* request; 345 BodyMode body_mode; 346 int64_t body_length; 347 int64_t body_total; 348 int64_t body_sent; 349 int64_t chunk_length; 350 int64_t chunk_total; 351 char body_has_data; 352 char body_is_full; 353 char body_is_closed; 354 char parse_chunk_header; 355 char parse_chunk_trailer; 356 } RewriteConnection; 357 358 359 static void 360 rewrite_connection_free( ProxyConnection* root ) 361 { 362 RewriteConnection* conn = (RewriteConnection*)root; 363 364 if (conn->slirp_fd >= 0) { 365 socket_close(conn->slirp_fd); 366 conn->slirp_fd = -1; 367 } 368 http_request_free(conn->request); 369 proxy_connection_done(root); 370 qemu_free(conn); 371 } 372 373 374 static int 375 rewrite_connection_init( RewriteConnection* conn ) 376 { 377 HttpService* service = (HttpService*) conn->root->service; 378 ProxyConnection* root = conn->root; 379 380 conn->slirp_fd = -1; 381 conn->state = STATE_CONNECTING; 382 383 if (socket_connect( root->socket, &service->server_addr ) < 0) { 384 if (errno == EINPROGRESS || errno == EWOULDBLOCK || errno == EAGAIN) { 385 PROXY_LOG("%s: connecting", conn->root->name); 386 } 387 else { 388 PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str); 389 return -1; 390 } 391 } 392 else { 393 PROXY_LOG("%s: immediate connection", root->name); 394 conn->state = STATE_CREATE_SOCKET_PAIR; 395 } 396 return 0; 397 } 398 399 static int 400 rewrite_connection_create_sockets( RewriteConnection* conn ) 401 { 402 /* immediate connection to the proxy. now create a socket 403 * pair and send a 'success' event to slirp */ 404 int slirp_1; 405 ProxyConnection* root = conn->root; 406 407 if (socket_pair( &slirp_1, &conn->slirp_fd ) < 0) { 408 PROXY_LOG("%s: coult not create socket pair: %s", 409 root->name, errno_str); 410 return -1; 411 } 412 413 root->ev_func( root->ev_opaque, slirp_1, PROXY_EVENT_CONNECTED ); 414 conn->state = STATE_REQUEST_FIRST_LINE; 415 return 0; 416 } 417 418 419 /* read the first line of a given HTTP request. returns -1/0/+1 */ 420 static DataStatus 421 rewrite_connection_read_request( RewriteConnection* conn ) 422 { 423 ProxyConnection* root = conn->root; 424 DataStatus ret; 425 426 ret = proxy_connection_receive_line(root, conn->slirp_fd); 427 if (ret == DATA_COMPLETED) { 428 /* now parse the first line to see if we can handle it */ 429 char* line = root->str->s; 430 char* method; 431 char* uri; 432 char* version; 433 char* p = line; 434 435 method = strsep(&p, " "); 436 if (p == NULL) { 437 PROXY_LOG("%s: can't parse method in '%'", 438 root->name, line); 439 return DATA_ERROR; 440 } 441 uri = strsep(&p, " "); 442 if (p == NULL) { 443 PROXY_LOG( "%s: can't parse URI in '%s'", 444 root->name, line); 445 return DATA_ERROR; 446 } 447 version = strsep(&p, " "); 448 if (p != NULL) { 449 PROXY_LOG( "%s: extra data after version in '%s'", 450 root->name, line); 451 return DATA_ERROR; 452 } 453 if (conn->request) 454 http_request_free(conn->request); 455 456 conn->request = http_request_alloc( method, uri, version ); 457 if (!conn->request) 458 return DATA_ERROR; 459 460 proxy_connection_rewind(root); 461 } 462 return ret; 463 } 464 465 466 static DataStatus 467 rewrite_connection_read_reply( RewriteConnection* conn ) 468 { 469 ProxyConnection* root = conn->root; 470 DataStatus ret; 471 472 ret = proxy_connection_receive_line( root, root->socket ); 473 if (ret == DATA_COMPLETED) { 474 HttpRequest* request = conn->request; 475 476 char* line = stralloc_cstr( root->str ); 477 char* p = line; 478 char* protocol; 479 char* number; 480 char* readable; 481 482 protocol = strsep(&p, " "); 483 if (p == NULL) { 484 PROXY_LOG("%s: can't parse response protocol: '%s'", 485 root->name, line); 486 return DATA_ERROR; 487 } 488 number = strsep(&p, " "); 489 if (p == NULL) { 490 PROXY_LOG("%s: can't parse response number: '%s'", 491 root->name, line); 492 return DATA_ERROR; 493 } 494 readable = p; 495 496 if (http_request_set_reply(request, protocol, number, readable) < 0) 497 return DATA_ERROR; 498 499 proxy_connection_rewind(root); 500 } 501 return ret; 502 } 503 504 505 static DataStatus 506 rewrite_connection_read_headers( RewriteConnection* conn, 507 int fd ) 508 { 509 int ret; 510 ProxyConnection* root = conn->root; 511 512 for (;;) { 513 char* line; 514 stralloc_t* str = root->str; 515 516 ret = proxy_connection_receive_line(root, fd); 517 if (ret != DATA_COMPLETED) 518 break; 519 520 str->n = 0; 521 line = str->s; 522 523 if (line[0] == 0) { 524 /* an empty line means the end of headers */ 525 ret = 1; 526 break; 527 } 528 529 /* it this a continuation ? */ 530 if (line[0] == ' ' || line[0] == '\t') { 531 ret = http_request_add_to_last_header( conn->request, line ); 532 } 533 else { 534 char* key; 535 char* value; 536 537 value = line; 538 key = strsep(&value, ":"); 539 if (value == NULL) { 540 PROXY_LOG("%s: can't parse header '%s'", root->name, line); 541 ret = -1; 542 break; 543 } 544 value += strspn(value, " "); 545 if (http_request_add_header(conn->request, key, value) < 0) 546 ret = -1; 547 } 548 if (ret == DATA_ERROR) 549 break; 550 } 551 return ret; 552 } 553 554 static int 555 rewrite_connection_rewrite_request( RewriteConnection* conn ) 556 { 557 ProxyConnection* root = conn->root; 558 HttpService* service = (HttpService*) root->service; 559 HttpRequest* r = conn->request; 560 stralloc_t* str = root->str; 561 HttpHeader* h; 562 563 proxy_connection_rewind(conn->root); 564 565 /* only rewrite the URI if it is not absolute */ 566 if (r->req_uri[0] == '/') { 567 char* host = http_request_find_header(r, "Host"); 568 if (host == NULL) { 569 PROXY_LOG("%s: uh oh, not Host: in request ?", root->name); 570 } else { 571 /* now create new URI */ 572 stralloc_add_str(str, "http://"); 573 stralloc_add_str(str, host); 574 stralloc_add_str(str, r->req_uri); 575 http_request_replace_uri(r, stralloc_cstr(str)); 576 proxy_connection_rewind(root); 577 } 578 } 579 580 stralloc_format( str, "%s %s %s\r\n", r->req_method, r->req_uri, r->req_version ); 581 for (h = r->headers->first; h; h = h->next) { 582 stralloc_add_format( str, "%s: %s\r\n", h->key, h->value ); 583 } 584 /* add the service's footer - includes final \r\n */ 585 stralloc_add_bytes( str, service->footer, service->footer_len ); 586 587 return 0; 588 } 589 590 static int 591 rewrite_connection_rewrite_reply( RewriteConnection* conn ) 592 { 593 HttpRequest* r = conn->request; 594 ProxyConnection* root = conn->root; 595 stralloc_t* str = root->str; 596 HttpHeader* h; 597 598 proxy_connection_rewind(root); 599 stralloc_format(str, "%s %d %s\r\n", r->rep_version, r->rep_code, r->rep_readable); 600 for (h = r->headers->first; h; h = h->next) { 601 stralloc_add_format(str, "%s: %s\r\n", h->key, h->value); 602 } 603 stralloc_add_str(str, "\r\n"); 604 605 return 0; 606 } 607 608 609 static int 610 rewrite_connection_get_body_length( RewriteConnection* conn, 611 int is_request ) 612 { 613 HttpRequest* r = conn->request; 614 ProxyConnection* root = conn->root; 615 char* content_length; 616 char* transfer_encoding; 617 618 conn->body_mode = BODY_NONE; 619 conn->body_length = 0; 620 conn->body_total = 0; 621 conn->body_sent = 0; 622 conn->body_is_closed = 0; 623 conn->body_is_full = 0; 624 conn->body_has_data = 0; 625 626 proxy_connection_rewind(root); 627 628 if (is_request) { 629 /* only POST and PUT should have a body */ 630 if (r->req_type != HTTP_REQUEST_POST && 631 r->req_type != HTTP_REQUEST_PUT) 632 { 633 return 0; 634 } 635 } else { 636 /* HTTP 1.1 Section 4.3 Message Body states that HEAD requests must not have 637 * a message body, as well as any 1xx, 204 and 304 replies */ 638 if (r->req_type == HTTP_REQUEST_HEAD || r->rep_code/100 == 1 || 639 r->rep_code == 204 || r->rep_code == 304) 640 return 0; 641 } 642 643 content_length = http_request_find_header(r, "Content-Length"); 644 if (content_length != NULL) { 645 char* end; 646 int64_t body_len = strtoll( content_length, &end, 10 ); 647 if (*end != '\0' || *content_length == '\0' || body_len < 0) { 648 PROXY_LOG("%s: bad content length: %s", root->name, content_length); 649 return DATA_ERROR; 650 } 651 if (body_len > 0) { 652 conn->body_mode = BODY_KNOWN_LENGTH; 653 conn->body_length = body_len; 654 } 655 } else { 656 transfer_encoding = http_request_find_header(r, "Transfer-Encoding"); 657 if (transfer_encoding && !strcasecmp(transfer_encoding, "Chunked")) { 658 conn->body_mode = BODY_CHUNKED; 659 conn->parse_chunk_header = 0; 660 conn->parse_chunk_trailer = 0; 661 conn->chunk_length = -1; 662 conn->chunk_total = 0; 663 } 664 } 665 if (conn->body_mode == BODY_NONE) { 666 char* connection = http_request_find_header(r, "Proxy-Connection"); 667 668 if (!connection) 669 connection = http_request_find_header(r, "Connection"); 670 671 if (!connection || strcasecmp(connection, "Close")) { 672 /* hum, we can't support this at all */ 673 PROXY_LOG("%s: can't determine content length, and client wants" 674 " to keep connection opened", 675 root->name); 676 return -1; 677 } 678 /* a negative value means that the data ends when the client 679 * disconnects the connection. 680 */ 681 conn->body_mode = BODY_UNTIL_CLOSE; 682 } 683 D("%s: body_length=%lld body_mode=%s", 684 root->name, conn->body_length, 685 body_mode_str[conn->body_mode]); 686 687 proxy_connection_rewind(root); 688 return 0; 689 } 690 691 #define MAX_BODY_BUFFER 65536 692 693 static DataStatus 694 rewrite_connection_read_body( RewriteConnection* conn, int fd ) 695 { 696 ProxyConnection* root = conn->root; 697 stralloc_t* str = root->str; 698 int wanted = 0, current, avail; 699 DataStatus ret; 700 701 if (conn->body_is_closed) { 702 return DATA_NEED_MORE; 703 } 704 705 /* first, determine how many bytes we want to read. */ 706 switch (conn->body_mode) { 707 case BODY_NONE: 708 D("%s: INTERNAL ERROR: SHOULDN'T BE THERE", root->name); 709 return DATA_COMPLETED; 710 711 case BODY_KNOWN_LENGTH: 712 { 713 if (conn->body_length == 0) 714 return DATA_COMPLETED; 715 716 if (conn->body_length > MAX_BODY_BUFFER) 717 wanted = MAX_BODY_BUFFER; 718 else 719 wanted = (int)conn->body_length; 720 } 721 break; 722 723 case BODY_UNTIL_CLOSE: 724 wanted = MAX_BODY_BUFFER; 725 break; 726 727 case BODY_CHUNKED: 728 if (conn->chunk_length < 0) { 729 /* chunk_length < 0 means we need to read a chunk header */ 730 /* ensure that 'str' is flushed before doing this */ 731 if (!conn->parse_chunk_header) { 732 if (conn->body_has_data) 733 return DATA_NEED_MORE; 734 D("%s: waiting chunk header", root->name); 735 conn->parse_chunk_header = 1; 736 } 737 ret = proxy_connection_receive_line(root, fd); 738 if (ret == DATA_COMPLETED) { 739 char* line = str->s; 740 char* end; 741 long long length; 742 743 length = strtoll(line, &end, 16); 744 if (line[0] == ' ' || (end[0] != '\0' && end[0] != ';')) { 745 PROXY_LOG("%s: invalid chunk header: %s", 746 root->name, line); 747 return DATA_ERROR; 748 } 749 if (length < 0) { 750 PROXY_LOG("%s: invalid chunk length %lld", 751 root->name, length); 752 return DATA_ERROR; 753 } 754 /* proxy_connection_receive_line() did remove the 755 * trailing \r\n, but we must preserve it when we 756 * send the chunk size to the proxy. 757 */ 758 stralloc_add_str(root->str, "\r\n"); 759 760 conn->chunk_length = length; 761 conn->chunk_total = 0; 762 if (length == 0) { 763 /* the last chunk, no we need to add the trailer */ 764 conn->parse_chunk_trailer = 0; 765 } 766 conn->parse_chunk_header = 0; 767 } 768 } 769 770 if (conn->chunk_length == 0) { 771 /* chunk_length == 0 means we're reading the chunk trailer */ 772 /* ensure that 'str' is flushed before reading the trailer */ 773 if (!conn->parse_chunk_trailer) { 774 if (conn->body_has_data) 775 return DATA_NEED_MORE; 776 conn->parse_chunk_trailer = 1; 777 } 778 ret = rewrite_connection_read_headers(conn, fd); 779 if (ret == DATA_COMPLETED) { 780 conn->body_is_closed = 1; 781 } 782 return ret; 783 } 784 785 /* if we get here, body_length > 0 */ 786 if (conn->chunk_length > MAX_BODY_BUFFER) 787 wanted = MAX_BODY_BUFFER; 788 else 789 wanted = (int)conn->chunk_length; 790 break; 791 792 default: 793 ; 794 } 795 796 /* we don't want more than MAX_BODY_BUFFER bytes in the 797 * buffer we used to pass the body */ 798 current = str->n; 799 avail = MAX_BODY_BUFFER - current; 800 if (avail <= 0) { 801 /* wait for some flush */ 802 conn->body_is_full = 1; 803 D("%s: waiting to flush %d bytes", 804 root->name, current); 805 return DATA_NEED_MORE; 806 } 807 808 if (wanted > avail) 809 wanted = avail; 810 811 ret = proxy_connection_receive(root, fd, wanted); 812 conn->body_has_data = (str->n > 0); 813 conn->body_is_full = (str->n == MAX_BODY_BUFFER); 814 815 if (ret == DATA_ERROR) { 816 if (conn->body_mode == BODY_UNTIL_CLOSE) { 817 /* a disconnection here is normal and signals the 818 * end of the body */ 819 conn->body_total += root->str_recv; 820 D("%s: body completed by close (%lld bytes)", 821 root->name, conn->body_total); 822 conn->body_is_closed = 1; 823 ret = DATA_COMPLETED; 824 } 825 } else { 826 avail = root->str_recv; 827 ret = DATA_NEED_MORE; /* we're not really done yet */ 828 829 switch (conn->body_mode) { 830 case BODY_CHUNKED: 831 conn->chunk_total += avail; 832 conn->chunk_length -= avail; 833 834 if (conn->chunk_length == 0) { 835 D("%s: chunk completed (%lld bytes)", 836 root->name, conn->chunk_length); 837 conn->body_total += conn->chunk_total; 838 conn->chunk_total = 0; 839 conn->chunk_length = -1; 840 } 841 break; 842 843 case BODY_KNOWN_LENGTH: 844 conn->body_length -= avail; 845 conn->body_total += avail; 846 847 if (conn->body_length == 0) { 848 D("%s: body completed (%lld bytes)", 849 root->name, conn->body_total); 850 conn->body_is_closed = 1; 851 ret = DATA_COMPLETED; 852 } 853 break; 854 855 case BODY_UNTIL_CLOSE: 856 conn->body_total += avail; 857 break; 858 859 default: 860 ; 861 } 862 } 863 return ret; 864 } 865 866 static DataStatus 867 rewrite_connection_send_body( RewriteConnection* conn, int fd ) 868 { 869 ProxyConnection* root = conn->root; 870 stralloc_t* str = root->str; 871 DataStatus ret = DATA_NEED_MORE; 872 873 if (conn->body_has_data) { 874 ret = proxy_connection_send(root, fd); 875 if (ret != DATA_ERROR) { 876 int pos = root->str_pos; 877 878 memmove(str->s, str->s+pos, str->n-pos); 879 str->n -= pos; 880 root->str_pos = 0; 881 conn->body_is_full = (str->n == MAX_BODY_BUFFER); 882 conn->body_has_data = (str->n > 0); 883 conn->body_sent += root->str_sent; 884 885 /* ensure that we return DATA_COMPLETED only when 886 * we have sent everything, and there is no more 887 * body pieces to read */ 888 if (ret == DATA_COMPLETED) { 889 if (!conn->body_is_closed || conn->body_has_data) 890 ret = DATA_NEED_MORE; 891 else { 892 D("%s: sent all body (%lld bytes)", 893 root->name, conn->body_sent); 894 } 895 } 896 D("%s: sent closed=%d data=%d n=%d ret=%d", 897 root->name, conn->body_is_closed, 898 conn->body_has_data, str->n, 899 ret); 900 } 901 } 902 return ret; 903 } 904 905 906 static void 907 rewrite_connection_select( ProxyConnection* root, 908 ProxySelect* sel ) 909 { 910 RewriteConnection* conn = (RewriteConnection*)root; 911 int slirp = conn->slirp_fd; 912 int proxy = root->socket; 913 914 switch (conn->state) { 915 case STATE_CONNECTING: 916 case STATE_CREATE_SOCKET_PAIR: 917 /* try to connect to the proxy server */ 918 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 919 break; 920 921 case STATE_REQUEST_FIRST_LINE: 922 case STATE_REQUEST_HEADERS: 923 proxy_select_set( sel, slirp, PROXY_SELECT_READ ); 924 break; 925 926 case STATE_REQUEST_SEND: 927 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 928 break; 929 930 case STATE_REQUEST_BODY: 931 if (!conn->body_is_closed && !conn->body_is_full) 932 proxy_select_set( sel, slirp, PROXY_SELECT_READ ); 933 934 if (conn->body_has_data) 935 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 936 break; 937 938 case STATE_REPLY_FIRST_LINE: 939 case STATE_REPLY_HEADERS: 940 proxy_select_set( sel, proxy, PROXY_SELECT_READ ); 941 break; 942 943 case STATE_REPLY_SEND: 944 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE ); 945 break; 946 947 case STATE_REPLY_BODY: 948 if (conn->body_has_data) 949 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE ); 950 951 if (!conn->body_is_closed && !conn->body_is_full) 952 proxy_select_set( sel, proxy, PROXY_SELECT_READ ); 953 break; 954 default: 955 ; 956 }; 957 } 958 959 static void 960 rewrite_connection_poll( ProxyConnection* root, 961 ProxySelect* sel ) 962 { 963 RewriteConnection* conn = (RewriteConnection*)root; 964 965 int slirp = conn->slirp_fd; 966 int proxy = root->socket; 967 int has_slirp = proxy_select_poll(sel, slirp); 968 int has_proxy = proxy_select_poll(sel, proxy); 969 DataStatus ret = DATA_NEED_MORE; 970 971 switch (conn->state) { 972 case STATE_CONNECTING: 973 if (has_proxy) { 974 PROXY_LOG("%s: connected to proxy", root->name); 975 conn->state = STATE_CREATE_SOCKET_PAIR; 976 } 977 break; 978 979 case STATE_CREATE_SOCKET_PAIR: 980 if (has_proxy) { 981 if (rewrite_connection_create_sockets(conn) < 0) { 982 ret = DATA_ERROR; 983 } else { 984 D("%s: socket pair created", root->name); 985 conn->state = STATE_REQUEST_FIRST_LINE; 986 } 987 } 988 break; 989 990 case STATE_REQUEST_FIRST_LINE: 991 if (has_slirp) { 992 ret = rewrite_connection_read_request(conn); 993 if (ret == DATA_COMPLETED) { 994 PROXY_LOG("%s: request first line ok", root->name); 995 conn->state = STATE_REQUEST_HEADERS; 996 } 997 } 998 break; 999 1000 case STATE_REQUEST_HEADERS: 1001 if (has_slirp) { 1002 ret = rewrite_connection_read_headers(conn, slirp); 1003 if (ret == DATA_COMPLETED) { 1004 PROXY_LOG("%s: request headers ok", root->name); 1005 if (rewrite_connection_rewrite_request(conn) < 0) 1006 ret = DATA_ERROR; 1007 else 1008 conn->state = STATE_REQUEST_SEND; 1009 } 1010 } 1011 break; 1012 1013 case STATE_REQUEST_SEND: 1014 if (has_proxy) { 1015 ret = proxy_connection_send(root, proxy); 1016 if (ret == DATA_COMPLETED) { 1017 if (rewrite_connection_get_body_length(conn, 1) < 0) { 1018 ret = DATA_ERROR; 1019 } else if (conn->body_mode != BODY_NONE) { 1020 PROXY_LOG("%s: request sent, waiting for body", 1021 root->name); 1022 conn->state = STATE_REQUEST_BODY; 1023 } else { 1024 PROXY_LOG("%s: request sent, waiting for reply", 1025 root->name); 1026 conn->state = STATE_REPLY_FIRST_LINE; 1027 } 1028 } 1029 } 1030 break; 1031 1032 case STATE_REQUEST_BODY: 1033 if (has_slirp) { 1034 ret = rewrite_connection_read_body(conn, slirp); 1035 } 1036 if (ret != DATA_ERROR && has_proxy) { 1037 ret = rewrite_connection_send_body(conn, proxy); 1038 if (ret == DATA_COMPLETED) { 1039 PROXY_LOG("%s: request body ok, waiting for reply", 1040 root->name); 1041 conn->state = STATE_REPLY_FIRST_LINE; 1042 } 1043 } 1044 break; 1045 1046 case STATE_REPLY_FIRST_LINE: 1047 if (has_proxy) { 1048 ret = rewrite_connection_read_reply(conn); 1049 if (ret == DATA_COMPLETED) { 1050 PROXY_LOG("%s: reply first line ok", root->name); 1051 conn->state = STATE_REPLY_HEADERS; 1052 } 1053 } 1054 break; 1055 1056 case STATE_REPLY_HEADERS: 1057 if (has_proxy) { 1058 ret = rewrite_connection_read_headers(conn, proxy); 1059 if (ret == DATA_COMPLETED) { 1060 PROXY_LOG("%s: reply headers ok", root->name); 1061 if (rewrite_connection_rewrite_reply(conn) < 0) 1062 ret = DATA_ERROR; 1063 else 1064 conn->state = STATE_REPLY_SEND; 1065 } 1066 } 1067 break; 1068 1069 case STATE_REPLY_SEND: 1070 if (has_slirp) { 1071 ret = proxy_connection_send(conn->root, slirp); 1072 if (ret == DATA_COMPLETED) { 1073 if (rewrite_connection_get_body_length(conn, 0) < 0) { 1074 ret = DATA_ERROR; 1075 } else if (conn->body_mode != BODY_NONE) { 1076 PROXY_LOG("%s: reply sent, waiting for body", 1077 root->name); 1078 conn->state = STATE_REPLY_BODY; 1079 } else { 1080 PROXY_LOG("%s: reply sent, looping to waiting request", 1081 root->name); 1082 conn->state = STATE_REQUEST_FIRST_LINE; 1083 } 1084 } 1085 } 1086 break; 1087 1088 case STATE_REPLY_BODY: 1089 if (has_proxy) { 1090 ret = rewrite_connection_read_body(conn, proxy); 1091 } 1092 if (ret != DATA_ERROR && has_slirp) { 1093 ret = rewrite_connection_send_body(conn, slirp); 1094 if (ret == DATA_COMPLETED) { 1095 if (conn->body_mode == BODY_UNTIL_CLOSE) { 1096 PROXY_LOG("%s: closing connection", root->name); 1097 ret = DATA_ERROR; 1098 } else { 1099 PROXY_LOG("%s: reply body ok, looping to waiting request", 1100 root->name); 1101 conn->state = STATE_REQUEST_FIRST_LINE; 1102 } 1103 } 1104 } 1105 break; 1106 1107 default: 1108 ; 1109 } 1110 if (ret == DATA_ERROR) 1111 proxy_connection_free(root, 0, PROXY_EVENT_NONE); 1112 1113 return; 1114 } 1115 1116 1117 ProxyConnection* 1118 http_rewriter_connect( HttpService* service, 1119 SockAddress* address ) 1120 { 1121 RewriteConnection* conn; 1122 int s; 1123 1124 s = socket_create(address->family, SOCKET_STREAM ); 1125 if (s < 0) 1126 return NULL; 1127 1128 conn = qemu_mallocz(sizeof(*conn)); 1129 if (conn == NULL) { 1130 socket_close(s); 1131 return NULL; 1132 } 1133 1134 proxy_connection_init( conn->root, s, address, service->root, 1135 rewrite_connection_free, 1136 rewrite_connection_select, 1137 rewrite_connection_poll ); 1138 1139 if ( rewrite_connection_init( conn ) < 0 ) { 1140 rewrite_connection_free( conn->root ); 1141 return NULL; 1142 } 1143 1144 return conn->root; 1145 } 1146