Index: pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h
===================================================================
--- pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 5296)
+++ pjproject/trunk/pjsip/include/pjsua-lib/pjsua.h	(revision 5297)
@@ -1582,4 +1582,9 @@
      * start if it fails to resolve or contact any of the STUN servers.
      *
+     * This setting will also determine what happens if STUN servers are
+     * unavailable during runtime (if set to PJ_FALSE, calls will
+     * directly fail, otherwise (if PJ_TRUE) call medias will
+     * fallback to proceed as though not using STUN servers.
+     *
      * Default: PJ_TRUE
      */
@@ -2083,4 +2088,28 @@
  */
 PJ_DECL(pj_status_t) pjsua_get_nat_type(pj_stun_nat_type *type);
+
+
+/**
+ * Update the STUN servers list. The #pjsua_init() must have been called
+ * before calling this function.
+ *
+ * @param count		Number of STUN server entries.
+ * @param srv		Array of STUN server entries to try. Please see
+ *			the \a stun_srv field in the #pjsua_config 
+ *			documentation about the format of this entry.
+ * @param wait		Specify non-zero to make the function block until
+ *			it gets the result. In this case, the function
+ *			will block while the resolution is being done,
+ *			and the callback will be called before this function
+ *			returns.
+ *
+ * @return		If \a wait parameter is non-zero, this will return
+ *			PJ_SUCCESS if one usable STUN server is found.
+ *			Otherwise it will always return PJ_SUCCESS, and
+ *			application will be notified about the result in
+ *			the callback #on_stun_resolution_complete.
+ */
+PJ_DECL(pj_status_t) pjsua_update_stun_servers(unsigned count, pj_str_t srv[],
+					       pj_bool_t wait);
 
 
@@ -2723,5 +2752,14 @@
      * this setting has no effect.
      */
-    PJSUA_STUN_USE_DISABLED
+    PJSUA_STUN_USE_DISABLED,
+    
+    /**
+     * Retry other STUN servers if the STUN server selected during
+     * startup (#pjsua_init()) or after calling #pjsua_update_stun_servers()
+     * is unavailable during runtime. This setting is valid only for
+     * account's media STUN setting and if the call is using UDP media
+     * transport.
+     */
+    PJSUA_STUN_RETRY_ON_FAILURE
 
 } pjsua_stun_use;
Index: pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp
===================================================================
--- pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp	(revision 5296)
+++ pjproject/trunk/pjsip/include/pjsua2/endpoint.hpp	(revision 5297)
@@ -903,4 +903,30 @@
      */
     pj_stun_nat_type natGetType() throw(Error);
+
+    /**
+     * Update the STUN servers list. The libInit() must have been called
+     * before calling this function.
+     *
+     * @param prmServers	Array of STUN servers to try. The endpoint
+     * 				will try to resolve and contact each of the
+     * 				STUN server entry until it finds one that is
+     * 				usable. Each entry may be a domain name, host
+     * 				name, IP address, and it may contain an
+     * 				optional port number. For example:
+     *				- "pjsip.org" (domain name)
+     *				- "sip.pjsip.org" (host name)
+     *				- "pjsip.org:33478" (domain name and a non-
+     *				   standard port number)
+     *				- "10.0.0.1:3478" (IP address and port number)
+     * @param prmWait		Specify if the function should block until
+     *				it gets the result. In this case, the
+     *				function will block while the resolution
+     * 				is being done, and the callback
+     * 				onNatCheckStunServersComplete() will be called
+     * 				before this function returns.
+     *
+     */
+    void natUpdateStunServers(const StringVector &prmServers,
+                              bool prmWait) throw(Error);
 
     /**
@@ -1190,5 +1216,5 @@
      * Callback when the Endpoint has finished performing STUN server
      * checking that is initiated when calling libInit(), or by
-     * calling natCheckStunServers().
+     * calling natCheckStunServers() or natUpdateStunServers().
      *
      * @param prm	Callback parameters.
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 5296)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_core.c	(revision 5297)
@@ -1377,4 +1377,34 @@
 
 /*
+ * Update STUN servers.
+ */
+PJ_DEF(pj_status_t) pjsua_update_stun_servers(unsigned count, pj_str_t srv[],
+					      pj_bool_t wait)
+{
+    unsigned i;
+    pj_status_t status;
+
+    PJ_ASSERT_RETURN(count && srv, PJ_EINVAL);
+    
+    PJSUA_LOCK();
+
+    pjsua_var.ua_cfg.stun_srv_cnt = count;
+    for (i = 0; i < count; i++) {
+        if (pj_strcmp(&pjsua_var.ua_cfg.stun_srv[i], &srv[i]))
+            pj_strdup(pjsua_var.pool, &pjsua_var.ua_cfg.stun_srv[i], &srv[i]);
+    }
+    pjsua_var.stun_status = PJ_EUNKNOWN;
+
+    status = resolve_stun_server(wait);
+    if (wait == PJ_FALSE && status == PJ_EPENDING)
+        status = PJ_SUCCESS;
+
+    PJSUA_UNLOCK();
+    
+    return status;
+}
+
+
+/*
  * Resolve STUN server.
  */
