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