From e7716fed2b589439f7ac59b834dbdc7685dddca4 Mon Sep 17 00:00:00 2001 From: Benny Prijono Date: Wed, 20 Apr 2011 09:16:27 +0000 Subject: Fix #1229: bug fix and enhancements for PJLIB-UTIL STUN client: Bug: 1. Bug: if UDP packet is lost, the resolver will wait until all retransmissions are done, which means 4 seconds delay. Enhancements: 1. Allow caller to specify only 1 STUN server, for faster result. 1. If both servers point to the same address, only one will be used. 1. Decrease retransmission delay from 1000 ms to 500 ms for more responsive result. 1. Reduce memory consumption (from 1024 to 400 bytes). git-svn-id: http://svn.pjsip.org/repos/pjproject/trunk@3540 74dad513-b988-da41-8d7b-12977e46ad98 --- pjlib-util/src/pjlib-util/stun_simple_client.c | 70 +++++++++++++++++++++----- 1 file changed, 58 insertions(+), 12 deletions(-) (limited to 'pjlib-util') diff --git a/pjlib-util/src/pjlib-util/stun_simple_client.c b/pjlib-util/src/pjlib-util/stun_simple_client.c index fa4fb966..0c6c6786 100644 --- a/pjlib-util/src/pjlib-util/stun_simple_client.c +++ b/pjlib-util/src/pjlib-util/stun_simple_client.c @@ -28,12 +28,13 @@ enum { MAX_REQUEST = 4 }; -static int stun_timer[] = {1000, 1000, 1000, 1000 }; +static int stun_timer[] = {500, 500, 500, 500 }; #define STUN_MAGIC 0x2112A442 #define THIS_FILE "stun_client.c" #define LOG_ADDR(addr) pj_inet_ntoa(addr.sin_addr), pj_ntohs(addr.sin_port) +#define TRACE_(x) PJ_LOG(6,x) PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, int sock_cnt, pj_sock_t sock[], @@ -41,6 +42,7 @@ 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[]) { + unsigned srv_cnt; pj_sockaddr_in srv_addr[2]; int i, j, send_cnt = 0; pj_pool_t *pool; @@ -57,8 +59,10 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, PJ_CHECK_STACK(); + TRACE_((THIS_FILE, "Entering pjstun_get_mapped_addr()")); + /* Create pool. */ - pool = pj_pool_create(pf, "stun%p", 1024, 1024, NULL); + pool = pj_pool_create(pf, "stun%p", 400, 400, NULL); if (!pool) return PJ_ENOMEM; @@ -70,6 +74,7 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, goto on_error; } + TRACE_((THIS_FILE, " Memory allocated.")); /* Create the outgoing BIND REQUEST message template */ status = pjstun_create_bind_req( pool, &out_msg, &out_msg_len, @@ -77,18 +82,37 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, if (status != PJ_SUCCESS) goto on_error; + TRACE_((THIS_FILE, " Binding request created.")); + /* Resolve servers. */ status = pj_sockaddr_in_init(&srv_addr[0], srv1, (pj_uint16_t)port1); if (status != PJ_SUCCESS) goto on_error; - status = pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2); - if (status != PJ_SUCCESS) - goto on_error; + srv_cnt = 1; + + if (srv2 && port2) { + status = pj_sockaddr_in_init(&srv_addr[1], srv2, (pj_uint16_t)port2); + if (status != PJ_SUCCESS) + goto on_error; + + if (srv_addr[1].sin_addr.s_addr != srv_addr[0].sin_addr.s_addr && + srv_addr[1].sin_port != srv_addr[0].sin_port) + { + srv_cnt++; + } + } + + TRACE_((THIS_FILE, " Server initialized, using %d server(s)", srv_cnt)); /* Init mapped addresses to zero */ pj_memset(mapped_addr, 0, sock_cnt * sizeof(pj_sockaddr_in)); + /* We need these many responses */ + wait_resp = sock_cnt * srv_cnt; + + TRACE_((THIS_FILE, " Done initialization.")); + /* Main retransmission loop. */ for (send_cnt=0; send_cnttsx[2]); srv_idx = pj_ntohl(msg.hdr->tsx[3]); - if (sock_idx<0 || sock_idx>=sock_cnt || srv_idx<0 || srv_idx>=2) { + if (sock_idx<0 || sock_idx>=sock_cnt || sock_idx!=i || + srv_idx<0 || srv_idx>=2) + { status = PJLIB_UTIL_ESTUNININDEX; continue; } @@ -211,6 +237,11 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, continue; } + if (rec[sock_idx].srv[srv_idx].mapped_port != 0) { + /* Already got response */ + continue; + } + /* From this part, we consider the packet as a valid STUN * response for our request. */ @@ -248,9 +279,20 @@ PJ_DEF(pj_status_t) pjstun_get_mapped_addr( pj_pool_factory *pf, break; } + TRACE_((THIS_FILE, " All responses received, calculating result..")); + for (i=0; i