From 6f3bffff9fcb6e0d40830a73e3e4ef6ab14a40b9 Mon Sep 17 00:00:00 2001
From: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
Date: Tue, 27 Mar 2012 09:06:36 -0400
Subject: [PATCH] #9547: Extract all the transport layer from SIPVoIPLink to
 new SipTransport Class

---
 daemon/src/dbus/configurationmanager.cpp |   7 +-
 daemon/src/managerimpl.cpp               |   4 +-
 daemon/src/sip/Makefile.am               |   2 +
 daemon/src/sip/sipaccount.cpp            |   4 +-
 daemon/src/sip/sipvoiplink.cpp           | 529 ++---------------------
 daemon/src/sip/sipvoiplink.h             | 124 +-----
 6 files changed, 38 insertions(+), 632 deletions(-)

diff --git a/daemon/src/dbus/configurationmanager.cpp b/daemon/src/dbus/configurationmanager.cpp
index f1043603cb..fe6b4c3a6a 100644
--- a/daemon/src/dbus/configurationmanager.cpp
+++ b/daemon/src/dbus/configurationmanager.cpp
@@ -37,6 +37,7 @@
 #include "config.h"
 #include "../manager.h"
 #include "sip/sipvoiplink.h"
+#include "sip/siptransport.h"
 #include "account.h"
 #include "sip/sipaccount.h"
 
@@ -411,17 +412,17 @@ std::vector<std::map<std::string, std::string> > ConfigurationManager::getHistor
 std::string
 ConfigurationManager::getAddrFromInterfaceName(const std::string& interface)
 {
-    return SIPVoIPLink::getInterfaceAddrFromName(interface);
+    return SipTransport::getInterfaceAddrFromName(interface);
 }
 
 std::vector<std::string> ConfigurationManager::getAllIpInterface()
 {
-    return SIPVoIPLink::getAllIpInterface();
+    return SipTransport::getAllIpInterface();
 }
 
 std::vector<std::string> ConfigurationManager::getAllIpInterfaceByName()
 {
-    return SIPVoIPLink::getAllIpInterfaceByName();
+    return SipTransport::getAllIpInterfaceByName();
 }
 
 std::map<std::string, std::string> ConfigurationManager::getShortcuts()
diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp
index 3cb0d6cac8..a22b5c6989 100644
--- a/daemon/src/managerimpl.cpp
+++ b/daemon/src/managerimpl.cpp
@@ -2563,7 +2563,7 @@ void ManagerImpl::loadDefaultAccountMap()
 {
     // build a default IP2IP account with default parameters
     accountMap_[SIPAccount::IP2IP_PROFILE] = new SIPAccount(SIPAccount::IP2IP_PROFILE);
-    SIPVoIPLink::instance()->createDefaultSipUdpTransport();
+    SIPVoIPLink::instance()->sipTransport.createDefaultSipUdpTransport();
     accountMap_[SIPAccount::IP2IP_PROFILE]->registerVoIPLink();
 }
 
@@ -2627,7 +2627,7 @@ void ManagerImpl::loadAccountMap(Conf::YamlParser &parser)
 
     // Initialize default UDP transport according to
     // IP to IP settings (most likely using port 5060)
-    SIPVoIPLink::instance()->createDefaultSipUdpTransport();
+    SIPVoIPLink::instance()->sipTransport.createDefaultSipUdpTransport();
 
     // Force IP2IP settings to be loaded to be loaded
     // No registration in the sense of the REGISTER method is performed.
diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am
index bc3fdf7ba2..6ad33a74a4 100644
--- a/daemon/src/sip/Makefile.am
+++ b/daemon/src/sip/Makefile.am
@@ -9,12 +9,14 @@ libsiplink_la_SOURCES = \
 		sipaccount.cpp \
 		sipcall.cpp \
 		sipvoiplink.cpp \
+		siptransport.cpp \
 		pattern.h \
 		sdes_negotiator.h \
 		sdp.h \
 		sipaccount.h \
 		sipcall.h \
 		sipvoiplink.h \
+		siptransport.h \
 		sip_utils.cpp \
 		sip_utils.h
 
diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index 5750f57e4e..a59aaf39e0 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -407,7 +407,7 @@ void SIPAccount::setAccountDetails(std::map<std::string, std::string> details)
     publishedPort_ = atoi(details[CONFIG_PUBLISHED_PORT].c_str());
     if(stunServer_ != details[CONFIG_STUN_SERVER]) {
         DEBUG("Stun server changed!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
-        link_->destroyStunResolver(stunServer_);
+        link_->sipTransport.destroyStunResolver(stunServer_);
         // pj_stun_sock_destroy(pj_stun_sock *stun_sock);
     }
     stunServer_ = details[CONFIG_STUN_SERVER];
@@ -816,7 +816,7 @@ std::string SIPAccount::getContactHeader() const
 
     // Else we determine this infor based on transport information
     std::string address, port;
-    link_->findLocalAddressFromTransport(transport_, transportType, address, port);
+    link_->sipTransport.findLocalAddressFromTransport(transport_, transportType, address, port);
 
     // UDP does not require the transport specification
     std::string scheme;
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index 2780bbb9a4..23c69e833f 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -76,8 +76,6 @@ using namespace sfl;
 
 namespace {
 
-static pjsip_transport *localUDPTransport_ = NULL; /** The default transport (5060) */
-
 /** A map to retreive SFLphone internal call id
  *  Given a SIP call ID (usefull for transaction sucha as transfer)*/
 static std::map<std::string, std::string> transferCallID;
@@ -121,18 +119,6 @@ int SIPSessionReinvite(SIPCall *);
  */
 void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata);
 
-std::string getSIPLocalIP()
-{
-    pj_sockaddr ip_addr;
-
-    if (pj_gethostip(pj_AF_INET(), &ip_addr) == PJ_SUCCESS)
-        return pj_inet_ntoa(ip_addr.ipv4.sin_addr);
-    else  {
-        ERROR("SIPVoIPLink: Could not get local IP");
-        return "";
-    }
-}
-
 pjsip_route_hdr *createRouteSet(const std::string &route, pj_pool_t *hdr_pool)
 {
     int port = 0;
@@ -309,15 +295,15 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
     Manager::instance().associateCallToAccount(call->getCallId(), account_id);
 
     // May use the published address as well
-    std::string addrToUse = SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface());
+    std::string addrToUse = SipTransport::getInterfaceAddrFromName(account->getLocalInterface());
     std::string addrSdp = account->isStunEnabled()
                           ? account->getPublishedAddress()
                           : addrToUse;
 
-    pjsip_tpselector *tp = SIPVoIPLink::instance()->initTransportSelector(account->transport_, call->getMemoryPool());
+    pjsip_tpselector *tp = SIPVoIPLink::instance()->sipTransport.initTransportSelector(account->transport_, call->getMemoryPool());
 
     if (addrToUse == "0.0.0.0")
-        addrToUse = getSIPLocalIP();
+        addrToUse = SipTransport::getSIPLocalIP();
 
     if (addrSdp == "0.0.0.0")
         addrSdp = addrToUse;
@@ -427,7 +413,7 @@ pj_bool_t transaction_request_cb(pjsip_rx_data *rdata)
 
 /*************************************************************************************************/
 
-SIPVoIPLink::SIPVoIPLink() : transportMap_(), stunSocketMap_(), evThread_(new EventThread(this))
+SIPVoIPLink::SIPVoIPLink() : sipTransport(endpt_, cp_, pool_), evThread_(new EventThread(this))
 {
 #define TRY(ret) do { \
     if (ret != PJ_SUCCESS) \
@@ -450,7 +436,11 @@ SIPVoIPLink::SIPVoIPLink() : transportMap_(), stunSocketMap_(), evThread_(new Ev
 
     TRY(pjsip_endpt_create(&cp_->factory, pj_gethostname()->ptr, &endpt_));
 
-    if (getSIPLocalIP().empty())
+    sipTransport.setEndpoint(endpt_);
+    sipTransport.setCachingPool(cp_);
+    sipTransport.setPool(pool_);
+
+    if (SipTransport::getSIPLocalIP().empty())
         throw VoipLinkException("UserAgent: Unable to determine network capabilities");
 
     TRY(pjsip_tsx_layer_init_module(endpt_));
@@ -540,7 +530,7 @@ SIPVoIPLink::getEvent()
 void SIPVoIPLink::sendRegister(Account *a)
 {
     SIPAccount *account = dynamic_cast<SIPAccount*>(a);
-    createSipTransport(account);
+    sipTransport.createSipTransport(account);
 
     account->setRegister(true);
     account->setRegistrationState(Trying);
@@ -588,7 +578,7 @@ void SIPVoIPLink::sendRegister(Account *a)
     if (pjsip_regc_register(regc, PJ_TRUE, &tdata) != PJ_SUCCESS)
         throw VoipLinkException("Unable to initialize transaction data for account registration");
 
-    if (pjsip_regc_set_transport(regc, initTransportSelector(account->transport_, pool_)) != PJ_SUCCESS)
+    if (pjsip_regc_set_transport(regc, sipTransport.initTransportSelector(account->transport_, pool_)) != PJ_SUCCESS)
         throw VoipLinkException("Unable to set transport");
 
     // decrease transport's ref count, counter incrementation is managed when acquiring transport
@@ -683,20 +673,20 @@ Call *SIPVoIPLink::newOutgoingCall(const std::string& id, const std::string& toU
         toUri = account->getToUri(toUrl);
 
     call->setPeerNumber(toUri);
-    std::string localAddr(getInterfaceAddrFromName(account->getLocalInterface()));
+    std::string localAddr(SipTransport::getInterfaceAddrFromName(account->getLocalInterface()));
 
     if (localAddr == "0.0.0.0")
-        localAddr = getSIPLocalIP();
+        localAddr = SipTransport::getSIPLocalIP();
 
     setCallMediaLocal(call, localAddr);
 
     // May use the published address as well
     std::string addrSdp = account->isStunEnabled() ?
     account->getPublishedAddress() :
-    getInterfaceAddrFromName(account->getLocalInterface());
+    SipTransport::getInterfaceAddrFromName(account->getLocalInterface());
 
     if (addrSdp == "0.0.0.0")
-        addrSdp = getSIPLocalIP();
+        addrSdp = SipTransport::getSIPLocalIP();
 
     // Initialize the session using ULAW as default codec in case of early media
     // The session should be ready to receive media once the first INVITE is sent, before
@@ -1094,7 +1084,7 @@ SIPVoIPLink::SIPStartCall(SIPCall *call)
     if (pjsip_inv_invite(call->inv, &tdata) != PJ_SUCCESS)
         return false;
 
-    pjsip_tpselector *tp = initTransportSelector(account->transport_, call->inv->pool);
+    pjsip_tpselector *tp = sipTransport.initTransportSelector(account->transport_, call->inv->pool);
 
     if (pjsip_dlg_set_transport(dialog, tp) != PJ_SUCCESS)
         return false;
@@ -1164,10 +1154,10 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to)
     call->setIPToIP(true);
     call->initRecFilename(to);
 
-    std::string localAddress(getInterfaceAddrFromName(account->getLocalInterface()));
+    std::string localAddress(SipTransport::getInterfaceAddrFromName(account->getLocalInterface()));
 
     if (localAddress == "0.0.0.0")
-        localAddress = getSIPLocalIP();
+        localAddress = SipTransport::getSIPLocalIP();
 
     setCallMediaLocal(call, localAddress);
 
@@ -1205,8 +1195,8 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to)
             return false;
         }
 
-        shutdownSipTransport(account);
-        pjsip_transport *transport = createTlsTransport(remoteAddr, account->getTlsListenerPort(),
+        sipTransport.shutdownSipTransport(account);
+        pjsip_transport *transport = sipTransport.createTlsTransport(remoteAddr, account->getTlsListenerPort(),
                                                               account->getTlsSetting());
 
         if (transport == NULL) {
@@ -1231,410 +1221,6 @@ bool SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to)
 // Private functions
 ///////////////////////////////////////////////////////////////////////////////
 
-pj_bool_t
-stun_sock_on_status_cb(pj_stun_sock * /*stun_sock*/, pj_stun_sock_op op,
-                       pj_status_t status)
-{
-    switch (op) {
-        case PJ_STUN_SOCK_DNS_OP:
-            DEBUG("UserAgent: Stun operation dns resolution");
-            break;
-        case PJ_STUN_SOCK_BINDING_OP:
-            DEBUG("UserAgent: Stun operation binding");
-            break;
-        case PJ_STUN_SOCK_KEEP_ALIVE_OP:
-            DEBUG("UserAgent: Stun operation keep alive");
-            break;
-        case PJ_STUN_SOCK_MAPPED_ADDR_CHANGE:
-            DEBUG("UserAgent: Stun operation address mapping change");
-            break;
-        default:
-            DEBUG("UserAgent: Stun unknown operation");
-            break;
-    }
-
-    if (status == PJ_SUCCESS) {
-        DEBUG("UserAgent: Stun operation success");
-    } else {
-        ERROR("UserAgent: Stun operation failure");
-    }
-
-    // Always return true so the stun transport registration retry even on failure
-    return true;
-}
-
-static pj_bool_t
-stun_sock_on_rx_data_cb(pj_stun_sock * /*stun_sock*/, void * /*pkt*/,
-                        unsigned /*pkt_len*/,
-                        const pj_sockaddr_t * /*src_addr*/,
-                        unsigned /*addr_len*/)
-{
-    return PJ_TRUE;
-}
-
-
-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,
-        stun_sock_on_status_cb
-    };
-
-    pj_stun_sock *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, stun_sock));
-
-    if (status != PJ_SUCCESS) {
-        char errmsg[PJ_ERR_MSG_SIZE];
-        pj_strerror(status, errmsg, sizeof(errmsg));
-        ERROR("UserAgent: Error creating STUN socket for %.*s: %s", (int) serverName.slen, serverName.ptr, errmsg);
-        return status;
-    }
-
-    status = pj_stun_sock_start(stun_sock, &serverName, port, NULL);
-
-    if (status != PJ_SUCCESS) {
-        char errmsg[PJ_ERR_MSG_SIZE];
-        pj_strerror(status, errmsg, sizeof(errmsg));
-        DEBUG("UserAgent: Error starting STUN socket for %.*s: %s", (int) serverName.slen, serverName.ptr, errmsg);
-        pj_stun_sock_destroy(stun_sock);
-    }
-
-    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;
-    int counter = 0;
-
-    SIPAccount *account = Manager::instance().getIP2IPAccount();
-
-    pjsip_transport *transport = NULL;
-    static const int DEFAULT_TRANSPORT_ATTEMPTS = 5;
-    for (; transport == NULL and counter < DEFAULT_TRANSPORT_ATTEMPTS; ++counter) {
-        // if default udp transport fails to init on 5060, try other ports
-        // with 2 step size increment (i.e. 5062, 5064, ...)
-        port = account->getLocalPort() + (counter * 2);
-        transport = createUdpTransport(account->getLocalInterface(), port);
-    }
-
-    if (transport == NULL) {
-        ERROR("UserAgent: Create UDP transport");
-        return;
-    }
-
-    DEBUG("UserAgent: Created default sip transport on %d", port);
-
-    // set transport for this account
-    account->transport_ = transport;
-
-    // set local udp transport
-    localUDPTransport_ = account->transport_;
-}
-
-void SIPVoIPLink::createTlsListener(pj_uint16_t tlsListenerPort, pjsip_tls_setting *tlsSetting, pjsip_tpfactory **listener)
-{
-    pj_sockaddr_in local_addr;
-    pj_sockaddr_in_init(&local_addr, 0, 0);
-    local_addr.sin_port = pj_htons(tlsListenerPort);
-
-    if (tlsSetting == NULL) {
-        ERROR("Error TLS settings not specified");
-        return;
-    }
-
-    if (listener == NULL) {
-        ERROR("Error no pointer to store new TLS listener");
-        return;
-    }
-
-    pj_str_t pjAddress;
-    pj_cstr(&pjAddress, PJ_INADDR_ANY);
-    pj_sockaddr_in_set_str_addr(&local_addr, &pjAddress);
-    std::string localIP(getSIPLocalIP());
-
-    pjsip_host_port a_name = {
-        pj_str((char*) localIP.c_str()),
-        local_addr.sin_port
-    };
-
-    pjsip_tls_transport_start(endpt_, tlsSetting, &local_addr, &a_name, 1, listener);
-}
-
-
-pjsip_transport *
-SIPVoIPLink::createTlsTransport(const std::string &remoteAddr,
-                                pj_uint16_t tlsListenerPort,
-                                pjsip_tls_setting *tlsSettings)
-{
-    pjsip_transport *transport = NULL;
-
-    pj_str_t remote;
-    pj_cstr(&remote, remoteAddr.c_str());
-
-    pj_sockaddr_in rem_addr;
-    pj_sockaddr_in_init(&rem_addr, &remote, (pj_uint16_t) DEFAULT_SIP_TLS_PORT);
-
-    // The local tls listener
-    static pjsip_tpfactory *localTlsListener = NULL;
-
-    if (localTlsListener == NULL)
-        createTlsListener(tlsListenerPort, tlsSettings, &localTlsListener);
-
-    pjsip_endpt_acquire_transport(endpt_, PJSIP_TRANSPORT_TLS, &rem_addr,
-                                  sizeof rem_addr, NULL, &transport);
-
-    if (transport == NULL)
-        ERROR("Error: Could not create new TLS transport\n");
-
-    return transport;
-}
-
-void SIPVoIPLink::createSipTransport(SIPAccount *account)
-{
-    if (account == NULL) {
-        ERROR("UserAgent: Account is NULL while creating sip transport");
-        return;
-    }
-
-    shutdownSipTransport(account);
-
-    if (account->isTlsEnabled()) {
-        std::string remoteSipUri(account->getServerUri());
-        static const char SIPS_PREFIX[] = "<sips:";
-        size_t sips = remoteSipUri.find(SIPS_PREFIX) + (sizeof SIPS_PREFIX) - 1;
-        size_t trns = remoteSipUri.find(";transport");
-        std::string remoteAddr(remoteSipUri.substr(sips, trns-sips));
-
-        pjsip_transport *transport = createTlsTransport(remoteAddr, account->getTlsListenerPort(), account->getTlsSetting());
-        account->transport_ = transport;
-    } else if (account->isStunEnabled()) {
-        pjsip_transport *transport = createStunTransport(account->getStunServerName(), account->getStunPort());
-        account->transport_ = transport;
-    }
-    else {
-        pjsip_transport *transport = createUdpTransport(account->getLocalInterface(), account->getLocalPort());
-        account->transport_ = transport;
-    }
-
-    if (!account->transport_) {
-        // Could not create new transport, this transport may already exists
-        account->transport_ = transportMap_[account->getLocalPort()];
-
-        if (account->transport_)
-            pjsip_transport_add_ref(account->transport_);
-        else {
-            account->transport_ = localUDPTransport_;
-            account->setLocalPort(localUDPTransport_->local_name.port);
-        }
-    }
-}
-
-pjsip_transport *SIPVoIPLink::createUdpTransport(std::string interface, unsigned int port)
-{
-    // init socket to bind this transport to
-    pj_sockaddr_in bound_addr;
-    pj_bzero(&bound_addr, sizeof(bound_addr));
-    pj_uint16_t listeningPort = (pj_uint16_t) port;
-    bound_addr.sin_port = pj_htons(listeningPort);
-    bound_addr.sin_family = PJ_AF_INET;
-
-    // determine the ip address for this transport
-    static const char * const DEFAULT_INTERFACE = "default";
-    std::string listeningAddress;
-    if (interface == DEFAULT_INTERFACE) {
-        listeningAddress = getSIPLocalIP();
-        bound_addr.sin_addr.s_addr = pj_htonl(PJ_INADDR_ANY);
-    } else {
-        listeningAddress = getInterfaceAddrFromName(interface);
-        bound_addr.sin_addr = pj_inet_addr2(listeningAddress.c_str());
-    }
-
-    if (listeningAddress.empty()) {
-        ERROR("SIP: Could not determine ip address for this transport");
-        return NULL;
-    }
-
-    if (listeningPort == 0) {
-        ERROR("SIP: Could not determine port for this transport");
-        return NULL;
-    }
-
-    // The published address for this transport
-    const pjsip_host_port a_name = {
-        pj_str((char*) listeningAddress.c_str()),
-        listeningPort
-    };
-
-    pjsip_transport *transport = NULL;
-    pj_status_t status = pjsip_udp_transport_start(endpt_, &bound_addr, &a_name, 1, &transport);
-    if (status != PJ_SUCCESS) {
-        ERROR("SIP: Could not create UDP transport for port %u", port);
-        return NULL;
-    }
-
-    // dump debug information to stdout
-    pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_));
-    transportMap_[listeningPort] = transport;
-
-    return transport;
-}
-
-pjsip_tpselector *SIPVoIPLink::initTransportSelector(pjsip_transport *transport, pj_pool_t *tp_pool) const
-{
-    assert(transport);
-    pjsip_tpselector *tp = (pjsip_tpselector *) pj_pool_zalloc(tp_pool, sizeof(pjsip_tpselector));
-    tp->type = PJSIP_TPSELECTOR_TRANSPORT;
-    tp->u.transport = transport;
-    return tp;
-}
-
-pjsip_transport *SIPVoIPLink::createStunTransport(pj_str_t serverName, pj_uint16_t port)
-{
-    pjsip_transport *transport;
-
-    DEBUG("UserAgent: Create stun transport  server name: %s, port: %d", serverName, port);// account->getStunPort());
-    if (createStunResolver(serverName, port) != PJ_SUCCESS) {
-        ERROR("UserAgent: Can't resolve STUN server");
-        Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure("");
-        return NULL;
-    }
-
-    pj_sock_t sock = PJ_INVALID_SOCKET;
-
-    pj_sockaddr_in boundAddr;
-
-    if (pj_sockaddr_in_init(&boundAddr, &serverName, 0) != PJ_SUCCESS) {
-        ERROR("UserAgent: Can't initialize IPv4 socket on %*s:%i", serverName.slen, serverName.ptr, port);
-        Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure("");
-        return NULL;
-    }
-
-    if (pj_sock_socket(pj_AF_INET(), pj_SOCK_DGRAM(), 0, &sock) != PJ_SUCCESS) {
-        ERROR("UserAgent: Can't create or bind socket");
-        Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure("");
-        return NULL;
-    }
-
-    // Query the mapped IP address and port on the 'outside' of the NAT
-    pj_sockaddr_in pub_addr;
-
-    if (pjstun_get_mapped_addr(&cp_->factory, 1, &sock, &serverName, port, &serverName, port, &pub_addr) != PJ_SUCCESS) {
-        ERROR("UserAgent: Can't contact STUN server");
-        pj_sock_close(sock);
-        Manager::instance().getDbusManager()->getConfigurationManager()->stunStatusFailure("");
-        return NULL;
-    }
-
-    pjsip_host_port a_name = {
-        pj_str(pj_inet_ntoa(pub_addr.sin_addr)),
-        pj_ntohs(pub_addr.sin_port)
-    };
-
-    pjsip_udp_transport_attach2(endpt_, PJSIP_TRANSPORT_UDP, sock, &a_name, 1,
-                                &transport);
-
-    pjsip_tpmgr_dump_transports(pjsip_endpt_get_tpmgr(endpt_));
-
-    return transport;
-}
-
-void SIPVoIPLink::shutdownSipTransport(SIPAccount *account)
-{
-    if (account->isStunEnabled()) {
-        pj_str_t stunServerName = account->getStunServerName();
-        std::string server(stunServerName.ptr, stunServerName.slen);
-        destroyStunResolver(server);
-    }
-
-    if (account->transport_) {
-        pjsip_transport_dec_ref(account->transport_);
-        account->transport_ = NULL;
-    }
-}
-
-void SIPVoIPLink::findLocalAddressFromTransport(pjsip_transport *transport, pjsip_transport_type_e transportType, std::string &addr, std::string &port) const
-{
-    // Initialize the sip port with the default SIP port
-    std::stringstream ss;
-    ss << DEFAULT_SIP_PORT;
-    port = ss.str();
-
-    // Initialize the sip address with the hostname
-    const pj_str_t *pjMachineName = pj_gethostname();
-    addr = std::string(pjMachineName->ptr, pjMachineName->slen);
-
-    // Update address and port with active transport
-    if (!transport) {
-        ERROR("SIPVoIPLink: Transport is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str());
-        return;
-    }
-
-    // get the transport manager associated with the SIP enpoint
-    pjsip_tpmgr *tpmgr = pjsip_endpt_get_tpmgr(endpt_);
-    if (!tpmgr) {
-        ERROR("SIPVoIPLink: Transport manager is NULL in findLocalAddress, using local address %s:%s", addr.c_str(), port.c_str());
-        return;
-    }
-
-    // initialize a transport selector
-    // TODO Need to determine why we exclude TLS here...
-    // if (transportType == PJSIP_TRANSPORT_UDP and transport_)
-    pjsip_tpselector *tp_sel = initTransportSelector(transport, pool_);
-    if (!tp_sel) {
-        ERROR("SIPVoIPLink: Could not initialize transport selector, using local address %s:%s", addr.c_str(), port.c_str());
-        return;
-    }
-
-    pj_str_t localAddress = {0,0};
-    int i_port = 0;
-
-    // Find the local address and port for this transport
-    if (pjsip_tpmgr_find_local_addr(tpmgr, pool_, transportType, tp_sel, &localAddress, &i_port) != PJ_SUCCESS) {
-        WARN("SIPVoIPLink: Could not retrieve local address and port from transport, using %s:%s", addr.c_str(), port.c_str());
-        return;
-    }
-
-    // Update local address based on the transport type
-    addr = std::string(localAddress.ptr, localAddress.slen);
-
-    // Fallback on local ip provided by pj_gethostip()
-    if (addr == "0.0.0.0")
-        addr = getSIPLocalIP();
-
-    // Determine the local port based on transport information
-    ss.str("");
-    ss << i_port;
-    port = ss.str();
-}
-
 namespace {
 int SIPSessionReinvite(SIPCall *call)
 {
@@ -1725,11 +1311,11 @@ void sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
 
     SIPAccount *account = dynamic_cast<SIPAccount *>(Manager::instance().getAccount(accountid));
 
-    std::string localAddress(SIPVoIPLink::instance()->getInterfaceAddrFromName(account->getLocalInterface()));
+    std::string localAddress(SipTransport::getInterfaceAddrFromName(account->getLocalInterface()));
     std::string addrSdp(localAddress);
 
     if (localAddress == "0.0.0.0")
-        localAddress = getSIPLocalIP();
+        localAddress = SipTransport::getSIPLocalIP();
 
     if (addrSdp == "0.0.0.0")
         addrSdp = localAddress;
@@ -1984,7 +1570,7 @@ void update_contact_header(pjsip_regc_cbparam *param, SIPAccount *account)
     std::string recvContactPort = ss.str();
 
     std::string currentAddress, currentPort;
-    siplink->findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort);
+    siplink->sipTransport.findLocalAddressFromTransport(account->transport_, PJSIP_TRANSPORT_UDP, currentAddress, currentPort);
 
     bool updateContact = false;
     std::string currentContactHeader = account->getContactHeader();
@@ -2037,7 +1623,7 @@ void registration_cb(pjsip_regc_cbparam *param)
         account->setRegistrationState(ErrorAuth);
         account->setRegister(false);
 
-        SIPVoIPLink::instance()->shutdownSipTransport(account);
+        SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account);
         return;
     }
 
