diff options
-rw-r--r-- | pjlib-util/include/pjlib-util/stun_simple.h | 75 | ||||
-rw-r--r-- | pjlib-util/src/pjlib-util/stun_simple_client.c | 31 | ||||
-rw-r--r-- | pjsip/include/pjsua-lib/pjsua.h | 9 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_core.c | 13 | ||||
-rw-r--r-- | pjsip/src/pjsua-lib/pjsua_media.c | 12 |
5 files changed, 132 insertions, 8 deletions
diff --git a/pjlib-util/include/pjlib-util/stun_simple.h b/pjlib-util/include/pjlib-util/stun_simple.h index 773548d2..87a10110 100644 --- a/pjlib-util/include/pjlib-util/stun_simple.h +++ b/pjlib-util/include/pjlib-util/stun_simple.h @@ -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/stun_simple_client.c b/pjlib-util/src/pjlib-util/stun_simple_client.c index dc13fe1a..109a49cd 100644 --- a/pjlib-util/src/pjlib-util/stun_simple_client.c +++ b/pjlib-util/src/pjlib-util/stun_simple_client.c @@ -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. */ diff --git a/pjsip/include/pjsua-lib/pjsua.h b/pjsip/include/pjsua-lib/pjsua.h index 40517423..fdc35c7c 100644 --- a/pjsip/include/pjsua-lib/pjsua.h +++ b/pjsip/include/pjsua-lib/pjsua.h @@ -1462,6 +1462,15 @@ typedef struct pjsua_config pj_bool_t stun_ignore_failure; /** + * This specifies whether STUN requests for resolving socket mapped + * address should use the new format, i.e: having STUN magic cookie + * in its transaction ID. + * + * Default: PJ_FALSE + */ + pj_bool_t stun_map_use_stun2; + + /** * Support for adding and parsing NAT type in the SDP to assist * troubleshooting. The valid values are: * - 0: no information will be added in SDP, and parsing is disabled. diff --git a/pjsip/src/pjsua-lib/pjsua_core.c b/pjsip/src/pjsua-lib/pjsua_core.c index f86eadf1..f0b44119 100644 --- a/pjsip/src/pjsua-lib/pjsua_core.c +++ b/pjsip/src/pjsua-lib/pjsua_core.c @@ -1922,6 +1922,8 @@ static pj_status_t create_sip_udp_sock(int af, pj_sockaddr_set_port(p_pub_addr, (pj_uint16_t)port); } else if (stun_srv.slen) { + pjstun_setting stun_opt; + /* * STUN is specified, resolve the address with STUN. */ @@ -1931,10 +1933,13 @@ static pj_status_t create_sip_udp_sock(int af, return PJ_EAFNOTSUP; } - status = pjstun_get_mapped_addr(&pjsua_var.cp.factory, 1, &sock, - &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), - &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), - &p_pub_addr->ipv4); + pj_bzero(&stun_opt, sizeof(stun_opt)); + stun_opt.use_stun2 = pjsua_var.ua_cfg.stun_map_use_stun2; + stun_opt.srv1 = stun_opt.srv2 = stun_srv; + stun_opt.port1 = stun_opt.port2 = + pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port); + status = pjstun_get_mapped_addr2(&pjsua_var.cp.factory, &stun_opt, + 1, &sock, &p_pub_addr->ipv4); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "Error contacting STUN server", status); pj_sock_close(sock); diff --git a/pjsip/src/pjsua-lib/pjsua_media.c b/pjsip/src/pjsua-lib/pjsua_media.c index 24f0ee61..4bd80337 100644 --- a/pjsip/src/pjsua-lib/pjsua_media.c +++ b/pjsip/src/pjsua-lib/pjsua_media.c @@ -328,15 +328,19 @@ static pj_status_t create_rtp_rtcp_sock(pjsua_call_media *call_med, { char ip_addr[32]; pj_str_t stun_srv; + pjstun_setting stun_opt; pj_ansi_strcpy(ip_addr, pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr)); stun_srv = pj_str(ip_addr); - status=pjstun_get_mapped_addr(&pjsua_var.cp.factory, 2, sock, - &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), - &stun_srv, pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port), - mapped_addr); + pj_bzero(&stun_opt, sizeof(stun_opt)); + stun_opt.use_stun2 = pjsua_var.ua_cfg.stun_map_use_stun2; + stun_opt.srv1 = stun_opt.srv2 = stun_srv; + stun_opt.port1 = stun_opt.port2 = + pj_ntohs(pjsua_var.stun_srv.ipv4.sin_port); + status=pjstun_get_mapped_addr2(&pjsua_var.cp.factory, &stun_opt, + 2, sock, mapped_addr); if (status != PJ_SUCCESS) { pjsua_perror(THIS_FILE, "STUN resolve error", status); goto on_error; |