]> git.ipfire.org Git - thirdparty/asterisk.git/commitdiff
res_pjsip: Add common ast_sip_get_host_ip API. 38/1138/2
authorJoshua Colp <jcolp@digium.com>
Tue, 25 Aug 2015 12:17:34 +0000 (09:17 -0300)
committerJoshua Colp <jcolp@digium.com>
Tue, 25 Aug 2015 16:56:16 +0000 (13:56 -0300)
Modules commonly used the pj_gethostip function for retrieving the
IP address of the host. This function does not cache the result and may
result in a DNS lookup occurring, or additional work. If the DNS
server is unreachable or network issues arise this can cause the
pj_gethostip function to block for a period of time.

This change adds an ast_sip_get_host_ip and ast_sip_get_host_ip_string
function which does the same thing but caches the host IP address at
module load time. This results in no additional work being done each
time the local host IP address is needed.

ASTERISK-25342 #close

Change-Id: I3205deb679b01fa5ac05a94b623bfd620a2abe1e

include/asterisk/res_pjsip.h
res/res_pjsip.c
res/res_pjsip_multihomed.c
res/res_pjsip_sdp_rtp.c
res/res_pjsip_session.c
res/res_pjsip_t38.c

index aaff0a443a32d594e9f22341f868286bb1c8da7e..2be906128cb3b29eff315e7f12cb322dedac17d5 100644 (file)
@@ -2060,4 +2060,31 @@ char *ast_sip_get_endpoint_identifier_order(void);
  */
 unsigned int ast_sip_get_keep_alive_interval(void);
 
+/*!
+ * \brief Retrieve the local host address in IP form
+ *
+ * \param af The address family to retrieve
+ * \param addr A place to store the local host address
+ *
+ * \retval 0 success
+ * \retval -1 failure
+ *
+ * \since 13.6.0
+ */
+int ast_sip_get_host_ip(int af, pj_sockaddr *addr);
+
+/*!
+ * \brief Retrieve the local host address in string form
+ *
+ * \param af The address family to retrieve
+ *
+ * \retval non-NULL success
+ * \retval NULL failure
+ *
+ * \since 13.6.0
+ *
+ * \note An empty string may be returned if the address family is valid but no local address exists
+ */
+const char *ast_sip_get_host_ip_string(int af);
+
 #endif /* _RES_PJSIP_H */
index 436145a17a738fa8b40b99c9ee9a7ece151edf95..1871bd4555b1ba5ae1d9b8952285c2a88a35c860 100644 (file)
@@ -1829,6 +1829,18 @@ static pjsip_endpoint *ast_pjsip_endpoint;
 
 static struct ast_threadpool *sip_threadpool;
 
