]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
[Core] switch_core_port_allocator: Replace getaddrinfo() (may get stuck) with switch_...
authorAndrey Volk <andywolk@gmail.com>
Sat, 7 Nov 2020 00:17:36 +0000 (04:17 +0400)
committerAndrey Volk <andywolk@gmail.com>
Thu, 17 Dec 2020 17:15:14 +0000 (21:15 +0400)
src/include/switch_apr.h
src/switch_apr.c
src/switch_core_port_allocator.c
tests/unit/switch_core.c

index 62d207261e79c1874ea1b2a68f64f00760c852d5..e9799c2068361d1bd63b6e21e07ee2ef8302cb24 100644 (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.
index 25ff8641296b858363df41171f52a03ca07e9619..c033d87bc4bb324e7be8f55e3f6ef0d0d9d1801b 100644 (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) {
index 5c440537ee3c17003850567b3b5be25153a30fea..3bbed2a351cdc0ca965df5f9808497b7cac20dda 100644 (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");
                        }
 
index 05b3b7f60d98d03b22d62ff216bc833296562556..9f58969a6f2ba97919048c501daf75bcdbebd9e4 100644 (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()
 }