aboutsummaryrefslogtreecommitdiffstats
path: root/proxy
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:35 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:35 -0800
commitf721e3ac031f892af46f255a47d7f54a91317b30 (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904 /proxy
parentbae1bc39312d5019bd9a5b8d840a529213a69a17 (diff)
downloadexternal_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.zip
external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.gz
external_qemu-f721e3ac031f892af46f255a47d7f54a91317b30.tar.bz2
auto import from //depot/cupcake/@135843
Diffstat (limited to 'proxy')
-rw-r--r--proxy/proxy_common.c532
-rw-r--r--proxy/proxy_common.h88
-rw-r--r--proxy/proxy_http.c186
-rw-r--r--proxy/proxy_http.h24
-rw-r--r--proxy/proxy_http_connector.c203
-rw-r--r--proxy/proxy_http_int.h38
-rw-r--r--proxy/proxy_http_rewriter.c1125
-rw-r--r--proxy/proxy_int.h201
8 files changed, 0 insertions, 2397 deletions
diff --git a/proxy/proxy_common.c b/proxy/proxy_common.c
deleted file mode 100644
index 7794a62..0000000
--- a/proxy/proxy_common.c
+++ /dev/null
@@ -1,532 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "proxy_int.h"
-#include "sockets.h"
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include "android/utils/misc.h"
-#include "android/utils/system.h"
-#include <stdlib.h>
-
-int proxy_log = 0;
-
-void
-proxy_LOG(const char* fmt, ...)
-{
- va_list args;
- va_start(args, fmt);
- vfprintf(stderr, fmt, args);
- va_end(args);
- fprintf(stderr, "\n");
-}
-
-void
-proxy_set_verbose(int mode)
-{
- proxy_log = mode;
-}
-
-/** Global connection list
- **/
-
-static ProxyConnection s_connections[1];
-
-#define MAX_HEX_DUMP 512
-
-static void
-hex_dump( void* base, int size, const char* prefix )
-{
- STRALLOC_DEFINE(s);
- if (size > MAX_HEX_DUMP)
- size = MAX_HEX_DUMP;
- stralloc_add_hexdump(s, base, size, prefix);
- proxy_LOG( "%s", stralloc_cstr(s) );
- stralloc_reset(s);
-}
-
-void
-proxy_connection_init( ProxyConnection* conn,
- int socket,
- SockAddress* address,
- ProxyService* service,
- ProxyConnectionFreeFunc conn_free,
- ProxyConnectionSelectFunc conn_select,
- ProxyConnectionPollFunc conn_poll )
-{
- conn->socket = socket;
- conn->address = address[0];
- conn->service = service;
- conn->next = NULL;
-
- conn->conn_free = conn_free;
- conn->conn_select = conn_select;
- conn->conn_poll = conn_poll;
-
- socket_set_nonblock(socket);
-
- {
- SocketType type = socket_get_type(socket);
-
- snprintf( conn->name, sizeof(conn->name),
- "%s:%s(%d)",
- (type == SOCKET_STREAM) ? "tcp" : "udp",
- sock_address_to_string(address), socket );
-
- /* just in case */
- conn->name[sizeof(conn->name)-1] = 0;
- }
-
- stralloc_reset(conn->str);
- conn->str_pos = 0;
-}
-
-void
-proxy_connection_done( ProxyConnection* conn )
-{
- stralloc_reset( conn->str );
- if (conn->socket >= 0) {
- socket_close(conn->socket);
- conn->socket = -1;
- }
-}
-
-
-void
-proxy_connection_rewind( ProxyConnection* conn )
-{
- stralloc_t* str = conn->str;
-
- /* only keep a small buffer in the heap */
- conn->str_pos = 0;
- str->n = 0;
- if (str->a > 1024)
- stralloc_reset(str);
-}
-
-DataStatus
-proxy_connection_send( ProxyConnection* conn, int fd )
-{
- stralloc_t* str = conn->str;
- int avail = str->n - conn->str_pos;
-
- conn->str_sent = 0;
-
- if (avail <= 0)
- return 1;
-
- if (proxy_log) {
- PROXY_LOG("%s: sending %d bytes:", conn->name, avail );
- hex_dump( str->s + conn->str_pos, avail, ">> " );
- }
-
- while (avail > 0) {
- int n = socket_send(fd, str->s + conn->str_pos, avail);
- if (n == 0) {
- PROXY_LOG("%s: connection reset by peer (send)",
- conn->name);
- return DATA_ERROR;
- }
- if (n < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- return DATA_NEED_MORE;
-
- PROXY_LOG("%s: error: %s", conn->name, errno_str);
- return DATA_ERROR;
- }
- conn->str_pos += n;
- conn->str_sent += n;
- avail -= n;
- }
-
- proxy_connection_rewind(conn);
- return DATA_COMPLETED;
-}
-
-
-DataStatus
-proxy_connection_receive( ProxyConnection* conn, int fd, int wanted )
-{
- stralloc_t* str = conn->str;
-
- conn->str_recv = 0;
-
- while (wanted > 0) {
- int n;
-
- stralloc_readyplus( str, wanted );
- n = socket_recv(fd, str->s + str->n, wanted);
- if (n == 0) {
- PROXY_LOG("%s: connection reset by peer (receive)",
- conn->name);
- return DATA_ERROR;
- }
- if (n < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- return DATA_NEED_MORE;
-
- PROXY_LOG("%s: error: %s", conn->name, errno_str);
- return DATA_ERROR;
- }
-
- if (proxy_log) {
- PROXY_LOG("%s: received %d bytes:", conn->name, n );
- hex_dump( str->s + str->n, n, "<< " );
- }
-
- str->n += n;
- wanted -= n;
- conn->str_recv += n;
- }
- return DATA_COMPLETED;
-}
-
-
-DataStatus
-proxy_connection_receive_line( ProxyConnection* conn, int fd )
-{
- stralloc_t* str = conn->str;
-
- for (;;) {
- char c;
- int n = socket_recv(fd, &c, 1);
- if (n == 0) {
- PROXY_LOG("%s: disconnected from server", conn->name );
- return DATA_ERROR;
- }
- if (n < 0) {
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- PROXY_LOG("%s: blocked", conn->name);
- return DATA_NEED_MORE;
- }
- PROXY_LOG("%s: error: %s", conn->name, errno_str);
- return DATA_ERROR;
- }
-
- stralloc_add_c(str, c);
- if (c == '\n') {
- str->s[--str->n] = 0;
- if (str->n > 0 && str->s[str->n-1] == '\r')
- str->s[--str->n] = 0;
-
- PROXY_LOG("%s: received '%s'", conn->name,
- quote_bytes(str->s, str->n));
- return DATA_COMPLETED;
- }
- }
-}
-
-static void
-proxy_connection_insert( ProxyConnection* conn, ProxyConnection* after )
-{
- conn->next = after->next;
- after->next->prev = conn;
- after->next = conn;
- conn->prev = after;
-}
-
-static void
-proxy_connection_remove( ProxyConnection* conn )
-{
- conn->prev->next = conn->next;
- conn->next->prev = conn->prev;
-
- conn->next = conn->prev = conn;
-}
-
-/** Global service list
- **/
-
-#define MAX_SERVICES 4
-
-static ProxyService* s_services[ MAX_SERVICES ];
-static int s_num_services;
-static int s_init;
-
-static void proxy_manager_atexit( void );
-
-static void
-proxy_manager_init(void)
-{
- s_init = 1;
- s_connections->next = s_connections;
- s_connections->prev = s_connections;
- atexit( proxy_manager_atexit );
-}
-
-
-extern int
-proxy_manager_add_service( ProxyService* service )
-{
- if (!service || s_num_services >= MAX_SERVICES)
- return -1;
-
- if (!s_init)
- proxy_manager_init();
-
- s_services[s_num_services++] = service;
- return 0;
-}
-
-
-extern void
-proxy_manager_atexit( void )
-{
- ProxyConnection* conn = s_connections->next;
- int n;
-
- /* free all proxy connections */
- while (conn != s_connections) {
- ProxyConnection* next = conn->next;
- conn->conn_free( conn );
- conn = next;
- }
- conn->next = conn;
- conn->prev = conn;
-
- /* free all proxy services */
- for (n = s_num_services; n-- > 0;) {
- ProxyService* service = s_services[n];
- service->serv_free( service->opaque );
- }
- s_num_services = 0;
-}
-
-
-void
-proxy_connection_free( ProxyConnection* conn,
- int keep_alive,
- ProxyEvent event )
-{
- if (conn) {
- int fd = conn->socket;
-
- proxy_connection_remove(conn);
-
- if (event != PROXY_EVENT_NONE)
- conn->ev_func( conn->ev_opaque, fd, event );
-
- if (keep_alive)
- conn->socket = -1;
-
- conn->conn_free(conn);
- }
-}
-
-
-int
-proxy_manager_add( SockAddress* address,
- SocketType sock_type,
- ProxyEventFunc ev_func,
- void* ev_opaque )
-{
- int n;
-
- if (!s_init) {
- proxy_manager_init();
- }
-
- for (n = 0; n < s_num_services; n++) {
- ProxyService* service = s_services[n];
- ProxyConnection* conn = service->serv_connect( service->opaque,
- sock_type,
- address );
- if (conn != NULL) {
- conn->ev_func = ev_func;
- conn->ev_opaque = ev_opaque;
- proxy_connection_insert(conn, s_connections->prev);
- return 0;
- }
- }
- return -1;
-}
-
-
-/* remove an on-going proxified socket connection from the manager's list.
- * this is only necessary when the socket connection must be canceled before
- * the connection accept/refusal occured
- */
-void
-proxy_manager_del( void* ev_opaque )
-{
- ProxyConnection* conn = s_connections->next;
- for ( ; conn != s_connections; conn = conn->next ) {
- if (conn->ev_opaque == ev_opaque) {
- proxy_connection_remove(conn);
- conn->conn_free(conn);
- return;
- }
- }
-}
-
-void
-proxy_select_set( ProxySelect* sel,
- int fd,
- unsigned flags )
-{
- if (fd < 0 || !flags)
- return;
-
- if (*sel->pcount < fd+1)
- *sel->pcount = fd+1;
-
- if (flags & PROXY_SELECT_READ) {
- FD_SET( fd, sel->reads );
- } else {
- FD_CLR( fd, sel->reads );
- }
- if (flags & PROXY_SELECT_WRITE) {
- FD_SET( fd, sel->writes );
- } else {
- FD_CLR( fd, sel->writes );
- }
- if (flags & PROXY_SELECT_ERROR) {
- FD_SET( fd, sel->errors );
- } else {
- FD_CLR( fd, sel->errors );
- }
-}
-
-unsigned
-proxy_select_poll( ProxySelect* sel, int fd )
-{
- unsigned flags = 0;
-
- if (fd >= 0) {
- if ( FD_ISSET(fd, sel->reads) )
- flags |= PROXY_SELECT_READ;
- if ( FD_ISSET(fd, sel->writes) )
- flags |= PROXY_SELECT_WRITE;
- if ( FD_ISSET(fd, sel->errors) )
- flags |= PROXY_SELECT_ERROR;
- }
- return flags;
-}
-
-/* this function is called to update the select file descriptor sets
- * with those of the proxified connection sockets that are currently managed */
-void
-proxy_manager_select_fill( int *pcount, fd_set* read_fds, fd_set* write_fds, fd_set* err_fds)
-{
- ProxyConnection* conn;
- ProxySelect sel[1];
-
- if (!s_init)
- proxy_manager_init();
-
- sel->pcount = pcount;
- sel->reads = read_fds;
- sel->writes = write_fds;
- sel->errors = err_fds;
-
- conn = s_connections->next;
- while (conn != s_connections) {
- ProxyConnection* next = conn->next;
- conn->conn_select(conn, sel);
- conn = next;
- }
-}
-
-/* this function is called to act on proxified connection sockets when network events arrive */
-void
-proxy_manager_poll( fd_set* read_fds, fd_set* write_fds, fd_set* err_fds )
-{
- ProxyConnection* conn = s_connections->next;
- ProxySelect sel[1];
-
- sel->pcount = NULL;
- sel->reads = read_fds;
- sel->writes = write_fds;
- sel->errors = err_fds;
-
- while (conn != s_connections) {
- ProxyConnection* next = conn->next;
- conn->conn_poll( conn, sel );
- conn = next;
- }
-}
-
-
-int
-proxy_base64_encode( const char* src, int srclen,
- char* dst, int dstlen )
-{
- static const char cb64[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
- const char* srcend = src + srclen;
- int result = 0;
-
- while (src+3 <= srcend && result+4 <= dstlen)
- {
- dst[result+0] = cb64[ src[0] >> 2 ];
- dst[result+1] = cb64[ ((src[0] & 3) << 4) | ((src[1] & 0xf0) >> 4) ];
- dst[result+2] = cb64[ ((src[1] & 0xf) << 2) | ((src[2] & 0xc0) >> 6) ];
- dst[result+3] = cb64[ src[2] & 0x3f ];
- src += 3;
- result += 4;
- }
-
- if (src < srcend) {
- unsigned char in[4];
-
- if (result+4 > dstlen)
- return -1;
-
- in[0] = src[0];
- in[1] = src+1 < srcend ? src[1] : 0;
- in[2] = src+2 < srcend ? src[2] : 0;
-
- dst[result+0] = cb64[ in[0] >> 2 ];
- dst[result+1] = cb64[ ((in[0] & 3) << 4) | ((in[1] & 0xf0) >> 4) ];
- dst[result+2] = (unsigned char) (src+1 < srcend ? cb64[ ((in[1] & 0xf) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
- dst[result+3] = (unsigned char) (src+2 < srcend ? cb64[ in[2] & 0x3f ] : '=');
- result += 4;
- }
- return result;
-}
-
-int
-proxy_resolve_server( SockAddress* addr,
- const char* servername,
- int servernamelen,
- int serverport )
-{
- char name0[64], *name = name0;
- int result = -1;
-
- if (servernamelen < 0)
- servernamelen = strlen(servername);
-
- if (servernamelen >= sizeof(name0)) {
- AARRAY_NEW(name, servernamelen+1);
- }
-
- memcpy(name, servername, servernamelen);
- name[servernamelen] = 0;
-
- if (sock_address_init_resolve( addr, name, serverport, 0 ) < 0) {
- PROXY_LOG("%s: can't resolve proxy server name '%s'",
- __FUNCTION__, name);
- goto Exit;
- }
-
- PROXY_LOG("server name '%s' resolved to %s", name, sock_address_to_string(addr));
- result = 0;
-
-Exit:
- if (name != name0)
- AFREE(name);
-
- return result;
-}
-
-
diff --git a/proxy/proxy_common.h b/proxy/proxy_common.h
deleted file mode 100644
index 78eddd8..0000000
--- a/proxy/proxy_common.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#ifndef _PROXY_COMMON_H_
-#define _PROXY_COMMON_H_
-
-#include "sockets.h"
-
-#ifdef _WIN32
-#include <winsock2.h>
-#else
-#include <sys/select.h>
-#endif
-
-/* types and definitions used by all proxy connections */
-
-typedef enum {
- PROXY_EVENT_NONE,
- PROXY_EVENT_CONNECTED,
- PROXY_EVENT_CONNECTION_REFUSED,
- PROXY_EVENT_SERVER_ERROR
-} ProxyEvent;
-
-/* event can't be NONE when this callback is called */
-typedef void (*ProxyEventFunc)( void* opaque, int fd, ProxyEvent event );
-
-extern void proxy_set_verbose(int mode);
-
-
-typedef enum {
- PROXY_OPTION_AUTH_USERNAME = 1,
- PROXY_OPTION_AUTH_PASSWORD,
-
- PROXY_OPTION_HTTP_NOCACHE = 100,
- PROXY_OPTION_HTTP_KEEPALIVE,
- PROXY_OPTION_HTTP_USER_AGENT,
-
- PROXY_OPTION_MAX
-
-} ProxyOptionType;
-
-
-typedef struct {
- ProxyOptionType type;
- const char* string;
- int string_len;
-} ProxyOption;
-
-
-/* add a new proxified socket connection to the manager's list. the event function
- * will be called when the connection is established or refused.
- *
- * only IPv4 is supported at the moment, since our slirp code cannot handle IPv6
- *
- * returns 0 on success, or -1 if there is no proxy service for this type of connection
- */
-extern int proxy_manager_add( SockAddress* address,
- SocketType sock_type,
- ProxyEventFunc ev_func,
- void* ev_opaque );
-
-/* remove an on-going proxified socket connection from the manager's list.
- * this is only necessary when the socket connection must be canceled before
- * the connection accept/refusal occured
- */
-extern void proxy_manager_del( void* ev_opaque );
-
-/* this function is called to update the select file descriptor sets
- * with those of the proxified connection sockets that are currently managed */
-extern void proxy_manager_select_fill( int *pcount,
- fd_set* read_fds,
- fd_set* write_fds,
- fd_set* err_fds);
-
-/* this function is called to act on proxified connection sockets when network events arrive */
-extern void proxy_manager_poll( fd_set* read_fds,
- fd_set* write_fds,
- fd_set* err_fds );
-
-#endif /* END */
diff --git a/proxy/proxy_http.c b/proxy/proxy_http.c
deleted file mode 100644
index f753587..0000000
--- a/proxy/proxy_http.c
+++ /dev/null
@@ -1,186 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "proxy_int.h"
-#include "proxy_http_int.h"
-#include "qemu-common.h"
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-
-#define HTTP_VERSION "1.1"
-
-static void
-http_service_free( HttpService* service )
-{
- PROXY_LOG("%s", __FUNCTION__);
- if (service->footer != service->footer0)
- qemu_free(service->footer);
- qemu_free(service);
-}
-
-
-static ProxyConnection*
-http_service_connect( HttpService* service,
- SocketType sock_type,
- SockAddress* address )
-{
- /* the HTTP proxy can only handle TCP connections */
- if (sock_type != SOCKET_STREAM)
- return NULL;
-
- /* if the client tries to directly connect to the proxy, let it do so */
- if (sock_address_equal( address, &service->server_addr ))
- return NULL;
-
- PROXY_LOG("%s: trying to connect to %s",
- __FUNCTION__, sock_address_to_string(address));
-
- if (sock_address_get_port(address) == 80) {
- /* use the rewriter for HTTP */
- PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
- return http_rewriter_connect(service, address);
- } else {
- PROXY_LOG("%s: using HTTP rewriter", __FUNCTION__);
- return http_connector_connect(service, address);
- }
-}
-
-
-int
-proxy_http_setup( const char* servername,
- int servernamelen,
- int serverport,
- int num_options,
- const ProxyOption* options )
-{
- HttpService* service;
- SockAddress server_addr;
- const ProxyOption* opt_nocache = NULL;
- const ProxyOption* opt_keepalive = NULL;
- const ProxyOption* opt_auth_user = NULL;
- const ProxyOption* opt_auth_pass = NULL;
- const ProxyOption* opt_user_agent = NULL;
-
- if (servernamelen < 0)
- servernamelen = strlen(servername);
-
- PROXY_LOG( "%s: creating http proxy service connecting to: %.*s:%d",
- __FUNCTION__, servernamelen, servername, serverport );
-
- /* resolve server address */
- if (proxy_resolve_server(&server_addr, servername,
- servernamelen, serverport) < 0)
- {
- return -1;
- }
-
- /* create service object */
- service = qemu_mallocz(sizeof(*service));
- if (service == NULL) {
- PROXY_LOG("%s: not enough memory to allocate new proxy service", __FUNCTION__);
- return -1;
- }
-
- service->server_addr = server_addr;
-
- /* parse options */
- {
- const ProxyOption* opt = options;
- const ProxyOption* end = opt + num_options;
-
- for ( ; opt < end; opt++ ) {
- switch (opt->type) {
- case PROXY_OPTION_HTTP_NOCACHE: opt_nocache = opt; break;
- case PROXY_OPTION_HTTP_KEEPALIVE: opt_keepalive = opt; break;
- case PROXY_OPTION_AUTH_USERNAME: opt_auth_user = opt; break;
- case PROXY_OPTION_AUTH_PASSWORD: opt_auth_pass = opt; break;
- case PROXY_OPTION_HTTP_USER_AGENT: opt_user_agent = opt; break;
- default: ;
- }
- }
- }
-
- /* prepare footer */
- {
- int wlen;
- char* p = service->footer0;
- char* end = p + sizeof(service->footer0);
-
- /* no-cache */
- if (opt_nocache) {
- p += snprintf(p, end-p, "Pragma: no-cache\r\nCache-Control: no-cache\r\n");
- if (p >= end) goto FooterOverflow;
- }
- /* keep-alive */
- if (opt_keepalive) {
- p += snprintf(p, end-p, "Connection: Keep-Alive\r\nProxy-Connection: Keep-Alive\r\n");
- if (p >= end) goto FooterOverflow;
- }
- /* authentication */
- if (opt_auth_user && opt_auth_pass) {
- char user_pass[256];
- char encoded[512];
- int uplen;
-
- uplen = snprintf( user_pass, sizeof(user_pass), "%.*s:%.*s",
- opt_auth_user->string_len, opt_auth_user->string,
- opt_auth_pass->string_len, opt_auth_pass->string );
-
- if (uplen >= sizeof(user_pass)) goto FooterOverflow;
-
- wlen = proxy_base64_encode(user_pass, uplen, encoded, (int)sizeof(encoded));
- if (wlen < 0) {
- PROXY_LOG( "could not base64 encode '%.*s'", uplen, user_pass);
- goto FooterOverflow;
- }
-
- p += snprintf(p, end-p, "Proxy-authorization: Basic %.*s\r\n", wlen, encoded);
- if (p >= end) goto FooterOverflow;
- }
- /* user agent */
- if (opt_user_agent) {
- p += snprintf(p, end-p, "User-Agent: %.*s\r\n",
- opt_user_agent->string_len,
- opt_user_agent->string);
- if (p >= end) goto FooterOverflow;
- }
-
- p += snprintf(p, end-p, "\r\n");
-
- if (p >= end) {
- FooterOverflow:
- PROXY_LOG( "%s: buffer overflow when creating connection footer",
- __FUNCTION__);
- http_service_free(service);
- return -1;
- }
-
- service->footer = service->footer0;
- service->footer_len = (p - service->footer);
- }
-
- PROXY_LOG( "%s: creating HTTP Proxy Service Footer is (len=%d):\n'%.*s'",
- __FUNCTION__, service->footer_len,
- service->footer_len, service->footer );
-
- service->root->opaque = service;
- service->root->serv_free = (ProxyServiceFreeFunc) http_service_free;
- service->root->serv_connect = (ProxyServiceConnectFunc) http_service_connect;
-
- if (proxy_manager_add_service( service->root ) < 0) {
- PROXY_LOG("%s: could not register service ?", __FUNCTION__);
- http_service_free(service);
- return -1;
- }
- return 0;
-}
-
diff --git a/proxy/proxy_http.h b/proxy/proxy_http.h
deleted file mode 100644
index a2e2917..0000000
--- a/proxy/proxy_http.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#ifndef _PROXY_HTTP_H
-#define _PROXY_HTTP_H
-
-#include "proxy_common.h"
-
-extern int
-proxy_http_setup( const char* servername,
- int servernamelen,
- int serverport,
- int num_options,
- const ProxyOption* options );
-
-#endif /* END */
diff --git a/proxy/proxy_http_connector.c b/proxy/proxy_http_connector.c
deleted file mode 100644
index 6f03d9b..0000000
--- a/proxy/proxy_http_connector.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "proxy_http_int.h"
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include "qemu-common.h"
-
-/* A HttpConnector implements a non-HTTP proxied connection
- * through the CONNECT method. Many firewalls are configured
- * to reject these for port 80, so these connections should
- * use a HttpRewriter instead.
- */
-
-typedef enum {
- STATE_NONE = 0,
- STATE_CONNECTING, /* connecting to the server */
- STATE_SEND_HEADER, /* connected, sending header to the server */
- STATE_RECEIVE_ANSWER_LINE1,
- STATE_RECEIVE_ANSWER_LINE2 /* connected, reading server's answer */
-} ConnectorState;
-
-typedef struct Connection {
- ProxyConnection root[1];
- ConnectorState state;
-} Connection;
-
-
-static void
-connection_free( ProxyConnection* root )
-{
- proxy_connection_done(root);
- qemu_free(root);
-}
-
-
-
-#define HTTP_VERSION "1.1"
-
-static int
-connection_init( Connection* conn )
-{
- HttpService* service = (HttpService*) conn->root->service;
- ProxyConnection* root = conn->root;
- stralloc_t* str = root->str;
-
- proxy_connection_rewind(root);
- stralloc_add_format(str, "CONNECT %s HTTP/" HTTP_VERSION "\r\n",
- sock_address_to_string(&root->address));
-
- stralloc_add_bytes(str, service->footer, service->footer_len);
-
- if (!socket_connect( root->socket, &service->server_addr )) {
- /* immediate connection ?? */
- conn->state = STATE_SEND_HEADER;
- PROXY_LOG("%s: immediate connection", root->name);
- }
- else {
- if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
- conn->state = STATE_CONNECTING;
- PROXY_LOG("%s: connecting", root->name);
- }
- else {
- PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str);
- return -1;
- }
- }
- return 0;
-}
-
-
-static void
-connection_select( ProxyConnection* root,
- ProxySelect* sel )
-{
- unsigned flags;
- Connection* conn = (Connection*)root;
-
- switch (conn->state) {
- case STATE_RECEIVE_ANSWER_LINE1:
- case STATE_RECEIVE_ANSWER_LINE2:
- flags = PROXY_SELECT_READ;
- break;
-
- case STATE_CONNECTING:
- case STATE_SEND_HEADER:
- flags = PROXY_SELECT_WRITE;
- break;
-
- default:
- flags = 0;
- };
- proxy_select_set(sel, root->socket, flags);
-}
-
-static void
-connection_poll( ProxyConnection* root,
- ProxySelect* sel )
-{
- DataStatus ret = DATA_NEED_MORE;
- Connection* conn = (Connection*)root;
- int fd = root->socket;
-
- if (!proxy_select_poll(sel, fd))
- return;
-
- switch (conn->state)
- {
- case STATE_CONNECTING:
- PROXY_LOG("%s: connected to http proxy, sending header", root->name);
- conn->state = STATE_SEND_HEADER;
- break;
-
- case STATE_SEND_HEADER:
- ret = proxy_connection_send(root, fd);
- if (ret == DATA_COMPLETED) {
- conn->state = STATE_RECEIVE_ANSWER_LINE1;
- PROXY_LOG("%s: header sent, receiving first answer line", root->name);
- }
- break;
-
- case STATE_RECEIVE_ANSWER_LINE1:
- case STATE_RECEIVE_ANSWER_LINE2:
- ret = proxy_connection_receive_line(root, root->socket);
- if (ret == DATA_COMPLETED) {
- if (conn->state == STATE_RECEIVE_ANSWER_LINE1) {
- int http1, http2, codenum;
- const char* line = root->str->s;
-
- if ( sscanf(line, "HTTP/%d.%d %d", &http1, &http2, &codenum) != 3 ) {
- PROXY_LOG( "%s: invalid answer from proxy: '%s'",
- root->name, line );
- ret = DATA_ERROR;
- break;
- }
-
- /* success is 2xx */
- if (codenum/2 != 100) {
- PROXY_LOG( "%s: connection refused, error=%d",
- root->name, codenum );
- proxy_connection_free( root, 0, PROXY_EVENT_CONNECTION_REFUSED );
- return;
- }
- PROXY_LOG("%s: receiving second answer line", root->name);
- conn->state = STATE_RECEIVE_ANSWER_LINE2;
- proxy_connection_rewind(root);
- } else {
- /* ok, we're connected */
- PROXY_LOG("%s: connection succeeded", root->name);
- proxy_connection_free( root, 1, PROXY_EVENT_CONNECTED );
- }
- }
- break;
-
- default:
- PROXY_LOG("%s: invalid state for read event: %d", root->name, conn->state);
- }
-
- if (ret == DATA_ERROR) {
- proxy_connection_free( root, 0, PROXY_EVENT_SERVER_ERROR );
- }
-}
-
-
-
-ProxyConnection*
-http_connector_connect( HttpService* service,
- SockAddress* address )
-{
- Connection* conn;
- int s;
-
- s = socket_create_inet( SOCKET_STREAM );
- if (s < 0)
- return NULL;
-
- conn = qemu_mallocz(sizeof(*conn));
- if (conn == NULL) {
- socket_close(s);
- return NULL;
- }
-
- proxy_connection_init( conn->root, s, address, service->root,
- connection_free,
- connection_select,
- connection_poll );
-
- if ( connection_init( conn ) < 0 ) {
- connection_free( conn->root );
- return NULL;
- }
-
- return conn->root;
-}
diff --git a/proxy/proxy_http_int.h b/proxy/proxy_http_int.h
deleted file mode 100644
index 6daa9cb..0000000
--- a/proxy/proxy_http_int.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#ifndef _PROXY_HTTP_INT_H
-#define _PROXY_HTTP_INT_H
-
-#include "proxy_http.h"
-#include "proxy_int.h"
-
-/* the HttpService object */
-typedef struct HttpService {
- ProxyService root[1];
- SockAddress server_addr; /* server address and port */
- char* footer; /* the footer contains the static parts of the */
- int footer_len; /* connection header, we generate it only once */
- char footer0[512];
-} HttpService;
-
-/* create a CONNECT connection (for port != 80) */
-extern ProxyConnection* http_connector_connect(
- HttpService* service,
- SockAddress* address );
-
-/* create a HTTP rewriting connection (for port == 80) */
-extern ProxyConnection* http_rewriter_connect(
- HttpService* service,
- SockAddress* address );
-
-
-#endif /* _PROXY_HTTP_INT_H */
diff --git a/proxy/proxy_http_rewriter.c b/proxy/proxy_http_rewriter.c
deleted file mode 100644
index 812bf9c..0000000
--- a/proxy/proxy_http_rewriter.c
+++ /dev/null
@@ -1,1125 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#include "proxy_http_int.h"
-#include <stdio.h>
-#include <string.h>
-#include "qemu-common.h"
-#include "android/utils/system.h" /* strsep */
-
-/* this implements a transparent HTTP rewriting proxy
- *
- * this is needed because the HTTP spec mandates that
- * any query made to a proxy uses an absolute URI as
- * in:
- *
- * GET http://www.example.com/index.html HTTP/1.1
- *
- * while the Android browser will think it's talking to
- * a normal web server and will issue a:
- *
- * GET /index.html HTTP/1.1
- * Host: www.example.com
- *
- * what we do here is thus the following:
- *
- * - read the request header
- * - rewrite the request's URI to use absolute URI
- * - send the rewritten header to the proxy
- * - then read the rest of the request, and tunnel it to the
- * proxy as well
- * - read the answer as-is and send it back to the system
- *
- * this sounds all easy, but the rules for computing the
- * sizes of HTTP Message Bodies makes the implementation
- * a *bit* funky.
- */
-
-/* define D_ACTIVE to 1 to dump additionnal debugging
- * info when -debug-proxy is used. These are only needed
- * when debugging the proxy code.
- */
-#define D_ACTIVE 1
-
-#if D_ACTIVE
-# define D(...) PROXY_LOG(__VA_ARGS__)
-#else
-# define D(...) ((void)0)
-#endif
-
-
-/** *************************************************************
- **
- ** HTTP HEADERS
- **
- **/
-
-typedef struct HttpHeader {
- struct HttpHeader* next;
- const char* key;
- const char* value;
-} HttpHeader;
-
-static void
-http_header_free( HttpHeader* h )
-{
- if (h) {
- qemu_free((char*)h->value);
- qemu_free(h);
- }
-}
-
-static int
-http_header_append( HttpHeader* h, const char* value )
-{
- int old = strlen(h->value);
- int new = strlen(value);
- char* s = realloc((char*)h->value, old+new+1);
- if (s == NULL)
- return -1;
- memcpy(s + old, value, new+1);
- h->value = (const char*)s;
- return 0;
-}
-
-static HttpHeader*
-http_header_alloc( const char* key, const char* value )
-{
- int len = strlen(key)+1;
- HttpHeader* h = malloc(sizeof(*h) + len+1);
- if (h) {
- h->next = NULL;
- h->key = (const char*)(h+1);
- memcpy( (char*)h->key, key, len );
- h->value = qemu_strdup(value);
- }
- return h;
-}
-
-typedef struct {
- HttpHeader* first;
- HttpHeader* last;
-} HttpHeaderList;
-
-static void
-http_header_list_init( HttpHeaderList* l )
-{
- l->first = l->last = NULL;
-}
-
-static void
-http_header_list_done( HttpHeaderList* l )
-{
- while (l->first) {
- HttpHeader* h = l->first;
- l->first = h->next;
- http_header_free(h);
- }
- l->last = NULL;
-}
-
-static void
-http_header_list_add( HttpHeaderList* l,
- HttpHeader* h )
-{
- if (!l->first) {
- l->first = h;
- } else {
- l->last->next = h;
- }
- h->next = NULL;
- l->last = h;
-}
-
-static const char*
-http_header_list_find( HttpHeaderList* l,
- const char* key )
-{
- HttpHeader* h;
- for (h = l->first; h; h = h->next)
- if (!strcasecmp(h->key, key))
- return h->value;
-
- return NULL;
-}
-
-/** *************************************************************
- **
- ** HTTP REQUEST AND REPLY
- **
- **/
-
-typedef enum {
- HTTP_REQUEST_UNSUPPORTED = 0,
- HTTP_REQUEST_GET,
- HTTP_REQUEST_HEAD,
- HTTP_REQUEST_POST,
- HTTP_REQUEST_PUT,
- HTTP_REQUEST_DELETE,
-} HttpRequestType;
-
-typedef struct {
- HttpRequestType req_type;
- char* req_method;
- char* req_uri;
- char* req_version;
- char* rep_version;
- int rep_code;
- char* rep_readable;
- HttpHeaderList headers[1];
-} HttpRequest;
-
-
-static HttpRequest*
-http_request_alloc( const char* method,
- const char* uri,
- const char* version )
-{
- HttpRequest* r = malloc(sizeof(*r));
-
- r->req_method = qemu_strdup(method);
- r->req_uri = qemu_strdup(uri);
- r->req_version = qemu_strdup(version);
- r->rep_version = NULL;
- r->rep_code = -1;
- r->rep_readable = NULL;
-
- if (!strcmp(method,"GET")) {
- r->req_type = HTTP_REQUEST_GET;
- } else if (!strcmp(method,"POST")) {
- r->req_type = HTTP_REQUEST_POST;
- } else if (!strcmp(method,"HEAD")) {
- r->req_type = HTTP_REQUEST_HEAD;
- } else if (!strcmp(method,"PUT")) {
- r->req_type = HTTP_REQUEST_PUT;
- } else if (!strcmp(method,"DELETE")) {
- r->req_type = HTTP_REQUEST_DELETE;
- } else
- r->req_type = HTTP_REQUEST_UNSUPPORTED;
-
- http_header_list_init(r->headers);
- return r;
-}
-
-static void
-http_request_replace_uri( HttpRequest* r,
- const char* uri )
-{
- const char* old = r->req_uri;
- r->req_uri = qemu_strdup(uri);
- qemu_free((char*)old);
-}
-
-static void
-http_request_free( HttpRequest* r )
-{
- if (r) {
- http_header_list_done(r->headers);
-
- qemu_free(r->req_method);
- qemu_free(r->req_uri);
- qemu_free(r->req_version);
- qemu_free(r->rep_version);
- qemu_free(r->rep_readable);
- qemu_free(r);
- }
-}
-
-static char*
-http_request_find_header( HttpRequest* r,
- const char* key )
-{
- return (char*)http_header_list_find(r->headers, key);
-}
-
-
-static int
-http_request_add_header( HttpRequest* r,
- const char* key,
- const char* value )
-{
- HttpHeader* h = http_header_alloc(key,value);
- if (h) {
- http_header_list_add(r->headers, h);
- return 0;
- }
- return -1;
-}
-
-static int
-http_request_add_to_last_header( HttpRequest* r,
- const char* line )
-{
- if (r->headers->last) {
- return http_header_append( r->headers->last, line );
- } else {
- return -1;
- }
-}
-
-static int
-http_request_set_reply( HttpRequest* r,
- const char* version,
- const char* code,
- const char* readable )
-{
- if (strcmp(version,"HTTP/1.0") && strcmp(version,"HTTP/1.1")) {
- PROXY_LOG("%s: bad reply protocol: %s", __FUNCTION__, version);
- return -1;
- }
- r->rep_code = atoi(code);
- if (r->rep_code == 0) {
- PROXY_LOG("%s: bad reply code: %d", __FUNCTION__, code);
- return -1;
- }
-
- r->rep_version = qemu_strdup(version);
- r->rep_readable = qemu_strdup(readable);
-
- /* reset the list of headers */
- http_header_list_done(r->headers);
- return 0;
-}
-
-/** *************************************************************
- **
- ** REWRITER CONNECTION
- **
- **/
-
-typedef enum {
- STATE_CONNECTING = 0,
- STATE_CREATE_SOCKET_PAIR,
- STATE_REQUEST_FIRST_LINE,
- STATE_REQUEST_HEADERS,
- STATE_REQUEST_SEND,
- STATE_REQUEST_BODY,
- STATE_REPLY_FIRST_LINE,
- STATE_REPLY_HEADERS,
- STATE_REPLY_SEND,
- STATE_REPLY_BODY,
-} ConnectionState;
-
-/* root->socket is connected to the proxy server. while
- * slirp_fd is connected to the slirp code through a
- * socket_pair() we created for this specific purpose.
- */
-
-typedef enum {
- BODY_NONE = 0,
- BODY_KNOWN_LENGTH,
- BODY_UNTIL_CLOSE,
- BODY_CHUNKED,
- BODY_MODE_MAX
-} BodyMode;
-
-static const char* const body_mode_str[BODY_MODE_MAX] = {
- "NONE", "KNOWN_LENGTH", "UNTIL_CLOSE", "CHUNKED"
-};
-
-typedef struct {
- ProxyConnection root[1];
- int slirp_fd;
- ConnectionState state;
- HttpRequest* request;
- BodyMode body_mode;
- int64_t body_length;
- int64_t body_total;
- int64_t body_sent;
- int64_t chunk_length;
- int64_t chunk_total;
- char body_has_data;
- char body_is_full;
- char body_is_closed;
- char parse_chunk_header;
- char parse_chunk_trailer;
-} RewriteConnection;
-
-
-static void
-rewrite_connection_free( ProxyConnection* root )
-{
- RewriteConnection* conn = (RewriteConnection*)root;
-
- if (conn->slirp_fd >= 0) {
- socket_close(conn->slirp_fd);
- conn->slirp_fd = -1;
- }
- http_request_free(conn->request);
- proxy_connection_done(root);
- qemu_free(conn);
-}
-
-
-static int
-rewrite_connection_init( RewriteConnection* conn )
-{
- HttpService* service = (HttpService*) conn->root->service;
- ProxyConnection* root = conn->root;
-
- conn->slirp_fd = -1;
- conn->state = STATE_CONNECTING;
-
- if (socket_connect( root->socket, &service->server_addr ) < 0) {
- if (errno == EINPROGRESS || errno == EWOULDBLOCK) {
- PROXY_LOG("%s: connecting", conn->root->name);
- }
- else {
- PROXY_LOG("%s: cannot connect to proxy: %s", root->name, errno_str);
- return -1;
- }
- }
- else {
- PROXY_LOG("%s: immediate connection", root->name);
- conn->state = STATE_CREATE_SOCKET_PAIR;
- }
- return 0;
-}
-
-static int
-rewrite_connection_create_sockets( RewriteConnection* conn )
-{
- /* immediate connection to the proxy. now create a socket
- * pair and send a 'success' event to slirp */
- int slirp_1;
- ProxyConnection* root = conn->root;
-
- if (socket_pair( &slirp_1, &conn->slirp_fd ) < 0) {
- PROXY_LOG("%s: coult not create socket pair: %s",
- root->name, errno_str);
- return -1;
- }
-
- root->ev_func( root->ev_opaque, slirp_1, PROXY_EVENT_CONNECTED );
- conn->state = STATE_REQUEST_FIRST_LINE;
- return 0;
-}
-
-
-/* read the first line of a given HTTP request. returns -1/0/+1 */
-static DataStatus
-rewrite_connection_read_request( RewriteConnection* conn )
-{
- ProxyConnection* root = conn->root;
- DataStatus ret;
-
- ret = proxy_connection_receive_line(root, conn->slirp_fd);
- if (ret == DATA_COMPLETED) {
- /* now parse the first line to see if we can handle it */
- char* line = root->str->s;
- char* method;
- char* uri;
- char* version;
- char* p = line;
-
- method = strsep(&p, " ");
- if (p == NULL) {
- PROXY_LOG("%s: can't parse method in '%'",
- root->name, line);
- return DATA_ERROR;
- }
- uri = strsep(&p, " ");
- if (p == NULL) {
- PROXY_LOG( "%s: can't parse URI in '%s'",
- root->name, line);
- return DATA_ERROR;
- }
- version = strsep(&p, " ");
- if (p != NULL) {
- PROXY_LOG( "%s: extra data after version in '%s'",
- root->name, line);
- return DATA_ERROR;
- }
- if (conn->request)
- http_request_free(conn->request);
-
- conn->request = http_request_alloc( method, uri, version );
- if (!conn->request)
- return DATA_ERROR;
-
- proxy_connection_rewind(root);
- }
- return ret;
-}
-
-
-static DataStatus
-rewrite_connection_read_reply( RewriteConnection* conn )
-{
- ProxyConnection* root = conn->root;
- DataStatus ret;
-
- ret = proxy_connection_receive_line( root, root->socket );
- if (ret == DATA_COMPLETED) {
- HttpRequest* request = conn->request;
-
- char* line = stralloc_cstr( root->str );
- char* p = line;
- char* protocol;
- char* number;
- char* readable;
-
- protocol = strsep(&p, " ");
- if (p == NULL) {
- PROXY_LOG("%s: can't parse response protocol: '%s'",
- root->name, line);
- return DATA_ERROR;
- }
- number = strsep(&p, " ");
- if (p == NULL) {
- PROXY_LOG("%s: can't parse response number: '%s'",
- root->name, line);
- return DATA_ERROR;
- }
- readable = p;
-
- if (http_request_set_reply(request, protocol, number, readable) < 0)
- return DATA_ERROR;
-
- proxy_connection_rewind(root);
- }
- return ret;
-}
-
-
-static DataStatus
-rewrite_connection_read_headers( RewriteConnection* conn,
- int fd )
-{
- int ret;
- ProxyConnection* root = conn->root;
-
- for (;;) {
- char* line;
- stralloc_t* str = root->str;
-
- ret = proxy_connection_receive_line(root, fd);
- if (ret != DATA_COMPLETED)
- break;
-
- str->n = 0;
- line = str->s;
-
- if (line[0] == 0) {
- /* an empty line means the end of headers */
- ret = 1;
- break;
- }
-
- /* it this a continuation ? */
- if (line[0] == ' ' || line[0] == '\t') {
- ret = http_request_add_to_last_header( conn->request, line );
- }
- else {
- char* key;
- char* value;
-
- value = line;
- key = strsep(&value, ":");
- if (value == NULL) {
- PROXY_LOG("%s: can't parse header '%s'", root->name, line);
- ret = -1;
- break;
- }
- value += strspn(value, " ");
- if (http_request_add_header(conn->request, key, value) < 0)
- ret = -1;
- }
- if (ret == DATA_ERROR)
- break;
- }
- return ret;
-}
-
-static int
-rewrite_connection_rewrite_request( RewriteConnection* conn )
-{
- ProxyConnection* root = conn->root;
- HttpService* service = (HttpService*) root->service;
- HttpRequest* r = conn->request;
- stralloc_t* str = root->str;
- HttpHeader* h;
-
- proxy_connection_rewind(conn->root);
-
- /* only rewrite the URI if it is not absolute */
- if (r->req_uri[0] == '/') {
- char* host = http_request_find_header(r, "Host");
- if (host == NULL) {
- PROXY_LOG("%s: uh oh, not Host: in request ?", root->name);
- } else {
- /* now create new URI */
- stralloc_add_str(str, "http://");
- stralloc_add_str(str, host);
- stralloc_add_str(str, r->req_uri);
- http_request_replace_uri(r, stralloc_cstr(str));
- proxy_connection_rewind(root);
- }
- }
-
- stralloc_format( str, "%s %s %s\r\n", r->req_method, r->req_uri, r->req_version );
- for (h = r->headers->first; h; h = h->next) {
- stralloc_add_format( str, "%s: %s\r\n", h->key, h->value );
- }
- /* add the service's footer - includes final \r\n */
- stralloc_add_bytes( str, service->footer, service->footer_len );
-
- return 0;
-}
-
-static int
-rewrite_connection_rewrite_reply( RewriteConnection* conn )
-{
- HttpRequest* r = conn->request;
- ProxyConnection* root = conn->root;
- stralloc_t* str = root->str;
- HttpHeader* h;
-
- proxy_connection_rewind(root);
- stralloc_format(str, "%s %d %s\r\n", r->rep_version, r->rep_code, r->rep_readable);
- for (h = r->headers->first; h; h = h->next) {
- stralloc_add_format(str, "%s: %s\r\n", h->key, h->value);
- }
- stralloc_add_str(str, "\r\n");
-
- return 0;
-}
-
-
-static int
-rewrite_connection_get_body_length( RewriteConnection* conn,
- int is_request )
-{
- HttpRequest* r = conn->request;
- ProxyConnection* root = conn->root;
- char* content_length;
- char* transfer_encoding;
-
- conn->body_mode = BODY_NONE;
- conn->body_length = 0;
- conn->body_total = 0;
- conn->body_sent = 0;
- conn->body_is_closed = 0;
- conn->body_is_full = 0;
- conn->body_has_data = 0;
-
- proxy_connection_rewind(root);
-
- if (is_request) {
- /* only POST and PUT should have a body */
- if (r->req_type != HTTP_REQUEST_POST &&
- r->req_type != HTTP_REQUEST_PUT)
- {
- return 0;
- }
- } else {
- /* HTTP 1.1 Section 4.3 Message Body states that HEAD requests must not have
- * a message body, as well as any 1xx, 204 and 304 replies */
- if (r->req_type == HTTP_REQUEST_HEAD || r->rep_code/100 == 1 ||
- r->rep_code == 204 || r->rep_code == 304)
- return 0;
- }
-
- content_length = http_request_find_header(r, "Content-Length");
- if (content_length != NULL) {
- char* end;
- int64_t body_len = strtoll( content_length, &end, 10 );
- if (*end != '\0' || *content_length == '\0' || body_len < 0) {
- PROXY_LOG("%s: bad content length: %s", root->name, content_length);
- return DATA_ERROR;
- }
- if (body_len > 0) {
- conn->body_mode = BODY_KNOWN_LENGTH;
- conn->body_length = body_len;
- }
- } else {
- char* connection = http_request_find_header(r, "Proxy-Connection");
-
- if (!connection)
- connection = http_request_find_header(r, "Connection");
-
- if (!connection || strcasecmp(connection, "Close")) {
- /* hum, we can't support this at all */
- PROXY_LOG("%s: can't determine content length, and client wants"
- " to keep connection opened",
- root->name);
- return -1;
- }
- /* a negative value means that the data ends when the client
- * disconnects the connection.
- */
- conn->body_mode = BODY_UNTIL_CLOSE;
- }
- transfer_encoding = http_request_find_header(r, "Transfer-Encoding");
- if (transfer_encoding && !strcasecmp(transfer_encoding, "Chunked")) {
- conn->body_mode = BODY_CHUNKED;
- conn->parse_chunk_header = 0;
- conn->parse_chunk_trailer = 0;
- conn->chunk_length = -1;
- conn->chunk_total = 0;
- }
- D("%s: body_length=%lld body_mode=%s",
- root->name, conn->body_length,
- body_mode_str[conn->body_mode]);
-
- proxy_connection_rewind(root);
- return 0;
-}
-
-#define MAX_BODY_BUFFER 65536
-
-static DataStatus
-rewrite_connection_read_body( RewriteConnection* conn, int fd )
-{
- ProxyConnection* root = conn->root;
- stralloc_t* str = root->str;
- int wanted = 0, current, avail;
- DataStatus ret;
-
- if (conn->body_is_closed) {
- return DATA_NEED_MORE;
- }
-
- /* first, determine how many bytes we want to read. */
- switch (conn->body_mode) {
- case BODY_NONE:
- D("%s: INTERNAL ERROR: SHOULDN'T BE THERE", root->name);
- return DATA_COMPLETED;
-
- case BODY_KNOWN_LENGTH:
- {
- if (conn->body_length == 0)
- return DATA_COMPLETED;
-
- if (conn->body_length > MAX_BODY_BUFFER)
- wanted = MAX_BODY_BUFFER;
- else
- wanted = (int)conn->body_length;
- }
- break;
-
- case BODY_UNTIL_CLOSE:
- wanted = MAX_BODY_BUFFER;
- break;
-
- case BODY_CHUNKED:
- if (conn->chunk_length < 0) {
- /* chunk_length < 0 means we need to read a chunk header */
- /* ensure that 'str' is flushed before doing this */
- if (!conn->parse_chunk_header) {
- if (conn->body_has_data)
- return DATA_NEED_MORE;
- D("%s: waiting chunk header", root->name);
- conn->parse_chunk_header = 1;
- }
- ret = proxy_connection_receive_line(root, fd);
- if (ret == DATA_COMPLETED) {
- char* line = str->s;
- char* end;
- long long length;
-
- length = strtoll(line, &end, 16);
- if (line[0] == ' ' || (end[0] != '\0' && end[0] != ';')) {
- PROXY_LOG("%s: invalid chunk header: %s",
- root->name, line);
- return DATA_ERROR;
- }
- if (length < 0) {
- PROXY_LOG("%s: invalid chunk length %lld",
- root->name, length);
- return DATA_ERROR;
- }
- conn->chunk_length = length;
- conn->chunk_total = 0;
- if (length == 0) {
- /* the last chunk, no we need to add the trailer */
- conn->parse_chunk_trailer = 0;
- }
- conn->parse_chunk_header = 0;
- }
- }
-
- if (conn->chunk_length == 0) {
- /* chunk_length == 0 means we're reading the chunk trailer */
- /* ensure that 'str' is flushed before reading the trailer */
- if (!conn->parse_chunk_trailer) {
- if (conn->body_has_data)
- return DATA_NEED_MORE;
- conn->parse_chunk_trailer = 1;
- }
- ret = rewrite_connection_read_headers(conn, fd);
- if (ret == DATA_COMPLETED) {
- conn->body_is_closed = 1;
- }
- return ret;
- }
-
- /* if we get here, body_length > 0 */
- if (conn->chunk_length > MAX_BODY_BUFFER)
- wanted = MAX_BODY_BUFFER;
- else
- wanted = (int)conn->chunk_length;
- break;
-
- default:
- ;
- }
-
- /* we don't want more than MAX_BODY_BUFFER bytes in the
- * buffer we used to pass the body */
- current = str->n;
- avail = MAX_BODY_BUFFER - current;
- if (avail <= 0) {
- /* wait for some flush */
- conn->body_is_full = 1;
- D("%s: waiting to flush %d bytes",
- root->name, current);
- return DATA_NEED_MORE;
- }
-
- if (wanted > avail)
- wanted = avail;
-
- ret = proxy_connection_receive(root, fd, wanted);
- conn->body_has_data = (str->n > 0);
- conn->body_is_full = (str->n == MAX_BODY_BUFFER);
-
- if (ret == DATA_ERROR) {
- if (conn->body_mode == BODY_UNTIL_CLOSE) {
- /* a disconnection here is normal and signals the
- * end of the body */
- conn->body_total += root->str_recv;
- D("%s: body completed by close (%lld bytes)",
- root->name, conn->body_total);
- conn->body_is_closed = 1;
- ret = DATA_COMPLETED;
- }
- } else {
- avail = root->str_recv;
- ret = DATA_NEED_MORE; /* we're not really done yet */
-
- switch (conn->body_mode) {
- case BODY_CHUNKED:
- conn->chunk_total += avail;
- conn->chunk_length -= avail;
-
- if (conn->chunk_length == 0) {
- D("%s: chunk completed (%lld bytes)",
- root->name, conn->chunk_length);
- conn->body_total += conn->chunk_total;
- conn->chunk_total = 0;
- conn->chunk_length = -1;
- }
- break;
-
- case BODY_KNOWN_LENGTH:
- conn->body_length -= avail;
- conn->body_total += avail;
-
- if (conn->body_length == 0) {
- D("%s: body completed (%lld bytes)",
- root->name, conn->body_total);
- conn->body_is_closed = 1;
- ret = DATA_COMPLETED;
- }
- break;
-
- case BODY_UNTIL_CLOSE:
- conn->body_total += avail;
- break;
-
- default:
- ;
- }
- }
- return ret;
-}
-
-static DataStatus
-rewrite_connection_send_body( RewriteConnection* conn, int fd )
-{
- ProxyConnection* root = conn->root;
- stralloc_t* str = root->str;
- DataStatus ret = DATA_NEED_MORE;
-
- if (conn->body_has_data) {
- ret = proxy_connection_send(root, fd);
- if (ret != DATA_ERROR) {
- int pos = root->str_pos;
-
- memmove(str->s, str->s+pos, str->n-pos);
- str->n -= pos;
- root->str_pos = 0;
- conn->body_is_full = (str->n == MAX_BODY_BUFFER);
- conn->body_has_data = (str->n > 0);
- conn->body_sent += root->str_sent;
-
- /* ensure that we return DATA_COMPLETED only when
- * we have sent everything, and there is no more
- * body pieces to read */
- if (ret == DATA_COMPLETED) {
- if (!conn->body_is_closed || conn->body_has_data)
- ret = DATA_NEED_MORE;
- else {
- D("%s: sent all body (%lld bytes)",
- root->name, conn->body_sent);
- }
- }
- D("%s: sent closed=%d data=%d n=%d ret=%d",
- root->name, conn->body_is_closed,
- conn->body_has_data, str->n,
- ret);
- }
- }
- return ret;
-}
-
-
-static void
-rewrite_connection_select( ProxyConnection* root,
- ProxySelect* sel )
-{
- RewriteConnection* conn = (RewriteConnection*)root;
- int slirp = conn->slirp_fd;
- int proxy = root->socket;
-
- switch (conn->state) {
- case STATE_CONNECTING:
- case STATE_CREATE_SOCKET_PAIR:
- /* try to connect to the proxy server */
- proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
- break;
-
- case STATE_REQUEST_FIRST_LINE:
- case STATE_REQUEST_HEADERS:
- proxy_select_set( sel, slirp, PROXY_SELECT_READ );
- break;
-
- case STATE_REQUEST_SEND:
- proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
- break;
-
- case STATE_REQUEST_BODY:
- if (!conn->body_is_closed && !conn->body_is_full)
- proxy_select_set( sel, slirp, PROXY_SELECT_READ );
-
- if (conn->body_has_data)
- proxy_select_set( sel, proxy, PROXY_SELECT_WRITE );
- break;
-
- case STATE_REPLY_FIRST_LINE:
- case STATE_REPLY_HEADERS:
- proxy_select_set( sel, proxy, PROXY_SELECT_READ );
- break;
-
- case STATE_REPLY_SEND:
- proxy_select_set( sel, slirp, PROXY_SELECT_WRITE );
- break;
-
- case STATE_REPLY_BODY:
- if (conn->body_has_data)
- proxy_select_set( sel, slirp, PROXY_SELECT_WRITE );
-
- if (!conn->body_is_closed && !conn->body_is_full)
- proxy_select_set( sel, proxy, PROXY_SELECT_READ );
- break;
- default:
- ;
- };
-}
-
-static void
-rewrite_connection_poll( ProxyConnection* root,
- ProxySelect* sel )
-{
- RewriteConnection* conn = (RewriteConnection*)root;
-
- int slirp = conn->slirp_fd;
- int proxy = root->socket;
- int has_slirp = proxy_select_poll(sel, slirp);
- int has_proxy = proxy_select_poll(sel, proxy);
- DataStatus ret = DATA_NEED_MORE;
-
- switch (conn->state) {
- case STATE_CONNECTING:
- if (has_proxy) {
- PROXY_LOG("%s: connected to proxy", root->name);
- conn->state = STATE_CREATE_SOCKET_PAIR;
- }
- break;
-
- case STATE_CREATE_SOCKET_PAIR:
- if (has_proxy) {
- if (rewrite_connection_create_sockets(conn) < 0) {
- ret = DATA_ERROR;
- } else {
- D("%s: socket pair created", root->name);
- conn->state = STATE_REQUEST_FIRST_LINE;
- }
- }
- break;
-
- case STATE_REQUEST_FIRST_LINE:
- if (has_slirp) {
- ret = rewrite_connection_read_request(conn);
- if (ret == DATA_COMPLETED) {
- PROXY_LOG("%s: request first line ok", root->name);
- conn->state = STATE_REQUEST_HEADERS;
- }
- }
- break;
-
- case STATE_REQUEST_HEADERS:
- if (has_slirp) {
- ret = rewrite_connection_read_headers(conn, slirp);
- if (ret == DATA_COMPLETED) {
- PROXY_LOG("%s: request headers ok", root->name);
- if (rewrite_connection_rewrite_request(conn) < 0)
- ret = DATA_ERROR;
- else
- conn->state = STATE_REQUEST_SEND;
- }
- }
- break;
-
- case STATE_REQUEST_SEND:
- if (has_proxy) {
- ret = proxy_connection_send(root, proxy);
- if (ret == DATA_COMPLETED) {
- if (rewrite_connection_get_body_length(conn, 1) < 0) {
- ret = DATA_ERROR;
- } else if (conn->body_mode != BODY_NONE) {
- PROXY_LOG("%s: request sent, waiting for body",
- root->name);
- conn->state = STATE_REQUEST_BODY;
- } else {
- PROXY_LOG("%s: request sent, waiting for reply",
- root->name);
- conn->state = STATE_REPLY_FIRST_LINE;
- }
- }
- }
- break;
-
- case STATE_REQUEST_BODY:
- if (has_slirp) {
- ret = rewrite_connection_read_body(conn, slirp);
- }
- if (ret != DATA_ERROR && has_proxy) {
- ret = rewrite_connection_send_body(conn, proxy);
- if (ret == DATA_COMPLETED) {
- PROXY_LOG("%s: request body ok, waiting for reply",
- root->name);
- conn->state = STATE_REPLY_FIRST_LINE;
- }
- }
- break;
-
- case STATE_REPLY_FIRST_LINE:
- if (has_proxy) {
- ret = rewrite_connection_read_reply(conn);
- if (ret == DATA_COMPLETED) {
- PROXY_LOG("%s: reply first line ok", root->name);
- conn->state = STATE_REPLY_HEADERS;
- }
- }
- break;
-
- case STATE_REPLY_HEADERS:
- if (has_proxy) {
- ret = rewrite_connection_read_headers(conn, proxy);
- if (ret == DATA_COMPLETED) {
- PROXY_LOG("%s: reply headers ok", root->name);
- if (rewrite_connection_rewrite_reply(conn) < 0)
- ret = DATA_ERROR;
- else
- conn->state = STATE_REPLY_SEND;
- }
- }
- break;
-
- case STATE_REPLY_SEND:
- if (has_slirp) {
- ret = proxy_connection_send(conn->root, slirp);
- if (ret == DATA_COMPLETED) {
- if (rewrite_connection_get_body_length(conn, 0) < 0) {
- ret = DATA_ERROR;
- } else if (conn->body_mode != BODY_NONE) {
- PROXY_LOG("%s: reply sent, waiting for body",
- root->name);
- conn->state = STATE_REPLY_BODY;
- } else {
- PROXY_LOG("%s: reply sent, looping to waiting request",
- root->name);
- conn->state = STATE_REQUEST_FIRST_LINE;
- }
- }
- }
- break;
-
- case STATE_REPLY_BODY:
- if (has_proxy) {
- ret = rewrite_connection_read_body(conn, proxy);
- }
- if (ret != DATA_ERROR && has_slirp) {
- ret = rewrite_connection_send_body(conn, slirp);
- if (ret == DATA_COMPLETED) {
- if (conn->body_mode == BODY_UNTIL_CLOSE) {
- PROXY_LOG("%s: closing connection", root->name);
- ret = DATA_ERROR;
- } else {
- PROXY_LOG("%s: reply body ok, looping to waiting request",
- root->name);
- conn->state = STATE_REQUEST_FIRST_LINE;
- }
- }
- }
- break;
-
- default:
- ;
- }
- if (ret == DATA_ERROR)
- proxy_connection_free(root, 0, PROXY_EVENT_NONE);
-
- return;
-}
-
-
-ProxyConnection*
-http_rewriter_connect( HttpService* service,
- SockAddress* address )
-{
- RewriteConnection* conn;
- int s;
-
- s = socket_create_inet( SOCKET_STREAM );
- if (s < 0)
- return NULL;
-
- conn = qemu_mallocz(sizeof(*conn));
- if (conn == NULL) {
- socket_close(s);
- return NULL;
- }
-
- proxy_connection_init( conn->root, s, address, service->root,
- rewrite_connection_free,
- rewrite_connection_select,
- rewrite_connection_poll );
-
- if ( rewrite_connection_init( conn ) < 0 ) {
- rewrite_connection_free( conn->root );
- return NULL;
- }
-
- return conn->root;
-}
diff --git a/proxy/proxy_int.h b/proxy/proxy_int.h
deleted file mode 100644
index 739bb75..0000000
--- a/proxy/proxy_int.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Copyright (C) 2007-2008 The Android Open Source Project
-**
-** This software is licensed under the terms of the GNU General Public
-** License version 2, as published by the Free Software Foundation, and
-** may be copied, distributed, and modified under those terms.
-**
-** This program is distributed in the hope that it will be useful,
-** but WITHOUT ANY WARRANTY; without even the implied warranty of
-** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-** GNU General Public License for more details.
-*/
-#ifndef _PROXY_INT_H
-#define _PROXY_INT_H
-
-#include "proxy_common.h"
-#include "sockets.h"
-#include "android/utils/stralloc.h"
-
-extern int proxy_log;
-
-extern void
-proxy_LOG(const char* fmt, ...);
-
-#define PROXY_LOG(...) \
- do { if (proxy_log) proxy_LOG(__VA_ARGS__); } while (0)
-
-
-/* ProxySelect is used to handle events */
-
-enum {
- PROXY_SELECT_READ = (1 << 0),
- PROXY_SELECT_WRITE = (1 << 1),
- PROXY_SELECT_ERROR = (1 << 2)
-};
-
-typedef struct {
- int* pcount;
- fd_set* reads;
- fd_set* writes;
- fd_set* errors;
-} ProxySelect;
-
-extern void proxy_select_set( ProxySelect* sel,
- int fd,
- unsigned flags );
-
-extern unsigned proxy_select_poll( ProxySelect* sel, int fd );
-
-
-/* sockets proxy manager internals */
-
-typedef struct ProxyConnection ProxyConnection;
-typedef struct ProxyService ProxyService;
-
-/* free a given proxified connection */
-typedef void (*ProxyConnectionFreeFunc) ( ProxyConnection* conn );
-
-/* modify the ProxySelect to tell which events to listen to */
-typedef void (*ProxyConnectionSelectFunc) ( ProxyConnection* conn,
- ProxySelect* sel );
-
-/* action a proxy connection when select() returns certain events for its socket */
-typedef void (*ProxyConnectionPollFunc) ( ProxyConnection* conn,
- ProxySelect* sel );
-
-
-/* root ProxyConnection object */
-struct ProxyConnection {
- int socket;
- SockAddress address; /* for debugging */
- ProxyConnection* next;
- ProxyConnection* prev;
- ProxyEventFunc ev_func;
- void* ev_opaque;
- ProxyService* service;
-
- /* the following is useful for all types of services */
- char name[64]; /* for debugging purposes */
-
- stralloc_t str[1]; /* network buffer (dynamic) */
- int str_pos; /* see proxy_connection_send() */
- int str_sent; /* see proxy_connection_send() */
- int str_recv; /* see proxy_connection_receive() */
-
- /* connection methods */
- ProxyConnectionFreeFunc conn_free;
- ProxyConnectionSelectFunc conn_select;
- ProxyConnectionPollFunc conn_poll;
-
- /* rest of data depend on exact implementation */
-};
-
-
-
-extern void
-proxy_connection_init( ProxyConnection* conn,
- int socket,
- SockAddress* address,
- ProxyService* service,
- ProxyConnectionFreeFunc conn_free,
- ProxyConnectionSelectFunc conn_select,
- ProxyConnectionPollFunc conn_poll );
-
-extern void
-proxy_connection_done( ProxyConnection* conn );
-
-/* free the proxy connection object. this will also
- * close the corresponding socket unless the
- * 'keep_alive' flag is set to TRUE.
- */
-extern void
-proxy_connection_free( ProxyConnection* conn,
- int keep_alive,
- ProxyEvent event );
-
-/* status of data transfer operations */
-typedef enum {
- DATA_ERROR = -1,
- DATA_NEED_MORE = 0,
- DATA_COMPLETED = 1
-} DataStatus;
-
-/* try to send data from the connection's buffer to a socket.
- * starting from offset conn->str_pos in the buffer
- *
- * returns DATA_COMPLETED if everything could be written
- * returns DATA_ERROR for a socket disconnection or error
- * returns DATA_NEED_MORE if all data could not be sent.
- *
- * on exit, conn->str_sent contains the number of bytes
- * that were really sent. conn->str_pos will be incremented
- * by conn->str_sent as well.
- *
- * note that in case of success (DATA_COMPLETED), this also
- * performs a proxy_connection_rewind which sets conn->str_pos
- * to 0.
- */
-extern DataStatus
-proxy_connection_send( ProxyConnection* conn, int fd );
-
-/* try to read 'wanted' bytes into conn->str from a socket
- *
- * returns DATA_COMPLETED if all bytes could be read
- * returns DATA_NEED_MORE if not all bytes could be read
- * returns DATA_ERROR in case of socket disconnection or error
- *
- * on exit, the amount of data received is in conn->str_recv
- */
-extern DataStatus
-proxy_connection_receive( ProxyConnection* conn, int fd, int wanted );
-
-/* tries to receive a line of text from the proxy.
- * when an entire line is read, the trailing \r\n is stripped
- * and replaced by a terminating zero. str->n will be the
- * lenght of the line, exclusing the terminating zero.
- * returns 1 when a line has been received
- * returns 0 if there is still some data to receive
- * returns -1 in case of error
- */
-extern DataStatus
-proxy_connection_receive_line( ProxyConnection* conn, int fd );
-
-/* rewind the string buffer for a new operation */
-extern void
-proxy_connection_rewind( ProxyConnection* conn );
-
-/* base64 encode a source string, returns size of encoded result,
- * or -1 if there was not enough room in the destination buffer
- */
-extern int
-proxy_base64_encode( const char* src, int srclen,
- char* dst, int dstlen );
-
-extern int
-proxy_resolve_server( SockAddress* addr,
- const char* servername,
- int servernamelen,
- int serverport );
-
-/* a ProxyService is really a proxy server and associated options */
-
-/* destroy a given proxy service */
-typedef void (*ProxyServiceFreeFunc) ( void* opaque );
-
-/* tries to create a new proxified connection, returns NULL if the service can't
- * handle this address */
-typedef ProxyConnection* (*ProxyServiceConnectFunc)( void* opaque,
- SocketType socket_type,
- const SockAddress* address );
-
-struct ProxyService {
- void* opaque;
- ProxyServiceFreeFunc serv_free;
- ProxyServiceConnectFunc serv_connect;
-};
-
-extern int
-proxy_manager_add_service( ProxyService* service );
-
-
-#endif /* _PROXY_INT_H */