@@ -2071,14 +1657,14 @@ void registration_cb(pjsip_regc_cbparam *param)
 
         account->setRegister(false);
 
-        SIPVoIPLink::instance()->shutdownSipTransport(account);
+        SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account);
 
     } else {
         if (account->isRegistered())
             account->setRegistrationState(Registered);
         else {
             account->setRegistrationState(Unregistered);
-            SIPVoIPLink::instance()->shutdownSipTransport(account);
+            SIPVoIPLink::instance()->sipTransport.shutdownSipTransport(account);
         }
     }
 }
@@ -2183,66 +1769,3 @@ void setCallMediaLocal(SIPCall* call, const std::string &localIP)
     call->getLocalSDP()->setLocalPublishedAudioPort(callLocalExternAudioPort);
 }
 } // end anonymous namespace
-
-std::vector<std::string> SIPVoIPLink::getAllIpInterfaceByName()
-{
-    static ifreq ifreqs[20];
-    ifconf ifconf;
-
-    std::vector<std::string> ifaceList;
-    ifaceList.push_back("default");
-
-    ifconf.ifc_buf = (char*) (ifreqs);
-    ifconf.ifc_len = sizeof(ifreqs);
-
-    int sock = socket(AF_INET,SOCK_STREAM,0);
-
-    if (sock >= 0) {
-        if (ioctl(sock, SIOCGIFCONF, &ifconf) >= 0)
-            for (unsigned i = 0; i < ifconf.ifc_len / sizeof(ifreq); ++i)
-                ifaceList.push_back(std::string(ifreqs[i].ifr_name));
-
-        close(sock);
-    }
-
-    return ifaceList;
-}
-
-std::string SIPVoIPLink::getInterfaceAddrFromName(const std::string &ifaceName)
-{
-    int fd = socket(AF_INET, SOCK_DGRAM,0);
-
-    if (fd < 0) {
-        ERROR("UserAgent: Error: could not open socket: %m");
-        return "";
-    }
-
-    ifreq ifr;
-    strcpy(ifr.ifr_name, ifaceName.c_str());
-    memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
-    ifr.ifr_addr.sa_family = AF_INET;
-
-    ioctl(fd, SIOCGIFADDR, &ifr);
-    close(fd);
-
-    sockaddr_in *saddr_in = (sockaddr_in *) &ifr.ifr_addr;
-    return inet_ntoa(saddr_in->sin_addr);
-}
-
-std::vector<std::string> SIPVoIPLink::getAllIpInterface()
-{
-    pj_sockaddr addrList[16];
-    unsigned addrCnt = PJ_ARRAY_SIZE(addrList);
-
-    std::vector<std::string> ifaceList;
-
-    if (pj_enum_ip_interface(pj_AF_INET(), &addrCnt, addrList) == PJ_SUCCESS) {
-        for (unsigned i = 0; i < addrCnt; i++) {
-            char addr[PJ_INET_ADDRSTRLEN];
-            pj_sockaddr_print(&addrList[i], addr, sizeof(addr), 0);
-            ifaceList.push_back(std::string(addr));
-        }
-    }
-
-    return ifaceList;
-}
diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h
index 863f93d215..c7f65aa731 100644
--- a/daemon/src/sip/sipvoiplink.h
+++ b/daemon/src/sip/sipvoiplink.h
@@ -49,6 +49,7 @@
 
 #include "sipaccount.h"
 #include "voiplink.h"
