changeset 354:c01e42fc9adb

More work on SOCKS proxy support, should work now.
author Matti Hamalainen <ccr@tnsp.org>
date Thu, 23 Jun 2011 08:26:48 +0300
parents 83ae825bb8c1
children ba2aa110755b
files libnnchat.c libnnchat.h nnchat.c
diffstat 3 files changed, 100 insertions(+), 58 deletions(-) [+]
line wrap: on
line diff
--- a/libnnchat.c	Thu Jun 23 06:31:34 2011 +0300
+++ b/libnnchat.c	Thu Jun 23 08:26:48 2011 +0300
@@ -72,6 +72,17 @@
     }
 }
 
+struct hostent *nn_resolve_host(nn_conn_t *conn, const char *name)
+{
+    struct hostent *res = gethostbyname(name);
+    if (res == NULL)
+        nn_conn_err(conn, "Could not resolve hostname: %s\n", strerror(h_errno));
+    else
+        nn_conn_msg(conn, "True hostname for %s is %s\n", name, res->h_name);
+
+    return res;
+}
+
 static const char *nn_proxy_types[] = {
     "none",
     "SOCKS 4",
@@ -79,51 +90,78 @@
     NULL
 };
 
-nn_conn_t * nn_conn_open(
-        void (*errfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap),
-        void (*msgfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap),
-        int ptype, int pport, struct in_addr *paddr,
-        struct in_addr *addr, const int port, const char *host)
+
+nn_conn_t * nn_conn_new(
+        void (*errfunc)(nn_conn_t *conn, const char *fmt, va_list ap),
+        void (*msgfunc)(nn_conn_t *conn, const char *fmt, va_list ap))
 {
     nn_conn_t *conn = th_calloc(1, sizeof(nn_conn_t));
+    
+    if (conn == NULL)
+        return NULL;
+
+    conn->errfunc = errfunc;
+    conn->msgfunc = msgfunc;
+
+    return conn;
+}
+
+int nn_conn_set_proxy(nn_conn_t *conn, int type, int port, const char *host)
+{
+    if (conn == NULL)
+        return -1;
+
+    conn->proxy.type = type;
+    conn->proxy.port = port;
+    conn->proxy.host = th_strdup(host);
+
+    if (host != NULL) {
+        conn->proxy.hst = nn_resolve_host(conn, host);
+        if (conn->proxy.hst != NULL)
+            conn->proxy.addr = *(struct in_addr *) (conn->proxy.hst->h_addr);
+        else {
+            conn->proxy.addr.s_addr = 0;
+        }
+    } else
+        return -2;
+
+    return 0;
+}
+
+int nn_conn_open(nn_conn_t *conn, const int port, const char *host)
+{
     struct sockaddr_in dest;
     static const char *userid = "James Bond";
 
     if (conn == NULL)
-        return NULL;
-
-    /* Initialize data */
-    conn->errfunc = errfunc;
-    conn->msgfunc = msgfunc;
-    
-    conn->proxy.type = ptype;
-    conn->proxy.port = pport;
-    if (paddr != NULL)
-        conn->proxy.addr = *paddr;
+        return -1;
 
     conn->port = port;
-    conn->addr = *addr;
+    if (host != NULL) {
+        conn->host = th_strdup(host);
+        conn->hst = nn_resolve_host(conn, host);
+    }
 
-    if (ptype == NN_PROXY_SOCKS4A && host == NULL) {
-        nn_conn_err(conn, "Host string NULL and proxy type SOCKS 4a specified. Using IP address instead.\n");
-        conn->host = th_strdup(inet_ntoa(dest.sin_addr));
-    } else
-        conn->host = th_strdup(host);
+    if (conn->hst != NULL)
+        conn->addr = *(struct in_addr *) (conn->hst->h_addr);
+    else {
+        conn->addr.s_addr = 0;
+    }
 
 
     /* Prepare for connection */
-    if (ptype > NN_PROXY_NONE && ptype < NN_PROXY_LAST) {
+    if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) {
         dest.sin_family = AF_INET;
-        dest.sin_port = htons(pport);
+        dest.sin_port = htons(conn->proxy.port);
         dest.sin_addr = conn->proxy.addr;
 
         nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n",
-            nn_proxy_types[ptype],
+            nn_proxy_types[conn->proxy.type],
             inet_ntoa(dest.sin_addr), port);
     } else {
         dest.sin_family = AF_INET;
         dest.sin_port = htons(port);
-        dest.sin_addr = *addr;
+        dest.sin_addr = conn->addr;
 
         nn_conn_msg(conn, "Connecting to %s:%d ...\n",
             inet_ntoa(dest.sin_addr), port);
@@ -147,7 +185,7 @@
     FD_SET(conn->socket, &(conn->sockfds));
 
     /* Proxy-specific setup */
-    if (ptype == NN_PROXY_SOCKS4 || ptype == NN_PROXY_SOCKS4A) {
+    if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) {
         struct nn_socks_t *socksh;
         size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1 + strlen(conn->host) + 1;
         char *ptr, *buf;
@@ -163,13 +201,13 @@
         /* Create SOCKS 4/4A request */        
         nn_conn_msg(conn, "Initializing proxy negotiation.\n");
         socksh = (struct nn_socks_t *) buf;
-        socksh->version = (ptype == NN_PROXY_SOCKS4) ? 4 : 5;
+        socksh->version = 4;
         socksh->command = SOCKS_CMD_CONNECT;
         socksh->port = htons(port);
-        if (ptype == NN_PROXY_SOCKS4A)
+        if (conn->proxy.type == NN_PROXY_SOCKS4A)
             socksh->addr = htonl(0x00000032);
         else
-            socksh->addr = dest.sin_addr.s_addr;
+            socksh->addr = conn->addr.s_addr;
         ptr += sizeof(struct nn_socks_t);
 
         strcpy(ptr, userid);
@@ -215,11 +253,11 @@
     }
 
     conn->status = NN_CONN_OPEN;
-    return conn;
+    return 0;
 
 error:
     conn->status = NN_CONN_CLOSED;
-    return conn;
+    return -2;
 }
 
 
