Home | History | Annotate | Download | only in proxy
      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                 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 
    860 static DataStatus
    861 rewrite_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 
    900 static void
    901 rewrite_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 
    953 static void
    954 rewrite_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 
   1111 ProxyConnection*
   1112 http_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