summaryrefslogtreecommitdiff
path: root/pjlib/src/pj/sock_common.c
diff options
context:
space:
mode:
Diffstat (limited to 'pjlib/src/pj/sock_common.c')
-rw-r--r--pjlib/src/pj/sock_common.c111
1 files changed, 88 insertions, 23 deletions
diff --git a/pjlib/src/pj/sock_common.c b/pjlib/src/pj/sock_common.c
index dd2ef6e..1528b5f 100644
--- a/pjlib/src/pj/sock_common.c
+++ b/pjlib/src/pj/sock_common.c
@@ -1,4 +1,4 @@
-/* $Id: sock_common.c 3841 2011-10-24 09:28:13Z ming $ */
+/* $Id: sock_common.c 4343 2013-02-07 09:35:34Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -24,6 +24,7 @@
#include <pj/ip_helper.h>
#include <pj/os.h>
#include <pj/addr_resolv.h>
+#include <pj/rand.h>
#include <pj/string.h>
#include <pj/compat/socket.h>
@@ -956,42 +957,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 +1014,70 @@ 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);
+}
+
+
+/*
+ * Bind socket at random port.
+ */
+PJ_DEF(pj_status_t) pj_sock_bind_random( pj_sock_t sockfd,
+ const pj_sockaddr_t *addr,
+ pj_uint16_t port_range,
+ pj_uint16_t max_try)
+{
+ pj_sockaddr bind_addr;
+ int addr_len;
+ pj_uint16_t base_port;
+ pj_status_t status = PJ_SUCCESS;
+
+ PJ_CHECK_STACK();
+
+ PJ_ASSERT_RETURN(addr, PJ_EINVAL);
+
+ pj_sockaddr_cp(&bind_addr, addr);
+ addr_len = pj_sockaddr_get_len(addr);
+ base_port = pj_sockaddr_get_port(addr);
+
+ if (base_port == 0 || port_range == 0) {
+ return pj_sock_bind(sockfd, &bind_addr, addr_len);
+ }
+
+ for (; max_try; --max_try) {
+ pj_uint16_t port;
+ port = (pj_uint16_t)(base_port + pj_rand() % (port_range + 1));
+ pj_sockaddr_set_port(&bind_addr, port);
+ status = pj_sock_bind(sockfd, &bind_addr, addr_len);
+ if (status == PJ_SUCCESS)
+ break;
+ }
+
+ return status;
+}
+
/* Only need to implement these in DLL build */
#if defined(PJ_DLL)