From c84d431320cc9ea5b15e8712588b4680404635c7 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Date: Mon, 26 Mar 2012 17:20:48 -0400
Subject: [PATCH] #9547: Destroy the STUN resolver if server name change

---
 daemon/src/sip/sipaccount.cpp  |  9 +++++++--
 daemon/src/sip/sipvoiplink.cpp | 33 ++++++++++++++++++++++++++++-----
 daemon/src/sip/sipvoiplink.h   | 22 +++++++++++++++++-----
 3 files changed, 52 insertions(+), 12 deletions(-)

diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index 72e832f85c..5750f57e4e 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -405,6 +405,11 @@ void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
     publishedIpAddress_ = details[CONFIG_PUBLISHED_ADDRESS];
     localPort_ = atoi(details[CONFIG_LOCAL_PORT].c_str());
     publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str());
+    if(stunServer_ != details[CONFIG_STUN_SERVER]) {
+        DEBUG("Stun server changed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
+        link_->destroyStunResolver(stunServer_);
+        // pj_stun_sock_destroy(pj_stun_sock *stun_sock);
+    }
     stunServer_ = details[CONFIG_STUN_SERVER];
     stunEnabled_ = details[CONFIG_STUN_ENABLE] == "true";
     dtmfType_ = details[CONFIG_ACCOUNT_DTMF_TYPE];
@@ -838,9 +843,9 @@ void SIPAccount::keepAliveRegistrationCb(UNUSED pj_timer_heap_t *th, pj_timer_en
 
     // IP2IP default does not require keep-alive
     if (sipAccount->isIP2IP())
-        return; 
+        return;
 
-    // TLS is connection oriented and does not require keep-alive 
+    // TLS is connection oriented and does not require keep-alive
     if (sipAccount->isTlsEnabled())
         return;
 
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index f61cec7165..196c56b2c5 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -57,7 +57,7 @@
 #include "pjsip/sip_endpoint.h"
 #include "pjsip/sip_transport_tls.h"
 #include "pjsip/sip_uri.h"
-#include <pjnath.h>
+#include "pjnath.h"
 
 #include <netinet/in.h>
 #include <arpa/nameser.h>
@@ -427,7 +427,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
 
 /*************************************************************************************************/
 
-SIPVoIPLink::SIPVoIPLink() : transportMap_(), evThread_(new EventThread(this))
+SIPVoIPLink::SIPVoIPLink() : transportMap_(), stunSocketMap_(), evThread_(new EventThread(this))
 {
 #define TRY(ret) do { \
     if (ret != PJ_SUCCESS) \
@@ -1273,11 +1273,13 @@ stun_sock_on_rx_data_cb(pj_stun_sock * /*stun_sock*/, void * /*pkt*/,
 }
 
 
-pj_status_t SIPVoIPLink::stunServerResolve(pj_str_t serverName, pj_uint16_t port)
+pj_status_t SIPVoIPLink::createStunResolver(pj_str_t serverName, pj_uint16_t port)
 {
     pj_stun_config stunCfg;
     pj_stun_config_init(&stunCfg, &cp_->factory, 0, pjsip_endpt_get_ioqueue(endpt_), pjsip_endpt_get_timer_heap(endpt_));
 
+    DEBUG("***************** Create Stun Resolver *********************");
+
     static const pj_stun_sock_cb stun_sock_cb = {
         stun_sock_on_rx_data_cb,
         NULL,
@@ -1285,7 +1287,12 @@ pj_status_t SIPVoIPLink::stunServerResolve(pj_str_t serverName, pj_uint16_t port
     };
 
     pj_stun_sock *stun_sock;
-    pj_status_t status = pj_stun_sock_create(&stunCfg, "stunresolve", pj_AF_INET(), &stun_sock_cb, NULL, NULL, &stun_sock);
+    std::string stunResolverName(serverName.ptr, serverName.slen);
+    pj_status_t status = pj_stun_sock_create(&stunCfg, stunResolverName.c_str(), pj_AF_INET(), &stun_sock_cb, NULL, NULL, &stun_sock);
+
+    // store socket inside list
+    DEBUG("     insert %s resolver in map", stunResolverName.c_str());
+    stunSocketMap_.insert(std::pair<std::string, pj_stun_sock *>(stunResolverName.c_str(), stun_sock));
 
     if (status != PJ_SUCCESS) {
         char errmsg[PJ_ERR_MSG_SIZE];
@@ -1306,6 +1313,22 @@ pj_status_t SIPVoIPLink::stunServerResolve(pj_str_t serverName, pj_uint16_t port
     return status;
 }
 
+pj_status_t SIPVoIPLink::destroyStunResolver(const std::string serverName)
+{
+    std::map<std::string, pj_stun_sock *>::iterator it;
+    it = stunSocketMap_.find(serverName);
+
+    DEBUG("***************** Destroy Stun Resolver *********************");
+
+    if(it != stunSocketMap_.end()) {
+        DEBUG("UserAgent: Deleting stun resolver %s", it->first.c_str());
+        pj_stun_sock_destroy(it->second);
+        stunSocketMap_.erase(it);
+    }
+
+    return PJ_SUCCESS;
+}
+
 void SIPVoIPLink::createDefaultSipUdpTransport()
 {
     pj_uint16_t port = 0;
@@ -1496,7 +1519,7 @@ pjsip_transport *SIPVoIPLink::createStunTransport(pj_str_t serverName, pj_uint16
     pjsip_transport *transport;
 
     DEBUG("UserAgent: Create stun transport  server name: %s, port: %d", serverName, port);// account->getStunPort());
-    if (stunServerResolve(serverName, port) != PJ_SUCCESS) {
+    if (createStunResolver(serverName, port) != PJ_SUCCESS) {
         ERROR("UserAgent: Can't resolve STUN server");
         Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure("");
         return NULL;
diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h
index efdb3251f4..b6014cdbd8 100644
--- a/daemon/src/sip/sipvoiplink.h
+++ b/daemon/src/sip/sipvoiplink.h
@@ -43,6 +43,7 @@
 #include <pjlib.h>
 #include <pjsip_ua.h>
 #include <pjlib-util.h>
+#include <pjnath.h>
 #include <pjnath/stun_config.h>
 ///////////////////////////////
 
@@ -279,6 +280,16 @@ class SIPVoIPLink : public VoIPLink {
          */
         void findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &address, std::string &port) const;
 
+        /**
+         * Create a new stun resolver. Store it inside the array. Resolve public address for this
+         * server name.
+         * @param serverName The name of the stun server
+         * @param port number
+         */
+        pj_status_t createStunResolver(pj_str_t serverName, pj_uint16_t port);
+
+        pj_status_t destroyStunResolver(const std::string serverName);
+
     private:
         /**
          * Start a SIP Call
@@ -293,11 +304,6 @@ class SIPVoIPLink : public VoIPLink {
 
         SIPVoIPLink();
 
-        /**
-         * Resolve public address for this account
-         */
-        pj_status_t stunServerResolve(pj_str_t serverName, pj_uint16_t port);
-
         /**
          * General Sip transport creation method according to the
          * transport type specified in account settings
@@ -348,6 +354,12 @@ class SIPVoIPLink : public VoIPLink {
          */
         std::map<pj_uint16_t, pjsip_transport*> transportMap_;
 
+        /**
+         * Stun resolver array
+         */
+        std::map<std::string, pj_stun_sock *> stunSocketMap_;
+
+
         /**
          * Threading object
          */
-- 
GitLab