comparison 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
comparison
equal deleted inserted replaced
353:83ae825bb8c1 354:c01e42fc9adb
70 conn->msgfunc(conn, fmt, ap); 70 conn->msgfunc(conn, fmt, ap);
71 va_end(ap); 71 va_end(ap);
72 } 72 }
73 } 73 }
74 74
75 struct hostent *nn_resolve_host(nn_conn_t *conn, const char *name)
76 {
77 struct hostent *res = gethostbyname(name);
78 if (res == NULL)
79 nn_conn_err(conn, "Could not resolve hostname: %s\n", strerror(h_errno));
80 else
81 nn_conn_msg(conn, "True hostname for %s is %s\n", name, res->h_name);
82
83 return res;
84 }
85
75 static const char *nn_proxy_types[] = { 86 static const char *nn_proxy_types[] = {
76 "none", 87 "none",
77 "SOCKS 4", 88 "SOCKS 4",
78 "SOCKS 4a", 89 "SOCKS 4a",
79 NULL 90 NULL
80 }; 91 };
81 92
82 nn_conn_t * nn_conn_open( 93
83 void (*errfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap), 94 nn_conn_t * nn_conn_new(
84 void (*msgfunc)(struct _nn_conn_t *conn, const char *fmt, va_list ap), 95 void (*errfunc)(nn_conn_t *conn, const char *fmt, va_list ap),
85 int ptype, int pport, struct in_addr *paddr, 96 void (*msgfunc)(nn_conn_t *conn, const char *fmt, va_list ap))
86 struct in_addr *addr, const int port, const char *host)
87 { 97 {
88 nn_conn_t *conn = th_calloc(1, sizeof(nn_conn_t)); 98 nn_conn_t *conn = th_calloc(1, sizeof(nn_conn_t));
99
100 if (conn == NULL)
101 return NULL;
102
103 conn->errfunc = errfunc;
104 conn->msgfunc = msgfunc;
105
106 return conn;
107 }
108
109 int nn_conn_set_proxy(nn_conn_t *conn, int type, int port, const char *host)
110 {
111 if (conn == NULL)
112 return -1;
113
114 conn->proxy.type = type;
115 conn->proxy.port = port;
116 conn->proxy.host = th_strdup(host);
117
118 if (host != NULL) {
119 conn->proxy.hst = nn_resolve_host(conn, host);
120 if (conn->proxy.hst != NULL)
121 conn->proxy.addr = *(struct in_addr *) (conn->proxy.hst->h_addr);
122 else {
123 conn->proxy.addr.s_addr = 0;
124 }
125 } else
126 return -2;
127
128 return 0;
129 }
130
131 int nn_conn_open(nn_conn_t *conn, const int port, const char *host)
132 {
89 struct sockaddr_in dest; 133 struct sockaddr_in dest;
90 static const char *userid = "James Bond"; 134 static const char *userid = "James Bond";
91 135
92 if (conn == NULL) 136 if (conn == NULL)
93 return NULL; 137 return -1;
94
95 /* Initialize data */
96 conn->errfunc = errfunc;
97 conn->msgfunc = msgfunc;
98
99 conn->proxy.type = ptype;
100 conn->proxy.port = pport;
101 if (paddr != NULL)
102 conn->proxy.addr = *paddr;
103 138
104 conn->port = port; 139 conn->port = port;
105 conn->addr = *addr; 140 if (host != NULL) {
106
107 if (ptype == NN_PROXY_SOCKS4A && host == NULL) {
108 nn_conn_err(conn, "Host string NULL and proxy type SOCKS 4a specified. Using IP address instead.\n");
109 conn->host = th_strdup(inet_ntoa(dest.sin_addr));
110 } else
111 conn->host = th_strdup(host); 141 conn->host = th_strdup(host);
142 conn->hst = nn_resolve_host(conn, host);
143 }
144
145 if (conn->hst != NULL)
146 conn->addr = *(struct in_addr *) (conn->hst->h_addr);
147 else {
148 conn->addr.s_addr = 0;
149 }
112 150
113 151
114 /* Prepare for connection */ 152 /* Prepare for connection */
115 if (ptype > NN_PROXY_NONE && ptype < NN_PROXY_LAST) { 153 if (conn->proxy.type > NN_PROXY_NONE && conn->proxy.type < NN_PROXY_LAST) {
116 dest.sin_family = AF_INET; 154 dest.sin_family = AF_INET;
117 dest.sin_port = htons(pport); 155 dest.sin_port = htons(conn->proxy.port);
118 dest.sin_addr = conn->proxy.addr; 156 dest.sin_addr = conn->proxy.addr;
119 157
120 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n", 158 nn_conn_msg(conn, "Connecting to %s proxy %s:%d ...\n",
121 nn_proxy_types[ptype], 159 nn_proxy_types[conn->proxy.type],
122 inet_ntoa(dest.sin_addr), port); 160 inet_ntoa(dest.sin_addr), port);
123 } else { 161 } else {
124 dest.sin_family = AF_INET; 162 dest.sin_family = AF_INET;
125 dest.sin_port = htons(port); 163 dest.sin_port = htons(port);
126 dest.sin_addr = *addr; 164 dest.sin_addr = conn->addr;
127 165
128 nn_conn_msg(conn, "Connecting to %s:%d ...\n", 166 nn_conn_msg(conn, "Connecting to %s:%d ...\n",
129 inet_ntoa(dest.sin_addr), port); 167 inet_ntoa(dest.sin_addr), port);
130 } 168 }
131 169
145 183
146 FD_ZERO(&(conn->sockfds)); 184 FD_ZERO(&(conn->sockfds));
147 FD_SET(conn->socket, &(conn->sockfds)); 185 FD_SET(conn->socket, &(conn->sockfds));
148 186
149 /* Proxy-specific setup */ 187 /* Proxy-specific setup */
150 if (ptype == NN_PROXY_SOCKS4 || ptype == NN_PROXY_SOCKS4A) { 188 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) {
151 struct nn_socks_t *socksh; 189 struct nn_socks_t *socksh;
152 size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1 + strlen(conn->host) + 1; 190 size_t bufsiz = sizeof(struct nn_socks_t) + strlen(userid) + 1 + strlen(conn->host) + 1;
153 char *ptr, *buf; 191 char *ptr, *buf;
154 int tries, status = -1; 192 int tries, status = -1;
155 193
161 } 199 }
162 200
163 /* Create SOCKS 4/4A request */ 201 /* Create SOCKS 4/4A request */
164 nn_conn_msg(conn, "Initializing proxy negotiation.\n"); 202 nn_conn_msg(conn, "Initializing proxy negotiation.\n");
165 socksh = (struct nn_socks_t *) buf; 203 socksh = (struct nn_socks_t *) buf;
166 socksh->version = (ptype == NN_PROXY_SOCKS4) ? 4 : 5; 204 socksh->version = 4;
167 socksh->command = SOCKS_CMD_CONNECT; 205 socksh->command = SOCKS_CMD_CONNECT;
168 socksh->port = htons(port); 206 socksh->port = htons(port);
169 if (ptype == NN_PROXY_SOCKS4A) 207 if (conn->proxy.type == NN_PROXY_SOCKS4A)
170 socksh->addr = htonl(0x00000032); 208 socksh->addr = htonl(0x00000032);
171 else 209 else
172 socksh->addr = dest.sin_addr.s_addr; 210 socksh->addr = conn->addr.s_addr;
173 ptr += sizeof(struct nn_socks_t); 211 ptr += sizeof(struct nn_socks_t);
174 212
175 strcpy(ptr, userid); 213 strcpy(ptr, userid);
176 ptr += strlen(userid) + 1; 214 ptr += strlen(userid) + 1;
177 215
213 else 251 else
214 goto error; 252 goto error;
215 } 253 }
216 254
217 conn->status = NN_CONN_OPEN; 255 conn->status = NN_CONN_OPEN;
218 return conn; 256 return 0;
219 257
220 error: 258 error:
221 conn->status = NN_CONN_CLOSED; 259 conn->status = NN_CONN_CLOSED;
222 return conn; 260 return -2;
223 } 261 }
224 262
225 263
226 void nn_conn_close(nn_conn_t *conn) 264 void nn_conn_close(nn_conn_t *conn)
227 { 265 {
234 #else 272 #else
235 close(conn->socket); 273 close(conn->socket);
236 #endif 274 #endif
237 conn->socket = -1; 275 conn->socket = -1;
238 } 276 }
239 277
278 th_free(conn->host);
279 th_free(conn->proxy.host);
280
240 conn->status = NN_CONN_CLOSED; 281 conn->status = NN_CONN_CLOSED;
241 282
242 th_free(conn); 283 th_free(conn);
243 } 284 }
244 285