1/* Copyright (C) 2007-2008 The Android Open Source Project
2**
3** This software is licensed under the terms of the GNU General Public
4** License version 2, as published by the Free Software Foundation, and
5** may be copied, distributed, and modified under those terms.
6**
7** This program is distributed in the hope that it will be useful,
8** but WITHOUT ANY WARRANTY; without even the implied warranty of
9** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10** GNU General Public License for more details.
11*/
12#include "proxy_http_int.h"
13#include <stdio.h>
14#include <string.h>
15#include "qemu-common.h"
16#include "android/utils/system.h"  /* strsep */
17
18/* this implements a transparent HTTP rewriting proxy
19 *
20 * this is needed because the HTTP spec mandates that
21 * any query made to a proxy uses an absolute URI as
22 * in:
23 *
24 *    GET http://www.example.com/index.html HTTP/1.1
25 *
26 * while the Android browser will think it's talking to
27 * a normal web server and will issue a:
28 *
29 *    GET /index.html HTTP/1.1
30 *    Host: www.example.com
31 *
32 * what we do here is thus the following:
33 *
34 * - read the request header
35 * - rewrite the request's URI to use absolute URI
36 * - send the rewritten header to the proxy
37 * - then read the rest of the request, and tunnel it to the
38 *   proxy as well
39 * - read the answer as-is and send it back to the system
40 *
41 * this sounds all easy, but the rules for computing the
42 * sizes of HTTP Message Bodies makes the implementation
43 * a *bit* funky.
44 */
45
46/* define D_ACTIVE to 1 to dump additionnal debugging
47 * info when -debug-proxy is used. These are only needed
48 * when debugging the proxy code.
49 */
50#define  D_ACTIVE  1
51
52#if D_ACTIVE
53#  define  D(...)   PROXY_LOG(__VA_ARGS__)
54#else
55#  define  D(...)   ((void)0)
56#endif
57
58
59/** *************************************************************
60 **
61 **   HTTP HEADERS
62 **
63 **/
64
65/* HttpHeader is a simple structure used to hold a (key,value)
66 * pair in a linked list.
67 */
68typedef struct HttpHeader {
69    struct HttpHeader*  next;
70    const char*         key;
71    const char*         value;
72} HttpHeader;
73
74static void
75http_header_free( HttpHeader*  h )
76{
77    if (h) {
78        qemu_free((char*)h->value);
79        qemu_free(h);
80    }
81}
82
83static int
84http_header_append( HttpHeader*  h, const char*  value )
85{
86    int    old = strlen(h->value);
87    int    new = strlen(value);
88    char*  s   = realloc((char*)h->value, old+new+1);
89    if (s == NULL)
90        return -1;
91    memcpy(s + old, value, new+1);
92    h->value = (const char*)s;
93    return 0;
94}
95
96static HttpHeader*
97http_header_alloc( const char*  key, const char*  value )
98{
99    int          len = strlen(key)+1;
100    HttpHeader*  h   = malloc(sizeof(*h) + len+1);
101    if (h) {
102        h->next  = NULL;
103        h->key   = (const char*)(h+1);
104        memcpy( (char*)h->key, key, len );
105        h->value = qemu_strdup(value);
106    }
107    return h;
108}
109
110/** *************************************************************
111 **
112 **   HTTP HEADERS LIST
113 **
114 **/
115
116typedef struct {
117    HttpHeader*   first;
118    HttpHeader*   last;
119} HttpHeaderList;
120
121static void
122http_header_list_init( HttpHeaderList*  l )
123{
124    l->first = l->last = NULL;
125}
126
127static void
128http_header_list_done( HttpHeaderList*  l )
129{
130    while (l->first) {
131        HttpHeader*  h = l->first;
132        l->first = h->next;
133        http_header_free(h);
134    }
135    l->last = NULL;
136}
137
138static void
139http_header_list_add( HttpHeaderList*  l,
140                      HttpHeader*      h )
141{
142    if (!l->first) {
143        l->first = h;
144    } else {
145        l->last->next = h;
146    }
147    h->next = NULL;
148    l->last = h;
149}
150
151static const char*
152http_header_list_find( HttpHeaderList*  l,
153                       const char*      key )
154{
155    HttpHeader*  h;
156    for (h = l->first; h; h = h->next)
157        if (!strcasecmp(h->key, key))
158            return h->value;
159
160    return NULL;
161}
162
163/** *************************************************************
164 **
165 **   HTTP REQUEST AND REPLY
166 **
167 **/
168
169typedef enum {
170    HTTP_REQUEST_UNSUPPORTED = 0,
171    HTTP_REQUEST_GET,
172    HTTP_REQUEST_HEAD,
173    HTTP_REQUEST_POST,
174    HTTP_REQUEST_PUT,
175    HTTP_REQUEST_DELETE,
176} HttpRequestType;
177
178/* HttpRequest is used both to store information about a specific
179 * request and the corresponding reply
180 */
181typedef struct {
182    HttpRequestType   req_type;     /* request type */
183    char*             req_method;   /* "GET", "POST", "HEAD", etc... */
184    char*             req_uri;      /* the request URI */
185    char*             req_version;  /* "HTTP/1.0" or "HTTP/1.1" */
186    char*             rep_version;  /* reply version string */
187    int               rep_code;     /* reply code as decimal */
188    char*             rep_readable; /* human-friendly reply/error message */
189    HttpHeaderList    headers[1];   /* headers */
190} HttpRequest;
191
192
193static HttpRequest*
194http_request_alloc( const char*      method,
195                    const char*      uri,
196                    const char*      version )
197{
198    HttpRequest*  r = malloc(sizeof(*r));
199
200    r->req_method   = qemu_strdup(method);
201    r->req_uri      = qemu_strdup(uri);
202    r->req_version  = qemu_strdup(version);
203    r->rep_version  = NULL;
204    r->rep_code     = -1;
205    r->rep_readable = NULL;
206
207    if (!strcmp(method,"GET")) {
208        r->req_type = HTTP_REQUEST_GET;
209    } else if (!strcmp(method,"POST")) {
210        r->req_type = HTTP_REQUEST_POST;
211    } else if (!strcmp(method,"HEAD")) {
212        r->req_type = HTTP_REQUEST_HEAD;
213    } else if (!strcmp(method,"PUT")) {
214        r->req_type = HTTP_REQUEST_PUT;
215    } else if (!strcmp(method,"DELETE")) {
216        r->req_type = HTTP_REQUEST_DELETE;
217    } else
218        r->req_type = HTTP_REQUEST_UNSUPPORTED;
219
220    http_header_list_init(r->headers);
221    return r;
222}
223
224static void
225http_request_replace_uri( HttpRequest*  r,
226                          const char*   uri )
227{
228    const char*  old = r->req_uri;
229    r->req_uri = qemu_strdup(uri);
230    qemu_free((char*)old);
231}
232
233static void
234http_request_free( HttpRequest*  r )
235{
236    if (r) {
237        http_header_list_done(r->headers);
238
239        qemu_free(r->req_method);
240        qemu_free(r->req_uri);
241        qemu_free(r->req_version);
242        qemu_free(r->rep_version);
243        qemu_free(r->rep_readable);
244        qemu_free(r);
245    }
246}
247
248static char*
249http_request_find_header( HttpRequest*  r,
250                          const char*   key )
251{
252    return (char*)http_header_list_find(r->headers, key);
253}
254
255
256static int
257http_request_add_header( HttpRequest*  r,
258                         const char*   key,
259                         const char*   value )
260{
261    HttpHeader*  h = http_header_alloc(key,value);
262    if (h) {
263        http_header_list_add(r->headers, h);
264        return 0;
265    }
266    return -1;
267}
268
269static int
270http_request_add_to_last_header( HttpRequest*  r,
271                                 const char*   line )
272{
273    if (r->headers->last) {
274        return http_header_append( r->headers->last, line );
275    } else {
276        return -1;
277    }
278}
279
280static int
281http_request_set_reply( HttpRequest*  r,
282                        const char*   version,
283                        const char*   code,
284                        const char*   readable )
285{
286    if (strcmp(version,"HTTP/1.0") && strcmp(version,"HTTP/1.1")) {
287        PROXY_LOG("%s: bad reply protocol: %s", __FUNCTION__, version);
288        return -1;
289    }
290    r->rep_code = atoi(code);
291    if (r->rep_code == 0) {
292        PROXY_LOG("%s: bad reply code: %d", __FUNCTION__, code);
293        return -1;
294    }
295
296    r->rep_version  = qemu_strdup(version);
297    r->rep_readable = qemu_strdup(readable);
298
299    /* reset the list of headers */
300    http_header_list_done(r->headers);
301    return 0;
302}
303
304/** *************************************************************
305 **
306 **   REWRITER CONNECTION
307 **
308 **/
309
310typedef enum {
311    STATE_CONNECTING = 0,
312    STATE_CREATE_SOCKET_PAIR,
313    STATE_REQUEST_FIRST_LINE,
314    STATE_REQUEST_HEADERS,
315    STATE_REQUEST_SEND,
316    STATE_REQUEST_BODY,
317    STATE_REPLY_FIRST_LINE,
318    STATE_REPLY_HEADERS,
319    STATE_REPLY_SEND,
320    STATE_REPLY_BODY,
321} ConnectionState;
322
323/* root->socket is connected to the proxy server. while
324 * slirp_fd is connected to the slirp code through a
325 * socket_pair() we created for this specific purpose.
326 */
327
328typedef enum {
329    BODY_NONE = 0,
330    BODY_KNOWN_LENGTH,
331    BODY_UNTIL_CLOSE,
332    BODY_CHUNKED,
333    BODY_MODE_MAX
334} BodyMode;
335
336static const char* const  body_mode_str[BODY_MODE_MAX] = {
337    "NONE", "KNOWN_LENGTH", "UNTIL_CLOSE", "CHUNKED"
338};
339
340enum {
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
347typedef 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
367static void
368rewrite_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
382static int
383rewrite_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
407static int
408rewrite_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 */
428static DataStatus
429rewrite_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
474static DataStatus
475rewrite_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
513static DataStatus
514rewrite_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
562static int
563rewrite_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
598static int
599rewrite_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
617static int
618rewrite_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
702static DataStatus
703rewrite_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
899static DataStatus
900rewrite_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
939static void
940rewrite_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
992static void
993rewrite_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
1150ProxyConnection*
1151http_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