diff --git a/daemon/src/sip/Makefile.am b/daemon/src/sip/Makefile.am
index 629a9d514a0cfee8cb086de30c1ef0978de5b884..323d944f0f8eee1fb3d62d11af9c7cb49dde0be7 100644
--- a/daemon/src/sip/Makefile.am
+++ b/daemon/src/sip/Makefile.am
@@ -4,11 +4,13 @@ noinst_LTLIBRARIES = libsiplink.la
 libsiplink_la_CXXFLAGS = @CXXFLAGS@
 
 libsiplink_la_SOURCES = \
+        sipaccountbase.cpp \
         sdp.cpp \
         sipaccount.cpp \
         sipcall.cpp \
         sipvoiplink.cpp \
         siptransport.cpp \
+        sipaccountbase.h \
         sdp.h \
         sipaccount.h \
         sipcall.h \
diff --git a/daemon/src/sip/pres_sub_server.cpp b/daemon/src/sip/pres_sub_server.cpp
index 5a07295be121e51fa78a1cd7160d615a52d8565e..fea6a2257362b2f546a35acf491e930871d6e52a 100644
--- a/daemon/src/sip/pres_sub_server.cpp
+++ b/daemon/src/sip/pres_sub_server.cpp
@@ -32,6 +32,7 @@
 
 #include "pjsip/sip_multipart.h"
 
+#include "sipaccount.h"
 #include "sipvoiplink.h"
 #include "manager.h"
 #include "sippresence.h"
diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp
index 67b3b76e25843ab89e941a6af131a8251c85152f..f18032c5e5e19cf7553795aca335a6755c1f0b03 100644
--- a/daemon/src/sip/sipaccount.cpp
+++ b/daemon/src/sip/sipaccount.cpp
@@ -75,9 +75,6 @@ static const char *const VALID_TLS_METHODS[] = {"Default", "TLSv1", "SSLv3", "SS
 static const char *const VALID_SRTP_KEY_EXCHANGES[] = {"", "sdes", "zrtp"};
 constexpr const char * const SIPAccount::ACCOUNT_TYPE;
 
-// we force RTP ports to be even, so we only need HALF_MAX_PORT booleans
-bool SIPAccount::portsInUse_[HALF_MAX_PORT];
-
 static void
 registration_cb(pjsip_regc_cbparam *param)
 {
@@ -96,30 +93,16 @@ registration_cb(pjsip_regc_cbparam *param)
 }
 
 SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
-    : Account(accountID)
+    : SIPAccountBase(accountID)
     , auto_rereg_()
     , credentials_()
-    , transport_(nullptr)
-    , tlsListener_(nullptr)
     , regc_(nullptr)
     , bRegister_(false)
     , registrationExpire_(MIN_REGISTRATION_TIME)
-    , interface_("default")
-    , publishedSameasLocal_(true)
-    , publishedIp_()
-    , publishedIpAddress_()
-    , localPort_(DEFAULT_SIP_PORT)
-    , publishedPort_(DEFAULT_SIP_PORT)
     , serviceRoute_()
-    , tlsListenerPort_(DEFAULT_SIP_TLS_PORT)
-    , transportType_(PJSIP_TRANSPORT_UNSPECIFIED)
     , cred_()
     , tlsSetting_()
     , ciphers_(100)
-    , stunServerName_()
-    , stunPort_(PJ_STUN_PORT)
-    , dtmfType_(OVERRTP_STR)
-    , tlsEnable_(false)
     , tlsCaListFile_()
     , tlsCertificateFile_()
     , tlsPrivateKeyFile_()
@@ -131,11 +114,6 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
     , tlsVerifyClient_(true)
     , tlsRequireClientCertificate_(true)
     , tlsNegotiationTimeoutSec_("2")
-    , stunServer_("")
-    , stunEnabled_(false)
-    , srtpEnabled_(false)
-    , srtpKeyExchange_("")
-    , srtpFallback_(false)
     , zrtpDisplaySas_(true)
     , zrtpDisplaySasOnce_(false)
     , zrtpHelloHash_(true)
@@ -144,7 +122,6 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
     , keepAliveEnabled_(false)
     , keepAliveTimer_()
     , keepAliveTimerActive_(false)
-    , link_(getSIPVoIPLink())
     , receivedParameter_("")
     , rPort_(-1)
     , via_addr_()
@@ -155,10 +132,6 @@ SIPAccount::SIPAccount(const std::string& accountID, bool presenceEnabled)
     , allowContactRewrite_(1)
     , contactOverwritten_(false)
     , via_tp_(nullptr)
-    , audioPortRange_({16384, 32766})
-#ifdef SFL_VIDEO
-    , videoPortRange_({49152, (MAX_PORT) - 2})
-#endif
 #ifdef SFL_PRESENCE
     , presence_(presenceEnabled ? new SIPPresence(this) : nullptr)
 #endif
@@ -220,7 +193,6 @@ unserializeRange(const Conf::YamlNode &mapNode, const char *minKey, const char *
     updateRange(tmpMin, tmpMax, range);
 }
 
-template <>
 std::shared_ptr<SIPCall>
 SIPAccount::newIncomingCall(const std::string& id)
 {
@@ -235,6 +207,8 @@ SIPAccount::newOutgoingCall(const std::string& id, const std::string& toUrl)
     std::string toUri;
     int family;
 
+    auto call = Manager::instance().callFactory.newCall<SIPCall, SIPAccount>(*this, id, Call::OUTGOING);
+
     if (isIP2IP()) {
         bool ipv6 = false;
 #if HAVE_IPV6
@@ -262,8 +236,6 @@ SIPAccount::newOutgoingCall(const std::string& id, const std::string& toUrl)
         DEBUG("UserAgent: New registered account call to %s", toUrl.c_str());
     }
 
-    auto call = Manager::instance().callFactory.newCall<SIPCall, SIPAccount>(*this, id, Call::OUTGOING);
-
     call->setIPToIP(isIP2IP());
     call->setPeerNumber(toUri);
     call->initRecFilename(to);
@@ -403,9 +375,6 @@ SIPAccount::SIPStartCall(std::shared_ptr<SIPCall>& call)
 void SIPAccount::serialize(Conf::YamlEmitter &emitter)
 {
     using namespace Conf;
-    using std::vector;
-    using std::string;
-    using std::map;
     MappingNode accountmap(nullptr);
     MappingNode srtpmap(nullptr);
     MappingNode zrtpmap(nullptr);
@@ -962,16 +931,7 @@ static std::string retrievePassword(const std::map<std::string, std::string>& ma
     return "";
 }
 
-void
-addRangeToDetails(std::map<std::string, std::string> &a, const char *minKey, const char *maxKey, const std::pair<uint16_t, uint16_t> &range)
-{
-    std::ostringstream os;
-    os << range.first;
-    a[minKey] = os.str();
-    os.str("");
-    os << range.second;
-    a[maxKey] = os.str();
-}
+
 
 std::map<std::string, std::string> SIPAccount::getAccountDetails() const
 {
@@ -2080,41 +2040,6 @@ SIPAccount::matches(const std::string &userName, const std::string &server,
     }
 }
 
-// returns even number in range [lower, upper]
-uint16_t
-SIPAccount::getRandomEvenNumber(const std::pair<uint16_t, uint16_t> &range)
-{
-    const uint16_t halfUpper = range.second * 0.5;
-    const uint16_t halfLower = range.first * 0.5;
-    uint16_t result;
-    do {
-        result = 2 * (halfLower + rand() % (halfUpper - halfLower + 1));
-    } while (portsInUse_[result / 2]);
-
-    portsInUse_[result / 2] = true;
-    return result;
-}
-
-void
-SIPAccount::releasePort(uint16_t port)
-{
-    portsInUse_[port / 2] = false;
-}
-
-uint16_t
-SIPAccount::generateAudioPort() const
-{
-    return getRandomEvenNumber(audioPortRange_);
-}
-
-#ifdef SFL_VIDEO
-uint16_t
-SIPAccount::generateVideoPort() const
-{
-    return getRandomEvenNumber(videoPortRange_);
-}
-#endif
-
 void
 SIPAccount::destroyRegistrationInfo()
 {
diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h
index 20a26302f97d02a26fae97c1758296a040cc06b4..56cdd166b2fadbeb80f6ce14434b70771921d0df 100644
--- a/daemon/src/sip/sipaccount.h
+++ b/daemon/src/sip/sipaccount.h
@@ -39,10 +39,9 @@
 #include "config.h"
 #endif
 
+#include "sipaccountbase.h"
 #include "siptransport.h"
-#include "account.h"
 #include "noncopyable.h"
-#include "ip_utils.h"
 #include "sfl_types.h" // enable_if_base_of
 
 #include <pjsip/sip_transport_tls.h>
@@ -55,64 +54,9 @@
 typedef std::vector<pj_ssl_cipher> CipherArray;
 
 namespace Conf {
-    class YamlEmitter;
-    class MappingNode;
-    // SIP specific configuration keys
-    const char *const INTERFACE_KEY = "interface";
-    const char *const PORT_KEY = "port";
-    const char *const PUBLISH_ADDR_KEY = "publishAddr";
-    const char *const PUBLISH_PORT_KEY = "publishPort";
-    const char *const SAME_AS_LOCAL_KEY = "sameasLocal";
-    const char *const DTMF_TYPE_KEY = "dtmfType";
-    const char *const SERVICE_ROUTE_KEY = "serviceRoute";
     const char *const KEEP_ALIVE_ENABLED = "keepAlive";
-    const char *const PRESENCE_ENABLED_KEY = "presenceEnabled";
-    const char *const PRESENCE_PUBLISH_SUPPORTED_KEY = "presencePublishSupported";
-    const char *const PRESENCE_SUBSCRIBE_SUPPORTED_KEY = "presenceSubscribeSupported";
-    const char *const PRESENCE_STATUS_KEY = "presenceStatus";
-    const char *const PRESENCE_NOTE_KEY = "presenceNote";
-
-    // TODO: write an object to store credential which implement serializable
-    const char *const SRTP_KEY = "srtp";
-    const char *const SRTP_ENABLE_KEY = "enable";
-    const char *const KEY_EXCHANGE_KEY = "keyExchange";
-    const char *const RTP_FALLBACK_KEY = "rtpFallback";
-
-    // TODO: wirte an object to store zrtp params wich implement serializable
-    const char *const ZRTP_KEY = "zrtp";
-    const char *const DISPLAY_SAS_KEY = "displaySas";
-    const char *const DISPLAY_SAS_ONCE_KEY = "displaySasOnce";
-    const char *const HELLO_HASH_ENABLED_KEY = "helloHashEnabled";
-    const char *const NOT_SUPP_WARNING_KEY = "notSuppWarning";
-
-    // TODO: write an object to store tls params which implement serializable
-    const char *const TLS_KEY = "tls";
-    const char *const TLS_PORT_KEY = "tlsPort";
-    const char *const CERTIFICATE_KEY = "certificate";
-    const char *const CALIST_KEY = "calist";
-    const char *const CIPHERS_KEY = "ciphers";
-    const char *const TLS_ENABLE_KEY = "enable";
-    const char *const METHOD_KEY = "method";
-    const char *const TIMEOUT_KEY = "timeout";
-    const char *const TLS_PASSWORD_KEY = "password";
-    const char *const PRIVATE_KEY_KEY = "privateKey";
-    const char *const REQUIRE_CERTIF_KEY = "requireCertif";
-    const char *const SERVER_KEY = "server";
-    const char *const VERIFY_CLIENT_KEY = "verifyClient";
-    const char *const VERIFY_SERVER_KEY = "verifyServer";
-
-    const char *const STUN_ENABLED_KEY = "stunEnabled";
-    const char *const STUN_SERVER_KEY = "stunServer";
-    const char *const CRED_KEY = "credential";
-    const char *const AUDIO_PORT_MIN_KEY = "audioPortMin";
-    const char *const AUDIO_PORT_MAX_KEY = "audioPortMax";
-#ifdef SFL_VIDEO
-    const char *const VIDEO_PORT_MIN_KEY = "videoPortMin";
-    const char *const VIDEO_PORT_MAX_KEY = "videoPortMax";
-#endif
 }
 
-class SIPVoIPLink;
 class SIPPresence;
 class SIPCall;
 
@@ -120,15 +64,9 @@ class SIPCall;
  * @file sipaccount.h
  * @brief A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink)
  */
-enum {MAX_PORT = 65536};
-enum {HALF_MAX_PORT = MAX_PORT / 2};
-enum class MatchRank {NONE, PARTIAL, FULL};
-
-class SIPAccount : public Account {
+class SIPAccount : public SIPAccountBase {
     public:
         constexpr static const char * const IP2IP_PROFILE = "IP2IP";
-        constexpr static const char * const OVERRTP_STR = "overrtp";
-        constexpr static const char * const SIPINFO_STR = "sipinfo";
         constexpr static const char * const ACCOUNT_TYPE = "SIP";
 
         /**
@@ -160,9 +98,6 @@ class SIPAccount : public Account {
          */
         bool isIP2IP() const;
 
-        static void
-        releasePort(uint16_t port);
-
         /**
          * Serialize internal state of this account for configuration
          * @param YamlEmitter the configuration engine which generate the configuration file
@@ -416,83 +351,6 @@ class SIPAccount : public Account {
          */
         pj_str_t getContactHeader();
 
-        /**
-         * Get the local interface name on which this account is bound.
-         */
-        const std::string& getLocalInterface() const {
-            return interface_;
-        }
-
-        /**
-         * Get a flag which determine the usage in sip headers of either the local
-         * IP address and port (_localAddress and localPort_) or to an address set
-         * manually (_publishedAddress and publishedPort_).
-         */
-        bool getPublishedSameasLocal() const {
-            return publishedSameasLocal_;
-        }
-
-        /**
-         * Get the port on which the transport/listener should use, or is
-         * actually using.
-         * @return pj_uint16 The port used for that account
-         */
-        pj_uint16_t getLocalPort() const {
-            return localPort_;
-        }
-
-        /**
-         * Set the new port on which this account is running over.
-         * @pram port The port used by this account.
-         */
-        void setLocalPort(pj_uint16_t port) {
-            localPort_ = port;
-        }
-
-        /**
-         * Get the published port, which is the port to be advertised as the port
-         * for the chosen SIP transport.
-         * @return pj_uint16 The port used for that account
-         */
-        pj_uint16_t getPublishedPort() const {
-            return (pj_uint16_t) publishedPort_;
-        }
-
-        /**
-         * Set the published port, which is the port to be advertised as the port
-         * for the chosen SIP transport.
-         * @pram port The port used by this account.
-         */
-        void setPublishedPort(pj_uint16_t port) {
-            publishedPort_ = port;
-        }
-
-        /**
-             * Get the local port for TLS listener.
-             * @return pj_uint16 The port used for that account
-             */
-        pj_uint16_t getTlsListenerPort() const {
-            return tlsListenerPort_;
-        }
-
-        /**
-         * Get the public IP address set by the user for this account.
-         * If this setting is not provided, the local bound adddress
-         * will be used.
-         * @return std::string The public IPv4 or IPv6 address formatted in standard notation.
-         */
-        std::string getPublishedAddress() const {
-            return publishedIpAddress_;
-        }
-
-        IpAddr getPublishedIpAddress() const {
-            return publishedIp_;
-        }
-
-        void setPublishedAddress(const IpAddr& ip_addr) {
-            publishedIp_ = ip_addr;
-            publishedIpAddress_ = ip_addr.toString();
-        }
 
         std::string getServiceRoute() const {
             return serviceRoute_;
@@ -500,21 +358,6 @@ class SIPAccount : public Account {
 
         bool hasServiceRoute() const { return not serviceRoute_.empty(); }
 
-        std::string getDtmfType() const {
-            return dtmfType_;
-        }
-
-        bool getSrtpEnabled() const {
-            return srtpEnabled_;
-        }
-
-        std::string getSrtpKeyExchange() const {
-            return srtpKeyExchange_;
-        }
-
-        bool getSrtpFallback() const {
-            return srtpFallback_;
-        }
 
         bool getZrtpHelloHash() const {
             return zrtpHelloHash_;
@@ -557,23 +400,8 @@ class SIPAccount : public Account {
             return keepAliveEnabled_;
         }
 
-        inline pjsip_transport* getTransport() {
-            return transport_;
-        }
-
         void setTransport(pjsip_transport* transport = nullptr, pjsip_tpfactory* lis = nullptr);
 
-        inline pjsip_transport_type_e getTransportType() const {
-            return transportType_;
-        }
-
-        /**
-         * Shortcut for SipTransport::getTransportSelector(account.getTransport()).
-         */
-        inline pjsip_tpselector getTransportSelector() {
-            return SipTransport::getTransportSelector(transport_);
-        }
-
         /* 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;
 
@@ -596,12 +424,6 @@ class SIPAccount : public Account {
         void supportPresence(int function, bool enable);
 #endif
 
-//        unsigned generateAudioPort() const;
-        uint16_t generateAudioPort() const;
-#ifdef SFL_VIDEO
-        uint16_t generateVideoPort() const;
-#endif
-
         void scheduleReregistration(pjsip_endpoint *endpt);
 
         /**
@@ -630,8 +452,7 @@ class SIPAccount : public Account {
          *      The type of this instance is given in template argument.
          *      This type can be any base class of SIPCall class (included).
          */
-        template <class T=SIPCall>
-        std::shared_ptr<enable_if_base_of<T, SIPCall> >
+        std::shared_ptr<SIPCall>
         newIncomingCall(const std::string& id);
 
         void onRegister(pjsip_regc_cbparam *param);
@@ -675,16 +496,6 @@ class SIPAccount : public Account {
          */
         std::vector< std::map<std::string, std::string > > credentials_;
 
-        /**
-         * Pointer to the transport used by this acccount
-         */
-        pjsip_transport* transport_;
-
-        /**
-         * If a TLS tranport, pointer to the tls listener.
-         */
-        pjsip_tpfactory* tlsListener_;
-
 #if HAVE_TLS
         /**
          * Maps a string description of the SSL method
@@ -735,51 +546,11 @@ class SIPAccount : public Account {
          */
         int registrationExpire_;
 
-        /**
-         * interface name on which this account is bound
-         */
-        std::string interface_;
-
-        /**
-         * Flag which determine if localIpAddress_ or publishedIpAddress_ is used in
-         * sip headers
-         */
-        bool publishedSameasLocal_;
-
-        /**
-         * Published IP address, used only if defined by the user in account
-         * configuration
-         */
-        IpAddr publishedIp_;
-        std::string publishedIpAddress_;
-
-        /**
-         * Local port to whih this account is bound
-         */
-        pj_uint16_t localPort_;
-
-        /**
-         * Published port, used only if defined by the user
-         */
-        pj_uint16_t publishedPort_;
-
         /**
          * Optional list of SIP service this
          */
         std::string serviceRoute_;
 
-        /**
-         * The global TLS listener port which can be configured through the IP2IP_PROFILE
-         */
-        pj_uint16_t tlsListenerPort_;
-
-        /**
-         * Transport type used for this sip account. Currently supported types:
-         *    PJSIP_TRANSPORT_UNSPECIFIED
-         *    PJSIP_TRANSPORT_UDP
-         *    PJSIP_TRANSPORT_TLS
-         */
-        pjsip_transport_type_e transportType_;
 
         /**
          * Credential information stored for further registration.
@@ -797,25 +568,28 @@ class SIPAccount : public Account {
         CipherArray ciphers_;
 
         /**
-         * The STUN server name (hostname)
+         * Determine if STUN public address resolution is required to register this account. In this case a
+         * STUN server hostname must be specified.
          */
-        pj_str_t stunServerName_;
+        bool stunEnabled_ {false};
 
         /**
-         * The STUN server port
+         * The stun server hostname (optional), used to provide the public IP address in case the softphone
+         * stay behind a NAT.
          */
-        pj_uint16_t stunPort_;
+        std::string stunServer_ {};
 
         /**
-         * DTMF type used for this account SIPINFO or RTP
+         * The STUN server name (hostname)
          */
-        std::string dtmfType_;
+        pj_str_t stunServerName_ {};
 
         /**
-         * Determine if TLS is enabled for this account. TLS provides a secured channel for
-         * SIP signalization. It is independant than the media encription provided by SRTP or ZRTP.
+         * The STUN server port
          */
-        bool tlsEnable_;
+        pj_uint16_t stunPort_ {PJ_STUN_PORT};
+
+
 
         /**
          * Certificate autority file
@@ -832,37 +606,6 @@ class SIPAccount : public Account {
         bool tlsRequireClientCertificate_;
         std::string tlsNegotiationTimeoutSec_;
 
-        /**
-         * The stun server hostname (optional), used to provide the public IP address in case the softphone
-         * stay behind a NAT.
-         */
-        std::string stunServer_;
-
-        /**
-         * Determine if STUN public address resolution is required to register this account. In this case a
-         * STUN server hostname must be specified.
-         */
-        bool stunEnabled_;
-
-        /**
-         * Determine if SRTP is enabled for this account, SRTP and ZRTP are mutually exclusive
-         * This only determine if the media channel is secured. One could only enable TLS
-         * with no secured media channel.
-         */
-        bool srtpEnabled_;
-
-        /**
-         * Specifies the type of key exchange usd for SRTP (sdes/zrtp)
-         */
-        std::string srtpKeyExchange_;
-
-        /**
-         * Determine if the softphone should fallback on non secured media channel if SRTP negotiation fails.
-         * Make sure other SIP endpoints share the same behavior since it could result in encrypted data to be
-         * played through the audio device.
-         */
-        bool srtpFallback_;
-
         /**
          * Determine if the SAS sould be displayed on client side. SAS is a 4-charcter string
          * that end users should verbaly validate to ensure the channel is secured. Used especially
@@ -901,11 +644,6 @@ class SIPAccount : public Account {
          */
         bool keepAliveTimerActive_;
 
-        /**
-         * Voice over IP Link contains a listener thread and calls
-         */
-        std::shared_ptr<SIPVoIPLink> link_;
-
         /**
          * Optional: "received" parameter from VIA header
          */
@@ -930,27 +668,12 @@ class SIPAccount : public Account {
         bool contactOverwritten_;
         pjsip_transport *via_tp_;
 
-        /*
-         * Port range for audio RTP ports
-         */
-        std::pair<uint16_t, uint16_t> audioPortRange_;
-
-#ifdef SFL_VIDEO
-        /**
-         * Port range for video RTP ports
-         */
-        std::pair<uint16_t, uint16_t> videoPortRange_;
-#endif
-
 #ifdef SFL_PRESENCE
         /**
          * Presence data structure
          */
         SIPPresence * presence_;
 #endif
-
-        static bool portsInUse_[HALF_MAX_PORT];
-        static uint16_t getRandomEvenNumber(const std::pair<uint16_t, uint16_t> &range);
 };
 
 #endif
diff --git a/daemon/src/sip/sipaccountbase.cpp b/daemon/src/sip/sipaccountbase.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..32cc48b4600964a7e2e0f9b404a3fb1ab827ad5c
--- /dev/null
+++ b/daemon/src/sip/sipaccountbase.cpp
@@ -0,0 +1,89 @@
+/*
+ *  Copyright (C) 2014 Savoir-Faire Linux Inc.
+ *
+ *  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
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#include "sipaccountbase.h"
+#include "sipvoiplink.h"
+
+bool SIPAccountBase::portsInUse_[HALF_MAX_PORT];
+
+SIPAccountBase::SIPAccountBase(const std::string& accountID)
+    : Account(accountID), link_(getSIPVoIPLink())
+{}
+
+
+void
+SIPAccountBase::setTransport(pjsip_transport* transport, pjsip_tpfactory* lis)
+{
+    // release old transport
+    if (transport_ && transport_ != transport) {
+        pjsip_transport_dec_ref(transport_);
+    }
+    if (tlsListener_ && tlsListener_ != lis)
+        tlsListener_->destroy(tlsListener_);
+    // set new transport
+    transport_ = transport;
+    tlsListener_ = lis;
+}
+
+// returns even number in range [lower, upper]
+uint16_t
+SIPAccountBase::getRandomEvenNumber(const std::pair<uint16_t, uint16_t> &range)
+{
+    const uint16_t halfUpper = range.second * 0.5;
+    const uint16_t halfLower = range.first * 0.5;
+    uint16_t result;
+    do {
+        result = 2 * (halfLower + rand() % (halfUpper - halfLower + 1));
+    } while (portsInUse_[result / 2]);
+
+    portsInUse_[result / 2] = true;
+    return result;
+}
+
+void
+SIPAccountBase::releasePort(uint16_t port)
+{
+    portsInUse_[port / 2] = false;
+}
+
+uint16_t
+SIPAccountBase::generateAudioPort() const
+{
+    return getRandomEvenNumber(audioPortRange_);
+}
+
+#ifdef SFL_VIDEO
+uint16_t
+SIPAccountBase::generateVideoPort() const
+{
+    return getRandomEvenNumber(videoPortRange_);
+}
+#endif
diff --git a/daemon/src/sip/sipaccountbase.h b/daemon/src/sip/sipaccountbase.h
new file mode 100644
index 0000000000000000000000000000000000000000..3a0da287cd7fef98ab675fdde74d3031215426b7
--- /dev/null
+++ b/daemon/src/sip/sipaccountbase.h
@@ -0,0 +1,408 @@
+/*
+ *  Copyright (C) 2014 Savoir-Faire Linux Inc.
+ *
+ *  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
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+#ifndef SIPACCOUNTBASE_H
+#define SIPACCOUNTBASE_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "siptransport.h"
+#include "account.h"
+#include "noncopyable.h"
+#include "ip_utils.h"
+//#include "sfl_types.h" // enable_if_base_of
+
+#include "global.h"
+
+#include <pjsip/sip_transport_tls.h>
+#include <pjsip/sip_types.h>
+
+#include <vector>
+#include <map>
+
+typedef std::vector<pj_ssl_cipher> CipherArray;
+
+namespace Conf {
+    class YamlEmitter;
+    class MappingNode;
+    // SIP specific configuration keys
+    const char *const INTERFACE_KEY = "interface";
+    const char *const PORT_KEY = "port";
+    const char *const PUBLISH_ADDR_KEY = "publishAddr";
+    const char *const PUBLISH_PORT_KEY = "publishPort";
+    const char *const SAME_AS_LOCAL_KEY = "sameasLocal";
+    const char *const DTMF_TYPE_KEY = "dtmfType";
+    const char *const SERVICE_ROUTE_KEY = "serviceRoute";
+    const char *const PRESENCE_ENABLED_KEY = "presenceEnabled";
+    const char *const PRESENCE_PUBLISH_SUPPORTED_KEY = "presencePublishSupported";
+    const char *const PRESENCE_SUBSCRIBE_SUPPORTED_KEY = "presenceSubscribeSupported";
+    const char *const PRESENCE_STATUS_KEY = "presenceStatus";
+    const char *const PRESENCE_NOTE_KEY = "presenceNote";
+
+    // TODO: write an object to store credential which implement serializable
+    const char *const SRTP_KEY = "srtp";
+    const char *const SRTP_ENABLE_KEY = "enable";
+    const char *const KEY_EXCHANGE_KEY = "keyExchange";
+    const char *const RTP_FALLBACK_KEY = "rtpFallback";
+
+    // TODO: wirte an object to store zrtp params wich implement serializable
+    const char *const ZRTP_KEY = "zrtp";
+    const char *const DISPLAY_SAS_KEY = "displaySas";
+    const char *const DISPLAY_SAS_ONCE_KEY = "displaySasOnce";
+    const char *const HELLO_HASH_ENABLED_KEY = "helloHashEnabled";
+    const char *const NOT_SUPP_WARNING_KEY = "notSuppWarning";
+
+    // TODO: write an object to store tls params which implement serializable
+    const char *const TLS_KEY = "tls";
+    const char *const TLS_PORT_KEY = "tlsPort";
+    const char *const CERTIFICATE_KEY = "certificate";
+    const char *const CALIST_KEY = "calist";
+    const char *const CIPHERS_KEY = "ciphers";
+    const char *const TLS_ENABLE_KEY = "enable";
+    const char *const METHOD_KEY = "method";
+    const char *const TIMEOUT_KEY = "timeout";
+    const char *const TLS_PASSWORD_KEY = "password";
+    const char *const PRIVATE_KEY_KEY = "privateKey";
+    const char *const REQUIRE_CERTIF_KEY = "requireCertif";
+    const char *const SERVER_KEY = "server";
+    const char *const VERIFY_CLIENT_KEY = "verifyClient";
+    const char *const VERIFY_SERVER_KEY = "verifyServer";
+
+    const char *const STUN_ENABLED_KEY = "stunEnabled";
+    const char *const STUN_SERVER_KEY = "stunServer";
+    const char *const CRED_KEY = "credential";
+    const char *const AUDIO_PORT_MIN_KEY = "audioPortMin";
+    const char *const AUDIO_PORT_MAX_KEY = "audioPortMax";
+#ifdef SFL_VIDEO
+    const char *const VIDEO_PORT_MIN_KEY = "videoPortMin";
+    const char *const VIDEO_PORT_MAX_KEY = "videoPortMax";
+#endif
+}
+
+class SIPVoIPLink;
+class SIPCall;
+
+/**
+ * @file sipaccount.h
+ * @brief A SIP Account specify SIP specific functions and object = SIPCall/SIPVoIPLink)
+ */
+enum {MAX_PORT = 65536};
+enum {HALF_MAX_PORT = MAX_PORT / 2};
+enum class MatchRank {NONE, PARTIAL, FULL};
+
+class SIPAccountBase : public Account {
+public:
+    constexpr static const char * const OVERRTP_STR = "overrtp";
+    constexpr static const char * const SIPINFO_STR = "sipinfo";
+
+    /**
+     * Constructor
+     * @param accountID The account identifier
+     */
+    SIPAccountBase(const std::string& accountID);
+
+    virtual ~SIPAccountBase() = default;
+
+    /**
+     * Create incoming SIPCall.
+     * @param[in] id The ID of the call
+     * @return std::shared_ptr<T> A shared pointer on the created call.
+     *      The type of this instance is given in template argument.
+     *      This type can be any base class of SIPCall class (included).
+     */
+    virtual std::shared_ptr<SIPCall>
+    newIncomingCall(const std::string& id) = 0;
+
+    virtual bool isStunEnabled() const {
+        return false;
+    }
+
+    virtual pj_str_t getStunServerName() const { return pj_str_t {}; };
+
+    virtual pj_uint16_t getStunPort() const { return 0; };
+
+    virtual std::string getDtmfType() const {
+        return dtmfType_;
+    }
+
+    bool isTlsEnabled() const {
+        return tlsEnable_;
+    }
+
+    virtual pjsip_tls_setting * getTlsSetting() {
+        return nullptr;
+    }
+
+    /**
+     * Get the local port for TLS listener.
+     * @return pj_uint16 The port used for that account
+     */
+    pj_uint16_t getTlsListenerPort() const {
+        return tlsListenerPort_;
+    }
+
+    /**
+     * Get the public IP address set by the user for this account.
+     * If this setting is not provided, the local bound adddress
+     * will be used.
+     * @return std::string The public IPv4 or IPv6 address formatted in standard notation.
+     */
+    std::string getPublishedAddress() const {
+        return publishedIpAddress_;
+    }
+
+    IpAddr getPublishedIpAddress() const {
+        return publishedIp_;
+    }
+
+    void setPublishedAddress(const IpAddr& ip_addr) {
+        publishedIp_ = ip_addr;
+        publishedIpAddress_ = ip_addr.toString();
+    }
+
+    /**
+     * Get the local interface name on which this account is bound.
+     */
+    const std::string& getLocalInterface() const {
+        return interface_;
+    }
+
+    /**
+     * Get a flag which determine the usage in sip headers of either the local
+     * IP address and port (_localAddress and localPort_) or to an address set
+     * manually (_publishedAddress and publishedPort_).
+     */
+    bool getPublishedSameasLocal() const {
+        return publishedSameasLocal_;
+    }
+
+    /**
+     * Get the port on which the transport/listener should use, or is
+     * actually using.
+     * @return pj_uint16 The port used for that account
+     */
+    pj_uint16_t getLocalPort() const {
+        return localPort_;
+    }
+
+    /**
+     * Set the new port on which this account is running over.
+     * @pram port The port used by this account.
+     */
+    void setLocalPort(pj_uint16_t port) {
+        localPort_ = port;
+    }
+
+    /**
+     * Get the published port, which is the port to be advertised as the port
+     * for the chosen SIP transport.
+     * @return pj_uint16 The port used for that account
+     */
+    pj_uint16_t getPublishedPort() const {
+        return (pj_uint16_t) publishedPort_;
+    }
+
+    /**
+     * Set the published port, which is the port to be advertised as the port
+     * for the chosen SIP transport.
+     * @pram port The port used by this account.
+     */
+    void setPublishedPort(pj_uint16_t port) {
+        publishedPort_ = port;
+    }
+
+    bool getSrtpEnabled() const {
+        return srtpEnabled_;
+    }
+
+    std::string getSrtpKeyExchange() const {
+        return srtpKeyExchange_;
+    }
+
+    bool getSrtpFallback() const {
+        return srtpFallback_;
+    }
+
+    /**
+     * Get the contact header for
+     * @return pj_str_t The contact header based on account information
+     */
+    virtual pj_str_t getContactHeader() = 0;
+
+    virtual std::string getToUri(const std::string& username) const = 0;
+
+    virtual std::string getServerUri() const = 0;
+
+    uint16_t generateAudioPort() const;
+#ifdef SFL_VIDEO
+    uint16_t generateVideoPort() const;
+#endif
+    static void releasePort(uint16_t port);
+
+    inline pjsip_transport* getTransport() {
+        return transport_;
+    }
+
+    virtual void setTransport(pjsip_transport* transport = nullptr, pjsip_tpfactory* lis = nullptr);
+
+    inline pjsip_transport_type_e getTransportType() const {
+        return transportType_;
+    }
+
+    /**
+     * Shortcut for SipTransport::getTransportSelector(account.getTransport()).
+     */
+    inline pjsip_tpselector getTransportSelector() {
+        return SipTransport::getTransportSelector(transport_);
+    }
+
+
+protected:
+    /**
+     * Voice over IP Link contains a listener thread and calls
+     */
+    std::shared_ptr<SIPVoIPLink> link_;
+
+    /**
+     * Pointer to the transport used by this acccount
+     */
+    pjsip_transport* transport_ {nullptr};
+
+    /**
+     * Transport type used for this sip account. Currently supported types:
+     *    PJSIP_TRANSPORT_UNSPECIFIED
+     *    PJSIP_TRANSPORT_UDP
+     *    PJSIP_TRANSPORT_TLS
+     */
+    pjsip_transport_type_e transportType_ {PJSIP_TRANSPORT_UNSPECIFIED};
+
+    /**
+     * interface name on which this account is bound
+     */
+    std::string interface_ {"default"};
+
+    /**
+     * Flag which determine if localIpAddress_ or publishedIpAddress_ is used in
+     * sip headers
+     */
+    bool publishedSameasLocal_ {true};
+
+    /**
+     * Published IP address, used only if defined by the user in account
+     * configuration
+     */
+    IpAddr publishedIp_ {};
+    std::string publishedIpAddress_ {};
+
+    /**
+     * Local port to whih this account is bound
+     */
+    pj_uint16_t localPort_ {DEFAULT_SIP_PORT};
+
+    /**
+     * Published port, used only if defined by the user
+     */
+    pj_uint16_t publishedPort_ {DEFAULT_SIP_PORT};
+
+    /**
+     * If a TLS tranport, pointer to the tls listener.
+     */
+    pjsip_tpfactory* tlsListener_ {nullptr};
+
+    /**
+     * The global TLS listener port which can be configured through the IP2IP_PROFILE
+     */
+    pj_uint16_t tlsListenerPort_ {DEFAULT_SIP_TLS_PORT};
+
+    /**
+     * DTMF type used for this account SIPINFO or RTP
+     */
+    std::string dtmfType_ {OVERRTP_STR};
+
+    /**
+     * Determine if TLS is enabled for this account. TLS provides a secured channel for
+     * SIP signalization. It is independant than the media encription provided by SRTP or ZRTP.
+     */
+    bool tlsEnable_ {false};
+
+    /**
+     * Determine if SRTP is enabled for this account, SRTP and ZRTP are mutually exclusive
+     * This only determine if the media channel is secured. One could only enable TLS
+     * with no secured media channel.
+     */
+    bool srtpEnabled_ {false};
+
+    /**
+     * Specifies the type of key exchange usd for SRTP (sdes/zrtp)
+     */
+    std::string srtpKeyExchange_ {""};
+
+    /**
+     * Determine if the softphone should fallback on non secured media channel if SRTP negotiation fails.
+     * Make sure other SIP endpoints share the same behavior since it could result in encrypted data to be
+     * played through the audio device.
+     */
+    bool srtpFallback_ {};
+
+    /*
+     * Port range for audio RTP ports
+     */
+    std::pair<uint16_t, uint16_t> audioPortRange_ {16384, 32766};
+
+#ifdef SFL_VIDEO
+    /**
+     * Port range for video RTP ports
+     */
+    std::pair<uint16_t, uint16_t> videoPortRange_ {49152, (MAX_PORT) - 2};
+#endif
+
+    static bool portsInUse_[HALF_MAX_PORT];
+    static uint16_t getRandomEvenNumber(const std::pair<uint16_t, uint16_t> &range);
+
+    static void
+    addRangeToDetails(std::map<std::string, std::string> &a, const char *minKey, const char *maxKey, const std::pair<uint16_t, uint16_t> &range)
+    {
+        std::ostringstream os;
+        os << range.first;
+        a[minKey] = os.str();
+        os.str("");
+        os << range.second;
+        a[maxKey] = os.str();
+    }
+
+private:
+    NON_COPYABLE(SIPAccountBase);
+
+};
+
+#endif
diff --git a/daemon/src/sip/sipcall.cpp b/daemon/src/sip/sipcall.cpp
index 0726ba6ab7eb26284f3e2279ab1fcadb06b2eaff..1c680ded9da4170159c620f3e2000979dfd620c8 100644
--- a/daemon/src/sip/sipcall.cpp
+++ b/daemon/src/sip/sipcall.cpp
@@ -34,6 +34,8 @@
 
 #include "call_factory.h"
 #include "sipcall.h"
+#include "sipaccount.h" // for SIPAccount::ACCOUNT_TYPE
+#include "sipaccountbase.h"
 #include "sipvoiplink.h"
 #include "sip_utils.h"
 #include "logger.h" // for _debug
@@ -96,7 +98,7 @@ dtmfSend(SIPCall &call, char code, const std::string &dtmf)
     call.sendSIPInfo(dtmf_body, "dtmf-relay");
 }
 
-SIPCall::SIPCall(SIPAccount& account, const std::string& id,
+SIPCall::SIPCall(SIPAccountBase& account, const std::string& id,
                  Call::CallType type)
     : Call(account, id, type)
     , audiortp_(this)
@@ -138,10 +140,10 @@ SIPCall::stopRtpIfCurrent()
     }
 }
 
-SIPAccount&
+SIPAccountBase&
 SIPCall::getSIPAccount() const
 {
-    return static_cast<SIPAccount&>(getAccount());
+    return static_cast<SIPAccountBase&>(getAccount());
 }
 
 void
diff --git a/daemon/src/sip/sipcall.h b/daemon/src/sip/sipcall.h
index a1a93ca1d0b740b401089f6925a19ea9b768393f..6191eba23da672c75765ff039fdabb2594ca08cf 100644
--- a/daemon/src/sip/sipcall.h
+++ b/daemon/src/sip/sipcall.h
@@ -56,7 +56,7 @@ struct pj_pool_t;
 struct pjsip_inv_session;
 
 class Sdp;
-class SIPAccount;
+class SIPAccountBase;
 
 /**
  * @file sipcall.h
@@ -74,7 +74,7 @@ class SIPCall : public Call
          * @param type  The type of the call. Could be Incoming
          *						 Outgoing
          */
-        SIPCall(SIPAccount& account, const std::string& id, Call::CallType type);
+        SIPCall(SIPAccountBase& account, const std::string& id, Call::CallType type);
 
     public:
         /**
@@ -147,7 +147,7 @@ class SIPCall : public Call
                              const std::string& from);
 #endif
 
-        SIPAccount& getSIPAccount() const;
+        SIPAccountBase& getSIPAccount() const;
 
         void updateSDPFromSTUN();
 
diff --git a/daemon/src/sip/siptransport.cpp b/daemon/src/sip/siptransport.cpp
index aad81aa0749de497d6b5fa6e9cf122529086448f..da4a2c6200ef4a618b937be70a15936071834fd7 100644
--- a/daemon/src/sip/siptransport.cpp
+++ b/daemon/src/sip/siptransport.cpp
@@ -146,7 +146,7 @@ SipTransport::waitForReleased(pjsip_transport* tp, std::function<void(bool)> rel
 }
 
 void
-SipTransport::createSipTransport(SIPAccount &account)
+SipTransport::createSipTransport(SIPAccountBase &account)
 {
     // Remove any existing transport from the account
     account.setTransport();
@@ -241,7 +241,7 @@ SipTransport::createUdpTransport(const std::string &interface, pj_uint16_t port,
 
 #if HAVE_TLS
 pjsip_tpfactory*
-SipTransport::createTlsListener(SIPAccount &account, pj_uint16_t family)
+SipTransport::createTlsListener(SIPAccountBase &account, pj_uint16_t family)
 {
     RETURN_IF_FAIL(account.getTlsSetting() != nullptr, nullptr, "TLS settings not specified");
 
@@ -271,7 +271,7 @@ SipTransport::createTlsListener(SIPAccount &account, pj_uint16_t family)
 }
 
 pjsip_transport *
-SipTransport::createTlsTransport(SIPAccount &account)
+SipTransport::createTlsTransport(SIPAccountBase &account)
 {
     std::string remoteSipUri(account.getServerUri());
     static const char SIPS_PREFIX[] = "<sips:";
@@ -362,7 +362,7 @@ SipTransport::_cleanupTransports()
 }
 
 std::vector<pj_sockaddr>
-SipTransport::getSTUNAddresses(const SIPAccount &account,
+SipTransport::getSTUNAddresses(const SIPAccountBase &account,
         std::vector<long> &socketDescriptors) const
 {
     const pj_str_t serverName = account.getStunServerName();
diff --git a/daemon/src/sip/siptransport.h b/daemon/src/sip/siptransport.h
index e513383ac4b80f609de8ad3cdcc7e8239f13d7f3..a592b03ba351af90c774958bb29fe4b3ca23e131 100644
--- a/daemon/src/sip/siptransport.h
+++ b/daemon/src/sip/siptransport.h
@@ -54,7 +54,7 @@
 #include <vector>
 #include <memory>
 
-class SIPAccount;
+class SIPAccountBase;
 
 
 class SipTransport {
@@ -67,7 +67,7 @@ class SipTransport {
          * transport type specified in account settings
          * @param account The account for which a transport must be created.
          */
-        void createSipTransport(SIPAccount &account);
+        void createSipTransport(SIPAccountBase &account);
 
         /**
          * Initialize the transport selector
@@ -82,7 +82,7 @@ class SipTransport {
         /**
          * This function returns a list of STUN mapped sockets for
          * a given set of socket file descriptors */
-        std::vector<pj_sockaddr> getSTUNAddresses(const SIPAccount &account, std::vector<long> &socks) const;
+        std::vector<pj_sockaddr> getSTUNAddresses(const SIPAccountBase &account, std::vector<long> &socks) const;
 
         /**
          * Get the correct address to use (ie advertised) from
@@ -122,7 +122,7 @@ class SipTransport {
          * @param the account that is creating the TLS transport
          */
         pjsip_transport *
-        createTlsTransport(SIPAccount &account);
+        createTlsTransport(SIPAccountBase &account);
 
         /**
          * Create The default TLS listener which is global to the application. This means that
@@ -132,7 +132,7 @@ class SipTransport {
          * @return a pointer to the new listener
          */
         pjsip_tpfactory *
-        createTlsListener(SIPAccount &account, pj_uint16_t family = pj_AF_UNSPEC());
+        createTlsListener(SIPAccountBase &account, pj_uint16_t family = pj_AF_UNSPEC());
 #endif
 
         /**
diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp
index bebe0ae1a4988f062524660240dd18eea8d48804..b5ba5624c20a57a3a95fb44fc30995adc61c1b07 100644
--- a/daemon/src/sip/sipvoiplink.cpp
+++ b/daemon/src/sip/sipvoiplink.cpp
@@ -40,6 +40,7 @@
 
 #include "sdp.h"
 #include "sipcall.h"
+#include "sipaccount.h"
 #include "sip_utils.h"
 
 #include "call_factory.h"
@@ -225,9 +226,12 @@ transaction_request_cb(pjsip_rx_data *rdata)
         return PJ_FALSE;
     }
     std::string toUsername(sip_to_uri->user.ptr, sip_to_uri->user.slen);
+    std::string toHost(sip_to_uri->host.ptr, sip_to_uri->host.slen);
     std::string viaHostname(sip_via.host.ptr, sip_via.host.slen);
+    const std::string remote_user(sip_from_uri->user.ptr, sip_from_uri->user.slen);
+    const std::string remote_hostname(sip_from_uri->host.ptr, sip_from_uri->host.slen);
 
-    auto sipaccount(getSIPVoIPLink()->guessAccountFromNameAndServer(toUsername, viaHostname));
+    auto sipaccount(getSIPVoIPLink()->guessAccount(toUsername, viaHostname, remote_hostname));
     if (!sipaccount) {
         ERROR("NULL account");
         return PJ_FALSE;
@@ -283,7 +287,7 @@ transaction_request_cb(pjsip_rx_data *rdata)
 
     Manager::instance().hookPreference.runHook(rdata->msg_info.msg);
 
-    auto call = sipaccount->newIncomingCall<SIPCall>(Manager::instance().getNewCallID());
+    auto call = sipaccount->newIncomingCall(Manager::instance().getNewCallID());
 
     // FIXME : for now, use the same address family as the SIP tranport
     auto family = pjsip_transport_type_get_af(sipaccount->getTransportType());
@@ -300,9 +304,6 @@ transaction_request_cb(pjsip_rx_data *rdata)
     std::string peerNumber(tmp, std::min(length, sizeof tmp));
     sip_utils::stripSipUriPrefix(peerNumber);
 
-    const std::string remote_user(sip_from_uri->user.ptr, sip_from_uri->user.slen);
-    const std::string remote_hostname(sip_from_uri->host.ptr, sip_from_uri->host.slen);
-
     if (not remote_user.empty() and not remote_hostname.empty())
         peerNumber = remote_user + "@" + remote_hostname;
 
@@ -616,14 +617,15 @@ SIPVoIPLink::~SIPVoIPLink()
     pj_shutdown();
 }
 
-std::shared_ptr<SIPAccount>
-SIPVoIPLink::guessAccountFromNameAndServer(const std::string &userName,
-                                           const std::string &server) const
+std::shared_ptr<SIPAccountBase>
+SIPVoIPLink::guessAccount(const std::string& userName,
+                           const std::string& server,
+                           const std::string& fromUri) const
 {
-    DEBUG("username = %s, server = %s", userName.c_str(), server.c_str());
+    DEBUG("username = %s, server = %s, from = %s", userName.c_str(), server.c_str(), fromUri.c_str());
     // Try to find the account id from username and server name by full match
 
-    auto result = std::static_pointer_cast<SIPAccount>(Manager::instance().getIP2IPAccount()); // default result
+    auto result = std::static_pointer_cast<SIPAccountBase>(Manager::instance().getIP2IPAccount()); // default result
     MatchRank best = MatchRank::NONE;
 
     for (const auto& sipaccount : Manager::instance().getAllAccounts<SIPAccount>()) {
@@ -634,7 +636,7 @@ SIPVoIPLink::guessAccountFromNameAndServer(const std::string &userName,
 
         // return right away if this is a full match
         if (match == MatchRank::FULL) {
-            return sipaccount;
+            return std::static_pointer_cast<SIPAccountBase>(sipaccount);
         } else if (match > best) {
             best = match;
             result = sipaccount;
diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h
index 6c259648dd35db1155914060bac4cf43d969b329..209cdf3b543231e9c1c0fe4ac6a0a97e7c11f1c1 100644
--- a/daemon/src/sip/sipvoiplink.h
+++ b/daemon/src/sip/sipvoiplink.h
@@ -42,7 +42,6 @@
 #endif
 
 #include "sfl_types.h"
-#include "sipaccount.h"
 #include "siptransport.h"
 
 #include <pjsip.h>
@@ -60,7 +59,8 @@
 #include <memory>
 
 class SIPCall;
-class SIPAccount;
+class SIPAccountBase;
+class SIPVoIPLink;
 
 typedef std::map<std::string, std::shared_ptr<SIPCall> > SipCallMap;
 
@@ -107,13 +107,6 @@ class SIPVoIPLink {
          */
         void cancelKeepAliveTimer(pj_timer_entry& timer);
 
-        /**
-         * Start a new SIP call using the IP2IP profile
-         * @param The call id
-         * @param The target sip uri
-         */
-        std::shared_ptr<Call> SIPNewIpToIpCall(const std::string& id, const std::string& to);
-
         /**
          * Get the memory pool factory since each calls has its own memory pool
          */
@@ -139,9 +132,14 @@ class SIPVoIPLink {
         static void enqueueKeyframeRequest(const std::string &callID);
 #endif
 
-        std::shared_ptr<SIPAccount>
-        guessAccountFromNameAndServer(const std::string &userName,
-                                      const std::string &server) const;
+        /**
+         * Guess the account related to an incoming SIP call.
+         */
+        std::shared_ptr<SIPAccountBase>
+        guessAccount(const std::string& userName,
+                     const std::string& server,
+                     const std::string& fromUri) const;
+
         int getModId();
         pjsip_endpoint * getEndpoint();
         pjsip_module * getMod();