From 03584a1735e49317099346033eefb923de2bebdc Mon Sep 17 00:00:00 2001
From: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
Date: Tue, 22 Sep 2009 16:37:45 -0400
Subject: [PATCH] [#2174] Create a default UDP transport + use tp selector for
 dialogs also

---
 sflphone-common/src/sip/sipaccount.cpp  | 374 ++++++++++++------------
 sflphone-common/src/sip/sipaccount.h    |  14 +
 sflphone-common/src/sip/sipvoiplink.cpp | 120 +++++++-
 3 files changed, 308 insertions(+), 200 deletions(-)

diff --git a/sflphone-common/src/sip/sipaccount.cpp b/sflphone-common/src/sip/sipaccount.cpp
index 8a3d6c747d..a0dcc76227 100644
--- a/sflphone-common/src/sip/sipaccount.cpp
+++ b/sflphone-common/src/sip/sipaccount.cpp
@@ -1,23 +1,23 @@
 /*
- *  Copyright (C) 2006-2009 Savoir-Faire Linux inc.
- *
- *  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
- *  Author: Pierre-Luc Bacon <pierre-luc.bacon@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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
+*  Copyright (C) 2006-2009 Savoir-Faire Linux inc.
+*
+*  Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
+*  Author: Pierre-Luc Bacon <pierre-luc.bacon@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., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
 
 #include "sipaccount.h"
 #include "manager.h"
@@ -25,240 +25,242 @@
 #include <pwd.h>
 
 SIPAccount::SIPAccount (const AccountID& accountID)
-        : Account (accountID, "sip")
-        , _regc (NULL)
-        , _bRegister (false)
-        , _registrationExpire ("")
-        , _localIpAddress ("")
-        , _publishedIpAddress ("")
-        , _localPort (atoi (DEFAULT_SIP_PORT))
-        , _publishedPort (atoi (DEFAULT_SIP_PORT))
-        , _transportType (PJSIP_TRANSPORT_UNSPECIFIED)
-        , _resolveOnce (false)
-        , _credentialCount (0)
-        , _cred (NULL)
-        , _realm (DEFAULT_REALM)
-        , _authenticationUsername ("")
-        , _tlsSetting (NULL)
-        , _displayName ("")
+	: Account (accountID, "sip")
+	, _regc (NULL)
+	, _bRegister (false)
+	, _registrationExpire ("")
+	, _localIpAddress ("")
+	, _publishedIpAddress ("")
+	, _actualSessionAddress ("")
+	, _localPort (atoi (DEFAULT_SIP_PORT))
+	, _publishedPort (atoi (DEFAULT_SIP_PORT))
+	, _actualSessionPort (atoi (DEFAULT_SIP_PORT))
+	, _transportType (PJSIP_TRANSPORT_UNSPECIFIED)
+	, _resolveOnce (false)
+	, _credentialCount (0)
+	, _cred (NULL)
+	, _realm (DEFAULT_REALM)
+	, _authenticationUsername ("")
+	, _tlsSetting (NULL)
+	, _displayName ("")
 {
-    /* SIPVoIPlink is used as a singleton, because we want to have only one link for all the SIP accounts created */
-    /* So instead of creating a new instance, we just fetch the static instance, or create one if it is not yet */
-    /* The SIP library initialization is done in the SIPVoIPLink constructor */
-    /* The SIP voip link is now independant of the account ID as it can manage several SIP accounts */
-    _link = SIPVoIPLink::instance ("");
+/* SIPVoIPlink is used as a singleton, because we want to have only one link for all the SIP accounts created */
+/* So instead of creating a new instance, we just fetch the static instance, or create one if it is not yet */
+/* The SIP library initialization is done in the SIPVoIPLink constructor */
+/* The SIP voip link is now independant of the account ID as it can manage several SIP accounts */
+_link = SIPVoIPLink::instance ("");
 
-    /* Represents the number of SIP accounts connected the same link */
-    dynamic_cast<SIPVoIPLink*> (_link)->incrementClients();
+/* Represents the number of SIP accounts connected the same link */
+dynamic_cast<SIPVoIPLink*> (_link)->incrementClients();
 
 }
 
 SIPAccount::~SIPAccount()
 {
-    /* One SIP account less connected to the sip voiplink */
-    dynamic_cast<SIPVoIPLink*> (_link)->decrementClients();
-    /* Delete accounts-related information */
-    _regc = NULL;
-    free (_cred);
-    free (_tlsSetting);
+/* One SIP account less connected to the sip voiplink */
+dynamic_cast<SIPVoIPLink*> (_link)->decrementClients();
+/* Delete accounts-related information */
+_regc = NULL;
+free (_cred);
+free (_tlsSetting);
 }
 
 int SIPAccount::initCredential (void)
 {
-    int credentialCount = 0;
-    credentialCount = Manager::instance().getConfigInt (_accountID, CONFIG_CREDENTIAL_NUMBER);
-    credentialCount += 1;
+int credentialCount = 0;
+credentialCount = Manager::instance().getConfigInt (_accountID, CONFIG_CREDENTIAL_NUMBER);
+credentialCount += 1;
 
-    bool md5HashingEnabled = false;
-    int dataType = 0;
-    md5HashingEnabled = Manager::instance().getConfigBool (PREFERENCES, CONFIG_MD5HASH);
-    std::string digest;
+bool md5HashingEnabled = false;
+int dataType = 0;
+md5HashingEnabled = Manager::instance().getConfigBool (PREFERENCES, CONFIG_MD5HASH);
+std::string digest;
 
-    // Create the credential array
-    pjsip_cred_info * cred_info = (pjsip_cred_info *) malloc (sizeof (pjsip_cred_info) * (credentialCount));
+// Create the credential array
+pjsip_cred_info * cred_info = (pjsip_cred_info *) malloc (sizeof (pjsip_cred_info) * (credentialCount));
 
-    if (cred_info == NULL) {
-        _debug ("Failed to set cred_info for account %s\n", _accountID.c_str());
-        return !SUCCESS;
-    }
+if (cred_info == NULL) {
+	_debug ("Failed to set cred_info for account %s\n", _accountID.c_str());
+	return !SUCCESS;
+}
 
-    pj_bzero (cred_info, sizeof (pjsip_cred_info) *credentialCount);
+pj_bzero (cred_info, sizeof (pjsip_cred_info) *credentialCount);
 
-    // Use authentication username if provided
+// Use authentication username if provided
 
-    if (!_authenticationUsername.empty()) {
-        cred_info[0].username = pj_str (strdup (_authenticationUsername.c_str()));
-    } else {
-        cred_info[0].username = pj_str (strdup (_username.c_str()));
-    }
+if (!_authenticationUsername.empty()) {
+	cred_info[0].username = pj_str (strdup (_authenticationUsername.c_str()));
+} else {
+	cred_info[0].username = pj_str (strdup (_username.c_str()));
+}
 
-    // Set password
-    cred_info[0].data =  pj_str (strdup (_password.c_str()));
+// Set password
+cred_info[0].data =  pj_str (strdup (_password.c_str()));
 
-    // Set realm for that credential. * by default.
-    cred_info[0].realm = pj_str (strdup (_realm.c_str()));
+// Set realm for that credential. * by default.
+cred_info[0].realm = pj_str (strdup (_realm.c_str()));
 
-    // We want to make sure that the password is really
-    // 32 characters long. Otherwise, pjsip will fail
-    // on an assertion.
-    if (md5HashingEnabled && _password.length() == 32) {
-        dataType = PJSIP_CRED_DATA_DIGEST;
-        _debug ("Setting digest \n");
-    } else {
-        dataType = PJSIP_CRED_DATA_PLAIN_PASSWD;
-    }
+// We want to make sure that the password is really
+// 32 characters long. Otherwise, pjsip will fail
+// on an assertion.
+if (md5HashingEnabled && _password.length() == 32) {
+	dataType = PJSIP_CRED_DATA_DIGEST;
+	_debug ("Setting digest \n");
+} else {
+	dataType = PJSIP_CRED_DATA_PLAIN_PASSWD;
+}
 
-    // Set the datatype
-    cred_info[0].data_type = dataType;
+// Set the datatype
+cred_info[0].data_type = dataType;
 
-    // Set the secheme
-    cred_info[0].scheme = pj_str ( (char*)"digest");
+// Set the secheme
+cred_info[0].scheme = pj_str ( (char*)"digest");
 
-    int i;
+int i;
 
-    for (i = 1; i < credentialCount; i++) {
-        std::string credentialIndex;
-        std::stringstream streamOut;
-        streamOut << i - 1;
-        credentialIndex = streamOut.str();
+for (i = 1; i < credentialCount; i++) {
+	std::string credentialIndex;
+	std::stringstream streamOut;
+	streamOut << i - 1;
+	credentialIndex = streamOut.str();
 
-        std::string section = std::string ("Credential") + std::string (":") + _accountID + std::string (":") + credentialIndex;
+	std::string section = std::string ("Credential") + std::string (":") + _accountID + std::string (":") + credentialIndex;
 
-        std::string username = Manager::instance().getConfigString (section, USERNAME);
-        std::string password = Manager::instance().getConfigString (section, PASSWORD);
-        std::string realm = Manager::instance().getConfigString (section, REALM);
+	std::string username = Manager::instance().getConfigString (section, USERNAME);
+	std::string password = Manager::instance().getConfigString (section, PASSWORD);
+	std::string realm = Manager::instance().getConfigString (section, REALM);
 
-        cred_info[i].username = pj_str (strdup (username.c_str()));
-        cred_info[i].data = pj_str (strdup (password.c_str()));
-        cred_info[i].realm = pj_str (strdup (realm.c_str()));
+	cred_info[i].username = pj_str (strdup (username.c_str()));
+	cred_info[i].data = pj_str (strdup (password.c_str()));
+	cred_info[i].realm = pj_str (strdup (realm.c_str()));
 
-        // We want to make sure that the password is really
-        // 32 characters long. Otherwise, pjsip will fail
-        // on an assertion.
+	// We want to make sure that the password is really
+	// 32 characters long. Otherwise, pjsip will fail
+	// on an assertion.
 
-        if (md5HashingEnabled && _password.length() == 32) {
-            dataType = PJSIP_CRED_DATA_DIGEST;
-            _debug ("Setting digest \n");
-        } else {
-            dataType = PJSIP_CRED_DATA_PLAIN_PASSWD;
-        }
+	if (md5HashingEnabled && _password.length() == 32) {
+		dataType = PJSIP_CRED_DATA_DIGEST;
+		_debug ("Setting digest \n");
+	} else {
+		dataType = PJSIP_CRED_DATA_PLAIN_PASSWD;
+	}
 
-        cred_info[i].data_type = dataType;
+	cred_info[i].data_type = dataType;
 
-        cred_info[i].scheme = pj_str ( (char*)"digest");
+	cred_info[i].scheme = pj_str ( (char*)"digest");
 
-        _debug ("Setting credential %d realm = %s passwd = %s username = %s data_type = %d\n", i, realm.c_str(), password.c_str(), username.c_str(), cred_info[i].data_type);
-    }
+	_debug ("Setting credential %d realm = %s passwd = %s username = %s data_type = %d\n", i, realm.c_str(), password.c_str(), username.c_str(), cred_info[i].data_type);
+}
 
-    _credentialCount = credentialCount;
+_credentialCount = credentialCount;
 
-    _cred = cred_info;
+_cred = cred_info;
 
-    return SUCCESS;
+return SUCCESS;
 }
 
 
 int SIPAccount::registerVoIPLink()
 {
-    // Init general settings
-    loadConfig();
+// Init general settings
+loadConfig();
 
-    if (_hostname.length() >= PJ_MAX_HOSTNAME) {
-        return !SUCCESS;
-    }
+if (_hostname.length() >= PJ_MAX_HOSTNAME) {
+	return !SUCCESS;
+}
 
-    // Init set of additional credentials, if supplied by the user
-    initCredential();
+// Init set of additional credentials, if supplied by the user
+initCredential();
 
-    // Init TLS settings if the user wants to use TLS
-    bool tlsEnabled = Manager::instance().getConfigBool (_accountID, TLS_ENABLE);
+// Init TLS settings if the user wants to use TLS
+bool tlsEnabled = Manager::instance().getConfigBool (_accountID, TLS_ENABLE);
 
-    if (tlsEnabled) {
-        _transportType = PJSIP_TRANSPORT_TLS;
-        initTlsConfiguration();
-    }
+if (tlsEnabled) {
+	_transportType = PJSIP_TRANSPORT_TLS;
+	initTlsConfiguration();
+}
 
-    // Init STUN settings for this account if the user selected it
-    bool stunEnabled = Manager::instance().getConfigBool (_accountID, STUN_ENABLE);
+// Init STUN settings for this account if the user selected it
+bool stunEnabled = Manager::instance().getConfigBool (_accountID, STUN_ENABLE);
 
-    if (stunEnabled) {
-        _transportType = PJSIP_TRANSPORT_START_OTHER;
-		initStunConfiguration ();
-    }
+if (stunEnabled) {
+	_transportType = PJSIP_TRANSPORT_START_OTHER;
+	initStunConfiguration ();
+}
 
-    // In our definition of the
-    // ip2ip profile (aka Direct IP Calls),
-    // no registration should be performed
-    if (_accountID != IP2IP_PROFILE) {
-        int status = _link->sendRegister (_accountID);
-        ASSERT (status , SUCCESS);
-    }
+// In our definition of the
+// ip2ip profile (aka Direct IP Calls),
+// no registration should be performed
+if (_accountID != IP2IP_PROFILE) {
+	int status = _link->sendRegister (_accountID);
+	ASSERT (status , SUCCESS);
+}
 
-    return SUCCESS;
+return SUCCESS;
 }
 
 int SIPAccount::unregisterVoIPLink()
 {
-    _debug ("unregister account %s\n" , getAccountID().c_str());
+_debug ("unregister account %s\n" , getAccountID().c_str());
 
-    if (_accountID == IP2IP_PROFILE) {
-        return true;
-    }
+if (_accountID == IP2IP_PROFILE) {
+	return true;
+}
 
-    if (_link->sendUnregister (_accountID)) {
-        setRegistrationInfo (NULL);
-        return true;
-    } else
-        return false;
+if (_link->sendUnregister (_accountID)) {
+	setRegistrationInfo (NULL);
+	return true;
+} else
+	return false;
 
 }
 
 pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum (const std::string& method)
 {
-    if (method == "Default") {
-        return PJSIP_SSL_UNSPECIFIED_METHOD;
-    }
+if (method == "Default") {
+	return PJSIP_SSL_UNSPECIFIED_METHOD;
+}
 
-    if (method == "TLSv1") {
-        return PJSIP_TLSV1_METHOD;
-    }
+if (method == "TLSv1") {
+	return PJSIP_TLSV1_METHOD;
+}
 
-    if (method == "SSLv2") {
-        return PJSIP_SSLV2_METHOD;
-    }
+if (method == "SSLv2") {
+	return PJSIP_SSLV2_METHOD;
+}
 
-    if (method == "SSLv3") {
-        return PJSIP_SSLV3_METHOD;
-    }
+if (method == "SSLv3") {
+	return PJSIP_SSLV3_METHOD;
+}
 
-    if (method == "SSLv23") {
-        return PJSIP_SSLV23_METHOD;
-    }
+if (method == "SSLv23") {
+	return PJSIP_SSLV23_METHOD;
+}
 
-    return PJSIP_SSL_UNSPECIFIED_METHOD;
+return PJSIP_SSL_UNSPECIFIED_METHOD;
 }
 
 void SIPAccount::initTlsConfiguration (void)
 {
-    /*
-     * Initialize structure to zero
-     */
-    _tlsSetting = (pjsip_tls_setting *) malloc (sizeof (pjsip_tls_setting));
-
-    assert (_tlsSetting);
-
-    pjsip_tls_setting_default (_tlsSetting);
-
-    std::string tlsCaListFile = Manager::instance().getConfigString (_accountID, TLS_CA_LIST_FILE);
-    std::string tlsCertificateFile = Manager::instance().getConfigString (_accountID, TLS_CERTIFICATE_FILE);
-    std::string tlsPrivateKeyFile = Manager::instance().getConfigString (_accountID, TLS_PRIVATE_KEY_FILE);
-    std::string tlsPassword = Manager::instance().getConfigString (_accountID, TLS_PASSWORD);
-    std::string tlsMethod = Manager::instance().getConfigString (_accountID, TLS_METHOD);
-    std::string tlsCiphers = Manager::instance().getConfigString (_accountID, TLS_CIPHERS);
-    std::string tlsServerName = Manager::instance().getConfigString (_accountID, TLS_SERVER_NAME);
-    bool tlsVerifyServer = Manager::instance().getConfigBool (_accountID, TLS_VERIFY_SERVER);
-    bool tlsVerifyClient = Manager::instance().getConfigBool (_accountID, TLS_VERIFY_CLIENT);
-    bool tlsRequireClientCertificate = Manager::instance().getConfigBool (_accountID, TLS_REQUIRE_CLIENT_CERTIFICATE);
+/*
+	* Initialize structure to zero
+	*/
+_tlsSetting = (pjsip_tls_setting *) malloc (sizeof (pjsip_tls_setting));
+
+assert (_tlsSetting);
+
+pjsip_tls_setting_default (_tlsSetting);
+
+std::string tlsCaListFile = Manager::instance().getConfigString (_accountID, TLS_CA_LIST_FILE);
+std::string tlsCertificateFile = Manager::instance().getConfigString (_accountID, TLS_CERTIFICATE_FILE);
+std::string tlsPrivateKeyFile = Manager::instance().getConfigString (_accountID, TLS_PRIVATE_KEY_FILE);
+std::string tlsPassword = Manager::instance().getConfigString (_accountID, TLS_PASSWORD);
+std::string tlsMethod = Manager::instance().getConfigString (_accountID, TLS_METHOD);
+std::string tlsCiphers = Manager::instance().getConfigString (_accountID, TLS_CIPHERS);
+std::string tlsServerName = Manager::instance().getConfigString (_accountID, TLS_SERVER_NAME);
+bool tlsVerifyServer = Manager::instance().getConfigBool (_accountID, TLS_VERIFY_SERVER);
+bool tlsVerifyClient = Manager::instance().getConfigBool (_accountID, TLS_VERIFY_CLIENT);
+bool tlsRequireClientCertificate = Manager::instance().getConfigBool (_accountID, TLS_REQUIRE_CLIENT_CERTIFICATE);
     std::string tlsNegotiationTimeoutSec = Manager::instance().getConfigString (_accountID, TLS_NEGOTIATION_TIMEOUT_SEC);
     std::string tlsNegotiationTimeoutMsec = Manager::instance().getConfigString (_accountID, TLS_NEGOTIATION_TIMEOUT_MSEC);
 
@@ -326,10 +328,12 @@ void SIPAccount::loadConfig()
     std::string publishedPort = Manager::instance().getConfigString (_accountID, PUBLISHED_PORT);
 
     _localPort = atoi (localPort.c_str());
+    _actualSessionPort = _localPort;
 
     _publishedPort = atoi (publishedPort.c_str());
 
     _localIpAddress = Manager::instance().getConfigString (_accountID, LOCAL_ADDRESS);
+	_actualSessionAddress = _localIpAddress;
 
     _publishedIpAddress = Manager::instance().getConfigString (_accountID, PUBLISHED_ADDRESS);
 
diff --git a/sflphone-common/src/sip/sipaccount.h b/sflphone-common/src/sip/sipaccount.h
index f1138c0e50..873647b2d5 100644
--- a/sflphone-common/src/sip/sipaccount.h
+++ b/sflphone-common/src/sip/sipaccount.h
@@ -253,6 +253,15 @@ class SIPAccount : public Account
 
 		inline void setAccountTransport (pjsip_transport *transport) { _transport = transport; }
 
+		inline std::string getSessionAddress () { return _actualSessionAddress; }
+
+		inline void setSessionAddress (std::string addr) { _actualSessionAddress = addr; }
+		
+		inline pj_uint16_t getSessionPort () { return _actualSessionPort; }
+
+		inline void setSessionPort (pj_uint16_t port) { _actualSessionPort = port; }
+
+
     private: 
 
         /* Maps a string description of the SSL method 
@@ -336,6 +345,11 @@ class SIPAccount : public Account
         
         // Display Name that can be used in  SIP URI.        
         std::string _displayName;        
+
+		// The actual address we use in the SDP to be contacted
+		// it needs to be per account, otherwise the same address is used for every account
+		std::string _actualSessionAddress;
+		pj_uint16_t _actualSessionPort;
 };
 
 #endif
diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp
index 034848956d..535ff631d9 100644
--- a/sflphone-common/src/sip/sipvoiplink.cpp
+++ b/sflphone-common/src/sip/sipvoiplink.cpp
@@ -71,7 +71,7 @@ struct result {
     pjsip_server_addresses  servers;
 };
 
-std::map<AccountID, pjsip_transport *> udp_transports;
+pjsip_transport *_localUDPTransport;
 
 const pj_str_t STR_USER_AGENT = { (char*) "User-Agent", 10 };
 
@@ -99,6 +99,9 @@ void handle_incoming_options (pjsip_rx_data *rxdata);
 
 std::string fetch_header_value (pjsip_msg *msg, std::string field);
 
+std::string getLocalAddressAssociatedToAccount (AccountID id);
+
+
 /*
  *  The global pool factory
  */
@@ -465,7 +468,8 @@ int SIPVoIPLink::sendRegister (AccountID id)
 	{
 		status = createUDPServer (id);
 		if (status != PJ_SUCCESS) {
-			_debug ("Failed to initialize UDP transport with a local address for account %s\n", id.c_str());
+			_debug ("Failed to initialize UDP transport with a local address for account %s\n. Try to use the local UDT transport", id.c_str());
+			account->setAccountTransport (_localUDPTransport);
 		}
 	}
 
@@ -653,6 +657,7 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
 {
     SIPAccount * account = NULL;
     pj_status_t status;
+	std::string localAddr;
 
     SIPCall* call = new SIPCall (id, Call::Outgoing, _pool);
 
@@ -672,7 +677,8 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
 
         call->setPeerNumber (toUri);
 
-        setCallAudioLocal (call, getLocalIPAddress());
+		localAddr = account->getSessionAddress ();
+        setCallAudioLocal (call, localAddr);
 
         try {
             _debug ("Creating new rtp session in newOutgoingCall\n");
@@ -685,7 +691,8 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl)
 
         _debug ("Try to make a call to: %s with call ID: %s\n", toUrl.data(), id.data());
         // Building the local SDP offer
-        call->getLocalSDP()->set_ip_address (getLocalIP());
+		// localAddr = getLocalAddressAssociatedToAccount (account->getAccountID());
+        call->getLocalSDP()->set_ip_address (localAddr);
         status = call->getLocalSDP()->create_initial_offer();
 
         if (status != PJ_SUCCESS) {
@@ -1237,6 +1244,7 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED)
     pjsip_inv_session *inv;
     pjsip_dialog *dialog;
     pjsip_tx_data *tdata;
+	pjsip_transport *transport;
 
     AccountID id;
 
@@ -1327,6 +1335,11 @@ SIPVoIPLink::SIPStartCall (SIPCall* call, const std::string& subject UNUSED)
     // Associate current invite session in the call
     call->setInvSession (inv);
 
+	// Set the appropriate transport
+	pjsip_tpselector *tp;
+	init_transport_selector (account->getAccountTransport (), &tp);
+	status = pjsip_dlg_set_transport (dialog, tp);
+
     status = pjsip_inv_send_msg (inv, tdata);
 
     if (status != PJ_SUCCESS) {
@@ -1702,12 +1715,12 @@ bool SIPVoIPLink::pjsip_init()
     _localExternPort = _localPort;
     // Create a UDP listener meant for all accounts
     // for which TLS was not enabled
-    //errPjsip = createUDPServer();
+    errPjsip = createUDPServer();
 
     // If the above UDP server
     // could not be created, then give it another try
     // on a random sip port
-    /*if (errPjsip != PJ_SUCCESS) {
+    if (errPjsip != PJ_SUCCESS) {
         _debug ("UserAgent: Could not initialize SIP listener on port %d\n", _localExternPort);
         _localExternPort = _localPort = RANDOM_SIP_PORT;
 
@@ -1718,7 +1731,7 @@ bool SIPVoIPLink::pjsip_init()
             _debug ("UserAgent: Fail to initialize SIP listener on port %d\n", _localExternPort);
             return errPjsip;
         }
-    }*/
+    }
 
     _debug ("UserAgent: SIP Init -- listening on port %d\n", _localExternPort);
 
@@ -1894,11 +1907,20 @@ int SIPVoIPLink::createUDPServer (AccountID id)
 	SIPAccount * account = NULL;
 	account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
 
+	// Set information to the local address and port
 	if (account == NULL) {
-		_debug ("Account is null. Returning");
-		return !PJ_SUCCESS;
+		// We are trying to initialize a UDP transport available for all local accounts and direct IP calls
+		_debug ("Account is null.");
+		_localExternAddress = _localIPAddress;
+		_localExternPort = _localPort;
+	}
+	else
+	{
+		_localExternAddress = account->getSessionAddress ();
+		_localExternPort = account->getSessionPort ();
 	}
 
+
     // Init bound address to ANY
     pj_memset (&bound_addr, 0, sizeof (bound_addr));
 
@@ -1916,14 +1938,19 @@ int SIPVoIPLink::createUDPServer (AccountID id)
 
     if (status != PJ_SUCCESS) {
         _debug ("UserAgent: (%d) Unable to start UDP transport!\n", status);
-        return -1;
+		// Try to acquire an existing one
+		// pjsip_tpmgr_acquire_transport ()
+        return status;
     } else {
         _debug ("UserAgent: UDP server listening on port %d\n", _localExternPort);
+		if (account == NULL) 
+			_localUDPTransport = transport;
+		else
+			account->setAccountTransport (transport);
     }
 
     _debug ("Transport initialized successfully! \n");
 	
-	account->setAccountTransport (transport);
 
     return PJ_SUCCESS;
 }
@@ -1945,10 +1972,15 @@ std::string SIPVoIPLink::findLocalAddressFromUri (const std::string& uri, pjsip_
     std::string machineName (pjMachineName.ptr, pjMachineName.slen);
 
     if (genericUri == NULL) {
-        _debug ("genericUri is NULL in findLocalPortFromUri\n");
+        _debug ("genericUri is NULL in findLocalAddressFromUri\n");
         return machineName;
     }
 
+	if (transport == NULL) {
+        _debug ("transport is NULL in findLocalAddressFromUri\n. Try the local UDP transport");
+        transport = _localUDPTransport;
+    }
+
     pjsip_sip_uri * sip_uri = NULL;
 
     sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri (genericUri);
@@ -1982,7 +2014,7 @@ std::string SIPVoIPLink::findLocalAddressFromUri (const std::string& uri, pjsip_
     pj_status_t status;
 
 	/* Init the transport selector */
-	_debug ("Transport ID: %s\n", transport->obj_name);
+	//_debug ("Transport ID: %s\n", transport->obj_name);
 	status = init_transport_selector (transport, &tp_sel);
 
 	if (status == PJ_SUCCESS)
@@ -2034,6 +2066,11 @@ int SIPVoIPLink::findLocalPortFromUri (const std::string& uri, pjsip_transport *
         return atoi (DEFAULT_SIP_PORT);
     }
 
+	if (transport == NULL) {
+        _debug ("transport is NULL in findLocalPortFromUri - Try the local UDP transport\n");
+		transport = _localUDPTransport;
+	}
+
     pjsip_sip_uri * sip_uri = NULL;
 
     sip_uri = (pjsip_sip_uri*) pjsip_uri_get_uri (genericUri);
@@ -2189,6 +2226,11 @@ pj_status_t SIPVoIPLink::createAlternateUdpTransport (AccountID id)
 
 	_localExternAddress = std::string (a_name.host.ptr);
 	_localExternPort =  (int)a_name.port;
+
+	// Set the address to be used in SDP
+	account->setSessionAddress (_localExternAddress);
+	account->setSessionPort (_localExternPort);
+
 	//account->setStunServerName (a_name.host);
 	//account->setStunPort (a_name.port);
 
@@ -2776,6 +2818,7 @@ mod_on_rx_request (pjsip_rx_data *rdata)
     CallID id;
     SIPCall* call;
     pjsip_inv_session *inv;
+	SIPAccount *account;
     pjmedia_sdp_session *r_sdp;
 
     // voicemail part
@@ -2908,12 +2951,21 @@ mod_on_rx_request (pjsip_rx_data *rdata)
         return false;
     }
 
+	std::string addrToUse;
+	account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (account_id));
+
+	if (account != NULL) {
+		addrToUse = account->getSessionAddress ();
+	}
+	else
+		addrToUse = link->getLocalIPAddress();
+
     // Have to do some stuff with the SDP
     // Set the codec map, IP, peer number and so on... for the SIPCall object
-    setCallAudioLocal (call, link->getLocalIPAddress());
+    setCallAudioLocal (call, addrToUse);
 
     // We retrieve the remote sdp offer in the rdata struct to begin the negociation
-    call->getLocalSDP()->set_ip_address (link->getLocalIPAddress());
+    call->getLocalSDP()->set_ip_address (addrToUse);
 
     get_remote_sdp_from_offer (rdata, &r_sdp);
 
@@ -3603,3 +3655,41 @@ pj_bool_t stun_sock_on_rx_data (pj_stun_sock *stun_sock, void *pkt, unsigned pkt
 {
 	return PJ_TRUE;
 }
+
+
+std::string getLocalAddressAssociatedToAccount (AccountID id)
+{
+	SIPAccount *account = NULL;
+	pj_sockaddr_in local_addr_ipv4;
+	pjsip_transport *tspt;
+	std::string localAddr;
+	pj_str_t tmp;
+	
+	account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id));
+
+	// Set the local address
+	if (account != NULL) {
+		tspt = account->getAccountTransport ();
+		if (tspt != NULL) {
+			local_addr_ipv4 = tspt->local_addr.ipv4;
+		}
+		else {
+			_debug ("In getLocalAddressAssociatedToAccount: transport is null");
+			local_addr_ipv4 = _localUDPTransport->local_addr.ipv4;
+		}
+	}
+	else {
+			_debug ("In getLocalAddressAssociatedToAccount: account is null");
+			local_addr_ipv4 = _localUDPTransport->local_addr.ipv4;
+	}
+
+	_debug ("slbvasjklbvaskbvaskvbaskvaskvbsdfk: %i\n", local_addr_ipv4.sin_addr.s_addr);
+
+	tmp = pj_str (pj_inet_ntoa (local_addr_ipv4.sin_addr));
+	localAddr = std::string (tmp.ptr);
+
+	_debug ("slbvasjklbvaskbvaskvbaskvaskvbsdfk: %s\n", localAddr.c_str());
+
+	return localAddr;
+
+}
-- 
GitLab