Changes in lib/proxy.c [71abe93:dbca297]
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/proxy.c
r71abe93 rdbca297 51 51 #endif 52 52 53 static GHashTable *phb_hash = NULL; 54 53 55 struct PHB { 54 56 b_event_handler func, proxy_func; … … 61 63 }; 62 64 65 typedef int (*proxy_connect_func)(const char *host, unsigned short port_, struct PHB *phb); 66 63 67 static int proxy_connect_none(const char *host, unsigned short port_, struct PHB *phb); 64 68 65 static gboolean phb_close(struct PHB *phb) 66 { 67 close(phb->fd); 68 phb->func(phb->data, -1, B_EV_IO_READ); 69 static gboolean phb_free(struct PHB *phb, gboolean success) 70 { 71 g_hash_table_remove(phb_hash, &phb->fd); 72 73 if (!success) { 74 if (phb->fd > 0) { 75 closesocket(phb->fd); 76 } 77 if (phb->func) { 78 phb->func(phb->data, -1, B_EV_IO_READ); 79 } 80 } 81 if (phb->gai) { 82 freeaddrinfo(phb->gai); 83 } 69 84 g_free(phb->host); 70 85 g_free(phb); … … 89 104 dup2(new_fd, source); 90 105 closesocket(new_fd); 106 phb->fd = source; 91 107 phb->inpa = b_input_add(source, B_EV_IO_WRITE, proxy_connected, phb); 92 108 return FALSE; … … 101 117 102 118 freeaddrinfo(phb->gai); 119 phb->gai = NULL; 120 103 121 b_event_remove(phb->inpa); 104 122 phb->inpa = 0; 123 105 124 if (phb->proxy_func) { 106 125 phb->proxy_func(phb->proxy_data, source, B_EV_IO_READ); 107 126 } else { 108 127 phb->func(phb->data, source, B_EV_IO_READ); 109 g_free(phb);128 phb_free(phb, TRUE); 110 129 } 111 130 … … 171 190 172 191 if (fd < 0 && host) { 173 g_free(phb);192 phb_free(phb, TRUE); 174 193 } 175 194 … … 204 223 (memcmp(HTTP_GOODSTRING2, inputline, strlen(HTTP_GOODSTRING2)) == 0)) { 205 224 phb->func(phb->data, source, B_EV_IO_READ); 206 g_free(phb->host); 207 g_free(phb); 208 return FALSE; 209 } 210 211 return phb_close(phb); 225 return phb_free(phb, TRUE); 226 } 227 228 return phb_free(phb, FALSE); 212 229 } 213 230 … … 224 241 len = sizeof(error); 225 242 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 226 return phb_ close(phb);243 return phb_free(phb, FALSE); 227 244 } 228 245 sock_make_blocking(source); … … 231 248 phb->host, phb->port); 232 249 if (send(source, cmd, strlen(cmd), 0) < 0) { 233 return phb_ close(phb);250 return phb_free(phb, FALSE); 234 251 } 235 252 … … 242 259 g_free(t2); 243 260 if (send(source, cmd, strlen(cmd), 0) < 0) { 244 return phb_ close(phb);261 return phb_free(phb, FALSE); 245 262 } 246 263 } … … 248 265 g_snprintf(cmd, sizeof(cmd), "\r\n"); 249 266 if (send(source, cmd, strlen(cmd), 0) < 0) { 250 return phb_ close(phb);267 return phb_free(phb, FALSE); 251 268 } 252 269 … … 279 296 if (read(source, packet, 9) >= 4 && packet[1] == 90) { 280 297 phb->func(phb->data, source, B_EV_IO_READ); 281 g_free(phb->host); 282 g_free(phb); 283 return FALSE; 284 } 285 286 return phb_close(phb); 298 return phb_free(phb, TRUE); 299 } 300 301 return phb_free(phb, FALSE); 287 302 } 288 303 … … 294 309 socklen_t len; 295 310 int error = ETIMEDOUT; 311 gboolean is_socks4a = (proxytype == PROXY_SOCKS4A); 296 312 297 313 if (phb->inpa > 0) { … … 300 316 len = sizeof(error); 301 317 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 302 return phb_ close(phb);318 return phb_free(phb, FALSE); 303 319 } 304 320 sock_make_blocking(source); 305 321 306 /* XXX does socks4 not support host name lookups by the proxy? */ 307 if (!(hp = gethostbyname(phb->host))) { 308 return phb_close(phb); 322 if (!is_socks4a && !(hp = gethostbyname(phb->host))) { 323 return phb_free(phb, FALSE); 309 324 } 310 325 … … 313 328 packet[2] = phb->port >> 8; 314 329 packet[3] = phb->port & 0xff; 315 packet[4] = (unsigned char) (hp->h_addr_list[0])[0]; 316 packet[5] = (unsigned char) (hp->h_addr_list[0])[1]; 317 packet[6] = (unsigned char) (hp->h_addr_list[0])[2]; 318 packet[7] = (unsigned char) (hp->h_addr_list[0])[3]; 330 if (is_socks4a) { 331 packet[4] = 0; 332 packet[5] = 0; 333 packet[6] = 0; 334 packet[7] = 1; 335 } else { 336 packet[4] = (unsigned char) (hp->h_addr_list[0])[0]; 337 packet[5] = (unsigned char) (hp->h_addr_list[0])[1]; 338 packet[6] = (unsigned char) (hp->h_addr_list[0])[2]; 339 packet[7] = (unsigned char) (hp->h_addr_list[0])[3]; 340 } 319 341 packet[8] = 0; 320 342 if (write(source, packet, 9) != 9) { 321 return phb_close(phb); 343 return phb_free(phb, FALSE); 344 } 345 346 if (is_socks4a) { 347 size_t host_len = strlen(phb->host) + 1; /* include the \0 */ 348 349 if (write(source, phb->host, host_len) != host_len) { 350 return phb_free(phb, FALSE); 351 } 322 352 } 323 353 … … 348 378 349 379 if (read(source, buf, 10) < 10) { 350 return phb_ close(phb);380 return phb_free(phb, FALSE); 351 381 } 352 382 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { 353 return phb_ close(phb);383 return phb_free(phb, FALSE); 354 384 } 355 385 356 386 phb->func(phb->data, source, B_EV_IO_READ); 357 g_free(phb->host); 358 g_free(phb); 359 360 return FALSE; 387 return phb_free(phb, TRUE); 361 388 } 362 389 … … 377 404 378 405 if (write(source, buf, (5 + strlen(phb->host) + 2)) < (5 + strlen(phb->host) + 2)) { 379 phb_ close(phb);406 phb_free(phb, FALSE); 380 407 return; 381 408 } … … 392 419 393 420 if (read(source, buf, 2) < 2) { 394 return phb_ close(phb);421 return phb_free(phb, FALSE); 395 422 } 396 423 397 424 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { 398 return phb_ close(phb);425 return phb_free(phb, FALSE); 399 426 } 400 427 … … 412 439 413 440 if (read(source, buf, 2) < 2) { 414 return phb_ close(phb);441 return phb_free(phb, FALSE); 415 442 } 416 443 417 444 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { 418 return phb_ close(phb);445 return phb_free(phb, FALSE); 419 446 } 420 447 … … 427 454 memcpy(buf + 2 + i + 1, proxypass, j); 428 455 if (write(source, buf, 3 + i + j) < 3 + i + j) { 429 return phb_ close(phb);456 return phb_free(phb, FALSE); 430 457 } 431 458 … … 451 478 len = sizeof(error); 452 479 if (getsockopt(source, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { 453 return phb_ close(phb);480 return phb_free(phb, FALSE); 454 481 } 455 482 sock_make_blocking(source); … … 469 496 470 497 if (write(source, buf, i) < i) { 471 return phb_ close(phb);498 return phb_free(phb, FALSE); 472 499 } 473 500 … … 487 514 } 488 515 516 static const proxy_connect_func proxy_connect_funcs_array[] = { 517 proxy_connect_none, /* PROXY_NONE */ 518 proxy_connect_http, /* PROXY_HTTP */ 519 proxy_connect_socks4, /* PROXY_SOCKS4 */ 520 proxy_connect_socks5, /* PROXY_SOCKS5 */ 521 proxy_connect_socks4, /* PROXY_SOCKS4A */ 522 }; 489 523 490 524 /* Export functions */ … … 493 527 { 494 528 struct PHB *phb; 529 proxy_connect_func fun; 530 int fd; 531 532 if (!phb_hash) { 533 phb_hash = g_hash_table_new(g_int_hash, g_int_equal); 534 } 495 535 496 536 if (!host || port <= 0 || !func || strlen(host) > 128) { … … 502 542 phb->data = data; 503 543 504 if (proxytype == PROXY_NONE || !proxyhost[0] || proxyport <= 0) { 505 return proxy_connect_none(host, port, phb); 506 } else if (proxytype == PROXY_HTTP) { 507 return proxy_connect_http(host, port, phb); 508 } else if (proxytype == PROXY_SOCKS4) { 509 return proxy_connect_socks4(host, port, phb); 510 } else if (proxytype == PROXY_SOCKS5) { 511 return proxy_connect_socks5(host, port, phb); 512 } 513 514 g_free(phb); 515 return -1; 516 } 544 if (proxyhost[0] && proxyport > 0 && proxytype >= 0 && proxytype < G_N_ELEMENTS(proxy_connect_funcs_array)) { 545 fun = proxy_connect_funcs_array[proxytype]; 546 } else { 547 fun = proxy_connect_none; 548 } 549 550 fd = fun(host, port, phb); 551 552 if (fd != -1) { 553 g_hash_table_insert(phb_hash, &phb->fd, phb); 554 } 555 556 return fd; 557 } 558 559 void proxy_disconnect(int fd) 560 { 561 struct PHB *phb = g_hash_table_lookup(phb_hash, &fd); 562 563 if (!phb) { 564 /* not in the early part of the connection - just close the fd */ 565 closesocket(fd); 566 return; 567 } 568 569 if (phb->inpa) { 570 b_event_remove(phb->inpa); 571 phb->inpa = 0; 572 } 573 574 /* avoid calling the callback, which might result in double-free */ 575 phb->func = NULL; 576 577 /* close and free */ 578 phb_free(phb, FALSE); 579 }
Note: See TracChangeset
for help on using the changeset viewer.