+#include "siptransport.h"
 
 class EventThread;
 class SIPCall;
@@ -211,49 +212,6 @@ class SIPVoIPLink : public VoIPLink {
          */
         std::string getUseragentName(SIPAccount *) const;
 
-        /**
-         * List all the interfaces on the system and return
-         * a vector list containing their IPV4 address.
-         * @param void
-         * @return std::vector<std::string> A std::string vector
-         * of IPV4 address available on all of the interfaces on
-         * the system.
-         */
-        static std::vector<std::string> getAllIpInterface();
-
-        /**
-        * List all the interfaces on the system and return
-        * a vector list containing their name (eth0, eth0:1 ...).
-        * @param void
-        * @return std::vector<std::string> A std::string vector
-        * of interface name available on all of the interfaces on
-        * the system.
-        */
-        static std::vector<std::string> getAllIpInterfaceByName();
-
-        /**
-         * List all the interfaces on the system and return
-         * a vector list containing their name (eth0, eth0:1 ...).
-         * @param void
-         * @return std::vector<std::string> A std::string vector
-         * of interface name available on all of the interfaces on
-         * the system.
-         */
-        static std::string getInterfaceAddrFromName(const std::string &ifaceName);
-
-        /**
-         * Initialize the transport selector
-         * @param transport		A transport associated with an account
-         *
-         * @return          	A pointer to the transport selector structure
-         */
-        pjsip_tpselector *initTransportSelector(pjsip_transport *, pj_pool_t *) const;
-
-        /**
-         * This function unset the transport for a given account.
-         */
-        void shutdownSipTransport(SIPAccount *account);
-
         /**
          * Send a SIP message to a call identified by its callid
          *
@@ -270,26 +228,7 @@ class SIPVoIPLink : public VoIPLink {
          */
         void createDefaultSipUdpTransport();
 
-        /**
-         * Get the correct address to use (ie advertised) from
-         * a uri. The corresponding transport that should be used
-         * with that uri will be discovered.
-         *
-         * @param uri The uri from which we want to discover the address to use
-         * @param transport The transport to use to discover the address
-         */
-        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);
-
+        SipTransport sipTransport;
     private:
         /**
          * Start a SIP Call
@@ -304,65 +243,6 @@ class SIPVoIPLink : public VoIPLink {
 
         SIPVoIPLink();
 
-        /**
-         * General Sip transport creation method according to the
-         * transport type specified in account settings
-         * @param account The account for which a transport must be created.
-         */
-        void createSipTransport(SIPAccount *account);
-
-        /**
-        * Create SIP UDP transport from account's setting
-        * @param account The account for which a transport must be created.
-        */
-        pjsip_transport *createUdpTransport(std::string interface, unsigned int port);
-
-        /**
-         * Create The default TLS listener which is global to the application. This means that
-         * only one TLS connection can be established for the momment.
-         * @param the port number to create the TCP socket
-         * @param pjsip's tls settings for the transport to be created which contains:
-         *      - path to ca certificate list file
-         *      - path to certertificate file
-         *      - path to private key file
-         *      - the password for the file
-         *      - the TLS method
-         * @param a pointer to store the listener created, in our case this is a static pointer
-         */
-        void createTlsListener(pj_uint16_t, pjsip_tls_setting *, pjsip_tpfactory **);
-
-        /**
-         * Create a connection oriented TLS transport and register to the specified remote address.
-         * First, initialize the TLS listener sole instance. This means that, for the momment, only one TLS transport
-         * is allowed to be created in the application. Any subsequent account attempting to
-         * register a new using this transport even if new settings are specified.
-         * @param the remote address for this transport to be connected
-         * @param the local port to initialize the TCP socket
-         * @param pjsip's tls transport parameters
-         */
-        pjsip_transport *
-        createTlsTransport(const std::string &remoteAddr,
-                           pj_uint16_t tlsListenerPort,
-                           pjsip_tls_setting *tlsSetting);
-
-        /**
-         * Create a UDP transport using stun server to resove public address
-         * @param account The account for which a transport must be created.
-         */
-        pjsip_transport *createStunTransport(pj_str_t serverName, pj_uint16_t port);
-
-        /**
-         * UDP Transports are stored in this map in order to retreive them in case
-         * several accounts would share the same port number.
-         */
-        std::map<pj_uint16_t, pjsip_transport*> transportMap_;
-
-        /**
-         * Stun resolver array
-         */
-        std::map<std::string, pj_stun_sock *> stunSocketMap_;
-
-
         /**
          * Threading object
          */
-- 
GitLab