diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp
index f76d77384241243e60c456602e0d23f9577ff48f..60853fb52d63299077671ca13ff3faa34925cdff 100644
--- a/daemon/src/sip/siptransport.cpp
+++ b/daemon/src/sip/siptransport.cpp
@@ -2,6 +2,7 @@
  *  Copyright (C) 2004-2013 Savoir-Faire Linux Inc.
  *
  *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
+ *  Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -68,7 +69,7 @@ static const char * const DEFAULT_INTERFACE = "default";
 
 pj_sockaddr SipTransport::getSIPLocalIP(pj_uint16_t family)
 {
-    if (family == pj_AF_UNSPEC()) family = pj_AF_INET();
+    if (family == pj_AF_UNSPEC()) family = pj_AF_INET6();
     pj_sockaddr ip_addr;
     pj_status_t status = pj_gethostip(family, &ip_addr);
     if (status == PJ_SUCCESS) return ip_addr;
@@ -105,14 +106,16 @@ std::vector<std::string> SipTransport::getAllIpInterfaceByName()
     return ifaceList;
 }
 
-pj_sockaddr SipTransport::getInterfaceAddr(const std::string &ifaceName, bool forceIPv6)
+pj_sockaddr SipTransport::getInterfaceAddr(const std::string &ifaceName, pj_uint16_t family)
 {
+    ERROR("getInterfaceAddr: %s %d", ifaceName.c_str(), family);
     if (ifaceName == DEFAULT_INTERFACE)
-        return getSIPLocalIP(forceIPv6 ? pj_AF_INET6() : pj_AF_INET());
-    int fd = socket(AF_INET6, SOCK_DGRAM, 0);
-    if(!forceIPv6) {
-        int no = 0;
-        setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&no, sizeof(no));
+        return getSIPLocalIP(family);
+    auto unix_family = (family == pj_AF_INET()) ? AF_INET : AF_INET6;
+    int fd = socket(unix_family, SOCK_DGRAM, 0);
+    if(unix_family == AF_INET6) {
+        int val = (family == pj_AF_UNSPEC()) ? 0 : 1;
+        setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (void *)&val, sizeof(val));
     }
     pj_sockaddr saddr;
     if(fd < 0) {
@@ -126,7 +129,7 @@ pj_sockaddr SipTransport::getInterfaceAddr(const std::string &ifaceName, bool fo
     ifr.ifr_name[sizeof(ifr.ifr_name) - 1] = '\0';
 
     memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr));
-    ifr.ifr_addr.sa_family = AF_INET6;
+    ifr.ifr_addr.sa_family = unix_family;
 
     ioctl(fd, SIOCGIFADDR, &ifr);
     close(fd);
@@ -142,7 +145,7 @@ pj_sockaddr SipTransport::getInterfaceAddr(const std::string &ifaceName, bool fo
 
 std::string SipTransport::getInterfaceAddrFromName(const std::string &ifaceName, bool forceIPv6)
 {
-    return sip_utils::addrToStr(getInterfaceAddr(ifaceName, forceIPv6));
+    return ip_utils::addrToStr(getInterfaceAddr(ifaceName, forceIPv6 ? pj_AF_INET6() : pj_AF_INET()));
 }
 
 std::vector<std::string> SipTransport::getAllIpInterface()
@@ -163,53 +166,92 @@ std::vector<std::string> SipTransport::getAllIpInterface()
     return ifaceList;
 }
 
