diff libnnchat.c @ 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 b54c8545dcb0
children ba2aa110755b
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);