[Core] switch_core_port_allocator: Replace getaddrinfo() (may get stuck) with switch_sockaddr_new() and fix IPv6.

This commit is contained in:
Andrey Volk 2020-11-07 04:17:36 +04:00
parent 040416b8db
commit 913551315b
4 changed files with 94 additions and 6 deletions

View File

@ -1145,6 +1145,8 @@ SWITCH_DECLARE(switch_status_t) switch_sockaddr_info_get(switch_sockaddr_t ** sa
SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, switch_memory_pool_t *pool);
SWITCH_DECLARE(switch_status_t) switch_sockaddr_new(switch_sockaddr_t ** sa, const char *ip, switch_port_t port, switch_memory_pool_t *pool);
/**
* Send data over a network.
* @param sock The socket to send the data over.

View File

@ -814,7 +814,6 @@ SWITCH_DECLARE(switch_status_t) switch_sockaddr_create(switch_sockaddr_t **sa, s
new_sa = apr_pcalloc(pool, sizeof(apr_sockaddr_t));
switch_assert(new_sa);
new_sa->pool = pool;
memset(new_sa, 0, sizeof(*new_sa));
new_sa->family = family;
new_sa->sa.sin.sin_family = family;
@ -834,6 +833,65 @@ SWITCH_DECLARE(switch_status_t) switch_sockaddr_info_get(switch_sockaddr_t ** sa
return apr_sockaddr_info_get(sa, hostname, family, port, flags, pool);
}
SWITCH_DECLARE(switch_status_t) switch_sockaddr_new(switch_sockaddr_t ** sa, const char *ip, switch_port_t port, switch_memory_pool_t *pool)
{
switch_status_t status = SWITCH_STATUS_SUCCESS;
apr_sockaddr_t *new_sa;
int family;
if (!sa || !pool || !ip) {
switch_goto_status(SWITCH_STATUS_GENERR, end);
}
new_sa = apr_pcalloc(pool, sizeof(apr_sockaddr_t));
switch_assert(new_sa);
new_sa->pool = pool;
if (strchr(ip, ':')) {
struct sockaddr_in6 sa6 = { 0 };
family = APR_INET6;
inet_pton(family, ip, &(sa6.sin6_addr));
memcpy(&new_sa->sa, &sa6, sizeof(struct sockaddr_in6));
} else {
struct sockaddr_in sa4 = { 0 };
family = APR_INET;
inet_pton(family, ip, &(sa4.sin_addr));
memcpy(&new_sa->sa, &sa4, sizeof(struct sockaddr_in));
}
new_sa->hostname = apr_pstrdup(pool, ip);
new_sa->family = family;
new_sa->sa.sin.sin_family = family;
if (port) {
/* XXX IPv6: assumes sin_port and sin6_port at same offset */
new_sa->sa.sin.sin_port = htons(port);
new_sa->port = port;
}
if (family == APR_INET) {
new_sa->salen = sizeof(struct sockaddr_in);
new_sa->addr_str_len = 16;
new_sa->ipaddr_ptr = &(new_sa->sa.sin.sin_addr);
new_sa->ipaddr_len = sizeof(struct in_addr);
}
#if APR_HAVE_IPV6
else if (family == APR_INET6) {
new_sa->salen = sizeof(struct sockaddr_in6);
new_sa->addr_str_len = 46;
new_sa->ipaddr_ptr = &(new_sa->sa.sin6.sin6_addr);
new_sa->ipaddr_len = sizeof(struct in6_addr);
}
#endif
*sa = new_sa;
end:
return status;
}
SWITCH_DECLARE(switch_status_t) switch_socket_opt_set(switch_socket_t *sock, int32_t opt, int32_t on)
{
if (opt == SWITCH_SO_TCP_KEEPIDLE) {

View File

@ -115,7 +115,7 @@ SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_new(const char *ip, s
return SWITCH_STATUS_SUCCESS;
}
static switch_bool_t test_port(switch_core_port_allocator_t *alloc, int family, int type, switch_port_t port)
static switch_bool_t test_port(switch_core_port_allocator_t *alloc, int type, switch_port_t port)
{
switch_memory_pool_t *pool = NULL;
switch_sockaddr_t *local_addr = NULL;
@ -126,8 +126,8 @@ static switch_bool_t test_port(switch_core_port_allocator_t *alloc, int family,
return SWITCH_FALSE;
}
if (switch_sockaddr_info_get(&local_addr, alloc->ip, SWITCH_UNSPEC, port, 0, pool) == SWITCH_STATUS_SUCCESS) {
if (switch_socket_create(&sock, family, type, 0, pool) == SWITCH_STATUS_SUCCESS) {
if (switch_sockaddr_new(&local_addr, alloc->ip, port, pool) == SWITCH_STATUS_SUCCESS) {
if (switch_socket_create(&sock, switch_sockaddr_get_family(local_addr), type, 0, pool) == SWITCH_STATUS_SUCCESS) {
if (switch_socket_bind(sock, local_addr) == SWITCH_STATUS_SUCCESS) {
r = SWITCH_TRUE;
}
@ -179,12 +179,12 @@ SWITCH_DECLARE(switch_status_t) switch_core_port_allocator_request_port(switch_c
}
if ((alloc->flags & SPF_ROBUST_UDP)) {
r = test_port(alloc, AF_INET, SOCK_DGRAM, port);
r = test_port(alloc, SOCK_DGRAM, port);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "UDP port robustness check for port %d %s\n", port, r ? "pass" : "fail");
}
if ((alloc->flags & SPF_ROBUST_TCP)) {
r = test_port(alloc, AF_INET, SOCK_STREAM, port);
r = test_port(alloc, SOCK_STREAM, port);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "TCP port robustness check for port %d %s\n", port, r ? "pass" : "fail");
}

View File

@ -82,6 +82,34 @@ FST_CORE_BEGIN("./conf")
switch_safe_free(var_default_password);
}
FST_TEST_END()
FST_TEST_BEGIN(test_switch_sockaddr_new)
{
int type = SOCK_DGRAM;
switch_port_t port = 12044;
const char *ip = "127.0.0.1";
switch_memory_pool_t *pool = NULL;
switch_sockaddr_t *local_addr = NULL;
switch_socket_t *sock = NULL;
switch_bool_t r = SWITCH_FALSE;
if (switch_core_new_memory_pool(&pool) == SWITCH_STATUS_SUCCESS) {
if (switch_sockaddr_new(&local_addr, ip, port, pool) == SWITCH_STATUS_SUCCESS) {
if (switch_socket_create(&sock, switch_sockaddr_get_family(local_addr), type, 0, pool) == SWITCH_STATUS_SUCCESS) {
if (switch_socket_bind(sock, local_addr) == SWITCH_STATUS_SUCCESS) {
r = SWITCH_TRUE;
}
switch_socket_close(sock);
}
}
switch_core_destroy_memory_pool(&pool);
}
fst_check_int_equals(r, SWITCH_TRUE);
}
FST_TEST_END()
}
FST_SUITE_END()
}