diff --git a/daemon/src/ringdht/ringaccount.cpp b/daemon/src/ringdht/ringaccount.cpp
index df72637b99f335f0ad3cb94c5a094cd628155138..192a83da1afb4965496f1e048cf570c7121e788b 100644
--- a/daemon/src/ringdht/ringaccount.cpp
+++ b/daemon/src/ringdht/ringaccount.cpp
@@ -104,7 +104,6 @@ RingAccount::RingAccount(const std::string& accountID, bool /* presenceEnabled *
 RingAccount::~RingAccount()
 {
     Manager::instance().unregisterEventHandler((uintptr_t)this);
-    setTransport();
     dht_.join();
     gnutls_global_deinit();
 }
@@ -1098,18 +1097,17 @@ std::string RingAccount::getToUri(const std::string& to) const
 pj_str_t
 RingAccount::getContactHeader(pjsip_transport* t)
 {
-    if (!t && transport_)
-        t = transport_->get();
     if (!t) {
-        RING_ERR("Transport not created yet");
-        pj_cstr(&contact_, "<sips:>");
+        RING_ERR("getContactHeader: no SIP transport provided");
+        contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE,
+                                     "<sips:%s@ring.dht>",
+                                     username_.c_str());
         return contact_;
     }
 
     // FIXME: be sure that given transport is from SipIceTransport
     auto tlsTr = reinterpret_cast<tls::SipsIceTransport::TransportData*>(t)->self;
     auto address = tlsTr->getLocalAddress();
-    RING_WARN("getContactHeader %s@%s", username_.c_str(), address.toString(true).c_str());
     contact_.slen = pj_ansi_snprintf(contact_.ptr, PJSIP_MAX_URL_SIZE,
                                      "<sips:%s%s%s;transport=%s>",
                                      username_.c_str(),
diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index 773746a78441fdef7eb665cb0f9e146116ec02ba..38f7597a4a291b32c1f46d58a230a99f4a63a37a 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -273,6 +273,64 @@ SIPAccount::newOutgoingCall(const std::string& toUrl)
     return call;
 }
 
+void
+SIPAccount::onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info)
+{
+    pj_status_t currentStatus = transportStatus_;
+    RING_DBG("Transport state changed to %s for account %s !", SipTransport::stateToStr(state), accountID_.c_str());
+    if (!SipTransport::isAlive(transport_, state)) {
+        if (info) {
+            char err_msg[128];
+            err_msg[0] = '\0';
+            pj_str_t descr = pj_strerror(info->status, err_msg, sizeof(err_msg));
+            transportStatus_ = info->status;
+            transportError_  = std::string(descr.ptr, descr.slen);
+            RING_ERR("Transport disconnected: %.*s", descr.slen, descr.ptr);
+        }
+        else {
+            // This is already the generic error used by pjsip.
+            transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE;
+            transportError_  = "";
+        }
+        setRegistrationState(RegistrationState::ERROR_GENERIC);
+        setTransport();
+    }
+    else {
+        // The status can be '0', this is the same as OK
+        transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK;
+        transportError_  = "";
+    }
+
+    // Notify the client of the new transport state
+    if (currentStatus != transportStatus_)
+        emitSignal<DRing::ConfigurationSignal::VolatileDetailsChanged>(accountID_, getVolatileAccountDetails());
+}
+
+void
+SIPAccount::setTransport(const std::shared_ptr<SipTransport>& t)
+{
+    if (t == transport_)
+        return;
+    if (transport_) {
+        RING_DBG("Removing transport from account");
+        if (regc_)
+            pjsip_regc_release_transport(regc_);
+        transport_->removeStateListener(reinterpret_cast<uintptr_t>(this));
+    }
+
+    transport_ = t;
+
+    if (transport_)
+        transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccount::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2));
+}
+
+pjsip_tpselector
+SIPAccount::getTransportSelector() {
+    if (!transport_)
+        return SIPVoIPLink::getTransportSelector(nullptr);
+    return SIPVoIPLink::getTransportSelector(transport_->get());
+}
+
 std::shared_ptr<Call>
 SIPAccount::newOutgoingCall(const std::string& toUrl)
 {
@@ -1589,16 +1647,6 @@ computeMd5HashFromCredential(const std::string& username,
     return std::string(hash, 32);
 }
 
-void
-SIPAccount::setTransport(const std::shared_ptr<SipTransport>& t)
-{
-    if (transport_ == t)
-        return;
-    if (transport_ && regc_)
-        pjsip_regc_release_transport(regc_);
-    SIPAccountBase::setTransport(t);
-}
-
 void SIPAccount::setCredentials(const std::vector<std::map<std::string, std::string> >& creds)
 {
     // we can not authenticate without credentials
diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h
index 30ca4ec03f3b51061b3afbaa41262ffa26bc6dfb..06dcecb5a5ed26d3044190160f17a68887bbc02a 100644
--- a/daemon/src/sip/sipaccount.h
+++ b/daemon/src/sip/sipaccount.h
@@ -437,7 +437,20 @@ class SIPAccount : public SIPAccountBase {
             return keepAliveEnabled_;
         }
 
-        virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
+        void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
+
+        virtual inline std::shared_ptr<SipTransport> getTransport() {
+            return transport_;
+        }
+
+        inline pjsip_transport_type_e getTransportType() const {
+            return transportType_;
+        }
+
+        /**
+         * Shortcut for SipTransport::getTransportSelector(account.getTransport()).
+         */
+        pjsip_tpselector getTransportSelector();
 
         /* Returns true if the username and/or hostname match this account */
         MatchRank matches(const std::string &username, const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
@@ -519,6 +532,12 @@ class SIPAccount : public SIPAccountBase {
         bool hostnameMatch(const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
         bool proxyMatch(const std::string &hostname, pjsip_endpoint *endpt, pj_pool_t *pool) const;
 
+        /**
+         * Callback called by the transport layer when the registration
+         * transport state changes.
+         */
+        virtual void onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info);
+
         struct {
             pj_bool_t    active;    /**< Flag of reregister status. */
             pj_timer_entry   timer;     /**< Timer for reregistration.  */
diff --git a/daemon/src/sip/sipaccountbase.cpp b/daemon/src/sip/sipaccountbase.cpp
index a83978da762ea33cc983ea5917759407cae7cb1e..ae0d93548dff42f10ec30e349d052b37a59f39d0 100644
--- a/daemon/src/sip/sipaccountbase.cpp
+++ b/daemon/src/sip/sipaccountbase.cpp
@@ -53,9 +53,7 @@ SIPAccountBase::SIPAccountBase(const std::string& accountID)
     : Account(accountID), link_(getSIPVoIPLink())
 {}
 
-SIPAccountBase::~SIPAccountBase() {
-    setTransport();
-}
+SIPAccountBase::~SIPAccountBase() {}
 
 template <typename T>
 static void
@@ -253,55 +251,6 @@ SIPAccountBase::getVolatileAccountDetails() const
     return a;
 }
 
-void
-SIPAccountBase::onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info)
-{
-    pj_status_t currentStatus = transportStatus_;
-    RING_DBG("Transport state changed to %s for account %s !", SipTransport::stateToStr(state), accountID_.c_str());
-    if (!SipTransport::isAlive(transport_, state)) {
-        if (info) {
-            char err_msg[128];
-            err_msg[0] = '\0';
-            pj_str_t descr = pj_strerror(info->status, err_msg, sizeof(err_msg));
-            transportStatus_ = info->status;
-            transportError_  = std::string(descr.ptr, descr.slen);
-            RING_ERR("Transport disconnected: %.*s", descr.slen, descr.ptr);
-        }
-        else {
-            // This is already the generic error used by pjsip.
-            transportStatus_ = PJSIP_SC_SERVICE_UNAVAILABLE;
-            transportError_  = "";
-        }
-        setRegistrationState(RegistrationState::ERROR_GENERIC);
-        setTransport();
-    }
-    else {
-        // The status can be '0', this is the same as OK
-        transportStatus_ = info && info->status ? info->status : PJSIP_SC_OK;
-        transportError_  = "";
-    }
-
-    // Notify the client of the new transport state
-    if (currentStatus != transportStatus_)
-        emitSignal<DRing::ConfigurationSignal::VolatileDetailsChanged>(accountID_, getVolatileAccountDetails());
-}
-
-void
-SIPAccountBase::setTransport(const std::shared_ptr<SipTransport>& t)
-{
-    if (t == transport_)
-        return;
-    if (transport_) {
-        RING_DBG("Removing transport from account");
-        transport_->removeStateListener(reinterpret_cast<uintptr_t>(this));
-    }
-
-    transport_ = t;
-
-    if (transport_)
-        transport_->addStateListener(reinterpret_cast<uintptr_t>(this), std::bind(&SIPAccountBase::onTransportStateChanged, this, std::placeholders::_1, std::placeholders::_2));
-}
-
 auto
 SIPAccountBase::getPortsReservation() noexcept -> decltype(getPortsReservation())
 {
@@ -345,11 +294,4 @@ SIPAccountBase::generateVideoPort() const
 }
 #endif
 
-pjsip_tpselector
-SIPAccountBase::getTransportSelector() {
-    if (!transport_)
-        return SIPVoIPLink::getTransportSelector(nullptr);
-    return SIPVoIPLink::getTransportSelector(transport_->get());
-}
-
 } // namespace ring
diff --git a/daemon/src/sip/sipaccountbase.h b/daemon/src/sip/sipaccountbase.h
index ea0ad0f76f3e8f08ab7c5f04cdceb093d48e4173..4607a6ce03742da2fde87b98c64bae3ceb6d86ee 100644
--- a/daemon/src/sip/sipaccountbase.h
+++ b/daemon/src/sip/sipaccountbase.h
@@ -248,23 +248,10 @@ public:
 
     virtual std::string getToUri(const std::string& username) const = 0;
 
-    virtual std::string getServerUri() const = 0;
-
-    virtual void setTransport(const std::shared_ptr<SipTransport>& = nullptr);
-
-    inline const std::shared_ptr<SipTransport>& getTransport() {
-        return transport_;
-    }
-
-    inline pjsip_transport_type_e getTransportType() const {
-        return transportType_;
+    virtual inline std::shared_ptr<SipTransport> getTransport() {
+        return nullptr;
     }
 
-    /**
-     * Shortcut for SipTransport::getTransportSelector(account.getTransport()).
-     */
-    pjsip_tpselector getTransportSelector();
-
     /**
      * Socket port generators for media
      * Note: given ports are application wide, a port cannot be given again
@@ -292,12 +279,6 @@ protected:
      */
     virtual std::map<std::string, std::string> getVolatileAccountDetails() const;
 
-    /**
-     * Callback called by the transport layer when the registration
-     * transport state changes.
-     */
-    virtual void onTransportStateChanged(pjsip_transport_state state, const pjsip_transport_state_info *info);
-
     /**
      * Voice over IP Link contains a listener thread and calls
      */
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index 01acb7de08b4d5be5dceee87f40aed1e6c72f29b..b80c5d3d94460dcebdb0ba591638e65193384dfc 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -889,10 +889,18 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
     auto call = std::static_pointer_cast<SIPCall>(call_ptr->shared_from_this());
 
     const auto& account = call->getSIPAccount();
-
+    auto family = pj_AF_INET();
     // FIXME : for now, use the same address family as the SIP transport
-    auto family = pjsip_transport_type_get_af(account.getTransportType());
-    IpAddr addrToUse = ip_utils::getInterfaceAddr(account.getLocalInterface(), family);
+    if (auto dlg = inv->dlg) {
+        if (dlg->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
+            if (auto tr = dlg->tp_sel.u.transport)
+                family = tr->local_addr.addr.sa_family;
+        } else if (dlg->tp_sel.type == PJSIP_TPSELECTOR_TRANSPORT) {
+            if (auto tr = dlg->tp_sel.u.listener)
+                family = tr->local_addr.addr.sa_family;
+        }
+    }
+    auto ifaceAddr = ip_utils::getInterfaceAddr(account.getLocalInterface(), family);
 
     IpAddr address;
     if (account.getUPnPActive()) {
@@ -901,11 +909,11 @@ sdp_create_offer_cb(pjsip_inv_session *inv, pjmedia_sdp_session **p_offer)
             account.getUPnPIpAddress() : account.getPublishedIpAddress();
     } else {
         address = account.getPublishedSameasLocal() ?
-            addrToUse : account.getPublishedIpAddress();
+            ifaceAddr : account.getPublishedIpAddress();
     }
 
     /* fallback on local address */
-    if (not address) address = addrToUse;
+    if (not address) address = ifaceAddr;
 
     call->setCallMediaLocal(address);