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 340typedef 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 359static void 360rewrite_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 374static int 375rewrite_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 399static int 400rewrite_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 */ 420static DataStatus 421rewrite_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 466static DataStatus 467rewrite_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 505static DataStatus 506rewrite_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 554static int 555rewrite_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 590static int 591rewrite_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 609static int 610rewrite_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 693static DataStatus 694rewrite_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 conn->chunk_length = length; 755 conn->chunk_total = 0; 756 if (length == 0) { 757 /* the last chunk, no we need to add the trailer */ 758 conn->parse_chunk_trailer = 0; 759 } 760 conn->parse_chunk_header = 0; 761 } 762 } 763 764 if (conn->chunk_length == 0) { 765 /* chunk_length == 0 means we're reading the chunk trailer */ 766 /* ensure that 'str' is flushed before reading the trailer */ 767 if (!conn->parse_chunk_trailer) { 768 if (conn->body_has_data) 769 return DATA_NEED_MORE; 770 conn->parse_chunk_trailer = 1; 771 } 772 ret = rewrite_connection_read_headers(conn, fd); 773 if (ret == DATA_COMPLETED) { 774 conn->body_is_closed = 1; 775 } 776 return ret; 777 } 778 779 /* if we get here, body_length > 0 */ 780 if (conn->chunk_length > MAX_BODY_BUFFER) 781 wanted = MAX_BODY_BUFFER; 782 else 783 wanted = (int)conn->chunk_length; 784 break; 785 786 default: 787 ; 788 } 789 790 /* we don't want more than MAX_BODY_BUFFER bytes in the 791 * buffer we used to pass the body */ 792 current = str->n; 793 avail = MAX_BODY_BUFFER - current; 794 if (avail <= 0) { 795 /* wait for some flush */ 796 conn->body_is_full = 1; 797 D("%s: waiting to flush %d bytes", 798 root->name, current); 799 return DATA_NEED_MORE; 800 } 801 802 if (wanted > avail) 803 wanted = avail; 804 805 ret = proxy_connection_receive(root, fd, wanted); 806 conn->body_has_data = (str->n > 0); 807 conn->body_is_full = (str->n == MAX_BODY_BUFFER); 808 809 if (ret == DATA_ERROR) { 810 if (conn->body_mode == BODY_UNTIL_CLOSE) { 811 /* a disconnection here is normal and signals the 812 * end of the body */ 813 conn->body_total += root->str_recv; 814 D("%s: body completed by close (%lld bytes)", 815 root->name, conn->body_total); 816 conn->body_is_closed = 1; 817 ret = DATA_COMPLETED; 818 } 819 } else { 820 avail = root->str_recv; 821 ret = DATA_NEED_MORE; /* we're not really done yet */ 822 823 switch (conn->body_mode) { 824 case BODY_CHUNKED: 825 conn->chunk_total += avail; 826 conn->chunk_length -= avail; 827 828 if (conn->chunk_length == 0) { 829 D("%s: chunk completed (%lld bytes)", 830 root->name, conn->chunk_length); 831 conn->body_total += conn->chunk_total; 832 conn->chunk_total = 0; 833 conn->chunk_length = -1; 834 } 835 break; 836 837 case BODY_KNOWN_LENGTH: 838 conn->body_length -= avail; 839 conn->body_total += avail; 840 841 if (conn->body_length == 0) { 842 D("%s: body completed (%lld bytes)", 843 root->name, conn->body_total); 844 conn->body_is_closed = 1; 845 ret = DATA_COMPLETED; 846 } 847 break; 848 849 case BODY_UNTIL_CLOSE: 850 conn->body_total += avail; 851 break; 852 853 default: 854 ; 855 } 856 } 857 return ret; 858} 859 860static DataStatus 861rewrite_connection_send_body( RewriteConnection* conn, int fd ) 862{ 863 ProxyConnection* root = conn->root; 864 stralloc_t* str = root->str; 865 DataStatus ret = DATA_NEED_MORE; 866 867 if (conn->body_has_data) { 868 ret = proxy_connection_send(root, fd); 869 if (ret != DATA_ERROR) { 870 int pos = root->str_pos; 871 872 memmove(str->s, str->s+pos, str->n-pos); 873 str->n -= pos; 874 root->str_pos = 0; 875 conn->body_is_full = (str->n == MAX_BODY_BUFFER); 876 conn->body_has_data = (str->n > 0); 877 conn->body_sent += root->str_sent; 878 879 /* ensure that we return DATA_COMPLETED only when 880 * we have sent everything, and there is no more 881 * body pieces to read */ 882 if (ret == DATA_COMPLETED) { 883 if (!conn->body_is_closed || conn->body_has_data) 884 ret = DATA_NEED_MORE; 885 else { 886 D("%s: sent all body (%lld bytes)", 887 root->name, conn->body_sent); 888 } 889 } 890 D("%s: sent closed=%d data=%d n=%d ret=%d", 891 root->name, conn->body_is_closed, 892 conn->body_has_data, str->n, 893 ret); 894 } 895 } 896 return ret; 897} 898 899 900static void 901rewrite_connection_select( ProxyConnection* root, 902 ProxySelect* sel ) 903{ 904 RewriteConnection* conn = (RewriteConnection*)root; 905 int slirp = conn->slirp_fd; 906 int proxy = root->socket; 907 908 switch (conn->state) { 909 case STATE_CONNECTING: 910 case STATE_CREATE_SOCKET_PAIR: 911 /* try to connect to the proxy server */ 912 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 913 break; 914 915 case STATE_REQUEST_FIRST_LINE: 916 case STATE_REQUEST_HEADERS: 917 proxy_select_set( sel, slirp, PROXY_SELECT_READ ); 918 break; 919 920 case STATE_REQUEST_SEND: 921 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 922 break; 923 924 case STATE_REQUEST_BODY: 925 if (!conn->body_is_closed && !conn->body_is_full) 926 proxy_select_set( sel, slirp, PROXY_SELECT_READ ); 927 928 if (conn->body_has_data) 929 proxy_select_set( sel, proxy, PROXY_SELECT_WRITE ); 930 break; 931 932 case STATE_REPLY_FIRST_LINE: 933 case STATE_REPLY_HEADERS: 934 proxy_select_set( sel, proxy, PROXY_SELECT_READ ); 935 break; 936 937 case STATE_REPLY_SEND: 938 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE ); 939 break; 940 941 case STATE_REPLY_BODY: 942 if (conn->body_has_data) 943 proxy_select_set( sel, slirp, PROXY_SELECT_WRITE ); 944 945 if (!conn->body_is_closed && !conn->body_is_full) 946 proxy_select_set( sel, proxy, PROXY_SELECT_READ ); 947 break; 948 default: 949 ; 950 }; 951} 952 953static void 954rewrite_connection_poll( ProxyConnection* root, 955 ProxySelect* sel ) 956{ 957 RewriteConnection* conn = (RewriteConnection*)root; 958 959 int slirp = conn->slirp_fd; 960 int proxy = root->socket; 961 int has_slirp = proxy_select_poll(sel, slirp); 962 int has_proxy = proxy_select_poll(sel, proxy); 963 DataStatus ret = DATA_NEED_MORE; 964 965 switch (conn->state) { 966 case STATE_CONNECTING: 967 if (has_proxy) { 968 PROXY_LOG("%s: connected to proxy", root->name); 969 conn->state = STATE_CREATE_SOCKET_PAIR; 970 } 971 break; 972 973 case STATE_CREATE_SOCKET_PAIR: 974 if (has_proxy) { 975 if (rewrite_connection_create_sockets(conn) < 0) { 976 ret = DATA_ERROR; 977 } else { 978 D("%s: socket pair created", root->name); 979 conn->state = STATE_REQUEST_FIRST_LINE; 980 } 981 } 982 break; 983 984 case STATE_REQUEST_FIRST_LINE: 985 if (has_slirp) { 986 ret = rewrite_connection_read_request(conn); 987 if (ret == DATA_COMPLETED) { 988 PROXY_LOG("%s: request first line ok", root->name); 989 conn->state = STATE_REQUEST_HEADERS; 990 } 991 } 992 break; 993 994 case STATE_REQUEST_HEADERS: 995 if (has_slirp) { 996 ret = rewrite_connection_read_headers(conn, slirp); 997 if (ret == DATA_COMPLETED) { 998 PROXY_LOG("%s: request headers ok", root->name); 999 if (rewrite_connection_rewrite_request(conn) < 0) 1000 ret = DATA_ERROR; 1001 else 1002 conn->state = STATE_REQUEST_SEND; 1003 } 1004 } 1005 break; 1006 1007 case STATE_REQUEST_SEND: 1008 if (has_proxy) { 1009 ret = proxy_connection_send(root, proxy); 1010 if (ret == DATA_COMPLETED) { 1011 if (rewrite_connection_get_body_length(conn, 1) < 0) { 1012 ret = DATA_ERROR; 1013 } else if (conn->body_mode != BODY_NONE) { 1014 PROXY_LOG("%s: request sent, waiting for body", 1015 root->name); 1016 conn->state = STATE_REQUEST_BODY; 1017 } else { 1018 PROXY_LOG("%s: request sent, waiting for reply", 1019 root->name); 1020 conn->state = STATE_REPLY_FIRST_LINE; 1021 } 1022 } 1023 } 1024 break; 1025 1026 case STATE_REQUEST_BODY: 1027 if (has_slirp) { 1028 ret = rewrite_connection_read_body(conn, slirp); 1029 } 1030 if (ret != DATA_ERROR && has_proxy) { 1031 ret = rewrite_connection_send_body(conn, proxy); 1032 if (ret == DATA_COMPLETED) { 1033 PROXY_LOG("%s: request body ok, waiting for reply", 1034 root->name); 1035 conn->state = STATE_REPLY_FIRST_LINE; 1036 } 1037 } 1038 break; 1039 1040 case STATE_REPLY_FIRST_LINE: 1041 if (has_proxy) { 1042 ret = rewrite_connection_read_reply(conn); 1043 if (ret == DATA_COMPLETED) { 1044 PROXY_LOG("%s: reply first line ok", root->name); 1045 conn->state = STATE_REPLY_HEADERS; 1046 } 1047 } 1048 break; 1049 1050 case STATE_REPLY_HEADERS: 1051 if (has_proxy) { 1052 ret = rewrite_connection_read_headers(conn, proxy); 1053 if (ret == DATA_COMPLETED) { 1054 PROXY_LOG("%s: reply headers ok", root->name); 1055 if (rewrite_connection_rewrite_reply(conn) < 0) 1056 ret = DATA_ERROR; 1057 else 1058 conn->state = STATE_REPLY_SEND; 1059 } 1060 } 1061 break; 1062 1063 case STATE_REPLY_SEND: 1064 if (has_slirp) { 1065 ret = proxy_connection_send(conn->root, slirp); 1066 if (ret == DATA_COMPLETED) { 1067 if (rewrite_connection_get_body_length(conn, 0) < 0) { 1068 ret = DATA_ERROR; 1069 } else if (conn->body_mode != BODY_NONE) { 1070 PROXY_LOG("%s: reply sent, waiting for body", 1071 root->name); 1072 conn->state = STATE_REPLY_BODY; 1073 } else { 1074 PROXY_LOG("%s: reply sent, looping to waiting request", 1075 root->name); 1076 conn->state = STATE_REQUEST_FIRST_LINE; 1077 } 1078 } 1079 } 1080 break; 1081 1082 case STATE_REPLY_BODY: 1083 if (has_proxy) { 1084 ret = rewrite_connection_read_body(conn, proxy); 1085 } 1086 if (ret != DATA_ERROR && has_slirp) { 1087 ret = rewrite_connection_send_body(conn, slirp); 1088 if (ret == DATA_COMPLETED) { 1089 if (conn->body_mode == BODY_UNTIL_CLOSE) { 1090 PROXY_LOG("%s: closing connection", root->name); 1091 ret = DATA_ERROR; 1092 } else { 1093 PROXY_LOG("%s: reply body ok, looping to waiting request", 1094 root->name); 1095 conn->state = STATE_REQUEST_FIRST_LINE; 1096 } 1097 } 1098 } 1099 break; 1100 1101 default: 1102 ; 1103 } 1104 if (ret == DATA_ERROR) 1105 proxy_connection_free(root, 0, PROXY_EVENT_NONE); 1106 1107 return; 1108} 1109 1110 1111ProxyConnection* 1112http_rewriter_connect( HttpService* service, 1113 SockAddress* address ) 1114{ 1115 RewriteConnection* conn; 1116 int s; 1117 1118 s = socket_create_inet( SOCKET_STREAM ); 1119 if (s < 0) 1120 return NULL; 1121 1122 conn = qemu_mallocz(sizeof(*conn)); 1123 if (conn == NULL) { 1124 socket_close(s); 1125 return NULL; 1126 } 1127 1128 proxy_connection_init( conn->root, s, address, service->root, 1129 rewrite_connection_free, 1130 rewrite_connection_select, 1131 rewrite_connection_poll ); 1132 1133 if ( rewrite_connection_init( conn ) < 0 ) { 1134 rewrite_connection_free( conn->root ); 1135 return NULL; 1136 } 1137 1138 return conn->root; 1139} 1140