comparison network.c @ 611:019a54b07f60

Clean up and modularize proxy connection code a bit.
author Matti Hamalainen <ccr@tnsp.org>
date Tue, 20 May 2014 05:34:33 +0300
parents 2cc5434a8ce0
children 2cd71b7c1e8e
comparison
equal deleted inserted replaced
610:224b28e82698 611:019a54b07f60
189 if (conn == NULL) 189 if (conn == NULL)
190 return -1; 190 return -1;
191 191
192 th_free(conn->proxy.userid); 192 th_free(conn->proxy.userid);
193 conn->proxy.userid = th_strdup(userid); 193 conn->proxy.userid = th_strdup(userid);
194
194 th_free(conn->proxy.passwd); 195 th_free(conn->proxy.passwd);
195 conn->proxy.passwd = th_strdup(passwd); 196 conn->proxy.passwd = th_strdup(passwd);
196 197
197 return 0; 198 return 0;
199 }
200
201
202 static int nn_conn_proxy_wait(nn_conn_t *conn)
203 {
204 int status, tries;
205
206 for (status = tries = 1; tries <= 20 && status > 0; tries++)
207 {
208 #ifdef __WIN32
209 Sleep(50);
210 #else
211 usleep(50000);
212 #endif
213 nn_conn_reset(conn);
214 status = nn_conn_pull(conn);
215 }
216
217 if (status < 0)
218 nn_conn_err(conn, "Proxy negotiation failed at try %d with network error: %d\n", tries, status);
219 else
220 nn_conn_err(conn, "Proxy negotiation timed out.\n");
221
222 return status;
223 }
224
225
226 static BOOL nn_conn_proxy_send(nn_conn_t *conn, void *buf, size_t bufsiz)
227 {
228 BOOL ret;
229 nn_conn_reset(conn);
230 if ((ret = nn_conn_send_buf(conn, buf, bufsiz)) == FALSE)
231 nn_conn_err(conn, "Error sending SOCKS proxy request.\n");
232 th_free(buf);
233 return ret;
198 } 234 }
199 235
200 236
201 int nn_conn_open(nn_conn_t *conn, const int port, const char *host) 237 int nn_conn_open(nn_conn_t *conn, const int port, const char *host)
202 { 238 {
253 FD_SET(conn->socket, &(conn->sockfds)); 289 FD_SET(conn->socket, &(conn->sockfds));
254 290
255 // Proxy-specific setup 291 // Proxy-specific setup
256 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A) 292 if (conn->proxy.type == NN_PROXY_SOCKS4 || conn->proxy.type == NN_PROXY_SOCKS4A)
257 { 293 {
294 struct nn_socks4_res_t *sockres;
258 struct nn_socks4_t *socksh; 295 struct nn_socks4_t *socksh;
259 size_t bufsiz; 296 size_t bufsiz;
260 char *ptr, *buf; 297 char *ptr, *buf;
261 int tries, status = -1;
262 298
263 nn_conn_msg(conn, "Initializing SOCKS 4/a proxy negotiation.\n"); 299 nn_conn_msg(conn, "Initializing SOCKS 4/a proxy negotiation.\n");
264 300
265 bufsiz = sizeof(struct nn_socks4_t) + strlen(conn->proxy.userid) + 1; 301 bufsiz = sizeof(struct nn_socks4_t) + strlen(conn->proxy.userid) + 1;
266 if (conn->proxy.type == NN_PROXY_SOCKS4A) 302 if (conn->proxy.type == NN_PROXY_SOCKS4A)
288 ptr += strlen(conn->proxy.userid) + 1; 324 ptr += strlen(conn->proxy.userid) + 1;
289 strcpy(ptr, conn->host); 325 strcpy(ptr, conn->host);
290 } 326 }
291 327
292 // Send request 328 // Send request
293 nn_conn_reset(conn); 329 if (!nn_conn_proxy_send(conn, buf, bufsiz))
294 if (!nn_conn_send_buf(conn, buf, bufsiz))
295 {
296 th_free(buf);
297 nn_conn_err(conn, "Error sending SOCKS proxy request.\n");
298 goto error; 330 goto error;
299 }
300 th_free(buf);
301 331
302 // Wait for SOCKS server to reply 332 // Wait for SOCKS server to reply
303 for (status = tries = 1; tries <= 20 && status > 0; tries++) 333 if (nn_conn_proxy_wait(conn) != 0)
304 { 334 goto error;
305 #ifdef __WIN32 335
306 Sleep(50); 336 sockres = (struct nn_socks4_res_t *) &(conn->buf);
307 #else 337 if (sockres->nb != 0)
308 usleep(50000); 338 {
309 #endif 339 nn_conn_err(conn, "Invalid SOCKS 4 server reply, does not begin with NUL byte (%d).\n", sockres->nb);
310 nn_conn_reset(conn); 340 goto error;
311 status = nn_conn_pull(conn); 341 }
312 } 342 if (sockres->result != 0x5a)
313 343 {
314 // Check results 344 char *s = NULL;
315 if (status == 0) 345 switch (sockres->result)
316 {
317 struct nn_socks4_res_t *res = (struct nn_socks4_res_t *) &(conn->buf);
318 if (res->nb != 0)
319 { 346 {
320 nn_conn_err(conn, "Invalid SOCKS server reply, does not begin with NUL byte (%d).\n", res->nb); 347 case 0x5b: s = "Request rejected or failed"; break;
321 goto error; 348 case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break;
349 case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break;
350 default: s = "Unknown SOCKS 4 error response"; break;
322 } 351 }
323 if (res->result != 0x5a) 352 nn_conn_err(conn, "SOCKS 4 setup failed, 0x%02x: %s.\n", sockres->result, s);
324 {
325 char *s = NULL;
326 switch (res->result)
327 {
328 case 0x5b: s = "Request rejected or failed"; break;
329 case 0x5c: s = "Request failed because client is not running identd (or not reachable from the server)"; break;
330 case 0x5d: s = "Request failed because client's identd could not confirm the user ID string in the request"; break;
331 default: s = "Unknown SOCKS error response"; break;
332 }
333 nn_conn_err(conn, "SOCKS setup failed, 0x%02x: %s.\n", res->result, s);
334 goto error;
335 }
336 nn_conn_msg(conn, "SOCKS connection established!\n");
337 }
338 else if (status < 0)
339 {
340 nn_conn_err(conn, "Proxy negotiation failed at try %d with network error: %d\n", tries, status);
341 goto error; 353 goto error;
342 } 354 }
343 else 355
344 { 356 nn_conn_msg(conn, "SOCKS 4 connection established!\n");
345 nn_conn_err(conn, "Proxy negotiation timed out.\n");
346 goto error;
347 }
348 } 357 }
349 358
350 nn_conn_reset(conn); 359 nn_conn_reset(conn);
351 conn->status = NN_CONN_OPEN; 360 conn->status = NN_CONN_OPEN;
352 return 0; 361 return 0;