changeset 132:11fa2bf90251

Network API changes due to preparation for fixes in proxy support.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 04 Jul 2014 02:18:26 +0300
parents 6624893ad528
children 84182dab4fca
files th_network.c th_network.h
diffstat 2 files changed, 117 insertions(+), 97 deletions(-) [+]
line wrap: on
line diff
--- a/th_network.c	Mon Jun 23 16:59:36 2014 +0300
+++ b/th_network.c	Fri Jul 04 02:18:26 2014 +0300
@@ -99,9 +99,10 @@
 
     if (res == NULL)
     {
-        th_conn_err(conn, h_errno,
+        int err = th_errno_to_error(h_errno);
+        th_conn_err(conn, err,
             "Could not resolve hostname '%s': %s\n",
-            name, th_error_str(h_errno));
+            name, th_error_str(err));
     }
     else
     {
@@ -113,6 +114,17 @@
 }
 
 
+BOOL th_base_conn_init(th_base_conn_t *base, ssize_t bufsize)
+{
+    // Allocate connection data buffer
+    base->bufsize = (bufsize <= 0) ? TH_CONNBUF_SIZE : bufsize;
+    if ((base->buf = th_malloc(base->bufsize)) == NULL)
+        return FALSE;
+    
+    return TRUE;
+}
+
+
 th_conn_t * th_conn_new(
     void (*errfunc)(th_conn_t *conn, int err, const char *msg),
     void (*msgfunc)(th_conn_t *conn, int loglevel, const char *msg),
@@ -127,9 +139,8 @@
     conn->errfunc = errfunc;
     conn->msgfunc = msgfunc;
 
-    // Allocate connection data buffer
-    conn->bufsize = (bufsize <= 0) ? TH_CONNBUF_SIZE : bufsize;
-    if ((conn->buf = th_malloc(conn->bufsize)) == NULL)
+    // Do base initialization
+    if (!th_base_conn_init(&conn->base, bufsize))
     {
         th_free(conn);
         return NULL;
@@ -160,16 +171,16 @@
         return THERR_NULLPTR;
 
     conn->proxy.type = type;
-    conn->proxy.port = port;
     conn->proxy.auth_type = auth_type;
     
-    th_free(conn->proxy.host);
-    conn->proxy.host = th_strdup(host);
+    conn->proxy.conn.port = port;
+    th_free(conn->proxy.conn.host);
+    conn->proxy.conn.host = th_strdup(host);
 
     if (host != NULL)
     {
-        conn->proxy.hst = th_resolve_host(conn, host);
-        th_get_addr(&(conn->proxy.addr), conn->proxy.hst);
+        conn->proxy.conn.hst = th_resolve_host(conn, host);
+        th_get_addr(&(conn->proxy.conn.addr), conn->proxy.conn.hst);
     }
     else
         return THERR_INVALID_DATA;
@@ -236,7 +247,7 @@
 
             case TH_CONN_DATA_AVAIL:
             case TH_CONN_NO_DATA:
-                if (conn->total_bytes < want)
+                if (conn->base.total_bytes < want)
                     status = TH_CONN_NO_DATA;
                 break;
             
@@ -287,7 +298,7 @@
     switch (conn->proxy.addr_type)
     {
         case TH_PROXY_ADDR_IPV4:
-            th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr));
+            th_growbuf_put_str(&buf, (uint8_t *) &(conn->base.addr.s_addr), sizeof(conn->base.addr.s_addr));
             break;
         
         case TH_PROXY_ADDR_DOMAIN:
@@ -321,7 +332,7 @@
     if (th_conn_proxy_wait(conn, 2) != TH_CONN_DATA_AVAIL)
         goto out;
 
-    ptr = (uint8_t*) conn->buf;
+    ptr = (uint8_t*) conn->base.buf;
     if (*ptr != 0)
     {
         err = THERR_INIT_FAIL;
@@ -359,8 +370,8 @@
 static int th_conn_socks5_negotiate(th_conn_t *conn, const int port, const char *host)
 {
     th_growbuf_t buf;
-    uint8_t *ptr;
-    int cmd, avail, auth, err = THERR_INIT_FAIL;
+    uint8_t *ptr, authlist[16];
+    int i, cmd, avail, auth, err = THERR_INIT_FAIL;
 
     th_growbuf_init(&buf, 256);
     th_conn_msg(conn, THLOG_INFO, "Initializing SOCKS 5 proxy negotiation.\n");
@@ -376,16 +387,11 @@
             goto out;
     }
 
+    avail = 0;
     switch (conn->proxy.auth_type)
     {
-        case TH_PROXY_AUTH_NONE:
-            avail = 1;
-            auth = SOCKS5_AUTH_NONE;
-            break;
-
         case TH_PROXY_AUTH_USER:
-            avail = 2;
-            auth = SOCKS5_AUTH_USER;
+            authlist[avail++] = SOCKS5_AUTH_USER;
             if (conn->proxy.userid == NULL || conn->proxy.passwd == NULL)
             {
                 err = THERR_INVALID_DATA;
@@ -402,6 +408,10 @@
                     "SOCKS 5 proxy userid or password is too long.\n");
                 goto out;
             }
+            //break;
+
+        case TH_PROXY_AUTH_NONE:
+            authlist[avail++] = SOCKS5_AUTH_NONE;
             break;
 
         default:
@@ -416,7 +426,8 @@
     th_growbuf_clear(&buf);
     th_growbuf_put_u8(&buf, 0x05);   // Protocol version
     th_growbuf_put_u8(&buf, avail);  // # of available auth methods
-    th_growbuf_put_u8(&buf, auth);
+    for (i = 0; i < avail; i++)
+        th_growbuf_put_u8(&buf, authlist[i]);
 
     // Send request
     if ((err = th_conn_proxy_send(conn, &buf)) != THERR_OK)
@@ -426,7 +437,7 @@
     if (th_conn_proxy_wait(conn, 2) != TH_CONN_DATA_AVAIL)
         goto out;
 
-    ptr = (uint8_t *) conn->buf;
+    ptr = (uint8_t *) conn->base.buf;
     if (*ptr != 0x05)
     {
         err = THERR_INVALID_DATA;
@@ -465,7 +476,7 @@
         if (th_conn_proxy_wait(conn, 2) != TH_CONN_DATA_AVAIL)
             goto out;
 
-        ptr = (uint8_t *) conn->buf;
+        ptr = (uint8_t *) conn->base.buf;
         if (*ptr != 0x01)
         {
             err = THERR_INVALID_DATA;
@@ -507,12 +518,12 @@
     {
         case TH_PROXY_ADDR_IPV4:
             th_growbuf_put_u8(&buf, SOCKS5_ADDR_IPV4);
-            th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr));
+            th_growbuf_put_str(&buf, (uint8_t *) &(conn->base.addr.s_addr), sizeof(conn->base.addr.s_addr));
             break;
 
         case TH_PROXY_ADDR_IPV6:
             th_growbuf_put_u8(&buf, SOCKS5_ADDR_IPV6);
-            //th_growbuf_put_str(&buf, (uint8_t *) &(conn->addr.s_addr), sizeof(conn->addr.s_addr));
+            //th_growbuf_put_str(&buf, (uint8_t *) &(conn->base.addr.s_addr), sizeof(conn->base.addr.s_addr));
             break;
         
         case TH_PROXY_ADDR_DOMAIN:
@@ -541,7 +552,7 @@
     if (th_conn_proxy_wait(conn, 3) != TH_CONN_DATA_AVAIL)
         goto out;
 
-    ptr = (uint8_t *) conn->buf;
+    ptr = (uint8_t *) conn->base.buf;
     if (*ptr != 0x05)
     {
         err = THERR_INVALID_DATA;
@@ -583,15 +594,15 @@
     if (conn == NULL)
         return THERR_NULLPTR;
 
-    conn->port = port;
-    conn->host = th_strdup(host);
-    conn->hst = th_resolve_host(conn, host);
+    conn->base.port = port;
+    conn->base.host = th_strdup(host);
+    conn->base.hst = th_resolve_host(conn, host);
     
     // If name resolving locally fails, force to domain addr type
-    if (conn->hst == NULL)
+    if (conn->base.hst == NULL)
         conn->proxy.addr_type = TH_PROXY_ADDR_DOMAIN;
 
-    th_get_addr(&(conn->addr), conn->hst);
+    th_get_addr(&(conn->base.addr), conn->base.hst);
 
     // Prepare for connection
     dest.sin_family = AF_INET;
@@ -599,38 +610,38 @@
     if (conn->proxy.type > TH_PROXY_NONE && conn->proxy.type < TH_PROXY_LAST)
     {
         // If using a proxy, we connect to the proxy server
-        dest.sin_port = htons(conn->proxy.port);
-        dest.sin_addr = conn->proxy.addr;
+        dest.sin_port = htons(conn->proxy.conn.port);
+        dest.sin_addr = conn->proxy.conn.addr;
 
         th_conn_msg(conn, THLOG_INFO, "Connecting to %s proxy %s:%d ...\n",
             th_proxy_types[conn->proxy.type],
-            inet_ntoa(conn->proxy.addr), conn->proxy.port);
+            inet_ntoa(conn->proxy.conn.addr), conn->proxy.conn.port);
     }
     else
     {
-        dest.sin_port = htons(conn->port);
-        dest.sin_addr = conn->addr;
+        dest.sin_port = htons(conn->base.port);
+        dest.sin_addr = conn->base.addr;
 
         th_conn_msg(conn, THLOG_INFO, "Connecting to %s:%d ...\n",
-            inet_ntoa(conn->addr), conn->port);
+            inet_ntoa(conn->base.addr), conn->base.port);
     }
 
-    if ((conn->socket = socket(PF_INET, SOCK_STREAM, 0)) == -1)
+    if ((conn->base.socket = socket(PF_INET, SOCK_STREAM, 0)) == -1)
     {
         err = th_errno_to_error(th_get_socket_errno());
         th_conn_err(conn, err, "Could not open socket: %s\n", th_error_str(err));
         goto error;
     }
 
-    if (connect(conn->socket, (struct sockaddr *) &dest, sizeof(dest)) == -1)
+    if (connect(conn->base.socket, (struct sockaddr *) &dest, sizeof(dest)) == -1)
     {
         err = th_errno_to_error(th_get_socket_errno());
         th_conn_err(conn, err, "Could not connect: %s\n", th_error_str(err));
         goto error;
     }
 
-    FD_ZERO(&(conn->sockfds));
-    FD_SET(conn->socket, &(conn->sockfds));
+    FD_ZERO(&(conn->base.sockfds));
+    FD_SET(conn->base.socket, &(conn->base.sockfds));
 
     // Proxy-specific setup
     switch (conn->proxy.type)
@@ -668,14 +679,14 @@
     if (conn == NULL)
         return -1;
 
-    if (conn->socket >= 0)
+    if (conn->base.socket >= 0)
     {
 #ifdef __WIN32
-        closesocket(conn->socket);
+        closesocket(conn->base.socket);
 #else
-        close(conn->socket);
+        close(conn->base.socket);
 #endif
-        conn->socket = -1;
+        conn->base.socket = -1;
     }
 
     conn->status = TH_CONN_CLOSED;
@@ -685,10 +696,10 @@
 
 static void th_conn_free_nodelete(th_conn_t *conn)
 {
-    th_free(conn->buf);
+    th_free(conn->base.buf);
     th_conn_close(conn);
-    th_free(conn->host);
-    th_free(conn->proxy.host);
+    th_free(conn->base.host);
+    th_free(conn->proxy.conn.host);
     th_free(conn);
 }
 
@@ -715,7 +726,7 @@
     while (bufLeft > 0)
     {
         ssize_t bufSent;
-        bufSent = send(conn->socket, bufPtr, bufLeft, 0);
+        bufSent = send(conn->base.socket, bufPtr, bufLeft, 0);
         if (bufSent < 0)
         {
             int err = th_errno_to_error(th_get_socket_errno());
@@ -742,8 +753,8 @@
 {
     if (conn != NULL)
     {
-        conn->ptr = conn->in_ptr = conn->buf;
-        conn->got_bytes = conn->total_bytes = 0;
+        conn->base.ptr = conn->base.in_ptr = conn->base.buf;
+        conn->base.got_bytes = conn->base.total_bytes = 0;
     }
 }
 
@@ -758,16 +769,16 @@
         return TH_CONN_ERROR;
 
     // Shift the input buffer
-    if (conn->ptr > conn->buf)
+    if (conn->base.ptr > conn->base.buf)
     {
-        size_t left = conn->in_ptr - conn->ptr;
+        size_t left = conn->base.in_ptr - conn->base.ptr;
         if (left > 0)
         {
-            size_t moved = conn->ptr - conn->buf;
-            memmove(conn->buf, conn->ptr, left);
-            conn->ptr = conn->buf;
-            conn->in_ptr -= moved;
-            conn->total_bytes -= moved;
+            size_t moved = conn->base.ptr - conn->base.buf;
+            memmove(conn->base.buf, conn->base.ptr, left);
+            conn->base.ptr = conn->base.buf;
+            conn->base.in_ptr -= moved;
+            conn->base.total_bytes -= moved;
         }
         else
             th_conn_reset(conn);        
@@ -776,9 +787,9 @@
     // Check for incoming data
     socktv.tv_sec = 0;
     socktv.tv_usec = TH_DELAY_USEC;
-    tmpfds = conn->sockfds;
+    tmpfds = conn->base.sockfds;
 
-    if ((result = select(conn->socket + 1, &tmpfds, NULL, NULL, &socktv)) == -1)
+    if ((result = select(conn->base.socket + 1, &tmpfds, NULL, NULL, &socktv)) == -1)
     {
         int err = th_get_socket_errno();
         if (err != EINTR)
@@ -789,16 +800,18 @@
             return TH_CONN_ERROR;
         }
     }
-    else if (FD_ISSET(conn->socket, &tmpfds))
+    else if (FD_ISSET(conn->base.socket, &tmpfds))
     {
-        conn->got_bytes = recv(conn->socket, conn->in_ptr, conn->bufsize - conn->total_bytes, 0);
-        if (conn->got_bytes < 0)
+        conn->base.got_bytes = recv(conn->base.socket,
+            conn->base.in_ptr, conn->base.bufsize - conn->base.total_bytes, 0);
+
+        if (conn->base.got_bytes < 0)
         {
             int err = th_errno_to_error(th_get_socket_errno());
             th_conn_err(conn, err, "Error in recv: %s\n", th_error_str(err));
             return TH_CONN_ERROR;
         }
-        else if (conn->got_bytes == 0)
+        else if (conn->base.got_bytes == 0)
         {
             th_conn_err(conn, ECONNABORTED, "Server closed connection.\n");
             conn->status = TH_CONN_CLOSED;
@@ -806,8 +819,8 @@
         }
         else
         {
-            conn->total_bytes += conn->got_bytes;
-            conn->in_ptr += conn->got_bytes;
+            conn->base.total_bytes += conn->base.got_bytes;
+            conn->base.in_ptr += conn->base.got_bytes;
             return TH_CONN_DATA_AVAIL;
         }
     }
@@ -870,7 +883,7 @@
 
 BOOL th_conn_buf_check(th_conn_t *conn, size_t n)
 {
-    return conn && (conn->ptr + n <= conn->in_ptr);
+    return conn && (conn->base.ptr + n <= conn->base.in_ptr);
 }
 
 
@@ -878,7 +891,7 @@
 {
     if (th_conn_buf_check(conn, n))
     {
-        conn->ptr += n;
+        conn->base.ptr += n;
         return TRUE;
     }
     else
@@ -892,9 +905,9 @@
     if (!th_conn_buf_check(conn, n))
         return -1;
 
-    if ((ret = strncmp(conn->ptr, str, n)) == 0)
+    if ((ret = strncmp(conn->base.ptr, str, n)) == 0)
     {
-        conn->ptr += n;
+        conn->base.ptr += n;
         return 0;
     }
     else
@@ -913,9 +926,9 @@
     char *pos;
     size_t n = strlen(str);
 
-    if (th_conn_buf_check(conn, n) && ((pos = strstr(conn->ptr, str)) != NULL))
+    if (th_conn_buf_check(conn, n) && ((pos = strstr(conn->base.ptr, str)) != NULL))
     {
-        conn->ptr = pos + n;
+        conn->base.ptr = pos + n;
         return pos;
     }
     else
@@ -932,11 +945,11 @@
     "\n--------------------------------------------------------------\n"
     "err=%d, status=%d, got_bytes=%d, total_bytes=%d\n"
     "buf=0x%p, in_ptr=0x%04x, ptr=0x%04x\n",
-    conn->err, conn->status, conn->got_bytes, conn->total_bytes,
-    conn->buf, conn->in_ptr - conn->buf, conn->ptr - conn->buf);
+    conn->err, conn->status, conn->base.got_bytes, conn->base.total_bytes,
+    conn->base.buf, conn->base.in_ptr - conn->base.buf, conn->base.ptr - conn->base.buf);
     
     // Dump buffer contents as a hexdump
-    for (offs = 0, left = conn->total_bytes, p = conn->buf; p < conn->in_ptr;)
+    for (offs = 0, left = conn->base.total_bytes, p = conn->base.buf; p < conn->base.in_ptr;)
     {
         char buf[TH_DUMP_BYTES + 1];
         size_t bufoffs, amount = left < TH_DUMP_BYTES ? left : TH_DUMP_BYTES;
--- a/th_network.h	Mon Jun 23 16:59:36 2014 +0300
+++ b/th_network.h	Fri Jul 04 02:18:26 2014 +0300
@@ -85,20 +85,8 @@
 };
 
 
-typedef struct _th_conn_t
+typedef struct _th_base_conn_t
 {
-    // Proxy settings and data
-    struct
-    {
-        char *host;
-        struct hostent *hst;
-        int type, auth_type;
-        int port;
-        struct in_addr addr;
-        char *userid, *passwd;
-        int mode, addr_type;
-    } proxy;
-
     // Target host data
     char *host;
     struct hostent *hst;
@@ -109,17 +97,35 @@
     struct in_addr addr;
     fd_set sockfds;
 
+    // Data buffer
+    char *buf, *ptr, *in_ptr;
+    ssize_t bufsize, got_bytes, total_bytes;
+
+} th_base_conn_t;
+
+
+typedef struct _th_conn_t
+{
+    // Connection
+    th_base_conn_t base;
+
+    // Proxy settings and data
+    struct
+    {
+        th_base_conn_t conn;
+        int type, auth_type;
+        int mode, addr_type;
+        char *userid, *passwd;
+    } proxy;
+
+    // Status
+    int err;
+    int status;
+
     // Error handling and status message functors
     void (*errfunc)(struct _th_conn_t *conn, int err, const char *msg);
     void (*msgfunc)(struct _th_conn_t *conn, int loglevel, const char *msg);
 
-    int err;
-    int status;
-
-    // Data buffer
-    char *buf, *ptr, *in_ptr;
-    ssize_t bufsize, got_bytes, total_bytes;
-
     void *node;
 } th_conn_t;
 
@@ -140,6 +146,7 @@
 int         th_conn_set_proxy_mode(th_conn_t *conn, const int mode);
 int         th_conn_set_proxy_addr_type(th_conn_t *conn, const int atype);
 int         th_conn_set_proxy_auth_user(th_conn_t *conn, const char *userid, const char *passwd);
+
 int         th_conn_open(th_conn_t *conn, const int port, const char *host);
 int         th_conn_close(th_conn_t *);
 void        th_conn_free(th_conn_t *);