18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Copyright (C) 2007-2008 The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This software is licensed under the terms of the GNU General Public
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** License version 2, as published by the Free Software Foundation, and
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** may be copied, distributed, and modified under those terms.
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project**
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** This program is distributed in the hope that it will be useful,
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** but WITHOUT ANY WARRANTY; without even the implied warranty of
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project** GNU General Public License for more details.
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project*/
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "proxy_int.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "sockets.h"
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdarg.h>
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdio.h>
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <string.h>
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <errno.h>
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/misc.h"
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "android/utils/system.h"
209b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner#include "iolooper.h"
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include <stdlib.h>
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint  proxy_log = 0;
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_LOG(const char*  fmt, ...)
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_list  args;
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_start(args, fmt);
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    vfprintf(stderr, fmt, args);
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    va_end(args);
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    fprintf(stderr, "\n");
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_set_verbose(int  mode)
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    proxy_log = mode;
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** Global connection list
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic ProxyConnection  s_connections[1];
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_HEX_DUMP  512
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecthex_dump( void*   base, int  size, const char*  prefix )
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    STRALLOC_DEFINE(s);
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (size > MAX_HEX_DUMP)
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        size = MAX_HEX_DUMP;
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_add_hexdump(s, base, size, prefix);
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    proxy_LOG( "%s", stralloc_cstr(s) );
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_reset(s);
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_init( ProxyConnection*           conn,
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int                        socket,
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       SockAddress*               address,
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ProxyService*              service,
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ProxyConnectionFreeFunc    conn_free,
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ProxyConnectionSelectFunc  conn_select,
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ProxyConnectionPollFunc    conn_poll )
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->socket    = socket;
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->address   = address[0];
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->service   = service;
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->next      = NULL;
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->conn_free   = conn_free;
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->conn_select = conn_select;
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->conn_poll   = conn_poll;
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    socket_set_nonblock(socket);
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        SocketType  type = socket_get_type(socket);
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        snprintf( conn->name, sizeof(conn->name),
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  "%s:%s(%d)",
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  (type == SOCKET_STREAM) ? "tcp" : "udp",
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  sock_address_to_string(address), socket );
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        /* just in case */
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->name[sizeof(conn->name)-1] = 0;
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_reset(conn->str);
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->str_pos = 0;
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_done( ProxyConnection*  conn )
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_reset( conn->str );
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (conn->socket >= 0) {
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        socket_close(conn->socket);
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->socket = -1;
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_rewind( ProxyConnection*  conn )
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_t*  str = conn->str;
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* only keep a small buffer in the heap */
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->str_pos = 0;
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    str->n        = 0;
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (str->a > 1024)
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_reset(str);
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectDataStatus
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_send( ProxyConnection*  conn, int  fd )
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_t*  str    = conn->str;
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int          avail  = str->n - conn->str_pos;
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->str_sent = 0;
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (avail <= 0)
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return 1;
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (proxy_log) {
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PROXY_LOG("%s: sending %d bytes:", conn->name, avail );
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        hex_dump( str->s + conn->str_pos, avail, ">> " );
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (avail > 0) {
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  n = socket_send(fd, str->s + conn->str_pos, avail);
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n == 0) {
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: connection reset by peer (send)",
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      conn->name);
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_ERROR;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n < 0) {
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (errno == EWOULDBLOCK || errno == EAGAIN)
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return DATA_NEED_MORE;
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: error: %s", conn->name, errno_str);
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_ERROR;
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->str_pos  += n;
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->str_sent += n;
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        avail          -= n;
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    proxy_connection_rewind(conn);
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return DATA_COMPLETED;
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectDataStatus
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_receive( ProxyConnection*  conn, int  fd, int  wanted )
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_t*  str    = conn->str;
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->str_recv = 0;
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (wanted > 0) {
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  n;
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_readyplus( str, wanted );
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        n = socket_recv(fd, str->s + str->n, wanted);
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n == 0) {
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: connection reset by peer (receive)",
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      conn->name);
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_ERROR;
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n < 0) {
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (errno == EWOULDBLOCK || errno == EAGAIN)
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return DATA_NEED_MORE;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: error: %s", conn->name, errno_str);
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_ERROR;
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (proxy_log) {
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: received %d bytes:", conn->name, n );
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            hex_dump( str->s + str->n, n, "<< " );
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        str->n         += n;
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        wanted         -= n;
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->str_recv += n;
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return DATA_COMPLETED;
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectDataStatus
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_receive_line( ProxyConnection*  conn, int  fd )
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    stralloc_t*  str = conn->str;
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (;;) {
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        char  c;
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int   n = socket_recv(fd, &c, 1);
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n == 0) {
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: disconnected from server", conn->name );
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_ERROR;
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (n < 0) {
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (errno == EWOULDBLOCK || errno == EAGAIN) {
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                PROXY_LOG("%s: blocked", conn->name);
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                return DATA_NEED_MORE;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: error: %s", conn->name, errno_str);
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_ERROR;
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        stralloc_add_c(str, c);
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (c == '\n') {
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            str->s[--str->n] = 0;
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (str->n > 0 && str->s[str->n-1] == '\r')
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                str->s[--str->n] = 0;
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PROXY_LOG("%s: received '%s'", conn->name,
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      quote_bytes(str->s, str->n));
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return DATA_COMPLETED;
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_insert( ProxyConnection*  conn, ProxyConnection*  after )
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->next        = after->next;
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    after->next->prev = conn;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    after->next       = conn;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->prev        = after;
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_remove( ProxyConnection*  conn )
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->prev->next = conn->next;
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->next->prev = conn->prev;
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->next = conn->prev = conn;
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/** Global service list
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project **/
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define  MAX_SERVICES  4
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic  ProxyService*  s_services[ MAX_SERVICES ];
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic  int            s_num_services;
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic  int            s_init;
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void  proxy_manager_atexit( void );
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_init(void)
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s_init = 1;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s_connections->next = s_connections;
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s_connections->prev = s_connections;
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    atexit( proxy_manager_atexit );
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern int
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_add_service( ProxyService*  service )
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!service || s_num_services >= MAX_SERVICES)
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return -1;
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s_init)
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proxy_manager_init();
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s_services[s_num_services++] = service;
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return 0;
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectextern void
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_atexit( void )
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ProxyConnection*  conn = s_connections->next;
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               n;
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* free all proxy connections */
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (conn != s_connections) {
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ProxyConnection*  next = conn->next;
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->conn_free( conn );
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn = next;
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->next = conn;
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn->prev = conn;
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    /* free all proxy services */
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (n = s_num_services; n-- > 0;) {
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ProxyService*  service = s_services[n];
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        service->serv_free( service->opaque );
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    s_num_services = 0;
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_connection_free( ProxyConnection*  conn,
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       int               keep_alive,
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                       ProxyEvent        event )
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (conn) {
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        int  fd = conn->socket;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proxy_connection_remove(conn);
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (event != PROXY_EVENT_NONE)
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            conn->ev_func( conn->ev_opaque, fd, event );
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (keep_alive)
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            conn->socket = -1;
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->conn_free(conn);
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_add( SockAddress*    address,
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   SocketType      sock_type,
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   ProxyEventFunc  ev_func,
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   void*           ev_opaque )
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int  n;
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s_init) {
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proxy_manager_init();
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for (n = 0; n < s_num_services; n++) {
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ProxyService*     service = s_services[n];
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ProxyConnection*  conn    = service->serv_connect( service->opaque,
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                           sock_type,
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                                                           address );
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conn != NULL) {
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            conn->ev_func   = ev_func;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            conn->ev_opaque = ev_opaque;
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            proxy_connection_insert(conn, s_connections->prev);
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return 0;
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return -1;
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* remove an on-going proxified socket connection from the manager's list.
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * this is only necessary when the socket connection must be canceled before
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the connection accept/refusal occured
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_del( void*  ev_opaque )
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ProxyConnection*  conn = s_connections->next;
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    for ( ; conn != s_connections; conn = conn->next ) {
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (conn->ev_opaque == ev_opaque) {
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            proxy_connection_remove(conn);
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            conn->conn_free(conn);
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        }
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_select_set( ProxySelect*  sel,
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  int           fd,
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  unsigned      flags )
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd < 0 || !flags)
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (*sel->pcount < fd+1)
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *sel->pcount = fd+1;
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & PROXY_SELECT_READ) {
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FD_SET( fd, sel->reads );
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FD_CLR( fd, sel->reads );
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & PROXY_SELECT_WRITE) {
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FD_SET( fd, sel->writes );
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FD_CLR( fd, sel->writes );
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (flags & PROXY_SELECT_ERROR) {
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FD_SET( fd, sel->errors );
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    } else {
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        FD_CLR( fd, sel->errors );
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectunsigned
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_select_poll( ProxySelect*  sel, int  fd )
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    unsigned  flags = 0;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (fd >= 0) {
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( FD_ISSET(fd, sel->reads) )
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            flags |= PROXY_SELECT_READ;
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( FD_ISSET(fd, sel->writes) )
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            flags |= PROXY_SELECT_WRITE;
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if ( FD_ISSET(fd, sel->errors) )
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            flags |= PROXY_SELECT_ERROR;
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return flags;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function is called to update the select file descriptor sets
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * with those of the proxified connection sockets that are currently managed */
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_select_fill( int  *pcount, fd_set*  read_fds, fd_set*  write_fds, fd_set*  err_fds)
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ProxyConnection*  conn;
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ProxySelect       sel[1];
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (!s_init)
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        proxy_manager_init();
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->pcount = pcount;
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->reads  = read_fds;
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->writes = write_fds;
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->errors = err_fds;
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    conn = s_connections->next;
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (conn != s_connections) {
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ProxyConnection*  next = conn->next;
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->conn_select(conn, sel);
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn = next;
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* this function is called to act on proxified connection sockets when network events arrive */
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_manager_poll( fd_set*  read_fds, fd_set*  write_fds, fd_set*  err_fds )
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ProxyConnection*  conn = s_connections->next;
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    ProxySelect       sel[1];
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->pcount = NULL;
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->reads  = read_fds;
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->writes = write_fds;
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    sel->errors = err_fds;
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (conn != s_connections) {
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        ProxyConnection*  next  = conn->next;
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn->conn_poll( conn, sel );
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        conn = next;
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_base64_encode( const char*  src, int  srclen,
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     char*        dst, int  dstlen )
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    static const char cb64[64]="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    const char*       srcend = src + srclen;
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int               result = 0;
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    while (src+3 <= srcend && result+4 <= dstlen)
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    {
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+0] = cb64[ src[0] >> 2 ];
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+1] = cb64[ ((src[0] & 3) << 4) | ((src[1] & 0xf0) >> 4) ];
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+2] = cb64[ ((src[1] & 0xf) << 2) | ((src[2] & 0xc0) >> 6) ];
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+3] = cb64[ src[2] & 0x3f ];
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        src    += 3;
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += 4;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (src < srcend) {
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        unsigned char  in[4];
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        if (result+4 > dstlen)
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return -1;
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        in[0] = src[0];
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        in[1] = src+1 < srcend ? src[1] : 0;
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        in[2] = src+2 < srcend ? src[2] : 0;
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+0] = cb64[ in[0] >> 2 ];
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+1] = cb64[ ((in[0] & 3) << 4) | ((in[1] & 0xf0) >> 4) ];
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+2] = (unsigned char) (src+1 < srcend ? cb64[ ((in[1] & 0xf) << 2) | ((in[2] & 0xc0) >> 6) ] : '=');
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        dst[result+3] = (unsigned char) (src+2 < srcend ? cb64[ in[2] & 0x3f ] : '=');
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        result += 4;
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectint
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectproxy_resolve_server( SockAddress*   addr,
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      const char*    servername,
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      int            servernamelen,
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                      int            serverport )
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char  name0[64], *name = name0;
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int   result = -1;
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (servernamelen < 0)
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        servernamelen = strlen(servername);
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (servernamelen >= sizeof(name0)) {
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        AARRAY_NEW(name, servernamelen+1);
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    memcpy(name, servername, servernamelen);
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    name[servernamelen] = 0;
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (sock_address_init_resolve( addr, name, serverport, 0 ) < 0) {
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        PROXY_LOG("%s: can't resolve proxy server name '%s'",
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  __FUNCTION__, name);
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        goto Exit;
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    }
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    PROXY_LOG("server name '%s' resolved to %s", name, sock_address_to_string(addr));
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    result = 0;
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source ProjectExit:
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    if (name != name0)
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        AFREE(name);
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    return result;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5349b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turnerint
5359b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turnerproxy_check_connection( const char* proxyname,
5369b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner                        int         proxyname_len,
5379b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner                        int         proxyport,
5389b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner                        int         timeout_ms )
5399b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner{
5409b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    SockAddress  addr;
5419b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    int          sock;
5429b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    IoLooper*    looper;
5439b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    int          ret;
5449b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5459b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    if (proxy_resolve_server(&addr, proxyname, proxyname_len, proxyport) < 0) {
5469b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        return -1;
5479b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    }
5489b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5499b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    sock = socket_create(addr.family, SOCKET_STREAM);
5509b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    if (sock < 0) {
5519b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        PROXY_LOG("%s: Could not create socket !?: %s", __FUNCTION__, errno_str);
5529b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        return -1;
5539b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    }
5549b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5559b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    socket_set_nonblock(sock);
5569b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5579b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    /* An immediate connection is very unlikely, but deal with it, just in case */
5589b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    if (socket_connect(sock, &addr) == 0) {
5599b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        PROXY_LOG("%s: Immediate connection to %.*s:%d: %s !",
5609b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner                    __FUNCTION__, proxyname_len, proxyname, proxyport);
5619b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        socket_close(sock);
5629b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        return 0;
5639b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    }
5649b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5659b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    /* Ok, create an IoLooper object to wait for the connection */
5669b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    looper = iolooper_new();
5679b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    iolooper_add_write(looper, sock);
5689b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5699b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    ret = iolooper_wait(looper, timeout_ms);
5709b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5719b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    iolooper_free(looper);
5729b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    socket_close(sock);
5739b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner
5749b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    if (ret == 0) {
5759b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        errno = ETIMEDOUT;
5769b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner        ret   = -1;
5779b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    }
5789b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner    return ret;
5799b98dbde344781e93e2bdcfa599428cda2fda41dDavid 'Digit' Turner}
580