proxy_http_rewriter.c revision c27f813900a3c114562efbb8df1065e94766fc48
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
65typedef struct HttpHeader {
66    struct HttpHeader*  next;
67    const char*         key;
68    const char*         value;
69} HttpHeader;
70
71static void
72http_header_free( HttpHeader*  h )
73{
74    if (h) {
75        qemu_free((char*)h->value);
76        qemu_free(h);
77    }
78}
79
80static int
81http_header_append( HttpHeader*  h, const char*  value )
82{
83    int    old = strlen(h->value);
84    int    new = strlen(value);
85    char*  s   = realloc((char*)h->value, old+new+1);
86    if (s == NULL)
87        return -1;
88    memcpy(s + old, value, new+1);
89    h->value = (const char*)s;
90    return 0;
91}
92
93static HttpHeader*
94http_header_alloc( const char*  key, const char*  value )
95{
96    int          len = strlen(key)+1;
97    HttpHeader*  h   = malloc(sizeof(*h) + len+1);
98    if (h) {
99        h->next  = NULL;
100        h->key   = (const char*)(h+1);
101        memcpy( (char*)h->key, key, len );
102        h->value = qemu_strdup(value);
103    }
104    return h;
105}
106
107typedef struct {
108    HttpHeader*   first;
109    HttpHeader*   last;
110} HttpHeaderList;
111
112static void
113http_header_list_init( HttpHeaderList*  l )
114{
115    l->first = l->last = NULL;
116}
117
118static void
119http_header_list_done( HttpHeaderList*  l )
120{
121    while (l->first) {
122        HttpHeader*  h = l->first;
123        l->first = h->next;
124        http_header_free(h);
125    }
126    l->last = NULL;
127}
128
129static void
130http_header_list_add( HttpHeaderList*  l,
131                      HttpHeader*      h )
132{
133    if (!l->first) {
134        l->first = h;
135    } else {
136        l->last->next = h;
137    }
138    h->next = NULL;
139    l->last = h;
140}
141
142static const char*
143http_header_list_find( HttpHeaderList*  l,
144                       const char*      key )
145{
146    HttpHeader*  h;
147    for (h = l->first; h; h = h->next)
148        if (!strcasecmp(h->key, key))
149            return h->value;
150
151    return NULL;
152}
153
154/** *************************************************************
155 **
156 **   HTTP REQUEST AND REPLY
157 **
158 **/
159
160typedef enum {
161    HTTP_REQUEST_UNSUPPORTED = 0,
162    HTTP_REQUEST_GET,
163    HTTP_REQUEST_HEAD,
164    HTTP_REQUEST_POST,
165    HTTP_REQUEST_PUT,
166    HTTP_REQUEST_DELETE,
167} HttpRequestType;
168
169typedef struct {
170    HttpRequestType   req_type;
171    char*             req_method;
172    char*             req_uri;
173    char*             req_version;
174    char*             rep_version;
175    int               rep_code;
176    char*             rep_readable;
177    HttpHeaderList    headers[1];
178} HttpRequest;
179
180
181static HttpRequest*
182http_request_alloc( const char*      method,
183                    const char*      uri,
184                    const char*      version )
185{
186    HttpRequest*  r = malloc(sizeof(*r));
187
188    r->req_method   = qemu_strdup(method);
189    r->req_uri      = qemu_strdup(uri);
190    r->req_version  = qemu_strdup(version);
191    r->rep_version  = NULL;
192    r->rep_code     = -1;
193    r->rep_readable = NULL;
194
195    if (!strcmp(method,"GET")) {
196        r->req_type = HTTP_REQUEST_GET;
197    } else if (!strcmp(method,"POST")) {
198        r->req_type = HTTP_REQUEST_POST;
199    } else if (!strcmp(method,"HEAD")) {
200        r->req_type = HTTP_REQUEST_HEAD;
201    } else if (!strcmp(method,"PUT")) {
202        r->req_type = HTTP_REQUEST_PUT;
203    } else if (!strcmp(method,"DELETE")) {
204        r->req_type = HTTP_REQUEST_DELETE;
205    } else
206        r->req_type = HTTP_REQUEST_UNSUPPORTED;
207
208    http_header_list_init(r->headers);
209    return r;
210}
211
212static void
213http_request_replace_uri( HttpRequest*  r,
214                          const char*   uri )
215{
216    const char*  old = r->req_uri;
217    r->req_uri = qemu_strdup(uri);
218    qemu_free((char*)old);
219}
220
221static void
222http_request_free( HttpRequest*  r )
223{
224    if (r) {
225        http_header_list_done(r->headers);
226
227        qemu_free(r->req_method);
228        qemu_free(r->req_uri);
229        qemu_free(r->req_version);
230        qemu_free(r->rep_version);
231        qemu_free(r->rep_readable);
232        qemu_free(r);
233    }
234}
235
236static char*
237http_request_find_header( HttpRequest*  r,
238                          const char*   key )
239{
240    return (char*)http_header_list_find(r->headers, key);
241}
242
243
244static int
245http_request_add_header( HttpRequest*  r,
246                         const char*   key,
247                         const char*   value )
248{
249    HttpHeader*  h = http_header_alloc(key,value);
250    if (h) {
251        http_header_list_add(r->headers, h);
252        return 0;
253    }
254    return -1;
255}
256
257static int
258http_request_add_to_last_header( HttpRequest*  r,
259                                 const char*   line )
260{
261    if (r->headers->last) {
262        return http_header_append( r->headers->last, line );
263    } else {
264        return -1;
265    }
266}
267
268static int
269http_request_set_reply( HttpRequest*  r,
270                        const char*   version,
271                        const char*   code,
272                        const char*   readable )
273{
274    if (strcmp(version,"HTTP/1.0") && strcmp(version,"HTTP/1.1")) {
275        PROXY_LOG("%s: bad reply protocol: %s", __FUNCTION__, version);
276        return -1;
277    }
278    r->rep_code = atoi(code);
279    if (r->rep_code == 0) {
280        PROXY_LOG("%s: bad reply code: %d", __FUNCTION__, code);
281        return -1;
282    }
283
284    r->rep_version  = qemu_strdup(version);
285    r->rep_readable = qemu_strdup(readable);
286
287    /* reset the list of headers */
288    http_header_list_done(r->headers);
289    return 0;
290}
291
292/** *************************************************************
293 **
294 **   REWRITER CONNECTION
295 **
296 **/
297
298typedef enum {
299    STATE_CONNECTING = 0,
300    STATE_CREATE_SOCKET_PAIR,
301    STATE_REQUEST_FIRST_LINE,
302    STATE_REQUEST_HEADERS,
303    STATE_REQUEST_SEND,
304    STATE_REQUEST_BODY,
305    STATE_REPLY_FIRST_LINE,
306    STATE_REPLY_HEADERS,
307    STATE_REPLY_SEND,
308    STATE_REPLY_BODY,
309} ConnectionState;
310
311/* root->socket is connected to the proxy server. while
312 * slirp_fd is connected to the slirp code through a
313 * socket_pair() we created for this specific purpose.
314 */
315
316typedef enum {
317    BODY_NONE = 0,
318    BODY_KNOWN_LENGTH,
319    BODY_UNTIL_CLOSE,
320    BODY_CHUNKED,
321    BODY_MODE_MAX
322} BodyMode;
323
324static const char* const  body_mode_str[BODY_MODE_MAX] = {
325    "NONE", "KNOWN_LENGTH", "UNTIL_CLOSE", "CHUNKED"
326};
327
328typedef struct {
329    ProxyConnection   root[1];
330    int               slirp_fd;
331    ConnectionState   state;
332    HttpRequest*      request;
333    BodyMode          body_mode;
334    int64_t           body_length;
335    int64_t           body_total;
336    int64_t           body_sent;
337    int64_t           chunk_length;
338    int64_t           chunk_total;
339    char              body_has_data;
340    char              body_is_full;
341    char              body_is_closed;
342    char              parse_chunk_header;
343    char              parse_chunk_trailer;
344} RewriteConnection;
345
346
347static void
348rewrite_connection_free( ProxyConnection*  root )
349{
350    RewriteConnection*  conn = (RewriteConnection*)root;
351
352    if (conn->slirp_fd >= 0) {
353        socket_close(conn->slirp_fd);
354        conn->slirp_fd = -1;
355    }
356    http_request_free(conn->request);
357    proxy_connection_done(root);
358    qemu_free(conn);
359}
360
361
362static int
363rewrite_connection_init( RewriteConnection*   conn )
364{
365    HttpService*      service = (HttpService*) conn->root->service;
366    ProxyConnection*  root    = conn->root;
367
368    conn->slirp_fd = -1;
369    conn->state    = STATE_CONNECTING;
370
371    if (socket_connect( root->socket, &service->server_addr ) < 0) {
372        if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
373            PROXY_LOG("%s: connecting", conn->root->name);
374        }
375        else {
376            PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str);
377            return -1;
378        }
379    }
380    else {
381        PROXY_LOG("%s: immediate connection", root->name);
382        conn->state = STATE_CREATE_SOCKET_PAIR;
383    }
384    return 0;
385}
386
387static int
388rewrite_connection_create_sockets( RewriteConnection*  conn )
389{
390    /* immediate connection to the proxy. now create a socket
391        * pair and send a 'success' event to slirp */
392    int               slirp_1;
393    ProxyConnection*  root = conn->root;
394
395    if (socket_pair( &slirp_1, &conn->slirp_fd ) < 0) {
396        PROXY_LOG("%s: coult not create socket pair: %s",
397                    root->name, errno_str);
398        return -1;
399    }
400
401    root->ev_func( root->ev_opaque, slirp_1, PROXY_EVENT_CONNECTED );
402    conn->state = STATE_REQUEST_FIRST_LINE;
403    return 0;
404}
405
406
407/* read the first line of a given HTTP request. returns -1/0/+1 */
408static DataStatus
409rewrite_connection_read_request( RewriteConnection*  conn )
410{
411    ProxyConnection*  root = conn->root;
412    DataStatus        ret;
413
414    ret = proxy_connection_receive_line(root, conn->slirp_fd);
415    if (ret == DATA_COMPLETED) {
416        /* now parse the first line to see if we can handle it */
417        char*  line   = root->str->s;
418        char*  method;
419        char*  uri;
420        char*  version;
421        char*  p = line;
422
423        method = strsep(&p, " ");
424        if (p == NULL) {
425            PROXY_LOG("%s: can't parse method in '%'",
426                      root->name, line);
427            return DATA_ERROR;
428        }
429        uri = strsep(&p, " ");
430        if (p == NULL) {
431            PROXY_LOG( "%s: can't parse URI in '%s'",
432                       root->name, line);
433            return DATA_ERROR;
434        }
435        version = strsep(&p, " ");
436        if (p != NULL) {
437            PROXY_LOG( "%s: extra data after version in '%s'",
438                       root->name, line);
439            return DATA_ERROR;
440        }
441        if (conn->request)
442            http_request_free(conn->request);
443
444        conn->request = http_request_alloc( method, uri, version );
445        if (!conn->request)
446            return DATA_ERROR;
447
448        proxy_connection_rewind(root);
449    }
450    return ret;
451}
452
453
454static DataStatus
455rewrite_connection_read_reply( RewriteConnection*  conn )
456{
457    ProxyConnection*  root = conn->root;
458    DataStatus        ret;
459
460    ret = proxy_connection_receive_line( root, root->socket );
461    if (ret == DATA_COMPLETED) {
462        HttpRequest*  request = conn->request;
463
464        char*  line = stralloc_cstr( root->str );
465        char*  p = line;
466        char*  protocol;
467        char*  number;
468        char*  readable;
469
470        protocol = strsep(&p, " ");
471        if (p == NULL) {
472            PROXY_LOG("%s: can't parse response protocol: '%s'",
473                      root->name, line);
474            return DATA_ERROR;
475        }
476        number = strsep(&p, " ");
477        if (p == NULL) {
478            PROXY_LOG("%s: can't parse response number: '%s'",
479                      root->name, line);
480            return DATA_ERROR;
481        }
482        readable = p;
483
484        if (http_request_set_reply(request, protocol, number, readable) < 0)
485            return DATA_ERROR;
486
487        proxy_connection_rewind(root);
488    }
489    return ret;
490}
491
492
493static DataStatus
494rewrite_connection_read_headers( RewriteConnection*   conn,
495                                 int                  fd )
496{
497    int               ret;
498    ProxyConnection*  root = conn->root;
499
500    for (;;) {
501        char*        line;
502        stralloc_t*  str = root->str;
503
504        ret = proxy_connection_receive_line(root, fd);
505        if (ret != DATA_COMPLETED)
506            break;
507
508        str->n = 0;
509        line   = str->s;
510
511        if (line[0] == 0) {
512            /* an empty line means the end of headers */
513            ret = 1;
514            break;
515        }
516
517        /* it this a continuation ? */
518        if (line[0] == ' ' || line[0] == '\t') {
519            ret = http_request_add_to_last_header( conn->request, line );
520        }
521        else {
522            char*  key;
523            char*  value;
524
525            value = line;
526            key   = strsep(&value, ":");
527            if (value == NULL) {
528                PROXY_LOG("%s: can't parse header '%s'", root->name, line);
529                ret = -1;
530                break;
531            }
532            value += strspn(value, " ");
533            if (http_request_add_header(conn->request, key, value) < 0)
534                ret = -1;
535        }
536        if (ret == DATA_ERROR)
537            break;
538    }
539    return ret;
540}
541
542static int
543rewrite_connection_rewrite_request( RewriteConnection*  conn )
544{
545    ProxyConnection* root    = conn->root;
546    HttpService*     service = (HttpService*) root->service;
547    HttpRequest*     r       = conn->request;
548    stralloc_t*      str     = root->str;
549    HttpHeader*      h;
550
551    proxy_connection_rewind(conn->root);
552
553    /* only rewrite the URI if it is not absolute */
554    if (r->req_uri[0] == '/') {
555        char*  host = http_request_find_header(r, "Host");
556        if (host == NULL) {
557            PROXY_LOG("%s: uh oh, not Host: in request ?", root->name);
558        } else {
559            /* now create new URI */
560            stralloc_add_str(str, "http://");
561            stralloc_add_str(str, host);
562            stralloc_add_str(str, r->req_uri);
563            http_request_replace_uri(r, stralloc_cstr(str));
564            proxy_connection_rewind(root);
565        }
566    }
567
568    stralloc_format( str, "%s %s %s\r\n", r->req_method, r->req_uri, r->req_version );
569    for (h = r->headers->first; h; h = h->next) {
570        stralloc_add_format( str, "%s: %s\r\n", h->key, h->value );
571    }
572    /* add the service's footer - includes final \r\n */
573    stralloc_add_bytes( str, service->footer, service->footer_len );
574
575    return 0;
576}
577
578static int
579rewrite_connection_rewrite_reply( RewriteConnection*  conn )
580{
581    HttpRequest*     r    = conn->request;
582    ProxyConnection* root = conn->root;
583    stralloc_t*      str  = root->str;
584    HttpHeader*      h;
585
586    proxy_connection_rewind(root);
587    stralloc_format(str, "%s %d %s\r\n", r->rep_version, r->rep_code, r->rep_readable);
588    for (h = r->headers->first; h; h = h->next) {
589        stralloc_add_format(str, "%s: %s\r\n", h->key, h->value);
590    }
591    stralloc_add_str(str, "\r\n");
592
593    return 0;
594}
595
596
597static int
598rewrite_connection_get_body_length( RewriteConnection*  conn,
599                                    int                 is_request )
600{
601    HttpRequest*      r    = conn->request;
602    ProxyConnection*  root = conn->root;
603    char*             content_length;
604    char*             transfer_encoding;
605
606    conn->body_mode      = BODY_NONE;
607    conn->body_length    = 0;
608    conn->body_total     = 0;
609    conn->body_sent      = 0;
610    conn->body_is_closed = 0;
611    conn->body_is_full   = 0;
612    conn->body_has_data  = 0;
613
614    proxy_connection_rewind(root);
615
616    if (is_request) {
617        /* only POST and PUT should have a body */
618        if (r->req_type != HTTP_REQUEST_POST &&
619            r->req_type != HTTP_REQUEST_PUT)
620        {
621            return 0;
622        }
623    } else {
624        /* HTTP 1.1 Section 4.3 Message Body states that HEAD requests must not have
625        * a message body, as well as any 1xx, 204 and 304 replies */
626        if (r->req_type == HTTP_REQUEST_HEAD || r->rep_code/100 == 1 ||
627            r->rep_code == 204 || r->rep_code == 304)
628            return 0;
629    }
630
631    content_length = http_request_find_header(r, "Content-Length");
632    if (content_length != NULL) {
633        char*    end;
634        int64_t  body_len = strtoll( content_length, &end, 10 );
635        if (*end != '\0' || *content_length == '\0' || body_len < 0) {
636            PROXY_LOG("%s: bad content length: %s", root->name, content_length);
637            return DATA_ERROR;
638        }
639        if (body_len > 0) {
640            conn->body_mode   = BODY_KNOWN_LENGTH;
641            conn->body_length = body_len;
642        }
643    } else {
644        char*  connection = http_request_find_header(r, "Proxy-Connection");
645
646        if (!connection)
647            connection = http_request_find_header(r, "Connection");
648
649        if (!connection || strcasecmp(connection, "Close")) {
650            /* hum, we can't support this at all */
651            PROXY_LOG("%s: can't determine content length, and client wants"
652                        " to keep connection opened",
653                        root->name);
654            return -1;
655        }
656        /* a negative value means that the data ends when the client
657         * disconnects the connection.
658         */
659        conn->body_mode = BODY_UNTIL_CLOSE;
660    }
661    transfer_encoding = http_request_find_header(r, "Transfer-Encoding");
662    if (transfer_encoding && !strcasecmp(transfer_encoding, "Chunked")) {
663        conn->body_mode           = BODY_CHUNKED;
664        conn->parse_chunk_header  = 0;
665        conn->parse_chunk_trailer = 0;
666        conn->chunk_length        = -1;
667        conn->chunk_total         = 0;
668    }
669    D("%s: body_length=%lld body_mode=%s",
670      root->name, conn->body_length,
671      body_mode_str[conn->body_mode]);
672
673    proxy_connection_rewind(root);
674    return 0;
675}
676
677#define  MAX_BODY_BUFFER  65536
678
679static DataStatus
680rewrite_connection_read_body( RewriteConnection*  conn, int  fd )
681{
682    ProxyConnection*  root   = conn->root;
683    stralloc_t*       str    = root->str;
684    int               wanted = 0, current, avail;
685    DataStatus        ret;
686
687    if (conn->body_is_closed) {
688        return DATA_NEED_MORE;
689    }
690
691    /* first, determine how many bytes we want to read. */
692    switch (conn->body_mode) {
693    case BODY_NONE:
694        D("%s: INTERNAL ERROR: SHOULDN'T BE THERE", root->name);
695        return DATA_COMPLETED;
696
697    case BODY_KNOWN_LENGTH:
698        {
699            if (conn->body_length == 0)
700                return DATA_COMPLETED;
701
702            if (conn->body_length > MAX_BODY_BUFFER)
703                wanted = MAX_BODY_BUFFER;
704            else
705                wanted = (int)conn->body_length;
706        }
707        break;
708
709    case BODY_UNTIL_CLOSE:
710        wanted = MAX_BODY_BUFFER;
711        break;
712
713    case BODY_CHUNKED:
714        if (conn->chunk_length < 0) {
715            /* chunk_length < 0 means we need to read a chunk header */
716            /* ensure that 'str' is flushed before doing this */
717            if (!conn->parse_chunk_header) {
718                if (conn->body_has_data)
719                    return DATA_NEED_MORE;
720                D("%s: waiting chunk header", root->name);
721                conn->parse_chunk_header = 1;
722            }
723            ret = proxy_connection_receive_line(root, fd);
724            if (ret == DATA_COMPLETED) {
725                char*      line = str->s;
726                char*      end;
727                long long  length;
728
729                length = strtoll(line, &end, 16);
730                if (line[0] == ' ' || (end[0] != '\0' && end[0] != ';')) {
731                    PROXY_LOG("%s: invalid chunk header: %s",
732                              root->name, line);
733                    return DATA_ERROR;
734                }
735                if (length < 0) {
736                    PROXY_LOG("%s: invalid chunk length %lld",
737                              root->name, length);
738                    return DATA_ERROR;
739                }
740                conn->chunk_length = length;
741                conn->chunk_total  = 0;
742                if (length == 0) {
743                    /* the last chunk, no we need to add the trailer */
744                    conn->parse_chunk_trailer = 0;
745                }
746                conn->parse_chunk_header = 0;
747            }
748        }
749
750        if (conn->chunk_length == 0) {
751            /* chunk_length == 0 means we're reading the chunk trailer */
752            /* ensure that 'str' is flushed before reading the trailer */
753            if (!conn->parse_chunk_trailer) {
754                if (conn->body_has_data)
755                    return DATA_NEED_MORE;
756                conn->parse_chunk_trailer = 1;
757            }
758            ret = rewrite_connection_read_headers(conn, fd);
759            if (ret == DATA_COMPLETED) {
760                conn->body_is_closed = 1;
761            }
762            return ret;
763        }
764
765        /* if we get here, body_length > 0 */
766        if (conn->chunk_length > MAX_BODY_BUFFER)
767            wanted = MAX_BODY_BUFFER;
768        else
769            wanted = (int)conn->chunk_length;
770        break;
771
772    default:
773        ;
774    }
775
776    /* we don't want more than MAX_BODY_BUFFER bytes in the
777     * buffer we used to pass the body */
778    current = str->n;
779    avail   = MAX_BODY_BUFFER - current;
780    if (avail <= 0) {
781        /* wait for some flush */
782        conn->body_is_full = 1;
783        D("%s: waiting to flush %d bytes",
784          root->name, current);
785        return DATA_NEED_MORE;
786    }
787
788    if (wanted > avail)
789        wanted = avail;
790
791    ret = proxy_connection_receive(root, fd, wanted);
792    conn->body_has_data = (str->n > 0);
793    conn->body_is_full  = (str->n == MAX_BODY_BUFFER);
794
795    if (ret == DATA_ERROR) {
796        if (conn->body_mode == BODY_UNTIL_CLOSE) {
797            /* a disconnection here is normal and signals the
798             * end of the body */
799            conn->body_total    += root->str_recv;
800            D("%s: body completed by close (%lld bytes)",
801                root->name, conn->body_total);
802            conn->body_is_closed = 1;
803            ret = DATA_COMPLETED;
804        }
805    } else {
806        avail = root->str_recv;
807        ret   = DATA_NEED_MORE;  /* we're not really done yet */
808
809        switch (conn->body_mode) {
810        case BODY_CHUNKED:
811            conn->chunk_total  += avail;
812            conn->chunk_length -= avail;
813
814            if (conn->chunk_length == 0) {
815                D("%s: chunk completed (%lld bytes)",
816                    root->name, conn->chunk_length);
817                conn->body_total  += conn->chunk_total;
818                conn->chunk_total  = 0;
819                conn->chunk_length = -1;
820            }
821            break;
822
823        case BODY_KNOWN_LENGTH:
824            conn->body_length -= avail;
825            conn->body_total  += avail;
826
827            if (conn->body_length == 0) {
828                D("%s: body completed (%lld bytes)",
829                    root->name, conn->body_total);
830                conn->body_is_closed = 1;
831                ret = DATA_COMPLETED;
832            }
833            break;
834
835        case BODY_UNTIL_CLOSE:
836            conn->body_total += avail;
837            break;
838
839        default:
840            ;
841        }
842    }
843    return ret;
844}
845
846static DataStatus
847rewrite_connection_send_body( RewriteConnection*  conn, int  fd )
848{
849    ProxyConnection*  root   = conn->root;
850    stralloc_t*       str    = root->str;
851    DataStatus        ret    = DATA_NEED_MORE;
852
853    if (conn->body_has_data) {
854        ret = proxy_connection_send(root, fd);
855        if (ret != DATA_ERROR) {
856            int  pos = root->str_pos;
857
858            memmove(str->s, str->s+pos, str->n-pos);
859            str->n         -= pos;
860            root->str_pos   = 0;
861            conn->body_is_full  = (str->n == MAX_BODY_BUFFER);
862            conn->body_has_data = (str->n > 0);
863            conn->body_sent    += root->str_sent;
864
865            /* ensure that we return DATA_COMPLETED only when
866            * we have sent everything, and there is no more
867            * body pieces to read */
868            if (ret == DATA_COMPLETED) {
869                if (!conn->body_is_closed || conn->body_has_data)
870                    ret = DATA_NEED_MORE;
871                else {
872                    D("%s: sent all body (%lld bytes)",
873                        root->name, conn->body_sent);
874                }
875            }
876            D("%s: sent closed=%d data=%d n=%d ret=%d",
877                root->name, conn->body_is_closed,
878                conn->body_has_data, str->n,
879                ret);
880        }
881    }
882    return ret;
883}
884
885
886static void
887rewrite_connection_select( ProxyConnection*  root,
888                           ProxySelect*      sel )
889{
890    RewriteConnection*  conn = (RewriteConnection*)root;
891    int  slirp = conn->slirp_fd;
892    int  proxy = root->socket;
893
894    switch (conn->state) {
895        case STATE_CONNECTING:
896        case STATE_CREATE_SOCKET_PAIR:
897            /* try to connect to the proxy server */
898            proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
899            break;
900
901        case STATE_REQUEST_FIRST_LINE:
902        case STATE_REQUEST_HEADERS:
903            proxy_select_set( sel, slirp, PROXY_SELECT_READ );
904            break;
905
906        case STATE_REQUEST_SEND:
907            proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
908            break;
909
910        case STATE_REQUEST_BODY:
911            if (!conn->body_is_closed && !conn->body_is_full)
912                proxy_select_set( sel, slirp, PROXY_SELECT_READ );
913
914            if (conn->body_has_data)
915                proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
916            break;
917
918        case STATE_REPLY_FIRST_LINE:
919        case STATE_REPLY_HEADERS:
920            proxy_select_set( sel, proxy, PROXY_SELECT_READ );
921            break;
922
923        case STATE_REPLY_SEND:
924            proxy_select_set( sel, slirp, PROXY_SELECT_WRITE );
925            break;
926
927        case STATE_REPLY_BODY:
928            if (conn->body_has_data)
929                proxy_select_set( sel, slirp, PROXY_SELECT_WRITE );
930
931            if (!conn->body_is_closed && !conn->body_is_full)
932                proxy_select_set( sel, proxy, PROXY_SELECT_READ );
933            break;
934        default:
935            ;
936    };
937}
938
939static void
940rewrite_connection_poll( ProxyConnection*  root,
941                         ProxySelect*      sel )
942{
943    RewriteConnection*  conn = (RewriteConnection*)root;
944
945    int         slirp     = conn->slirp_fd;
946    int         proxy     = root->socket;
947    int         has_slirp = proxy_select_poll(sel, slirp);
948    int         has_proxy = proxy_select_poll(sel, proxy);
949    DataStatus  ret       = DATA_NEED_MORE;
950
951    switch (conn->state) {
952        case STATE_CONNECTING:
953            if (has_proxy) {
954                PROXY_LOG("%s: connected to proxy", root->name);
955                conn->state = STATE_CREATE_SOCKET_PAIR;
956            }
957            break;
958
959        case STATE_CREATE_SOCKET_PAIR:
960            if (has_proxy) {
961                if (rewrite_connection_create_sockets(conn) < 0) {
962                    ret = DATA_ERROR;
963                } else {
964                    D("%s: socket pair created", root->name);
965                    conn->state = STATE_REQUEST_FIRST_LINE;
966                }
967            }
968            break;
969
970        case STATE_REQUEST_FIRST_LINE:
971            if (has_slirp) {
972                ret = rewrite_connection_read_request(conn);
973                if (ret == DATA_COMPLETED) {
974                    PROXY_LOG("%s: request first line ok", root->name);
975                    conn->state = STATE_REQUEST_HEADERS;
976                }
977            }
978            break;
979
980        case STATE_REQUEST_HEADERS:
981            if (has_slirp) {
982                ret = rewrite_connection_read_headers(conn, slirp);
983                if (ret == DATA_COMPLETED) {
984                    PROXY_LOG("%s: request headers ok", root->name);
985                    if (rewrite_connection_rewrite_request(conn) < 0)
986                        ret = DATA_ERROR;
987                    else
988                        conn->state = STATE_REQUEST_SEND;
989                }
990            }
991            break;
992
993        case STATE_REQUEST_SEND:
994            if (has_proxy) {
995                ret = proxy_connection_send(root, proxy);
996                if (ret == DATA_COMPLETED) {
997                    if (rewrite_connection_get_body_length(conn, 1) < 0) {
998                        ret = DATA_ERROR;
999                    } else if (conn->body_mode != BODY_NONE) {
1000                        PROXY_LOG("%s: request sent, waiting for body",
1001                                   root->name);
1002                        conn->state = STATE_REQUEST_BODY;
1003                    } else {
1004                        PROXY_LOG("%s: request sent, waiting for reply",
1005                                  root->name);
1006                        conn->state = STATE_REPLY_FIRST_LINE;
1007                    }
1008                }
1009            }
1010            break;
1011
1012        case STATE_REQUEST_BODY:
1013            if (has_slirp) {
1014                ret = rewrite_connection_read_body(conn, slirp);
1015            }
1016            if (ret != DATA_ERROR && has_proxy) {
1017                ret = rewrite_connection_send_body(conn, proxy);
1018                if (ret == DATA_COMPLETED) {
1019                    PROXY_LOG("%s: request body ok, waiting for reply",
1020                              root->name);
1021                    conn->state = STATE_REPLY_FIRST_LINE;
1022                }
1023            }
1024            break;
1025
1026        case STATE_REPLY_FIRST_LINE:
1027            if (has_proxy) {
1028                ret = rewrite_connection_read_reply(conn);
1029                if (ret == DATA_COMPLETED) {
1030                    PROXY_LOG("%s: reply first line ok", root->name);
1031                    conn->state = STATE_REPLY_HEADERS;
1032                }
1033            }
1034            break;
1035
1036        case STATE_REPLY_HEADERS:
1037            if (has_proxy) {
1038                ret = rewrite_connection_read_headers(conn, proxy);
1039                if (ret == DATA_COMPLETED) {
1040                    PROXY_LOG("%s: reply headers ok", root->name);
1041                    if (rewrite_connection_rewrite_reply(conn) < 0)
1042                        ret = DATA_ERROR;
1043                    else
1044                        conn->state = STATE_REPLY_SEND;
1045                }
1046            }
1047            break;
1048
1049        case STATE_REPLY_SEND:
1050            if (has_slirp) {
1051                ret = proxy_connection_send(conn->root, slirp);
1052                if (ret == DATA_COMPLETED) {
1053                    if (rewrite_connection_get_body_length(conn, 0) < 0) {
1054                        ret = DATA_ERROR;
1055                    } else if (conn->body_mode != BODY_NONE) {
1056                        PROXY_LOG("%s: reply sent, waiting for body",
1057                                  root->name);
1058                        conn->state = STATE_REPLY_BODY;
1059                    } else {
1060                        PROXY_LOG("%s: reply sent, looping to waiting request",
1061                                  root->name);
1062                        conn->state = STATE_REQUEST_FIRST_LINE;
1063                    }
1064                }
1065            }
1066            break;
1067
1068        case STATE_REPLY_BODY:
1069            if (has_proxy) {
1070                ret = rewrite_connection_read_body(conn, proxy);
1071            }
1072            if (ret != DATA_ERROR && has_slirp) {
1073                ret = rewrite_connection_send_body(conn, slirp);
1074                if (ret == DATA_COMPLETED) {
1075                    if (conn->body_mode == BODY_UNTIL_CLOSE) {
1076                        PROXY_LOG("%s: closing connection", root->name);
1077                        ret = DATA_ERROR;
1078                    } else {
1079                        PROXY_LOG("%s: reply body ok, looping to waiting request",
1080                                root->name);
1081                        conn->state = STATE_REQUEST_FIRST_LINE;
1082                    }
1083                }
1084            }
1085            break;
1086
1087        default:
1088            ;
1089    }
1090    if (ret == DATA_ERROR)
1091        proxy_connection_free(root, 0, PROXY_EVENT_NONE);
1092
1093    return;
1094}
1095
1096
1097ProxyConnection*
1098http_rewriter_connect( HttpService*  service,
1099                       SockAddress*  address )
1100{
1101    RewriteConnection*  conn;
1102    int                 s;
1103
1104    s = socket_create_inet( SOCKET_STREAM );
1105    if (s < 0)
1106        return NULL;
1107
1108    conn = qemu_mallocz(sizeof(*conn));
1109    if (conn == NULL) {
1110        socket_close(s);
1111        return NULL;
1112    }
1113
1114    proxy_connection_init( conn->root, s, address, service->root,
1115                           rewrite_connection_free,
1116                           rewrite_connection_select,
1117                           rewrite_connection_poll );
1118
1119    if ( rewrite_connection_init( conn ) < 0 ) {
1120        rewrite_connection_free( conn->root );
1121        return NULL;
1122    }
1123
1124    return conn->root;
1125}
1126