-SipTransport::SipTransport(pjsip_endpoint *endpt, pj_caching_pool& cp, pj_pool_t& pool) : transportMap_(), cp_(cp), pool_(pool), endpt_(endpt)
-{}
+void tp_state_callback(pjsip_transport *tp, pjsip_transport_state state, const pjsip_transport_state_info* /* info */)
+{
+    SipTransport& this_ = *SIPVoIPLink::instance().sipTransport;
+    this_.transportStateChanged(tp, state);
+}
+
+SipTransport::SipTransport(pjsip_endpoint *endpt, pj_caching_pool& cp, pj_pool_t& pool, std::function<void(pjsip_transport*)> transportDestroyed) :
+transportMap_(), transportDestroyedCb_(transportDestroyed), cp_(cp), pool_(pool), endpt_(endpt)
+{
+    auto status = pjsip_tpmgr_set_state_cb(pjsip_endpt_get_tpmgr(endpt_), tp_state_callback);
+    if (status != PJ_SUCCESS) {
+        ERROR("Can't set transport callback");
+        sip_utils::sip_strerror(status);
+    }
+}
+
+SipTransport::~SipTransport()
+{
+    pjsip_tpmgr_set_state_cb(pjsip_endpt_get_tpmgr(endpt_), nullptr);
+}
 
 namespace {
-std::string transportMapKey(const std::string &interface, int port)
+std::string transportMapKey(const std::string &interface, int port, pjsip_transport_type_e type)
 {
     std::ostringstream os;
-    os << interface << ":" << port;
+    char af_ver_num = (pjsip_transport_type_get_af(type) == pj_AF_INET6()) ? '6' : '4';
+    os << interface << ':' << port << ':' << pjsip_transport_get_type_name(type) << af_ver_num;
     return os.str();
 }
 }
 
