| 315 */ |
317 */ |
| 316 faim_export void aim_conn_close(aim_conn_t *deadconn) |
318 faim_export void aim_conn_close(aim_conn_t *deadconn) |
| 317 { |
319 { |
| 318 |
320 |
| 319 if (deadconn->fd >= 3) |
321 if (deadconn->fd >= 3) |
| |
322 #ifndef _WIN32 |
| 320 close(deadconn->fd); |
323 close(deadconn->fd); |
| |
324 #else |
| |
325 closesocket(deadconn->fd); |
| |
326 #endif |
| 321 deadconn->fd = -1; |
327 deadconn->fd = -1; |
| 322 if (deadconn->handlerlist) |
328 if (deadconn->handlerlist) |
| 323 aim_clearhandlers(deadconn); |
329 aim_clearhandlers(deadconn); |
| 324 if (deadconn->type == AIM_CONN_TYPE_RENDEZVOUS) |
330 if (deadconn->type == AIM_CONN_TYPE_RENDEZVOUS) |
| 325 aim_conn_close_rend((aim_session_t *)deadconn->sessv, deadconn); |
331 aim_conn_close_rend((aim_session_t *)deadconn->sessv, deadconn); |
| 427 sa.sin_family = hp->h_addrtype; |
433 sa.sin_family = hp->h_addrtype; |
| 428 |
434 |
| 429 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); |
435 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); |
| 430 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { |
436 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { |
| 431 faimdprintf(sess, 0, "proxyconnect: unable to connect to proxy\n"); |
437 faimdprintf(sess, 0, "proxyconnect: unable to connect to proxy\n"); |
| |
438 #ifndef _WIN32 |
| 432 close(fd); |
439 close(fd); |
| |
440 #else |
| |
441 closesocket(fd); |
| |
442 #endif |
| 433 return -1; |
443 return -1; |
| 434 } |
444 } |
| 435 |
445 |
| 436 i = 0; |
446 i = 0; |
| 437 buf[0] = 0x05; /* SOCKS version 5 */ |
447 buf[0] = 0x05; /* SOCKS version 5 */ |
| 443 } else { |
453 } else { |
| 444 buf[1] = 0x01; |
454 buf[1] = 0x01; |
| 445 buf[2] = 0x00; |
455 buf[2] = 0x00; |
| 446 i = 3; |
456 i = 3; |
| 447 } |
457 } |
| 448 |
458 #ifndef _WIN32 |
| 449 if (write(fd, buf, i) < i) { |
459 if (write(fd, buf, i) < i) { |
| |
460 #else |
| |
461 if (send(fd, buf, i, 0) < i) { |
| |
462 #endif |
| 450 *statusret = errno; |
463 *statusret = errno; |
| |
464 #ifndef _WIN32 |
| 451 close(fd); |
465 close(fd); |
| |
466 #else |
| |
467 closesocket(fd); |
| |
468 #endif |
| 452 return -1; |
469 return -1; |
| 453 } |
470 } |
| 454 |
471 #ifndef _WIN32 |
| 455 if (read(fd, buf, 2) < 2) { |
472 if (read(fd, buf, 2) < 2) { |
| |
473 #else |
| |
474 if (recv(fd, buf, 2, 0) < 2) { |
| |
475 #endif |
| 456 *statusret = errno; |
476 *statusret = errno; |
| |
477 #ifndef _WIN32 |
| 457 close(fd); |
478 close(fd); |
| |
479 #else |
| |
480 closesocket(fd); |
| |
481 #endif |
| 458 return -1; |
482 return -1; |
| 459 } |
483 } |
| 460 |
484 |
| 461 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { |
485 if ((buf[0] != 0x05) || (buf[1] == 0xff)) { |
| 462 *statusret = EINVAL; |
486 *statusret = EINVAL; |
| |
487 #ifndef _WIN32 |
| 463 close(fd); |
488 close(fd); |
| |
489 #else |
| |
490 closesocket(fd); |
| |
491 #endif |
| 464 return -1; |
492 return -1; |
| 465 } |
493 } |
| 466 |
494 |
| 467 /* check if we're doing username authentication */ |
495 /* check if we're doing username authentication */ |
| 468 if (buf[1] == 0x02) { |
496 if (buf[1] == 0x02) { |
| 469 i = aimutil_put8(buf, 0x01); /* version 1 */ |
497 i = aimutil_put8(buf, 0x01); /* version 1 */ |
| 470 i += aimutil_put8(buf+i, strlen(sess->socksproxy.username)); |
498 i += aimutil_put8(buf+i, strlen(sess->socksproxy.username)); |
| 471 i += aimutil_putstr(buf+i, sess->socksproxy.username, strlen(sess->socksproxy.username)); |
499 i += aimutil_putstr(buf+i, sess->socksproxy.username, strlen(sess->socksproxy.username)); |
| 472 i += aimutil_put8(buf+i, strlen(sess->socksproxy.password)); |
500 i += aimutil_put8(buf+i, strlen(sess->socksproxy.password)); |
| 473 i += aimutil_putstr(buf+i, sess->socksproxy.password, strlen(sess->socksproxy.password)); |
501 i += aimutil_putstr(buf+i, sess->socksproxy.password, strlen(sess->socksproxy.password)); |
| |
502 #ifndef _WIN32 |
| 474 if (write(fd, buf, i) < i) { |
503 if (write(fd, buf, i) < i) { |
| |
504 #else |
| |
505 if (send(fd, buf, i, 0) < i) { |
| |
506 #endif |
| 475 *statusret = errno; |
507 *statusret = errno; |
| |
508 #ifndef _WIN32 |
| 476 close(fd); |
509 close(fd); |
| |
510 #else |
| |
511 closesocket(fd); |
| |
512 #endif |
| 477 return -1; |
513 return -1; |
| 478 } |
514 } |
| |
515 #ifndef _WIN32 |
| 479 if (read(fd, buf, 2) < 2) { |
516 if (read(fd, buf, 2) < 2) { |
| |
517 #else |
| |
518 if (recv(fd, buf, 2, 0) < 2) { |
| |
519 #endif |
| 480 *statusret = errno; |
520 *statusret = errno; |
| |
521 #ifndef _WIN32 |
| 481 close(fd); |
522 close(fd); |
| |
523 #else |
| |
524 closesocket(fd); |
| |
525 #endif |
| 482 return -1; |
526 return -1; |
| 483 } |
527 } |
| 484 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { |
528 if ((buf[0] != 0x01) || (buf[1] != 0x00)) { |
| 485 *statusret = EINVAL; |
529 *statusret = EINVAL; |
| |
530 #ifndef _WIN32 |
| 486 close(fd); |
531 close(fd); |
| |
532 #else |
| |
533 closesocket(fd); |
| |
534 #endif |
| 487 return -1; |
535 return -1; |
| 488 } |
536 } |
| 489 } |
537 } |
| 490 |
538 |
| 491 i = aimutil_put8(buf, 0x05); |
539 i = aimutil_put8(buf, 0x05); |
| 493 i += aimutil_put8(buf+i, 0x00); /* reserved */ |
541 i += aimutil_put8(buf+i, 0x00); /* reserved */ |
| 494 i += aimutil_put8(buf+i, 0x03); /* address type: host name */ |
542 i += aimutil_put8(buf+i, 0x03); /* address type: host name */ |
| 495 i += aimutil_put8(buf+i, strlen(host)); |
543 i += aimutil_put8(buf+i, strlen(host)); |
| 496 i += aimutil_putstr(buf+i, host, strlen(host)); |
544 i += aimutil_putstr(buf+i, host, strlen(host)); |
| 497 i += aimutil_put16(buf+i, port); |
545 i += aimutil_put16(buf+i, port); |
| 498 |
546 #ifndef _WIN32 |
| 499 if (write(fd, buf, i) < i) { |
547 if (write(fd, buf, i) < i) { |
| |
548 #else |
| |
549 if (send(fd, buf, i, 0) < i) { |
| |
550 #endif |
| 500 *statusret = errno; |
551 *statusret = errno; |
| |
552 #ifndef _WIN32 |
| 501 close(fd); |
553 close(fd); |
| |
554 #else |
| |
555 closesocket(fd); |
| |
556 #endif |
| 502 return -1; |
557 return -1; |
| 503 } |
558 } |
| |
559 #ifndef _WIN32 |
| 504 if (read(fd, buf, 10) < 10) { |
560 if (read(fd, buf, 10) < 10) { |
| |
561 #else |
| |
562 if (recv(fd, buf, 10, 0) < 10) { |
| |
563 #endif |
| 505 *statusret = errno; |
564 *statusret = errno; |
| |
565 #ifndef _WIN32 |
| 506 close(fd); |
566 close(fd); |
| |
567 #else |
| |
568 closesocket(fd); |
| |
569 #endif |
| 507 return -1; |
570 return -1; |
| 508 } |
571 } |
| 509 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
572 if ((buf[0] != 0x05) || (buf[1] != 0x00)) { |
| 510 *statusret = EINVAL; |
573 *statusret = EINVAL; |
| |
574 #ifndef _WIN32 |
| 511 close(fd); |
575 close(fd); |
| |
576 #else |
| |
577 closesocket(fd); |
| |
578 #endif |
| 512 return -1; |
579 return -1; |
| 513 } |
580 } |
| 514 |
581 |
| 515 } else { /* connecting directly */ |
582 } else { /* connecting directly */ |
| 516 struct sockaddr_in sa; |
583 struct sockaddr_in sa; |
| 517 struct hostent *hp; |
584 struct hostent *hp; |
| 518 |
585 #ifdef _WIN32 |
| |
586 int imode = 1; |
| |
587 int w_errno = 0; |
| |
588 #endif |
| 519 if (!(hp = gethostbyname(host))) { |
589 if (!(hp = gethostbyname(host))) { |
| 520 *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); |
590 *statusret = (h_errno | AIM_CONN_STATUS_RESOLVERR); |
| 521 return -1; |
591 return -1; |
| 522 } |
592 } |
| 523 |
593 |
| 527 sa.sin_family = hp->h_addrtype; |
597 sa.sin_family = hp->h_addrtype; |
| 528 |
598 |
| 529 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); |
599 fd = socket(hp->h_addrtype, SOCK_STREAM, 0); |
| 530 |
600 |
| 531 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) |
601 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) |
| |
602 #ifndef _WIN32 |
| 532 fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */ |
603 fcntl(fd, F_SETFL, O_NONBLOCK); /* XXX save flags */ |
| 533 |
604 #else |
| |
605 ioctlsocket(fd, FIONBIO, (unsigned long *)&imode); |
| |
606 #endif |
| 534 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { |
607 if (connect(fd, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) < 0) { |
| 535 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) { |
608 if (sess->flags & AIM_SESS_FLAGS_NONBLOCKCONNECT) { |
| |
609 #ifndef _WIN32 |
| 536 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
610 if ((errno == EINPROGRESS) || (errno == EINTR)) { |
| |
611 #else |
| |
612 w_errno = WSAGetLastError(); |
| |
613 if ((w_errno == WSAEINPROGRESS) || (w_errno == WSAEINTR)) { |
| |
614 #endif |
| 537 if (statusret) |
615 if (statusret) |
| 538 *statusret |= AIM_CONN_STATUS_INPROGRESS; |
616 *statusret |= AIM_CONN_STATUS_INPROGRESS; |
| 539 return fd; |
617 return fd; |
| 540 } |
618 } |
| 541 } |
619 } |
| |
620 #ifndef _WIN32 |
| 542 close(fd); |
621 close(fd); |
| |
622 #else |
| |
623 closesocket(fd); |
| |
624 #endif |
| 543 fd = -1; |
625 fd = -1; |
| 544 } |
626 } |
| 545 } |
627 } |
| 546 return fd; |
628 return fd; |
| 547 } |
629 } |
| 1002 FD_SET(conn->fd, &wfds); |
1089 FD_SET(conn->fd, &wfds); |
| 1003 tv.tv_sec = 0; |
1090 tv.tv_sec = 0; |
| 1004 tv.tv_usec = 0; |
1091 tv.tv_usec = 0; |
| 1005 |
1092 |
| 1006 if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { |
1093 if ((res = select(conn->fd+1, &fds, &wfds, NULL, &tv)) == -1) { |
| |
1094 #ifndef _WIN32 |
| 1007 error = errno; |
1095 error = errno; |
| |
1096 #else |
| |
1097 error = WSAGetLastError(); |
| |
1098 #endif |
| 1008 aim_conn_close(conn); |
1099 aim_conn_close(conn); |
| 1009 errno = error; |
1100 errno = error; |
| 1010 return -1; |
1101 return -1; |
| 1011 } else if (res == 0) { |
1102 } else if (res == 0) { |
| 1012 faimdprintf(sess, 0, "aim_conn_completeconnect: false alarm on %d\n", conn->fd); |
1103 faimdprintf(sess, 0, "aim_conn_completeconnect: false alarm on %d\n", conn->fd); |
| 1013 return 0; /* hasn't really completed yet... */ |
1104 return 0; /* hasn't really completed yet... */ |
| 1014 } |
1105 } |
| 1015 |
1106 |
| 1016 if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { |
1107 if (FD_ISSET(conn->fd, &fds) || FD_ISSET(conn->fd, &wfds)) { |
| 1017 int len = sizeof(error); |
1108 int len = sizeof(error); |
| 1018 |
1109 #ifndef _WIN32 |
| 1019 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) |
1110 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) |
| 1020 error = errno; |
1111 error = errno; |
| |
1112 #else |
| |
1113 if (getsockopt(conn->fd, SOL_SOCKET, SO_ERROR, (char*)&error, &len) < 0) |
| |
1114 error = WSAGetLastError(); |
| |
1115 #endif |
| 1021 } |
1116 } |
| 1022 |
1117 |
| 1023 if (error) { |
1118 if (error) { |
| 1024 aim_conn_close(conn); |
1119 aim_conn_close(conn); |
| 1025 errno = error; |
1120 errno = error; |
| 1026 return -1; |
1121 return -1; |
| 1027 } |
1122 } |
| 1028 |
1123 #ifndef _WIN32 |
| 1029 fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ |
1124 fcntl(conn->fd, F_SETFL, 0); /* XXX should restore original flags */ |
| 1030 |
1125 #endif |
| 1031 conn->status &= ~AIM_CONN_STATUS_INPROGRESS; |
1126 conn->status &= ~AIM_CONN_STATUS_INPROGRESS; |
| 1032 |
1127 |
| 1033 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) |
1128 if ((userfunc = aim_callhandler(sess, conn, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNCOMPLETE))) |
| 1034 userfunc(sess, NULL, conn); |
1129 userfunc(sess, NULL, conn); |
| 1035 |
1130 |