+/*! Local host address for IPv4 */
+static pj_sockaddr host_ip_ipv4;
+
+/*! Local host address for IPv4 (string form) */
+static char host_ip_ipv4_string[PJ_INET6_ADDRSTRLEN + 2];
+
+/*! Local host address for IPv6 */
+static pj_sockaddr host_ip_ipv6;
+
+/*! Local host address for IPv6 (string form) */
+static char host_ip_ipv6_string[PJ_INET6_ADDRSTRLEN + 2];
+
 static int register_service(void *data)
 {
        pjsip_module **module = data;
@@ -3275,6 +3287,30 @@ int ast_sip_create_response(const pjsip_rx_data *rdata, int st_code,
        return res;
 }
 
+int ast_sip_get_host_ip(int af, pj_sockaddr *addr)
+{
+       if (af == pj_AF_INET() && !ast_strlen_zero(host_ip_ipv4_string)) {
+               pj_sockaddr_copy_addr(addr, &host_ip_ipv4);
+               return 0;
+       } else if (af == pj_AF_INET6() && !ast_strlen_zero(host_ip_ipv6_string)) {
+               pj_sockaddr_copy_addr(addr, &host_ip_ipv6);
+               return 0;
+       }
+
+       return -1;
+}
+
+const char *ast_sip_get_host_ip_string(int af)
+{
+       if (af == pj_AF_INET()) {
+               return host_ip_ipv4_string;
+       } else if (af == pj_AF_INET6()) {
+               return host_ip_ipv6_string;
+       }
+
+       return NULL;
+}
+
 static void remove_request_headers(pjsip_endpoint *endpt)
 {
        const pjsip_hdr *request_headers = pjsip_endpt_get_request_headers(endpt);
@@ -3389,6 +3425,16 @@ static int load_module(void)
                return AST_MODULE_LOAD_DECLINE;
        }
 
+       if (!pj_gethostip(pj_AF_INET(), &host_ip_ipv4)) {
+               pj_sockaddr_print(&host_ip_ipv4, host_ip_ipv4_string, sizeof(host_ip_ipv4_string), 2);
+               ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ip_ipv4_string);
+       }
+
+       if (!pj_gethostip(pj_AF_INET6(), &host_ip_ipv6)) {
+               pj_sockaddr_print(&host_ip_ipv6, host_ip_ipv6_string, sizeof(host_ip_ipv6_string), 2);
+               ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ip_ipv6_string);
+       }
+
        if (ast_sip_initialize_system()) {
                ast_log(LOG_ERROR, "Failed to initialize SIP 'system' configuration section. Aborting load\n");
                pj_pool_release(memory_pool);
index ca56b7c47f0fa6ff18a3d40706c4d2ea42cac7c6..31e514d1c1d4a4e67d42722fc11836a0dfe6eff0 100644 (file)
 #include "asterisk/res_pjsip.h"
 #include "asterisk/module.h"
 
-/*! \brief Local host address for IPv4 */
-static char host_ipv4[PJ_INET_ADDRSTRLEN + 2];
-
-/*! \brief Local host address for IPv6 */
-static char host_ipv6[PJ_INET6_ADDRSTRLEN + 2];
-
 /*! \brief Helper function which returns a UDP transport bound to the given address and port */
 static pjsip_transport *multihomed_get_udp_transport(pj_str_t *address, int port)
 {
@@ -75,8 +69,10 @@ static int multihomed_rewrite_sdp(struct pjmedia_sdp_session *sdp)
        }
 
        /* If the host address is used in the SDP replace it with the address of what this is going out on */
-       if ((!pj_strcmp2(&sdp->conn->addr_type, "IP4") && !pj_strcmp2(&sdp->conn->addr, host_ipv4)) ||
-               (!pj_strcmp2(&sdp->conn->addr_type, "IP6") && !pj_strcmp2(&sdp->conn->addr, host_ipv6))) {
+       if ((!pj_strcmp2(&sdp->conn->addr_type, "IP4") && !pj_strcmp2(&sdp->conn->addr,
+               ast_sip_get_host_ip_string(pj_AF_INET()))) ||
+               (!pj_strcmp2(&sdp->conn->addr_type, "IP6") && !pj_strcmp2(&sdp->conn->addr,
+               ast_sip_get_host_ip_string(pj_AF_INET6())))) {
                return 1;
        }
 
@@ -201,7 +197,6 @@ static int unload_module(void)
 static int load_module(void)
 {
        char hostname[MAXHOSTNAMELEN] = "";
-       pj_sockaddr addr;
 
        CHECK_PJSIP_MODULE_LOADED();
 
@@ -210,16 +205,6 @@ static int load_module(void)
                        hostname);
        }
 
-       if (!pj_gethostip(pj_AF_INET(), &addr)) {
-               pj_sockaddr_print(&addr, host_ipv4, sizeof(host_ipv4), 2);
-               ast_verb(3, "Local IPv4 address determined to be: %s\n", host_ipv4);
-       }
-
-       if (!pj_gethostip(pj_AF_INET6(), &addr)) {
-               pj_sockaddr_print(&addr, host_ipv6, sizeof(host_ipv6), 2);
-               ast_verb(3, "Local IPv6 address determined to be: %s\n", host_ipv6);
-       }
-
        if (ast_sip_register_service(&multihomed_module)) {
                ast_log(LOG_ERROR, "Could not register multihomed module for incoming and outgoing requests\n");
                return AST_MODULE_LOAD_FAILURE;
index 5adc48a842b2d0dc261eb6e6360001aee5d6074f..8ac1bb8df8bd763ca137062a72f3e05356e37871 100644 (file)
@@ -1013,7 +1013,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
        static const pj_str_t STR_IP6 = { "IP6", 3};
        static const pj_str_t STR_SENDRECV = { "sendrecv", 8 };
        pjmedia_sdp_media *media;
-       char hostip[PJ_INET6_ADDRSTRLEN+2];
+       const char *hostip = NULL;
        struct ast_sockaddr addr;
        char tmp[512];
        pj_str_t stmp;
@@ -1061,16 +1061,16 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
 
        /* Add connection level details */
        if (direct_media_enabled) {
-               ast_copy_string(hostip, ast_sockaddr_stringify_fmt(&session_media->direct_media_addr, AST_SOCKADDR_STR_ADDR), sizeof(hostip));
+               hostip = ast_sockaddr_stringify_fmt(&session_media->direct_media_addr, AST_SOCKADDR_STR_ADDR);
        } else if (ast_strlen_zero(session->endpoint->media.address)) {
-               pj_sockaddr localaddr;
-
-               if (pj_gethostip(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET(), &localaddr)) {
-                       return -1;
-               }
-               pj_sockaddr_print(&localaddr, hostip, sizeof(hostip), 2);
+               hostip = ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET());
        } else {
-               ast_copy_string(hostip, session->endpoint->media.address, sizeof(hostip));
+               hostip = session->endpoint->media.address;
+       }
+
+       if (ast_strlen_zero(hostip)) {
+               ast_log(LOG_ERROR, "No local host IP available for stream %s\n", session_media->stream_type);
+               return -1;
        }
 
        media->conn->net_type = STR_IN;
index edcb7f8b18192230882cc4b801735af8d50ac3b2..79aab76adb1df807153d6e0557c9851d896021e1 100644 (file)
@@ -2538,12 +2538,7 @@ static struct pjmedia_sdp_session *create_local_sdp(pjsip_inv_session *inv, stru
                if (!ast_strlen_zero(session->endpoint->media.address)) {
                        pj_strdup2(inv->pool_prov, &local->origin.addr, session->endpoint->media.address);
                } else {
-                       pj_sockaddr localaddr;
-                       char our_ip[PJ_INET6_ADDRSTRLEN];
-
-                       pj_gethostip(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET(), &localaddr);
-                       pj_sockaddr_print(&localaddr, our_ip, sizeof(our_ip), 0);
-                       pj_strdup2(inv->pool_prov, &local->origin.addr, our_ip);
+                       pj_strdup2(inv->pool_prov, &local->origin.addr, ast_sip_get_host_ip_string(session->endpoint->media.rtp.ipv6 ? pj_AF_INET6() : pj_AF_INET()));
                }
        }
 
index 1943b62ae4a022912adae975f171dd80b91ca7c7..0be9e2596e17a22ca8305f420bba7ac76ea46c4a 100644 (file)
@@ -697,7 +697,7 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
        static const pj_str_t STR_T38UDPREDUNDANCY = { "t38UDPRedundancy", 16 };
        struct t38_state *state;
        pjmedia_sdp_media *media;
-       char hostip[PJ_INET6_ADDRSTRLEN+2];
+       const char *hostip = NULL;
        struct ast_sockaddr addr;
        char tmp[512];
        pj_str_t stmp;
@@ -722,14 +722,13 @@ static int create_outgoing_sdp_stream(struct ast_sip_session *session, struct as
        media->desc.transport = STR_UDPTL;
 
        if (ast_strlen_zero(session->endpoint->media.address)) {
-               pj_sockaddr localaddr;
-
-               if (pj_gethostip(session->endpoint->media.t38.ipv6 ? pj_AF_INET6() : pj_AF_INET(), &localaddr)) {
-                       return -1;
-               }
-               pj_sockaddr_print(&localaddr, hostip, sizeof(hostip), 2);
+               hostip = ast_sip_get_host_ip_string(session->endpoint->media.t38.ipv6 ? pj_AF_INET6() : pj_AF_INET());
        } else {
-               ast_copy_string(hostip, session->endpoint->media.address, sizeof(hostip));
+               hostip = session->endpoint->media.address;
+       }
+
+       if (ast_strlen_zero(hostip)) {
+               return -1;
        }
 
        media->conn->net_type = STR_IN;