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