-void SipTransport::createSipTransport(SIPAccount &account, pj_uint16_t family)
+void
+SipTransport::transportStateChanged(pjsip_transport* tp, pjsip_transport_state state)
 {
+    WARN("SipTransport::transportStateChanged: {%s} is now in state %d", tp->info, state);
+    std::map<std::string, pjsip_transport*>::const_iterator transport_key = transportMap_.cend();
+    for (auto i = transportMap_.cbegin(); i != transportMap_.cend(); ++i) {
+        if (i->second == tp) {
+            transport_key = i;
+            break;
+        }
+    }
+    if (transport_key == transportMap_.cend()) {
+        ERROR("Transport not found.");
+        return;
+    }
+
+    if (state == PJSIP_TP_STATE_SHUTDOWN || state == PJSIP_TP_STATE_DESTROY) {
+        if (transportDestroyedCb_)
+            transportDestroyedCb_(transport_key->second);
+        transportMap_.erase(transport_key++);
+    }
+}
+
+void
+SipTransport::createSipTransport(SIPAccount &account)
+{
+    WARN("SipTransport::createSipTransport %s", account.getAccountID().c_str());
     if (account.transport_) {
         pjsip_transport_dec_ref(account.transport_);
-        //DEBUG("Transport %s has count %d", account.transport_->info, pj_atomic_get(account.transport_->ref_cnt));
+        DEBUG("Transport %s has count %d", account.transport_->info, pj_atomic_get(account.transport_->ref_cnt));
         account.transport_ = nullptr;
     }
+    auto type = account.getTransportType();
+    auto family = pjsip_transport_type_get_af(type);
     auto interface = account.getLocalInterface();
-    if (family == pj_AF_UNSPEC()) family = account.getPublishedIpAddress().addr.sa_family;
+    std::string key;
 
 #if HAVE_TLS
     if (account.isTlsEnabled()) {
-        std::string key(transportMapKey(interface, account.getTlsListenerPort()));
-        auto iter = transportMap_.find(key);
-
-        // if this transport already exists, reuse it
-        if (iter != transportMap_.end()) {
-            account.transport_ = iter->second;
-            auto status = pjsip_transport_add_ref(account.transport_);
-            if (status != PJ_SUCCESS)
-                account.transport_ = nullptr;
+        cleanupTransports();
+        key = transportMapKey(interface, account.getTlsListenerPort(), type);
+        if (transportMap_.find(key) != transportMap_.end()) {
+            throw std::runtime_error("TLS transport already exists");
         }
         if (!account.transport_) {
             account.transport_ = createTlsTransport(account);
-            transportMap_[key] = account.transport_;
         }
     } else {
 #else
     {
 #endif
         auto port = account.getLocalPort();
-        std::string key = transportMapKey(interface, port);
-        auto iter = transportMap_.find(key);
-
+        key = transportMapKey(interface, port, type);
         // if this transport already exists, reuse it
+        auto iter = transportMap_.find(key);
         if (iter != transportMap_.end()) {
             account.transport_ = iter->second;
             auto status = pjsip_transport_add_ref(account.transport_);
@@ -217,11 +259,13 @@ void SipTransport::createSipTransport(SIPAccount &account, pj_uint16_t family)
                 account.transport_ = nullptr;
         }
         if (!account.transport_) {
-            account.transport_ = createUdpTransport(interface, port);
-            transportMap_[key] = account.transport_;
+            account.transport_ = createUdpTransport(interface, port, family);
         }
     }
 
+    if (account.transport_)
+        transportMap_[key] = account.transport_;
+
     cleanupTransports();
 
     if (!account.transport_) {
@@ -232,6 +276,8 @@ void SipTransport::createSipTransport(SIPAccount &account, pj_uint16_t family)
 #endif
             throw std::runtime_error("Could not create new UDP transport");
     }
+
+    ERROR("Transport %s has count %d", account.transport_->info, pj_atomic_get(account.transport_->ref_cnt));
 }
 
 pjsip_transport *
@@ -241,7 +287,7 @@ SipTransport::createUdpTransport(const std::string &interface, pj_uint16_t port,
     if (interface == DEFAULT_INTERFACE)
         listeningAddress = ip_utils::getAnyHostAddr(family);
     else
-        listeningAddress = getInterfaceAddr(interface, family == pj_AF_INET6());
+        listeningAddress = getInterfaceAddr(interface, family);
 
     RETURN_IF_FAIL(not listeningAddress.addr.sa_family == pj_AF_UNSPEC(), nullptr, "Could not determine ip address for this transport");
     RETURN_IF_FAIL(port != 0, nullptr, "Could not determine port for this transport");
@@ -347,10 +393,17 @@ SipTransport::createTlsTransport(SIPAccount &account)
 void
 SipTransport::cleanupTransports()
 {
+    ERROR("SipTransport::cleanupTransports");
     for (auto it = transportMap_.cbegin(); it != transportMap_.cend();) {
         pjsip_transport* t = (*it).second;
+        if (!t) {
+            ERROR("Null pointer found in transportMap_ for key %s", (*it).first.c_str());
+            transportMap_.erase(it++);
+            continue;
+        }
         pj_lock_acquire(t->lock);
-        if (pj_atomic_get(t->ref_cnt) == 0 || t->is_shutdown || t->is_destroying) {
+        auto ref_cnt = pj_atomic_get(t->ref_cnt);
+        if (ref_cnt == 0 || t->is_shutdown || t->is_destroying) {
             DEBUG("Removing transport for %s", t->info );
             bool is_shutdown = t->is_shutdown || t->is_destroying;
             transportMap_.erase(it++);
@@ -358,6 +411,7 @@ SipTransport::cleanupTransports()
             if (!is_shutdown)
                 pjsip_transport_destroy(t);
         } else {
+            DEBUG("Transport {%s} has refcount %d", t->info, ref_cnt);
             ++it;
             pj_lock_release(t->lock);
         }
diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h
index 31ee3eba2f4fccf6213050fd51dac795c4e17123..595ee0ff477114e22ead450a2bc5104a3f3ba397 100644
--- a/daemon/src/sip/siptransport.h
+++ b/daemon/src/sip/siptransport.h
@@ -50,6 +50,8 @@
 #include <string>
 #include <vector>
 #include <memory>
+#include <functional>
+
 
 class SIPAccount;
 
@@ -60,7 +62,8 @@ class SIPAccount;
 
 class SipTransport {
     public:
-        SipTransport(pjsip_endpoint *endpt, pj_caching_pool& cp, pj_pool_t& pool);
+        SipTransport(pjsip_endpoint *endpt, pj_caching_pool& cp, pj_pool_t& pool, std::function<void(pjsip_transport*)> transportDestroyed = std::function<void(pjsip_transport*)>());
+        ~SipTransport();
 
         static pj_sockaddr getSIPLocalIP(pj_uint16_t family = pj_AF_UNSPEC());
 
@@ -69,7 +72,7 @@ class SipTransport {
          * @param forceIPv6 If IPv4 and IPv6 are available, will force to IPv6.
          */
         static std::string getInterfaceAddrFromName(const std::string &ifaceName, bool forceIPv6 = false);
-        static pj_sockaddr getInterfaceAddr(const std::string &ifaceName, bool forceIPv6 = false);
+        static pj_sockaddr getInterfaceAddr(const std::string &ifaceName, pj_uint16_t family = pj_AF_UNSPEC());
 
         /**
         * List all the interfaces on the system and return
@@ -96,7 +99,7 @@ class SipTransport {
          * transport type specified in account settings
          * @param account The account for which a transport must be created.
          */
-        void createSipTransport(SIPAccount &account, pj_uint16_t family = pj_AF_UNSPEC());
+        void createSipTransport(SIPAccount &account);
 
         /**
          * Initialize the transport selector
@@ -128,6 +131,13 @@ class SipTransport {
         void findLocalAddressFromSTUN(pjsip_transport *transport, pj_str_t *stunServerName,
                 int stunPort, std::string &address, pj_uint16_t &port) const;
 
+        /**
+         * Go through the transport list and remove unused ones.
+         */
+        void cleanupTransports();
+
+        void transportStateChanged(pjsip_transport* tp, pjsip_transport_state state);
+
     private:
         NON_COPYABLE(SipTransport);
 
@@ -162,17 +172,14 @@ class SipTransport {
         pjsip_transport *createUdpTransport(const std::string &interface,
                                             pj_uint16_t port, pj_uint16_t family = pj_AF_UNSPEC());
 
-        /**
-         * Go through the transport list and remove unused ones.
-         */
-        void cleanupTransports();
-
         /**
          * UDP Transports are stored in this map in order to retreive them in case
          * several accounts would share the same port number.
          */
         std::map<std::string, pjsip_transport*> transportMap_;
 
+        std::function<void(pjsip_transport*)> transportDestroyedCb_;
+
         pj_caching_pool& cp_;
         pj_pool_t& pool_;
 
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index 34b3521090bc4af985a7b87a9e9a872730370fa7..7dc3dfd5601fbd45d025856548f3b2f70dad86ef 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -550,7 +550,14 @@ SIPVoIPLink::SIPVoIPLink() : sipTransport(), sipAccountMap_(),
 
     TRY(pjsip_endpt_create(&cp_->factory, pj_gethostname()->ptr, &endpt_));
 
-    sipTransport.reset(new SipTransport(endpt_, *cp_, *pool_));
+    sipTransport.reset(new SipTransport(endpt_, *cp_, *pool_, [&](pjsip_transport* transport) {
+        for (auto& a : sipAccountMap_ ) {
+            SIPAccount* account = static_cast<SIPAccount*>(a.second);
+            if (account->transport_ == transport ) {
+                account->transport_ = nullptr;
+            }
+        }
+    }));
 
     if (SipTransport::getSIPLocalIP().addr.sa_family == pj_AF_UNSPEC())
         throw VoipLinkException("UserAgent: Unable to determine network capabilities");
@@ -817,6 +824,9 @@ SIPVoIPLink::sendRegister(Account& a)
     }
 
     account.setRegistrationInfo(regc);
+    ERROR("Transport %s has count %d", account.transport_->info, pj_atomic_get(account.transport_->ref_cnt));
+
+    sipTransport->cleanupTransports();
 }
 
 void SIPVoIPLink::sendUnregister(Account& a)
@@ -922,7 +932,7 @@ Call *SIPVoIPLink::SIPNewIpToIpCall(const std::string& id, const std::string& to
     call->setIPToIP(true);
     call->initRecFilename(to);
 
-    auto localAddress = SipTransport::getInterfaceAddr(account->getLocalInterface(), ipv6);
+    auto localAddress = SipTransport::getInterfaceAddr(account->getLocalInterface(), ipv6 ? pj_AF_INET6() : pj_AF_INET());
 
     setCallMediaLocal(call, localAddress);