aboutsummaryrefslogtreecommitdiffstats
path: root/proxy/proxy_common.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:04:49 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2008-12-17 18:04:49 -0800
commitdf7881f07f53b041dc0568be8528e9dbb74994cc (patch)
tree1b3e036f7df4241bf0c2d527b73198c50e1d7891 /proxy/proxy_common.c
parent55f4e4a5ec657a017e3bf75299ad71fd1c968dd3 (diff)
downloadexternal_qemu-df7881f07f53b041dc0568be8528e9dbb74994cc.zip
external_qemu-df7881f07f53b041dc0568be8528e9dbb74994cc.tar.gz
external_qemu-df7881f07f53b041dc0568be8528e9dbb74994cc.tar.bz2
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'proxy/proxy_common.c')
-rw-r--r--proxy/proxy_common.c345
1 files changed, 199 insertions, 146 deletions
diff --git a/proxy/proxy_common.c b/proxy/proxy_common.c
index c5762dc..0e45481 100644
--- a/proxy/proxy_common.c
+++ b/proxy/proxy_common.c
@@ -26,6 +26,7 @@ proxy_LOG(const char* fmt, ...)
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
+ fprintf(stderr, "\n");
}
void
@@ -39,49 +40,39 @@ proxy_set_verbose(int mode)
static ProxyConnection s_connections[1];
+#define MAX_HEX_DUMP 512
+
static void
hex_dump( void* base, int size, const char* prefix )
{
- uint8_t* p = (uint8_t*)base;
- const int max_count = 16;
-
- while (size > 0) {
- int count = size > max_count ? max_count : size;
- int n;
- const char* space = prefix;
-
- for (n = 0; n < count; n++) {
- proxy_LOG( "%s%02x", space, p[n] );
- space = " ";
- }
-
- proxy_LOG( "%-*s", 4 + 3*(max_count-n), "" );
-
- for (n = 0; n < count; n++) {
- int c = p[n];
-
- if (c < 32 || c > 127)
- c = '.';
- proxy_LOG( "%c", c );
- }
- proxy_LOG( "\n" );
- size -= count;
- p += count;
- }
+ 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,
- struct sockaddr_in* address,
- ProxyService* service )
+proxy_connection_init( ProxyConnection* conn,
+ int socket,
+ struct sockaddr_in* 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);
+
{
uint32_t ip = ntohl(address->sin_addr.s_addr);
uint16_t port = ntohs(address->sin_port);
@@ -98,122 +89,154 @@ proxy_connection_init( ProxyConnection* conn,
conn->name[sizeof(conn->name)-1] = 0;
}
- conn->buffer_pos = 0;
- conn->buffer_len = 0;
- conn->buffer = conn->buffer0;
+ stralloc_reset(conn->str);
+ conn->str_pos = 0;
}
void
proxy_connection_done( ProxyConnection* conn )
{
- if (conn->buffer != conn->buffer0) {
- qemu_free(conn->buffer);
+ stralloc_reset( conn->str );
+ if (conn->socket >= 0) {
+ socket_close(conn->socket);
+ conn->socket = -1;
}
}
-int
-proxy_connection_send( ProxyConnection* conn )
+void
+proxy_connection_rewind( ProxyConnection* conn )
{
- int result = -1;
- int fd = conn->socket;
- int avail = conn->buffer_len - conn->buffer_pos;
+ 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:\n", conn->name, avail );
- hex_dump( conn->buffer + conn->buffer_pos, avail, ">> " );
+ PROXY_LOG("%s: sending %d bytes:", conn->name, avail );
+ hex_dump( str->s + conn->str_pos, avail, ">> " );
}
while (avail > 0) {
- int n = send(fd, conn->buffer + conn->buffer_pos, avail, 0);
+ int n = send(fd, str->s + conn->str_pos, avail, 0);
+ if (n == 0) {
+ PROXY_LOG("%s: connection reset by peer (send)",
+ conn->name);
+ return DATA_ERROR;
+ }
if (n < 0) {
- if (errno == EINTR)
+ if (socket_errno == EINTR)
continue;
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- return 0;
- PROXY_LOG("%s: error: %s\n", conn->name, strerror(errno));
- return -1;
+
+ if (socket_errno == EWOULDBLOCK || socket_errno == EAGAIN)
+ return DATA_NEED_MORE;
+
+ PROXY_LOG("%s: error: %s", conn->name, socket_errstr());
+ return DATA_ERROR;
}
- conn->buffer_pos += n;
- avail -= n;
+ conn->str_pos += n;
+ conn->str_sent += n;
+ avail -= n;
}
- return 1;
+
+ proxy_connection_rewind(conn);
+ return DATA_COMPLETED;
}
-int
-proxy_connection_receive( ProxyConnection* conn )
+
+DataStatus
+proxy_connection_receive( ProxyConnection* conn, int fd, int wanted )
{
- int result = -1;
- int fd = conn->socket;
- int avail = conn->buffer_len - conn->buffer_pos;
+ stralloc_t* str = conn->str;
- while (avail > 0) {
- int n = recv(fd, conn->buffer + conn->buffer_pos, avail, 0);
+ conn->str_recv = 0;
+
+ while (wanted > 0) {
+ int n;
+
+ stralloc_readyplus( str, wanted );
+ n = recv(fd, str->s + str->n, wanted, 0);
+ if (n == 0) {
+ PROXY_LOG("%s: connection reset by peer (receive)",
+ conn->name);
+ return DATA_ERROR;
+ }
if (n < 0) {
- if (errno == EINTR)
+ if (socket_errno == EINTR)
continue;
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- return 0;
- PROXY_LOG("%s: error: %s\n", conn->name, strerror(errno));
- return -1;
+
+ if (socket_errno == EWOULDBLOCK || socket_errno == EAGAIN)
+ return DATA_NEED_MORE;
+
+ PROXY_LOG("%s: error: %s", conn->name, socket_errstr());
+ return DATA_ERROR;
}
if (proxy_log) {
- PROXY_LOG("%s: received %d bytes:\n", conn->name, n );
- hex_dump( conn->buffer + conn->buffer_pos, n, ">> " );
+ PROXY_LOG("%s: received %d bytes:", conn->name, n );
+ hex_dump( str->s + str->n, n, "<< " );
}
- conn->buffer_pos += n;
- avail -= n;
+ str->n += n;
+ wanted -= n;
+ conn->str_recv += n;
}
- return 1;
+ return DATA_COMPLETED;
}
-int
-proxy_connection_receive_line( ProxyConnection* conn )
+
+DataStatus
+proxy_connection_receive_line( ProxyConnection* conn, int fd )
{
- int result = -1;
- int fd = conn->socket;
+ stralloc_t* str = conn->str;
for (;;) {
char c;
int n = recv(fd, &c, 1, 0);
if (n == 0) {
- PROXY_LOG("%s: disconnected from server\n", conn->name );
- return -1;
+ PROXY_LOG("%s: disconnected from server", conn->name );
+ return DATA_ERROR;
}
if (n < 0) {
- if (errno == EINTR)
+ if (socket_errno == EINTR)
continue;
- if (errno == EWOULDBLOCK || errno == EAGAIN) {
- PROXY_LOG("%s: blocked\n", conn->name);
- return 0;
+
+ if (socket_errno == EWOULDBLOCK || socket_errno == EAGAIN) {
+ PROXY_LOG("%s: blocked", conn->name);
+ return DATA_NEED_MORE;
}
- PROXY_LOG("%s: error: %s\n", conn->name, strerror(errno));
- return -1;
+ PROXY_LOG("%s: error: %s", conn->name, socket_errstr());
+ return DATA_ERROR;
}
+ stralloc_add_c(str, c);
if (c == '\n') {
- if (conn->buffer_pos > 0 && conn->buffer[conn->buffer_pos-1] == '\r')
- conn->buffer_pos -= 1;
-
- conn->buffer[conn->buffer_pos] = 0;
+ 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'\n", conn->name,
- conn->buffer_pos, conn->buffer);
- return 1;
- }
-
- conn->buffer[ conn->buffer_pos++ ] = c;
- if (conn->buffer_pos == conn->buffer_len) {
- PROXY_LOG("%s: line received from proxy is too long\n", conn->name);
- return -1;
+ 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 )
{
@@ -276,7 +299,7 @@ proxy_manager_atexit( void )
/* free all proxy connections */
while (conn != s_connections) {
ProxyConnection* next = conn->next;
- conn->service->conn_free( conn );
+ conn->conn_free( conn );
conn = next;
}
conn->next = conn;
@@ -293,6 +316,7 @@ proxy_manager_atexit( void )
void
proxy_connection_free( ProxyConnection* conn,
+ int keep_alive,
ProxyEvent event )
{
if (conn) {
@@ -301,18 +325,21 @@ proxy_connection_free( ProxyConnection* conn,
proxy_connection_remove(conn);
if (event != PROXY_EVENT_NONE)
- conn->ev_func( conn->ev_opaque, event );
+ conn->ev_func( conn->ev_opaque, fd, event );
- conn->service->conn_free(conn);
+ if (keep_alive)
+ conn->socket = -1;
+
+ conn->conn_free(conn);
}
}
int
-proxy_manager_add( int socket,
- struct sockaddr_in* address,
- void* ev_opaque,
- ProxyEventFunc ev_func )
+proxy_manager_add( struct sockaddr_in* address,
+ int sock_type,
+ ProxyEventFunc ev_func,
+ void* ev_opaque )
{
int n;
@@ -320,16 +347,14 @@ proxy_manager_add( int socket,
proxy_manager_init();
}
- socket_set_nonblock(socket);
-
for (n = 0; n < s_num_services; n++) {
ProxyService* service = s_services[n];
ProxyConnection* conn = service->serv_connect( service->opaque,
- socket,
+ sock_type,
address );
if (conn != NULL) {
- conn->ev_opaque = ev_opaque;
conn->ev_func = ev_func;
+ conn->ev_opaque = ev_opaque;
proxy_connection_insert(conn, s_connections->prev);
return 0;
}
@@ -343,50 +368,83 @@ proxy_manager_add( int socket,
* the connection accept/refusal occured
*/
void
-proxy_manager_del( int socket )
+proxy_manager_del( void* ev_opaque )
{
ProxyConnection* conn = s_connections->next;
for ( ; conn != s_connections; conn = conn->next ) {
- if (conn->socket == socket) {
- int fd = conn->socket;
+ if (conn->ev_opaque == ev_opaque) {
proxy_connection_remove(conn);
- conn->service->conn_free(conn);
- socket_close(fd);
+ 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();
- conn = s_connections->next;
- for ( ; conn != s_connections; conn = conn->next ) {
- unsigned flags = conn->service->conn_select(conn);
- int fd = conn->socket;
-
- if (!flags)
- continue;
+ sel->pcount = pcount;
+ sel->reads = read_fds;
+ sel->writes = write_fds;
+ sel->errors = err_fds;
- if (*pcount < fd+1)
- *pcount = fd+1;
-
- if (flags & PROXY_SELECT_READ) {
- FD_SET( fd, read_fds );
- }
- if (flags & PROXY_SELECT_WRITE) {
- FD_SET( fd, write_fds );
- }
- if (flags & PROXY_SELECT_ERROR) {
- FD_SET( fd, err_fds );
- }
+ conn = s_connections->next;
+ while (conn != s_connections) {
+ ProxyConnection* next = conn->next;
+ conn->conn_select(conn, sel);
+ conn = next;
}
}
@@ -395,21 +453,16 @@ void
proxy_manager_poll( fd_set* read_fds, fd_set* write_fds, fd_set* err_fds )
{
ProxyConnection* conn = s_connections->next;
- while (conn != s_connections) {
- ProxyConnection* next = conn->next;
- int fd = conn->socket;
- unsigned flags = 0;
+ ProxySelect sel[1];
- if ( FD_ISSET(fd, read_fds) )
- flags |= PROXY_SELECT_READ;
- if ( FD_ISSET(fd, write_fds) )
- flags |= PROXY_SELECT_WRITE;
- if ( FD_ISSET(fd, err_fds) )
- flags |= PROXY_SELECT_ERROR;
+ sel->pcount = NULL;
+ sel->reads = read_fds;
+ sel->writes = write_fds;
+ sel->errors = err_fds;
- if (flags != 0) {
- conn->service->conn_poll( conn, flags );
- }
+ while (conn != s_connections) {
+ ProxyConnection* next = conn->next;
+ conn->conn_poll( conn, sel );
conn = next;
}
}
@@ -480,7 +533,7 @@ proxy_resolve_server( struct sockaddr_in* addr,
host = gethostbyname(name);
if (host == NULL) {
- PROXY_LOG("%s: can't resolve proxy server name '%s'\n",
+ PROXY_LOG("%s: can't resolve proxy server name '%s'",
__FUNCTION__, name);
goto Exit;
}
@@ -488,7 +541,7 @@ proxy_resolve_server( struct sockaddr_in* addr,
addr->sin_addr = *(struct in_addr*)host->h_addr;
{
uint32_t a = ntohl(addr->sin_addr.s_addr);
- PROXY_LOG("server name '%s' resolved to %d.%d.%d.%d\n", name, (a>>24)&255, (a>>16)&255,(a>>8)&255,a&255);
+ PROXY_LOG("server name '%s' resolved to %d.%d.%d.%d", name, (a>>24)&255, (a>>16)&255,(a>>8)&255,a&255);
}
result = 0;