diff --git a/sflphone-common/src/sip/sipaccount.cpp b/sflphone-common/src/sip/sipaccount.cpp index 8a3d6c747d89e7cd6597bc6fd04939048f8677dc..a0dcc762272df3e588e33a84ad92b2c31cf52d39 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 f1138c0e5001951caa2d2eab709b73ca1511fe4f..873647b2d5aacb8acafb9c5ab05bd616917a5d0e 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 27b346a3fe22f6814632756a86b70754c4e42351..c0b78de189ebe989ed35280c7825a2429a7b1e9a 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 */ @@ -463,13 +466,13 @@ int SIPVoIPLink::sendRegister (AccountID id) if (status != PJ_SUCCESS) { _debug ("Failed to initialize UDP transport with an extern published address for account %s\n", id.c_str()); } - } - else - { - _debug(" sendRegister: createUDPServer\n"); - status = createUDPServer (id); - if (status != PJ_SUCCESS) { - _debug ("Failed to initialize UDP transport with a local address for account %s\n", id.c_str()); + else + { + status = createUDPServer (id); + if (status != PJ_SUCCESS) { + _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); + } } } @@ -660,6 +663,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); @@ -679,7 +683,8 @@ SIPVoIPLink::newOutgoingCall (const CallID& id, const std::string& toUrl) call->setPeerNumber (toUri); - setCallAudioLocal (call, getLocalIPAddress()); + localAddr = account->getSessionAddress (); + setCallAudioLocal (call, call->getLocalIp()); try { _debug ("Creating new rtp session in newOutgoingCall\n"); @@ -692,7 +697,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) { @@ -1223,6 +1229,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; @@ -1313,6 +1320,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) { @@ -1444,7 +1456,7 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) call->setPeerNumber (toUri); _debug ("toUri in new_ip_to_ip call %s\n", toUri.c_str()); // Building the local SDP offer - call->getLocalSDP()->set_ip_address (getLocalIP()); + call->getLocalSDP()->set_ip_address (getLocalIPAddress ()); call->getLocalSDP()->create_initial_offer(); try { @@ -1460,9 +1472,9 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) fromUri = account->getFromUri(); - std::string address = findLocalAddressFromUri (toUri, account->getAccountTransport ()); + std::string address = findLocalAddressFromUri (toUri, _localUDPTransport); - int port = findLocalPortFromUri (toUri, account->getAccountTransport ()); + int port = findLocalPortFromUri (toUri, _localUDPTransport); std::stringstream ss; @@ -1502,6 +1514,16 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) PJ_ASSERT_RETURN (status == PJ_SUCCESS, false); + // Set the appropriate transport + pjsip_tpselector *tp; + init_transport_selector (_localUDPTransport, &tp); + status = pjsip_dlg_set_transport (dialog, tp); + + if (status != PJ_SUCCESS) { + _debug ("Failed to set the transport for an IP call\n"); + return status; + } + // Associate current call in the invite session inv->mod_data[getModId() ] = call; @@ -1689,12 +1711,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; @@ -1705,7 +1727,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); @@ -1878,24 +1900,27 @@ int SIPVoIPLink::createUDPServer (AccountID id) // pj_in_addr remote_addr; pj_sockaddr_in remote_addr; + /* * Retrieve the account information */ SIPAccount * account = NULL; account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (id)); - - if (account == NULL) { - _debug ("Account is null. Returning"); - return !PJ_SUCCESS; - } - _debug("Try to acquire transport for account host name: %s\n", (account->getHostname()).c_str()); - pj_str_t hostname = pj_str (const_cast<char*>((account->getHostname()).c_str())); + // Set information to the local address and port + if (account == NULL) { + // 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 (); + } - // pjsip_endpt_acquire_transport do not use the port number - pj_sockaddr_in_init(&remote_addr, &hostname, 0); - status = pjsip_endpt_acquire_transport(_endpt, PJSIP_TRANSPORT_UDP, &remote_addr, sizeof(remote_addr), NULL, &transport); if (status != PJ_SUCCESS) { @@ -1928,15 +1953,20 @@ int SIPVoIPLink::createUDPServer (AccountID id) pjsip_tpmgr_dump_transports(tpmgr); if (status != PJ_SUCCESS) { - _debug("UserAgent: (%d) Unable to start UDP transport!\n", status); - return -1; + _debug ("UserAgent: (%d) Unable to start UDP transport!\n", status); + // Try to acquire an existing one + // pjsip_tpmgr_acquire_transport () + return status; } else { - _debug("UserAgent: UDP server listening on port %d\n", _localExternPort); + _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; } @@ -1960,10 +1990,15 @@ std::string SIPVoIPLink::findLocalAddressFromUri(const std::string& uri, pjsip_t 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); @@ -1996,9 +2031,11 @@ std::string SIPVoIPLink::findLocalAddressFromUri(const std::string& uri, pjsip_t pj_status_t status; - /* Init the transport selector */ - _debug ("Transport ID: %s\n", transport->obj_name); - status = init_transport_selector (transport, &tp_sel); + + /* Init the transport selector */ + //_debug ("Transport ID: %s\n", transport->obj_name); + status = init_transport_selector (transport, &tp_sel); + if (status == PJ_SUCCESS) status = pjsip_tpmgr_find_local_addr (tpmgr, _pool, transportType, tp_sel, &localAddress, &port); @@ -2049,6 +2086,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); @@ -2204,6 +2246,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); @@ -2433,7 +2480,7 @@ void SIPVoIPLink::handle_reinvite (SIPCall *call) call->getAudioRtp()->stop (); call->setAudioStart (false); - _debug ("Create new rtp session from handle_reinvite \n"); + _debug ("Create new rtp session from handle_reinvite : %s:%i\n", call->getLocalIp().c_str(), call->getLocalAudioPort()); try { call->getAudioRtp()->initAudioRtpSession (call); @@ -2801,6 +2848,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 @@ -2933,12 +2981,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()); // 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); @@ -3627,3 +3684,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; + +}