From ed7f9eba764e5fb47f7bc881bd96ceeb359bb3cc Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Tue, 7 Aug 2012 02:18:15 +0000 Subject: Fixed #1412: Account specific NAT settings: STUN, ICE, and TURN git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@4218 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib/include/pj/addr_resolv.h | 25 +++++++++++++++ pjlib/src/pj/sock_common.c | 70 +++++++++++++++++++++++++++++------------- 2 files changed, 73 insertions(+), 22 deletions(-) (limited to 'pjlib') diff --git a/pjlib/include/pj/addr_resolv.h b/pjlib/include/pj/addr_resolv.h index 096dde14..7e89936c 100644 --- a/pjlib/include/pj/addr_resolv.h +++ b/pjlib/include/pj/addr_resolv.h @@ -116,6 +116,31 @@ PJ_DECL(pj_status_t) pj_gethostbyname(const pj_str_t *name, pj_hostent *he); PJ_DECL(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr); +/** + * Get the interface IP address to send data to the specified destination. + * + * @param af The desired address family to query. Valid values + * are pj_AF_INET() or pj_AF_INET6(). + * @param dst The destination host. + * @param itf_addr On successful resolution, the address family and address + * part of this socket address will be filled up with the host + * IP address, in network byte order. Other parts of the socket + * address should be ignored. + * @param allow_resolve If \a dst may contain hostname (instead of IP + * address), specify whether hostname resolution should + * be performed. If not, default interface address will + * be returned. + * @param p_dst_addr If not NULL, it will be filled with the IP address of + * the destination host. + * + * @return PJ_SUCCESS on success, or the appropriate error code. + */ +PJ_DECL(pj_status_t) pj_getipinterface(int af, + const pj_str_t *dst, + pj_sockaddr *itf_addr, + pj_bool_t allow_resolve, + pj_sockaddr *p_dst_addr); + /** * Get the IP address of the default interface. Default interface is the * interface of the default route. diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c index 948d47da..7aaf6689 100644 --- a/pjlib/src/pj/sock_common.c +++ b/pjlib/src/pj/sock_common.c @@ -956,42 +956,54 @@ PJ_DEF(pj_status_t) pj_gethostip(int af, pj_sockaddr *addr) return PJ_SUCCESS; } -/* Get the default IP interface */ -PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) +/* Get IP interface for sending to the specified destination */ +PJ_DEF(pj_status_t) pj_getipinterface(int af, + const pj_str_t *dst, + pj_sockaddr *itf_addr, + pj_bool_t allow_resolve, + pj_sockaddr *p_dst_addr) { + pj_sockaddr dst_addr; pj_sock_t fd; - pj_str_t cp; - pj_sockaddr a; int len; pj_uint8_t zero[64]; pj_status_t status; - addr->addr.sa_family = (pj_uint16_t)af; - - status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd); + pj_sockaddr_init(af, &dst_addr, NULL, 53); + status = pj_inet_pton(af, dst, pj_sockaddr_get_addr(&dst_addr)); if (status != PJ_SUCCESS) { - return status; - } + /* "dst" is not an IP address. */ + if (allow_resolve) { + status = pj_sockaddr_init(af, &dst_addr, dst, 53); + } else { + pj_str_t cp; - if (af == PJ_AF_INET) { - cp = pj_str("1.1.1.1"); - } else { - cp = pj_str("1::1"); + if (af == PJ_AF_INET) { + cp = pj_str("1.1.1.1"); + } else { + cp = pj_str("1::1"); + } + status = pj_sockaddr_init(af, &dst_addr, &cp, 53); + } + + if (status != PJ_SUCCESS) + return status; } - status = pj_sockaddr_init(af, &a, &cp, 53); + + /* Create UDP socket and connect() to the destination IP */ + status = pj_sock_socket(af, pj_SOCK_DGRAM(), 0, &fd); if (status != PJ_SUCCESS) { - pj_sock_close(fd); return status; } - status = pj_sock_connect(fd, &a, pj_sockaddr_get_len(&a)); + status = pj_sock_connect(fd, &dst_addr, pj_sockaddr_get_len(&dst_addr)); if (status != PJ_SUCCESS) { pj_sock_close(fd); return status; } - len = sizeof(a); - status = pj_sock_getsockname(fd, &a, &len); + len = sizeof(*itf_addr); + status = pj_sock_getsockname(fd, itf_addr, &len); if (status != PJ_SUCCESS) { pj_sock_close(fd); return status; @@ -1001,18 +1013,32 @@ PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) /* Check that the address returned is not zero */ pj_bzero(zero, sizeof(zero)); - if (pj_memcmp(pj_sockaddr_get_addr(&a), zero, - pj_sockaddr_get_addr_len(&a))==0) + if (pj_memcmp(pj_sockaddr_get_addr(itf_addr), zero, + pj_sockaddr_get_addr_len(itf_addr))==0) { return PJ_ENOTFOUND; } - pj_sockaddr_copy_addr(addr, &a); + if (p_dst_addr) + *p_dst_addr = dst_addr; - /* Success */ return PJ_SUCCESS; } +/* Get the default IP interface */ +PJ_DEF(pj_status_t) pj_getdefaultipinterface(int af, pj_sockaddr *addr) +{ + pj_str_t cp; + + if (af == PJ_AF_INET) { + cp = pj_str("1.1.1.1"); + } else { + cp = pj_str("1::1"); + } + + return pj_getipinterface(af, &cp, addr, PJ_FALSE, NULL); +} + /* Only need to implement these in DLL build */ #if defined(PJ_DLL) -- cgit v1.2.3