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