| 1497 | } |
| 1498 | |
| 1499 | int SIPpSocket::connect(struct sockaddr_storage* dest) |
| 1500 | { |
| 1501 | if (dest) |
| 1502 | { |
| 1503 | memcpy(&ss_dest, dest, sizeof(*dest)); |
| 1504 | } |
| 1505 | |
| 1506 | int ret; |
| 1507 | |
| 1508 | assert(ss_transport == T_TCP || ss_transport == T_TLS || ss_transport == T_SCTP); |
| 1509 | |
| 1510 | if (ss_transport == T_TCP || ss_transport == T_TLS) { |
| 1511 | struct sockaddr_storage with_optional_port; |
| 1512 | int port = -1; |
| 1513 | memcpy(&with_optional_port, &local_sockaddr, sizeof(struct sockaddr_storage)); |
| 1514 | if (local_ip_is_ipv6) { |
| 1515 | (_RCAST(struct sockaddr_in6*, &with_optional_port))->sin6_port = htons(ss_bind_port); |
| 1516 | } else { |
| 1517 | (_RCAST(struct sockaddr_in*, &with_optional_port))->sin_port = htons(ss_bind_port); |
| 1518 | } |
| 1519 | sipp_bind_socket(this, &with_optional_port, &port); |
| 1520 | #ifdef USE_SCTP |
| 1521 | } else if (ss_transport == T_SCTP) { |
| 1522 | int port = -1; |
| 1523 | sipp_bind_socket(this, &local_sockaddr, &port); |
| 1524 | #endif |
| 1525 | } |
| 1526 | |
| 1527 | int flags = fcntl(ss_fd, F_GETFL, 0); |
| 1528 | fcntl(ss_fd, F_SETFL, flags | O_NONBLOCK); |
| 1529 | |
| 1530 | errno = 0; |
| 1531 | ret = ::connect(ss_fd, _RCAST(struct sockaddr *, &ss_dest), socklen_from_addr(&ss_dest)); |
| 1532 | if (ret < 0) { |
| 1533 | if (errno == EINPROGRESS) { |
| 1534 | /* Block this socket until the connect completes - this is very similar to entering congestion, but we don't want to increment congestion statistics. */ |
| 1535 | enter_congestion(0); |
| 1536 | nb_net_cong--; |
| 1537 | } else { |
| 1538 | return ret; |
| 1539 | } |
| 1540 | } |
| 1541 | |
| 1542 | fcntl(ss_fd, F_SETFL, flags); |
| 1543 | |
| 1544 | if (ss_transport == T_TLS) { |
| 1545 | #if defined(USE_OPENSSL) || defined(USE_WOLFSSL) |
| 1546 | int rc; |
| 1547 | int i = 0; |
| 1548 | while ((rc = SSL_connect(ss_ssl)) < 0) { |
| 1549 | int err = SSL_get_error(ss_ssl, rc); |
| 1550 | if ((err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) && |
| 1551 | i < SIPP_SSL_MAX_RETRIES) { |
| 1552 | /* These errors are benign we just need to wait for the socket |
| 1553 | * to be readable/writable again. */ |
| 1554 | WARNING("SSL_connect failed with error: %s. Attempt %d. " |
| 1555 | "Retrying...", SSL_error_string(err, rc), ++i); |
| 1556 | sipp_usleep(SIPP_SSL_RETRY_TIMEOUT); |
no test coverage detected