@@ -236,7 +274,10 @@
 #endif
         conn->socket = -1;
     }
-    
+
+    th_free(conn->host);
+    th_free(conn->proxy.host);
+        
     conn->status = NN_CONN_CLOSED;
     
     th_free(conn);
--- a/libnnchat.h	Thu Jun 23 06:31:34 2011 +0300
+++ b/libnnchat.h	Thu Jun 23 08:26:48 2011 +0300
@@ -68,14 +68,18 @@
 
 typedef struct _nn_conn_t {
     struct {
+        char *host;
+        struct hostent *hst;
         int type;
         int port;
         struct in_addr addr;
     } proxy;
 
     char *host;
+    struct hostent *hst;
+    int port;
+
     int socket;
-    int port;
     struct in_addr addr;
     fd_set sockfds;
 
@@ -95,11 +99,13 @@
 BOOL        nn_network_init();
 void        nn_network_close(void);
 
-nn_conn_t * nn_conn_open(
-        void (*errfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap),
-        void (*msgfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap),
-        int ptype, int pport, struct in_addr *paddr,
-        struct in_addr *addr, const int port, const char *host);
+struct hostent *nn_resolve_host(nn_conn_t *conn, const char *name);
+nn_conn_t * nn_conn_new(
+        void (*errfunc)(nn_conn_t *conn, const char *fmt, va_list ap),
+        void (*msgfunc)(nn_conn_t *conn, const char *fmt, va_list ap));
+
+int         nn_conn_set_proxy(nn_conn_t *conn, int type, int port, const char *host);
+int         nn_conn_open(nn_conn_t *conn, const int port, const char *host);
 void        nn_conn_close(nn_conn_t *);
 int         nn_conn_pull(nn_conn_t *);
 BOOL        nn_conn_send_buf(nn_conn_t *, const char *buf, const size_t len);
--- a/nnchat.c	Thu Jun 23 06:31:34 2011 +0300
+++ b/nnchat.c	Thu Jun 23 08:26:48 2011 +0300
@@ -569,7 +569,7 @@
 void messageFunc(struct _nn_conn_t *conn, const char *fmt, va_list ap)
 {
     (void) conn;
-    printMsgV(chatWindows[0], LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap);
+    printMsgV(NULL, LOG_STAMP | LOG_WINDOW | LOG_FILE, fmt, ap);
 }
 
 
@@ -1272,7 +1272,6 @@
 int main(int argc, char *argv[])
 {
     nn_conn_t *conn = NULL;
-    struct hostent *tmpHost = NULL, *proxyHost = NULL;
     int curVis = ERR, updateCount = 0;
     BOOL argsOK, isError = FALSE,
         exitProg = FALSE,
@@ -1461,35 +1460,35 @@
         goto err_exit;
     }
 
+    /* Create a connection */
+    conn = nn_conn_new(errorFunc, messageFunc);
+    if (conn == NULL) {
+        errorMsg("Could not create connection structure.\n");
+        goto err_exit;
+    }
+
     /* Are we using a proxy? */
     if (optProxyType != NN_PROXY_NONE && optProxyServer != NULL) {
-        printMsg(currWin, "Trying to resolve proxy host '%s' ...\n", optProxyServer);
-        tmpHost = gethostbyname(optProxyServer);
-        if (tmpHost == NULL) {
-            errorMsg("Could not resolve hostname: %s.\n", strerror(h_errno));
+        if (nn_conn_set_proxy(conn, optProxyType, optProxyPort, optProxyServer) != 0) {
+            errorMsg("Error setting proxy information.\n");
             goto err_exit;
         }
-        printMsg(currWin, "True hostname: %s\n", tmpHost->h_name);
     }
     
     /* Okay ... */
     printMsg(currWin, "Trying to resolve host '%s' ...\n", optServer);
-    tmpHost = gethostbyname(optServer);
-    if (tmpHost == NULL) {
+    conn->host = th_strdup(optServer);
+    conn->hst = nn_resolve_host(conn, optServer);
+    if (conn->hst == NULL) {
         errorMsg("Could not resolve hostname: %s.\n", strerror(h_errno));
         goto err_exit;
     }
-    printMsg(currWin, "True hostname: %s\n", tmpHost->h_name);
 
 #ifdef FINAL_BUILD
     /* To emulate the official client, we first make a request for
      * policy file, even though we don't use it for anything...
      */
-    conn = nn_conn_open(errorFunc, messageFunc,
-        optProxyType, optProxyPort, proxyHost != NULL ? (struct in_addr *) proxyHost->h_addr : NULL,
-        (struct in_addr *) tmpHost->h_addr, 843, optServer);
-
-    if (!nn_conn_check(conn)) {
+    if (nn_conn_open(conn, 843, NULL) != 0) {
         errorMsg("Policy file request connection setup failed!\n");
         goto err_exit;
     }
@@ -1510,11 +1509,7 @@
 #endif
 
     /* Okay, now do the proper connection ... */
-    conn = nn_conn_open(errorFunc, messageFunc,
-        optProxyType, optProxyPort, proxyHost != NULL ? (struct in_addr *) proxyHost->h_addr : NULL,
-        (struct in_addr *) tmpHost->h_addr, optPort, optServer);
-
-    if (!nn_conn_check(conn)) {
+    if (nn_conn_open(conn, optPort, NULL) != 0) {
         errorMsg("Main connection setup failed!\n");
         goto err_exit;
     }