summaryrefslogtreecommitdiff
path: root/pjlib-util
diff options
context:
space:
mode:
authorJason Parker <jparker@digium.com>2013-03-11 15:09:56 -0500
committerJason Parker <jparker@digium.com>2013-03-11 15:09:56 -0500
commit483805f79570115ab95c69698792d238c1719b1b (patch)
tree6b53ab2fd2b2478f864ccc8bd1b0bfaedc4d2050 /pjlib-util
parentf3ab456a17af1c89a6e3be4d20c5944853df1cb0 (diff)
Import pjproject-2.1
Diffstat (limited to 'pjlib-util')
-rw-r--r--pjlib-util/build/Makefile2
-rw-r--r--pjlib-util/include/pjlib-util/stun_simple.h77
-rw-r--r--pjlib-util/src/pjlib-util/resolver.c150
-rw-r--r--pjlib-util/src/pjlib-util/scanner.c3
-rw-r--r--pjlib-util/src/pjlib-util/stun_simple_client.c39
5 files changed, 211 insertions, 60 deletions
diff --git a/pjlib-util/build/Makefile b/pjlib-util/build/Makefile
index fba93bb..d2ad65a 100644
--- a/pjlib-util/build/Makefile
+++ b/pjlib-util/build/Makefile
@@ -74,7 +74,7 @@ distclean: realclean
pjlib-util:
$(MAKE) -f $(RULES_MAK) APP=PJLIB_UTIL app=pjlib-util $(PJLIB_UTIL_LIB)
-pjlib-util-test:
+pjlib-util-test: pjlib-util
$(MAKE) -f $(RULES_MAK) APP=UTIL_TEST app=pjlib-util-test $(UTIL_TEST_EXE)
.PHONY: ../lib/pjlib-util.ko
diff --git a/pjlib-util/include/pjlib-util/stun_simple.h b/pjlib-util/include/pjlib-util/stun_simple.h
index 3d10379..a0b1b69 100644
--- a/pjlib-util/include/pjlib-util/stun_simple.h
+++ b/pjlib-util/include/pjlib-util/stun_simple.h
@@ -1,4 +1,4 @@
-/* $Id: stun_simple.h 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: stun_simple.h 4224 2012-08-09 05:21:25Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -199,6 +199,81 @@ PJ_DECL(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
const pj_str_t *srv2, int port2,
pj_sockaddr_in mapped_addr[]);
+
+/*
+ * This structre describes configurable setting for requesting mapped address.
+ */
+typedef struct pjstun_setting
+{
+ /**
+ * Specifies whether STUN request generated by old STUN library should
+ * insert magic cookie (specified in RFC 5389) in the transaction ID.
+ */
+ pj_bool_t use_stun2;
+
+ /**
+ * Host name or IP address string of the first STUN server.
+ */
+ pj_str_t srv1;
+
+ /**
+ * The port number of the first STUN server.
+ */
+ int port1;
+
+ /**
+ * Host name or IP address string of the second STUN server.
+ */
+ pj_str_t srv2;
+
+ /**
+ * The port number of the second STUN server.
+ */
+ int port2;
+
+} pjstun_setting;
+
+
+/**
+ * Another version of mapped address resolution of local sockets to multiple
+ * STUN servers configured in #pjstun_setting. This function is able to find
+ * the mapped addresses of multiple sockets simultaneously, and for each
+ * socket, two requests will be sent to two different STUN servers to see if
+ * both servers get the same public address for the same socket. (Note that
+ * application can specify the same address for the two servers, but still
+ * two requests will be sent for each server).
+ *
+ * This function will perform necessary retransmissions of the requests if
+ * response is not received within a predetermined period. When all responses
+ * have been received, the function will compare the mapped addresses returned
+ * by the servers, and when both are equal, the address will be returned in
+ * \a mapped_addr argument.
+ *
+ * @param pf The pool factory where memory will be allocated from.
+ * @param opt The STUN settings.
+ * @param sock_cnt Number of sockets in the socket array.
+ * @param sock Array of local UDP sockets which public addresses are
+ * to be queried from the STUN servers.
+ * @param mapped_addr Array to receive the mapped public address of the local
+ * UDP sockets, when the function returns PJ_SUCCESS.
+ *
+ * @return This functions returns PJ_SUCCESS if responses are
+ * received from all servers AND all servers returned the
+ * same mapped public address. Otherwise this function may
+ * return one of the following error codes:
+ * - PJLIB_UTIL_ESTUNNOTRESPOND: no respons from servers.
+ * - PJLIB_UTIL_ESTUNSYMMETRIC: different mapped addresses
+ * are returned by servers.
+ * - etc.
+ *
+ */
+PJ_DECL(pj_status_t) pjstun_get_mapped_addr2( pj_pool_factory *pf,
+ const pjstun_setting *opt,
+ int sock_cnt,
+ pj_sock_t sock[],
+ pj_sockaddr_in mapped_addr[]);
+
+
PJ_END_DECL
/**
diff --git a/pjlib-util/src/pjlib-util/resolver.c b/pjlib-util/src/pjlib-util/resolver.c
index 4be5350..25c6067 100644
--- a/pjlib-util/src/pjlib-util/resolver.c
+++ b/pjlib-util/src/pjlib-util/resolver.c
@@ -1,4 +1,4 @@
-/* $Id: resolver.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: resolver.c 4333 2013-01-23 09:53:39Z nanang $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -180,7 +180,8 @@ struct pj_dns_resolver
unsigned char udp_rx_pkt[UDPSZ];/**< UDP receive buffer. */
unsigned char udp_tx_pkt[UDPSZ];/**< UDP receive buffer. */
pj_ssize_t udp_len; /**< Length of received packet. */
- pj_ioqueue_op_key_t udp_op_key; /**< UDP read operation key. */
+ pj_ioqueue_op_key_t udp_op_rx_key; /**< UDP read operation key. */
+ pj_ioqueue_op_key_t udp_op_tx_key; /**< UDP write operation key. */
pj_sockaddr_in udp_src_addr; /**< Source address of packet */
int udp_addr_len; /**< Source address length. */
@@ -223,6 +224,63 @@ static pj_status_t select_nameservers(pj_dns_resolver *resolver,
unsigned servers[]);
+/* Close UDP socket */
+static void close_sock(pj_dns_resolver *resv)
+{
+ /* Close existing socket */
+ if (resv->udp_key != NULL) {
+ pj_ioqueue_unregister(resv->udp_key);
+ resv->udp_key = NULL;
+ resv->udp_sock = PJ_INVALID_SOCKET;
+ } else if (resv->udp_sock != PJ_INVALID_SOCKET) {
+ pj_sock_close(resv->udp_sock);
+ resv->udp_sock = PJ_INVALID_SOCKET;
+ }
+}
+
+
+/* Initialize UDP socket */
+static pj_status_t init_sock(pj_dns_resolver *resv)
+{
+ pj_ioqueue_callback socket_cb;
+ pj_status_t status;
+
+ /* Create the UDP socket */
+ status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Bind to any address/port */
+ status = pj_sock_bind_in(resv->udp_sock, 0, 0);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ /* Register to ioqueue */
+ pj_bzero(&socket_cb, sizeof(socket_cb));
+ socket_cb.on_read_complete = &on_read_complete;
+ status = pj_ioqueue_register_sock(resv->pool, resv->ioqueue,
+ resv->udp_sock, resv, &socket_cb,
+ &resv->udp_key);
+ if (status != PJ_SUCCESS)
+ return status;
+
+ pj_ioqueue_op_key_init(&resv->udp_op_rx_key, sizeof(resv->udp_op_rx_key));
+ pj_ioqueue_op_key_init(&resv->udp_op_tx_key, sizeof(resv->udp_op_tx_key));
+
+ /* Start asynchronous read to the UDP socket */
+ resv->udp_len = sizeof(resv->udp_rx_pkt);
+ resv->udp_addr_len = sizeof(resv->udp_src_addr);
+ status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_rx_key,
+ resv->udp_rx_pkt, &resv->udp_len,
+ PJ_IOQUEUE_ALWAYS_ASYNC,
+ &resv->udp_src_addr, &resv->udp_addr_len);
+ if (status != PJ_EPENDING)
+ return status;
+
+ return PJ_SUCCESS;
+}
+
+
/* Initialize DNS settings with default values */
PJ_DEF(void) pj_dns_settings_default(pj_dns_settings *s)
{
@@ -247,7 +305,6 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
{
pj_pool_t *pool;
pj_dns_resolver *resv;
- pj_ioqueue_callback socket_cb;
pj_status_t status;
/* Sanity check */
@@ -302,37 +359,11 @@ PJ_DEF(pj_status_t) pj_dns_resolver_create( pj_pool_factory *pf,
resv->hquerybyres = pj_hash_create(pool, Q_HASH_TABLE_SIZE);
pj_list_init(&resv->query_free_nodes);
- /* Create the UDP socket */
- status = pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &resv->udp_sock);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- /* Bind to any address/port */
- status = pj_sock_bind_in(resv->udp_sock, 0, 0);
+ /* Initialize the UDP socket */
+ status = init_sock(resv);
if (status != PJ_SUCCESS)
goto on_error;
- /* Register to ioqueue */
- pj_bzero(&socket_cb, sizeof(socket_cb));
- socket_cb.on_read_complete = &on_read_complete;
- status = pj_ioqueue_register_sock(pool, resv->ioqueue, resv->udp_sock,
- resv, &socket_cb, &resv->udp_key);
- if (status != PJ_SUCCESS)
- goto on_error;
-
- pj_ioqueue_op_key_init(&resv->udp_op_key, sizeof(resv->udp_op_key));
-
- /* Start asynchronous read to the UDP socket */
- resv->udp_len = sizeof(resv->udp_rx_pkt);
- resv->udp_addr_len = sizeof(resv->udp_src_addr);
- status = pj_ioqueue_recvfrom(resv->udp_key, &resv->udp_op_key,
- resv->udp_rx_pkt, &resv->udp_len,
- PJ_IOQUEUE_ALWAYS_ASYNC,
- &resv->udp_src_addr, &resv->udp_addr_len);
- if (status != PJ_EPENDING)
- goto on_error;
-
-
/* Looks like everything is okay */
*p_resolver = resv;
return PJ_SUCCESS;
@@ -392,14 +423,7 @@ PJ_DEF(pj_status_t) pj_dns_resolver_destroy( pj_dns_resolver *resolver,
resolver->timer = NULL;
}
- if (resolver->udp_key != NULL) {
- pj_ioqueue_unregister(resolver->udp_key);
- resolver->udp_key = NULL;
- resolver->udp_sock = PJ_INVALID_SOCKET;
- } else if (resolver->udp_sock != PJ_INVALID_SOCKET) {
- pj_sock_close(resolver->udp_sock);
- resolver->udp_sock = PJ_INVALID_SOCKET;
- }
+ close_sock(resolver);
if (resolver->own_ioqueue && resolver->ioqueue) {
pj_ioqueue_destroy(resolver->ioqueue);
@@ -561,15 +585,6 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver,
pj_time_val delay;
pj_status_t status;
- /* Create DNS query packet */
- pkt_size = sizeof(resolver->udp_tx_pkt);
- name = pj_str(q->key.name);
- status = pj_dns_make_query(resolver->udp_tx_pkt, &pkt_size,
- q->id, q->key.qtype, &name);
- if (status != PJ_SUCCESS) {
- return status;
- }
-
/* Select which nameserver(s) to send requests to. */
server_cnt = PJ_ARRAY_SIZE(servers);
status = select_nameservers(resolver, &server_cnt, servers);
@@ -595,6 +610,28 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver,
return status;
}
+ /* Check if the socket is available for sending */
+ if (pj_ioqueue_is_pending(resolver->udp_key, &resolver->udp_op_tx_key)) {
+ ++q->transmit_cnt;
+ PJ_LOG(4,(resolver->name.ptr,
+ "Socket busy in transmitting DNS %s query for %s%s",
+ pj_dns_get_type_name(q->key.qtype),
+ q->key.name,
+ (q->transmit_cnt < resolver->settings.qretr_count?
+ ", will try again later":"")));
+ return PJ_SUCCESS;
+ }
+
+ /* Create DNS query packet */
+ pkt_size = sizeof(resolver->udp_tx_pkt);
+ name = pj_str(q->key.name);
+ status = pj_dns_make_query(resolver->udp_tx_pkt, &pkt_size,
+ q->id, q->key.qtype, &name);
+ if (status != PJ_SUCCESS) {
+ pj_timer_heap_cancel(resolver->timer, &q->timer_entry);
+ return status;
+ }
+
/* Get current time. */
pj_gettimeofday(&now);
@@ -603,13 +640,16 @@ static pj_status_t transmit_query(pj_dns_resolver *resolver,
pj_ssize_t sent = (pj_ssize_t) pkt_size;
struct nameserver *ns = &resolver->ns[servers[i]];
- pj_sock_sendto(resolver->udp_sock, resolver->udp_tx_pkt, &sent, 0,
- &resolver->ns[servers[i]].addr, sizeof(pj_sockaddr_in));
+ status = pj_ioqueue_sendto(resolver->udp_key,
+ &resolver->udp_op_tx_key,
+ resolver->udp_tx_pkt, &sent, 0,
+ &resolver->ns[servers[i]].addr,
+ sizeof(pj_sockaddr_in));
- PJ_LOG(4,(resolver->name.ptr,
+ PJ_PERROR(4,(resolver->name.ptr, status,
"%s %d bytes to NS %d (%s:%d): DNS %s query for %s",
(q->transmit_cnt==0? "Transmitting":"Re-transmitting"),
- (int)sent, servers[i],
+ (int)pkt_size, servers[i],
pj_inet_ntoa(ns->addr.sin_addr),
(int)pj_ntohs(ns->addr.sin_port),
pj_dns_get_type_name(q->key.qtype),
@@ -1248,6 +1288,9 @@ static void on_timeout( pj_timer_heap_t *timer_heap,
pj_hash_set(NULL, resolver->hquerybyid, &q->id, sizeof(q->id), 0, NULL);
pj_hash_set(NULL, resolver->hquerybyres, &q->key, sizeof(q->key), 0, NULL);
+ /* Workaround for deadlock problem in #1565 (similar to #1108) */
+ pj_mutex_unlock(resolver->mutex);
+
/* Call application callback, if any. */
if (q->cb)
(*q->cb)(q->user_data, PJ_ETIMEDOUT, NULL);
@@ -1260,6 +1303,9 @@ static void on_timeout( pj_timer_heap_t *timer_heap,
cq = cq->next;
}
+ /* Workaround for deadlock problem in #1565 (similar to #1108) */
+ pj_mutex_lock(resolver->mutex);
+
/* Clear data */
q->timer_entry.id = 0;
q->user_data = NULL;
diff --git a/pjlib-util/src/pjlib-util/scanner.c b/pjlib-util/src/pjlib-util/scanner.c
index d8e1c8e..ba1152e 100644
--- a/pjlib-util/src/pjlib-util/scanner.c
+++ b/pjlib-util/src/pjlib-util/scanner.c
@@ -1,4 +1,4 @@
-/* $Id: scanner.c 3553 2011-05-05 06:14:19Z nanang $ */
+/* $Id: scanner.c 4209 2012-07-18 10:21:00Z ming $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -393,7 +393,6 @@ PJ_DEF(void) pj_scan_get_quotes(pj_scanner *scanner,
}
/* break from main loop if we have odd number of backslashes */
if (((unsigned)(q-r) & 0x01) == 1) {
- ++s;
break;
}
++s;
diff --git a/pjlib-util/src/pjlib-util/stun_simple_client.c b/pjlib-util/src/pjlib-util/stun_simple_client.c
index 345d121..2a59ae1 100644
--- a/pjlib-util/src/pjlib-util/stun_simple_client.c
+++ b/pjlib-util/src/pjlib-util/stun_simple_client.c
@@ -1,4 +1,4 @@
-/* $Id: stun_simple_client.c 3999 2012-03-30 07:10:13Z bennylp $ */
+/* $Id: stun_simple_client.c 4297 2012-11-13 08:46:42Z bennylp $ */
/*
* Copyright (C) 2008-2011 Teluu Inc. (http://www.teluu.com)
* Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
@@ -42,7 +42,27 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
const pj_str_t *srv2, int port2,
pj_sockaddr_in mapped_addr[])
{
+ pjstun_setting opt;
+
+ pj_bzero(&opt, sizeof(opt));
+ opt.use_stun2 = PJ_FALSE;
+ opt.srv1 = *srv1;
+ opt.port1 = port1;
+ opt.srv2 = *srv2;
+ opt.port2 = port2;
+
+ return pjstun_get_mapped_addr2(pf, &opt, sock_cnt, sock, mapped_addr);
+}
+
+PJ_DEF(pj_status_t) pjstun_get_mapped_addr2(pj_pool_factory *pf,
+ const pjstun_setting *opt,
+ int sock_cnt,
+ pj_sock_t sock[],
+ pj_sockaddr_in mapped_addr[])
+{
unsigned srv_cnt;
+ const pj_str_t *srv1, *srv2;
+ int port1, port2;
pj_sockaddr_in srv_addr[2];
int i, send_cnt = 0, nfds;
pj_pool_t *pool;
@@ -59,6 +79,11 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
PJ_CHECK_STACK();
+ srv1 = &opt->srv1;
+ port1 = opt->port1;
+ srv2 = &opt->srv1;
+ port2 = opt->port2;
+
TRACE_((THIS_FILE, "Entering pjstun_get_mapped_addr()"));
/* Create pool. */
@@ -82,6 +107,12 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
if (status != PJ_SUCCESS)
goto on_error;
+ /* Insert magic cookie (specified in RFC 5389) when requested to. */
+ if (opt->use_stun2) {
+ pjstun_msg_hdr *hdr = (pjstun_msg_hdr*)out_msg;
+ hdr->tsx[0] = pj_htonl(STUN_MAGIC);
+ }
+
TRACE_((THIS_FILE, " Binding request created."));
/* Resolve servers. */
@@ -162,15 +193,15 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf,
TRACE_((THIS_FILE, " Request(s) sent, counter=%d", send_cnt));
/* Calculate time of next retransmission. */
- pj_gettimeofday(&next_tx);
+ pj_gettickcount(&next_tx);
next_tx.sec += (stun_timer[send_cnt]/1000);
next_tx.msec += (stun_timer[send_cnt]%1000);
pj_time_val_normalize(&next_tx);
- for (pj_gettimeofday(&now), select_rc=1;
+ for (pj_gettickcount(&now), select_rc=1;
status==PJ_SUCCESS && select_rc>=1 && wait_resp>0
&& PJ_TIME_VAL_LT(now, next_tx);
- pj_gettimeofday(&now))
+ pj_gettickcount(&now))
{
pj_time_val timeout;