Index: pjproject/trunk/pjlib-util/include/pjlib-util/stun_simple.h
===================================================================
--- pjproject/trunk/pjlib-util/include/pjlib-util/stun_simple.h	(revision 4223)
+++ pjproject/trunk/pjlib-util/include/pjlib-util/stun_simple.h	(revision 4224)
@@ -200,4 +200,79 @@
 					      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
 
Index: pjproject/trunk/pjlib-util/src/pjlib-util/stun_simple_client.c
===================================================================
--- pjproject/trunk/pjlib-util/src/pjlib-util/stun_simple_client.c	(revision 4223)
+++ pjproject/trunk/pjlib-util/src/pjlib-util/stun_simple_client.c	(revision 4224)
@@ -43,5 +43,25 @@
 					    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;
@@ -60,4 +80,9 @@
     PJ_CHECK_STACK();
 
+    srv1 = &opt->srv1;
+    port1 = opt->port1;
+    srv2 = &opt->srv1;
+    port2 = opt->port2;
+
     TRACE_((THIS_FILE, "Entering pjstun_get_mapped_addr()"));
 
@@ -82,4 +107,10 @@
     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."));
Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4223)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 4224)
@@ -1463,4 +1463,13 @@
 
     /**
+     * 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:
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4223)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 4224)
@@ -1923,4 +1923,6 @@
 
     } else if (stun_srv.slen) {
+	pjstun_setting stun_opt;
+
 	/*
 	 * STUN is specified, resolve the address with STUN.
@@ -1932,8 +1934,11 @@
 	}
 
-	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);
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4223)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 4224)
@@ -329,4 +329,5 @@
 	    char ip_addr[32];
 	    pj_str_t stun_srv;
+	    pjstun_setting stun_opt;
 
 	    pj_ansi_strcpy(ip_addr,
@@ -334,8 +335,11 @@
 	    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);