@@ -1482,4 +1512,5 @@
 	/* Perform NAT type detection if not yet */
 	if (pjsua_var.nat_type == PJ_STUN_NAT_TYPE_UNKNOWN &&
+	    !pjsua_var.nat_in_progress &&
 	    pjsua_var.ua_cfg.nat_type_in_sdp)
 	{
Index: pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c
===================================================================
--- pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 5296)
+++ pjproject/trunk/pjsip/src/pjsua-lib/pjsua_media.c	(revision 5297)
@@ -390,4 +390,31 @@
 	    else
 #endif
+
+	    if (status != PJ_SUCCESS && pjsua_var.ua_cfg.stun_srv_cnt > 1 &&
+	        ((acc->cfg.media_stun_use & PJSUA_STUN_RETRY_ON_FAILURE)!=0))
+	    {
+	    	PJ_LOG(4,(THIS_FILE, "Failed to get STUN mapped address, "
+	    			     "retrying other STUN servers"));
+	    	status=pjsua_update_stun_servers(pjsua_var.ua_cfg.stun_srv_cnt,
+	    			   	    	 pjsua_var.ua_cfg.stun_srv,
+	    			   	    	 PJ_TRUE);
+	    	if (status == PJ_SUCCESS) {
+		    if (pjsua_var.stun_srv.addr.sa_family != 0) {
+			pj_ansi_strcpy(ip_addr,
+			    pj_inet_ntoa(pjsua_var.stun_srv.ipv4.sin_addr));
+			stun_srv = pj_str(ip_addr);
+	    	    } else {
+		    	stun_srv.slen = 0;
+    	            }
+    	    
+    	            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,
+	    				    	     resolved_addr);
+	        }
+	    }
+
 	    if (status != PJ_SUCCESS) {
 		if (!pjsua_var.ua_cfg.stun_ignore_failure) {
Index: pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp
===================================================================
--- pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp	(revision 5296)
+++ pjproject/trunk/pjsip/src/pjsua2/endpoint.cpp	(revision 5297)
@@ -1562,4 +1562,19 @@
 }
 
+void Endpoint::natUpdateStunServers(const StringVector &servers,
+				    bool wait) throw(Error)
+{
+    pj_str_t srv[MAX_STUN_SERVERS];
+    unsigned i, count = 0;
+
+    for (i=0; i<servers.size() && i<MAX_STUN_SERVERS; ++i) {
+	srv[count].ptr = (char*)servers[i].c_str();
+	srv[count].slen = servers[i].size();
+	++count;
+    }
+
+    PJSUA2_CHECK_EXPR(pjsua_update_stun_servers(count, srv, wait) );
+}
+
 void Endpoint::natCheckStunServers(const StringVector &servers,
 				   bool wait,
