diff options
author | Jason Parker <jparker@digium.com> | 2013-03-11 15:09:56 -0500 |
---|---|---|
committer | Jason Parker <jparker@digium.com> | 2013-03-11 15:09:56 -0500 |
commit | 483805f79570115ab95c69698792d238c1719b1b (patch) | |
tree | 6b53ab2fd2b2478f864ccc8bd1b0bfaedc4d2050 /pjlib-util | |
parent | f3ab456a17af1c89a6e3be4d20c5944853df1cb0 (diff) |
Import pjproject-2.1
Diffstat (limited to 'pjlib-util')
-rw-r--r-- | pjlib-util/build/Makefile | 2 | ||||
-rw-r--r-- | pjlib-util/include/pjlib-util/stun_simple.h | 77 | ||||
-rw-r--r-- | pjlib-util/src/pjlib-util/resolver.c | 150 | ||||
-rw-r--r-- | pjlib-util/src/pjlib-util/scanner.c | 3 | ||||
-rw-r--r-- | pjlib-util/src/pjlib-util/stun_simple_client.c | 39 |
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; |