From ed4694c0ba9fa72534e3d3421eeda14676923024 Mon Sep 17 00:00:00 2001 From: pierre-luc <pierre-luc.bacon@savoirfairelinux.com> Date: Thu, 20 Aug 2009 14:56:05 -0400 Subject: [PATCH] [#812] Deals with the published address/port problem when integrating TLS. Since STUN is not suitable for TCP transport, this information must be provided manually by the user. Otherwise, user must configure manual (static) traversal on her/his firewall. Not integrated yet under the UI. --- sflphone-common/src/account.h | 9 +- .../src/dbus/configurationmanager.cpp | 12 +- sflphone-common/src/managerimpl.cpp | 56 ++++-- sflphone-common/src/managerimpl.h | 2 +- sflphone-common/src/sip/sipaccount.cpp | 46 +++-- sflphone-common/src/sip/sipaccount.h | 178 ++++++++++++------ sflphone-common/src/sip/sipvoiplink.cpp | 135 ++++++++++--- sflphone-common/src/sip/sipvoiplink.h | 29 ++- 8 files changed, 339 insertions(+), 128 deletions(-) diff --git a/sflphone-common/src/account.h b/sflphone-common/src/account.h index d3c61eecc1..6a37fe0134 100644 --- a/sflphone-common/src/account.h +++ b/sflphone-common/src/account.h @@ -70,6 +70,14 @@ typedef enum RegistrationState { #define REALM "realm" #define DEFAULT_REALM "*" +#define LOCAL_PORT "Account.localPort" +#define LOCAL_ADDRESS "Account.localAddress" +#define PUBLISHED_PORT "Account.publishedPort" +#define PUBLISHED_ADDRESS "Account.publishedAddress" + +#define DISPLAY_NAME "Account.displayName" +#define DEFAULT_ADDRESS "0.0.0.0" + // SIP specific parameters #define SIP_PROXY "SIP.proxy" #define SIP_STUN_SERVER "STUN.server" @@ -86,7 +94,6 @@ typedef enum RegistrationState { #define ZRTP_DISPLAY_SAS_ONCE "ZRTP.displaySasOnce" #define TLS_ENABLE "TLS.enable" -#define TLS_PORT "TLS.port" #define TLS_CA_LIST_FILE "TLS.certificateListFile" #define TLS_CERTIFICATE_FILE "TLS.certificateFile" #define TLS_PRIVATE_KEY_FILE "TLS.privateKeyFile" diff --git a/sflphone-common/src/dbus/configurationmanager.cpp b/sflphone-common/src/dbus/configurationmanager.cpp index 5a3069cb62..1031105412 100644 --- a/sflphone-common/src/dbus/configurationmanager.cpp +++ b/sflphone-common/src/dbus/configurationmanager.cpp @@ -47,7 +47,6 @@ ConfigurationManager::getTlsSettingsDefault (void) _debug ("ConfigurationManager::getTlsDefaultSettings\n"); std::map<std::string, std::string> tlsSettingsDefault; - tlsSettingsDefault.insert(std::pair<std::string, std::string> (TLS_PORT, DEFAULT_SIP_TLS_PORT)); tlsSettingsDefault.insert(std::pair<std::string, std::string> (TLS_CA_LIST_FILE, "")); tlsSettingsDefault.insert(std::pair<std::string, std::string> (TLS_CERTIFICATE_FILE, "")); tlsSettingsDefault.insert(std::pair<std::string, std::string> (TLS_PRIVATE_KEY_FILE, "")); @@ -128,9 +127,7 @@ ConfigurationManager::getTlsSettings(const std::string& section) { std::map<std::string, std::string> tlsSettings; tlsSettings.insert(std::pair<std::string, std::string> - (TLS_ENABLE, Manager::instance().getConfigString(section, TLS_ENABLE))); - tlsSettings.insert(std::pair<std::string, std::string> - (TLS_PORT, Manager::instance().getConfigString(section, TLS_PORT))); + (TLS_ENABLE, Manager::instance().getConfigString(section, TLS_ENABLE))); tlsSettings.insert(std::pair<std::string, std::string> (TLS_CA_LIST_FILE, Manager::instance().getConfigString(section, TLS_CA_LIST_FILE))); tlsSettings.insert(std::pair<std::string, std::string> @@ -168,12 +165,7 @@ ConfigurationManager::setTlsSettings(const std::string& section, const std::map< if (it != details.end()) { Manager::instance().setConfig(section, TLS_ENABLE, it->second); } - - it = map_cpy.find(TLS_PORT); - if (it != details.end()) { - Manager::instance().setConfig(section, TLS_PORT, it->second); - } - + it = map_cpy.find(TLS_CA_LIST_FILE); if (it != details.end()) { Manager::instance().setConfig(section, TLS_CA_LIST_FILE, it->second); diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index a70fc654d4..215f96ae7b 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -47,7 +47,7 @@ #include <sstream> #include <sys/types.h> // mkdir(2) #include <sys/stat.h> // mkdir(2) - +#include <pwd.h> // getpwuid #define fill_config_str(name, value) \ (_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_str))) @@ -1260,7 +1260,7 @@ ManagerImpl::getStunInfo (StunAddress4& stunSvrAddr, int port) } bool -ManagerImpl::behindNat (const std::string& svr, int port) +ManagerImpl::isBehindNat (const std::string& svr, int port) { StunAddress4 stunSvrAddr; stunSvrAddr.addr = 0; @@ -1341,7 +1341,6 @@ ManagerImpl::initConfigFile (bool load_user_value, std::string alternate) _config.addDefaultValue(std::pair<std::string, std::string> (ZRTP_DISPLAY_SAS_ONCE, FALSE_STR), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (ZRTP_NOT_SUPP_WARNING, TRUE_STR), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (TLS_ENABLE, FALSE_STR), IP2IP_PROFILE); - _config.addDefaultValue(std::pair<std::string, std::string> (TLS_PORT, DEFAULT_SIP_TLS_PORT), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (TLS_CA_LIST_FILE, EMPTY_FIELD), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (TLS_CERTIFICATE_FILE, EMPTY_FIELD), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (TLS_PRIVATE_KEY_FILE, EMPTY_FIELD), IP2IP_PROFILE); @@ -1353,7 +1352,22 @@ ManagerImpl::initConfigFile (bool load_user_value, std::string alternate) _config.addDefaultValue(std::pair<std::string, std::string> (TLS_VERIFY_CLIENT, TRUE_STR), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (TLS_REQUIRE_CLIENT_CERTIFICATE, TRUE_STR), IP2IP_PROFILE); _config.addDefaultValue(std::pair<std::string, std::string> (TLS_NEGOTIATION_TIMEOUT_SEC, "2"), IP2IP_PROFILE); - _config.addDefaultValue(std::pair<std::string, std::string> (TLS_NEGOTIATION_TIMEOUT_MSEC, "0"), IP2IP_PROFILE); + _config.addDefaultValue(std::pair<std::string, std::string> (TLS_NEGOTIATION_TIMEOUT_MSEC, "0"), IP2IP_PROFILE); + _config.addDefaultValue(std::pair<std::string, std::string> (LOCAL_PORT, DEFAULT_SIP_PORT), IP2IP_PROFILE); + _config.addDefaultValue(std::pair<std::string, std::string> (PUBLISHED_PORT, DEFAULT_SIP_PORT), IP2IP_PROFILE); + _config.addDefaultValue(std::pair<std::string, std::string> (LOCAL_ADDRESS, DEFAULT_ADDRESS), IP2IP_PROFILE); + _config.addDefaultValue(std::pair<std::string, std::string> (PUBLISHED_ADDRESS, DEFAULT_ADDRESS), IP2IP_PROFILE); + + // Init display name to the username under which + // this sflphone instance is running. + std::string diplayName(""); + uid_t uid = getuid(); + struct passwd * user_info = NULL; + user_info = getpwuid(uid); + if (user_info != NULL) { + diplayName = user_info->pw_name; + } + _config.addDefaultValue(std::pair<std::string, std::string> (DISPLAY_NAME, diplayName), IP2IP_PROFILE); // Signalisation settings _config.addDefaultValue(std::pair<std::string, std::string> (SYMMETRIC, TRUE_STR), SIGNALISATION); @@ -2543,6 +2557,11 @@ std::map< std::string, std::string > ManagerImpl::getAccountDetails (const Accou a.insert(std::pair<std::string, std::string> (AUTHENTICATION_USERNAME, getConfigString(accountID, AUTHENTICATION_USERNAME))); a.insert(std::pair<std::string, std::string> (CONFIG_ACCOUNT_MAILBOX, getConfigString(accountID, CONFIG_ACCOUNT_MAILBOX))); a.insert(std::pair<std::string, std::string> (CONFIG_ACCOUNT_REGISTRATION_EXPIRE, getConfigString(accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE))); + a.insert(std::pair<std::string, std::string> (LOCAL_ADDRESS, getConfigString(accountID, LOCAL_ADDRESS))); + a.insert(std::pair<std::string, std::string> (PUBLISHED_ADDRESS, getConfigString(accountID, PUBLISHED_ADDRESS))); + a.insert(std::pair<std::string, std::string> (LOCAL_PORT, getConfigString(accountID, LOCAL_PORT))); + a.insert(std::pair<std::string, std::string> (PUBLISHED_PORT, getConfigString(accountID, PUBLISHED_PORT))); + a.insert(std::pair<std::string, std::string> (DISPLAY_NAME, getConfigString(accountID, DISPLAY_NAME))); RegistrationState state; state = account->getRegistrationState(); @@ -2555,7 +2574,6 @@ std::map< std::string, std::string > ManagerImpl::getAccountDetails (const Accou a.insert(std::pair<std::string, std::string> (ZRTP_NOT_SUPP_WARNING, getConfigString(accountID, ZRTP_NOT_SUPP_WARNING))); a.insert(std::pair<std::string, std::string> (TLS_ENABLE, Manager::instance().getConfigString(accountID, TLS_ENABLE))); - a.insert(std::pair<std::string, std::string> (TLS_PORT, Manager::instance().getConfigString(accountID, TLS_PORT))); a.insert(std::pair<std::string, std::string> (TLS_CA_LIST_FILE, Manager::instance().getConfigString(accountID, TLS_CA_LIST_FILE))); a.insert(std::pair<std::string, std::string> (TLS_CERTIFICATE_FILE, Manager::instance().getConfigString(accountID, TLS_CERTIFICATE_FILE))); a.insert(std::pair<std::string, std::string> (TLS_PRIVATE_KEY_FILE, Manager::instance().getConfigString(accountID, TLS_PRIVATE_KEY_FILE))); @@ -2728,6 +2746,11 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma std::string registrationExpire; std::string hostname; + std::string displayName; + std::string localAddress; + std::string publishedAddress; + std::string localPort; + std::string publishedPort; std::string srtpEnable; std::string zrtpDisplaySas; std::string zrtpDisplaySasOnce; @@ -2735,8 +2758,7 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma std::string zrtpHelloHash; std::string srtpKeyExchange; - std::string tlsEnable; - std::string tlsPort; + std::string tlsEnable; std::string tlsCaListFile; std::string tlsCertificateFile; std::string tlsPrivateKeyFile; @@ -2751,6 +2773,11 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma std::string tlsNegotiationTimeoutMsec; if((iter = map_cpy.find(HOSTNAME)) != map_cpy.end()) { hostname = iter->second; } + if((iter = map_cpy.find(DISPLAY_NAME)) != map_cpy.end()) { displayName = iter->second; } + if((iter = map_cpy.find(LOCAL_ADDRESS)) != map_cpy.end()) { localAddress = iter->second; } + if((iter = map_cpy.find(PUBLISHED_ADDRESS)) != map_cpy.end()) { publishedAddress = iter->second; } + if((iter = map_cpy.find(LOCAL_PORT)) != map_cpy.end()) { localPort = iter->second; } + if((iter = map_cpy.find(PUBLISHED_PORT)) != map_cpy.end()) { publishedPort = iter->second; } if((iter = map_cpy.find(SRTP_ENABLE)) != map_cpy.end()) { srtpEnable = iter->second; } if((iter = map_cpy.find(ZRTP_DISPLAY_SAS)) != map_cpy.end()) { zrtpDisplaySas = iter->second; } if((iter = map_cpy.find(ZRTP_DISPLAY_SAS_ONCE)) != map_cpy.end()) { zrtpDisplaySasOnce = iter->second; } @@ -2766,7 +2793,6 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma if((iter = map_cpy.find(CONFIG_ACCOUNT_REGISTRATION_EXPIRE)) != map_cpy.end()) { registrationExpire = iter->second; } if((iter = map_cpy.find(TLS_ENABLE)) != map_cpy.end()) { tlsEnable = iter->second; } - if((iter = map_cpy.find(TLS_PORT)) != map_cpy.end()) { tlsPort = iter->second; } if((iter = map_cpy.find(TLS_CA_LIST_FILE)) != map_cpy.end()) { tlsCaListFile = iter->second; } if((iter = map_cpy.find(TLS_CERTIFICATE_FILE)) != map_cpy.end()) { tlsCertificateFile = iter->second; } if((iter = map_cpy.find(TLS_PRIVATE_KEY_FILE)) != map_cpy.end()) { tlsPrivateKeyFile = iter->second; } @@ -2781,7 +2807,12 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma if((iter = map_cpy.find(TLS_NEGOTIATION_TIMEOUT_MSEC)) != map_cpy.end()) { tlsNegotiationTimeoutMsec = iter->second; } _debug("Enable account %s\n", accountEnable.c_str()); - setConfig(accountID, HOSTNAME, hostname); + setConfig(accountID, HOSTNAME, hostname); + setConfig(accountID, LOCAL_ADDRESS, localAddress); + setConfig(accountID, PUBLISHED_ADDRESS, publishedAddress); + setConfig(accountID, LOCAL_PORT, localPort); + setConfig(accountID, PUBLISHED_PORT, publishedPort); + setConfig(accountID, DISPLAY_NAME, displayName); setConfig(accountID, SRTP_ENABLE, srtpEnable); setConfig(accountID, ZRTP_DISPLAY_SAS, zrtpDisplaySas); setConfig(accountID, ZRTP_DISPLAY_SAS_ONCE, zrtpDisplaySasOnce); @@ -2790,7 +2821,6 @@ void ManagerImpl::setAccountDetails (const std::string& accountID, const std::ma setConfig(accountID, SRTP_KEY_EXCHANGE, srtpKeyExchange); setConfig(accountID, TLS_ENABLE, tlsEnable); - setConfig(accountID, TLS_PORT, tlsPort); setConfig(accountID, TLS_CA_LIST_FILE, tlsCaListFile); setConfig(accountID, TLS_CERTIFICATE_FILE, tlsCertificateFile); setConfig(accountID, TLS_PRIVATE_KEY_FILE, tlsPrivateKeyFile); @@ -3068,12 +3098,14 @@ ManagerImpl::loadAccountMap() // registration. This is useful since the Account object // provides a handful of method that simplifies URI creation // and loading of various settings. - // _directIpAccount = AccountCreator::createAccount (AccountCreator::SIP_DIRECT_IP_ACCOUNT, ""); if (_directIpAccount == NULL) { _debug("Failed to create direct ip calls \"account\"\n"); } else { - _directIpAccount->registerVoIPLink(); + // Force the options to be loaded + // No registration in the sense of + // the REGISTER method is performed. + _directIpAccount->registerVoIPLink(); } _debug ("nbAccount loaded %i \n",nbAccount); diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h index 394696961f..2b9d78bb90 100644 --- a/sflphone-common/src/managerimpl.h +++ b/sflphone-common/src/managerimpl.h @@ -904,7 +904,7 @@ class ManagerImpl { * @param port On which port we want to listen to * @return true if we are behind a NAT (without error) */ - bool behindNat(const std::string& svr, int port); + bool isBehindNat(const std::string& svr, int port); /** * Init default values for the different fields in the config file. diff --git a/sflphone-common/src/sip/sipaccount.cpp b/sflphone-common/src/sip/sipaccount.cpp index 5c5f24c364..ed04e13e39 100644 --- a/sflphone-common/src/sip/sipaccount.cpp +++ b/sflphone-common/src/sip/sipaccount.cpp @@ -26,15 +26,21 @@ SIPAccount::SIPAccount (const AccountID& accountID) : Account (accountID, "sip") - , _cred (NULL) - , _regc() - , _bRegister (false) - , _resolveOnce (false) - , _contact ("") - , _displayName ("") - , _tlsSetting (NULL) - , _port(DFT_SIP_PORT) - , _transportType(PJSIP_TRANSPORT_UNSPECIFIED) + , _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("") { /* 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 */ @@ -134,7 +140,6 @@ int SIPAccount::registerVoIPLink() // Init TLS settings if the user wants to use TLS bool tlsEnabled = Manager::instance().getConfigBool(_accountID, TLS_ENABLE); if (tlsEnabled) { - _port = (pj_uint16_t) Manager::instance().getConfigInt(_accountID, TLS_PORT); _transportType = PJSIP_TRANSPORT_TLS; initTlsConfiguration(); } @@ -221,23 +226,33 @@ void SIPAccount::initTlsConfiguration(void) } void SIPAccount::loadConfig() -{ - // Init general account settings - setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); +{ + // Load primary credential setUsername (Manager::instance().getConfigString (_accountID, USERNAME)); setPassword (Manager::instance().getConfigString (_accountID, PASSWORD)); - _authenticationUsername = Manager::instance().getConfigString (_accountID, AUTHENTICATION_USERNAME); _realm = Manager::instance().getConfigString (_accountID, REALM); _resolveOnce = Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_RESOLVE_ONCE) == "1" ? true : false; + // Load general account settings + setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); if (Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE).empty()) { _registrationExpire = DFT_EXPIRE_VALUE; } else { _registrationExpire = Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE); } - _port = Manager::instance().getSipPort(); + // Load network settings + std::string localPort = Manager::instance().getConfigString(_accountID, LOCAL_PORT); + std::string publishedPort = Manager::instance().getConfigString(_accountID, PUBLISHED_PORT); + std::stringstream ss; + ss << localPort; + ss >> _localPort; + ss << publishedPort; + ss >> _publishedPort; + + _localIpAddress = Manager::instance().getConfigString(_accountID, LOCAL_ADDRESS); + _publishedIpAddress = Manager::instance().getConfigString(_accountID, PUBLISHED_ADDRESS); _transportType = PJSIP_TRANSPORT_UDP; // Account generic @@ -421,4 +436,3 @@ std::string SIPAccount::getContactHeader(const std::string& address, const std:: return std::string(contact, len); } - diff --git a/sflphone-common/src/sip/sipaccount.h b/sflphone-common/src/sip/sipaccount.h index 7412b7170c..6375f986b8 100644 --- a/sflphone-common/src/sip/sipaccount.h +++ b/sflphone-common/src/sip/sipaccount.h @@ -73,10 +73,7 @@ class SIPAccount : public Account inline void setCredInfo(pjsip_cred_info *cred) {_cred = cred;} inline pjsip_cred_info *getCredInfo() {return _cred;} - - inline void setContact(const std::string &contact) {_contact = contact;} - inline std::string getContact() {return _contact;} - + inline std::string& getAuthenticationUsername(void) { return _authenticationUsername; } inline void setAuthenticationUsername(const std::string& username) { _authenticationUsername = username; } @@ -87,20 +84,49 @@ class SIPAccount : public Account bool fullMatch(const std::string& username, const std::string& hostname); bool userMatch(const std::string& username); bool hostnameMatch(const std::string& hostname); - - pjsip_regc* getRegistrationInfo( void ) { return _regc; } - void setRegistrationInfo( pjsip_regc *regc ) { _regc = regc; } - - inline int getCredentialCount(void) { return _credentialCount; } /* Registration flag */ bool isRegister() {return _bRegister;} void setRegister(bool result) {_bRegister = result;} + /** + * Get the registration stucture that is used + * for PJSIP in the registration process. + * Settings are loaded from configuration file. + * @param void + * @return pjsip_regc* A pointer to the registration structure + */ + pjsip_regc* getRegistrationInfo( void ) { return _regc; } + + /** + * Set the registration structure that is used + * for PJSIP in the registration process; + * @pram A pointer to the new registration structure + * @return void + */ + void setRegistrationInfo( pjsip_regc *regc ) { _regc = regc; } + + /** + * Get the number of credentials defined for + * this account. + * @param none + * @return int The number of credentials set for this account. + */ + inline int getCredentialCount(void) { return _credentialCount; } + + /** + * @return pjsip_tls_setting structure, filled from the configuration + * file, that can be used directly by PJSIP to initialize + * TLS transport. + */ inline pjsip_tls_setting * getTlsSetting(void) { return _tlsSetting; } + + /** + * @return bool Tells if current transport for that + * account is set to TLS. + */ inline bool isTlsEnabled(void) { return (_transportType == PJSIP_TRANSPORT_TLS) ? true: false; } - inline pj_uint16_t getPort(void) { return (pj_uint16_t) atoi(_port.c_str()); } - + /* * @return pj_str_t "From" uri based on account information. * From RFC3261: "The To header field first and foremost specifies the desired @@ -132,15 +158,70 @@ class SIPAccount : public Account */ std::string getServerUri(void); - /* + /** * @param port Optional port. Otherwise set to the port defined for that account. * @param hostname Optional local address. Otherwise set to the hostname defined for that account. * @return pj_str_t The contact header based on account information */ std::string getContactHeader(const std::string& address, const std::string& port); + + /** + * Get the port on which the transport/listener should use, or is + * actually using. + * @return pj_uint16 The port used for that account + */ + inline pj_uint16_t getLocalPort(void) { return (pj_uint16_t) _localPort; } - protected: - + /** + * Set the new port on which this account is running over. + * @pram port The port used by this account. + */ + inline 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 + */ + inline pj_uint16_t getPublishedPort(void) { 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. + */ + inline void setPublishedPort(pj_uint16_t port) { _publishedPort = port; } + + /** + * Get the bound address set by the user. + * @return std::string The public IPV4 address formatted in the standard dot notation. + */ + inline std::string getLocalAddress(void) { return _localIpAddress; } + + /** + * Set the bound address chosen by the user. + * @param The public IPV4 address in the standard dot notation. + * @return void + */ + inline void setLocalAddress(const std::string& address) { _localIpAddress = address; } + + /** + * 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 address formatted in the standard dot notation. + */ + inline std::string getPublishedAddress(void) { return _publishedIpAddress; } + + /** + * Set the public IP address to be used in Contact header. + * @param The public IPV4 address in the standard dot notation. + * @return void + */ + inline void setPublishedAddress(const std::string& publishedIpAddress) { _publishedIpAddress = publishedIpAddress; } + + private: + /* Maps a string description of the SSL method * to the corresponding enum value in pjsip_ssl_method. * @param method The string representation @@ -159,35 +240,6 @@ class SIPAccount : public Account */ int initCredential(void); - /** - * Credential information - */ - pjsip_cred_info *_cred; - - std::string _port; - - pjsip_transport_type_e _transportType; - - /** - * The TLS settings, if tls is chosen as - * a sip transport. - */ - pjsip_tls_setting * _tlsSetting; - - /** - * Special hack that is not here to stay - * See #1852 - */ - bool _resolveOnce; - - /** - * Display Name that can be used in - * SIP URI. - */ - std::string _displayName; - - private: - /** * If username is not provided, as it happens for Direct ip calls, * fetch the hostname of the machine on which the program is running @@ -205,28 +257,38 @@ class SIPAccount : public Account std::string getLoginName(void); private: - /** - * The pjsip client registration information - */ + + // The pjsip client registration information pjsip_regc *_regc; - - /** - * To check if the account is registered - */ + // To check if the account is registered bool _bRegister; + + // Network settings + std::string _registrationExpire; - /* - * SIP address - */ - std::string _contact; + std::string _localIpAddress; + std::string _publishedIpAddress; - std::string _registrationExpire; + pj_uint16_t _localPort; + pj_uint16_t _publishedPort; + pjsip_transport_type_e _transportType; + // Special hack that is not here to stay + // See #1852 + bool _resolveOnce; + + //Credential information + int _credentialCount; + pjsip_cred_info *_cred; + std::string _realm; std::string _authenticationUsername; + + // The TLS settings, if tls is chosen as + // a sip transport. + pjsip_tls_setting * _tlsSetting; - std::string _realm; - - int _credentialCount; + // Display Name that can be used in SIP URI. + std::string _displayName; }; #endif diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index 29e928c17a..9558f25502 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -1594,7 +1594,7 @@ bool SIPVoIPLink::pjsip_init() PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1); - /* Start resolving STUN server */ + // Start resolving STUN server // if we useStun and we failed to receive something on port 5060, we try a random port // If use STUN server, firewall address setup if (!loadSIPLocalIP()) { @@ -1609,10 +1609,10 @@ bool SIPVoIPLink::pjsip_init() this->setStunServer (Manager::instance().getConfigString (SIGNALISATION, SIP_STUN_SERVER)); this->useStun(useStun); - if (useStun && !Manager::instance().behindNat (getStunServer(), port)) { + if (useStun && !Manager::instance().isBehindNat (getStunServer(), port)) { port = RANDOM_SIP_PORT; - if (!Manager::instance().behindNat (getStunServer(), port)) { + if (!Manager::instance().isBehindNat (getStunServer(), port)) { _debug ("UserAgent: Unable to check NAT setting\n"); validStunServer = false; return false; // hoho we can't use the random sip port too... @@ -1621,37 +1621,75 @@ bool SIPVoIPLink::pjsip_init() _localPort = port; + + // Retreive Direct IP Calls settings. + // This corresponds to the accountID set to + // AccountNULL + SIPAccount * account = NULL; + bool directIpCallsTlsEnabled = false; + account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(AccountNULL)); + if (account == NULL) { + _debug("Account is null"); + } else { + directIpCallsTlsEnabled = account->isTlsEnabled(); + } + if (useStun) { - // set by last behindNat() call (ish)... + // set by last isBehindNat() call (ish)... stunServerResolve(); _localExternAddress = Manager::instance().getFirewallAddress(); - _localExternPort = Manager::instance().getFirewallPort(); - errPjsip = createUDPServer(); - - if (errPjsip != 0) { - _debug ("UserAgent: Could not initialize SIP listener on port %d\n", port); - return errPjsip; - } + _localExternPort = Manager::instance().getFirewallPort(); } else { _localExternAddress = _localIPAddress; _localExternPort = _localPort; errPjsip = createUDPServer(); + } + + // Create a UDP listener meant for all accounts + // for which TLS was not enabled + errPjsip = createUDPServer(); + + // If stun was not enabled an the above UDP server + // could not be created, then give it another try + // on a random sip port + if (errPjsip != PJ_SUCCESS && !useStun) { + _debug ("UserAgent: Could not initialize SIP listener on port %d\n", _localExternPort); + _localExternPort = _localPort = RANDOM_SIP_PORT; + + _debug ("UserAgent: Try to initialize SIP listener on port %d\n", _localExternPort); + errPjsip = createUDPServer(); - if (errPjsip != 0) { - _debug ("UserAgent: Could not initialize SIP listener on port %d\n", _localExternPort); - _localExternPort = _localPort = RANDOM_SIP_PORT; - _debug ("UserAgent: Try to initialize SIP listener on port %d\n", _localExternPort); - errPjsip = createUDPServer(); - - if (errPjsip != 0) { - _debug ("UserAgent: Fail to initialize SIP listener on port %d\n", _localExternPort); - return errPjsip; - } + if (errPjsip != PJ_SUCCESS) { + _debug ("UserAgent: Fail to initialize SIP listener on port %d\n", _localExternPort); + return errPjsip; } + } + + // If we use stun and UDP server creation + // failed, then just complain and return + // since retrying on a random sip port + // would just go against the need of + // using it. + if (errPjsip != PJ_SUCCESS && useStun) { + _debug("Could not create UDP server with STUN\n"); + return errPjsip; } _debug ("UserAgent: SIP Init -- listening on port %d\n", _localExternPort); + // Create a TLS listener meant for Direct IP calls + // if the user did enabled it. + if (directIpCallsTlsEnabled) { + errPjsip = createTlsTransportRetryOnFailure(AccountNULL); + } + + if (errPjsip != PJ_SUCCESS) { + _debug("pj_init(): could not start TLS transport for Direct Calls"); + } + + // TODO: For TLS, retry on random port, just we already do above + // for UDP transport. + // Initialize transaction layer status = pjsip_tsx_layer_init_module (_endpt); PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1); @@ -1912,7 +1950,46 @@ int SIPVoIPLink::findLocalPortFromUri(const std::string& uri) return port; } -int SIPVoIPLink::createTLSServer(AccountID id) + +pj_status_t SIPVoIPLink::createTlsTransportRetryOnFailure(AccountID id) +{ + pj_status_t success; + + // Create a TLS listener. + // Note that STUN cannot be used for + // TCP NAT traversal. At the moment (20/08/09) + // user must supply the public address/port + // manually. + success = createTlsTransport(id); + + if (success != PJ_SUCCESS) { + unsigned int randomPort = RANDOM_SIP_PORT; + + // Update new port in the corresponding SIPAccount + SIPAccount * account = NULL; + account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(id)); + if (account == NULL) { + _debug("createTlsTransportRetryOnFailure: Account is null. Returning"); + return !PJ_SUCCESS; + } + + account->setLocalPort((pj_uint16_t) randomPort); + + // Try to start the transport again on + // the new port. + success = createTlsTransport(id); + if (success != PJ_SUCCESS) { + _debug ("createTlsTransportRetryOnFailure: failed to retry on random port %d\n", randomPort); + return success; + } + + _debug ("createTlsTransportRetryOnFailure: TLS transport listening on port %d\n", randomPort); + } + + return PJ_SUCCESS; +} + +pj_status_t SIPVoIPLink::createTlsTransport(AccountID id) { pjsip_tpfactory *tls; pj_sockaddr_in local_addr; @@ -1934,21 +2011,23 @@ int SIPVoIPLink::createTLSServer(AccountID id) * IP interface address is not specified, * so socket will be bound to PJ_INADDR_ANY. * If user specified port is an empty string - * of if is equal to 0, then the port will + * or if it is equal to 0, then the port will * be chosen automatically by the OS. */ pj_sockaddr_in_init(&local_addr, 0, 0); - pj_uint16_t localTlsPort = account->getPort(); + pj_uint16_t localTlsPort = account->getLocalPort(); if (localTlsPort != 0) { local_addr.sin_port = pj_htons(localTlsPort); } /* Init published name */ pj_bzero(&a_name, sizeof(pjsip_host_port)); - pj_cstr(&a_name.host, _localExternAddress.c_str()); - a_name.port = (pj_uint16_t) _localExternPort; - + pj_cstr(&a_name.host, (account->getPublishedAddress()).c_str()); + a_name.port = account->getPublishedPort(); + + /* Get TLS settings. Expected to be filled */ pjsip_tls_setting * tls_setting = account->getTlsSetting(); + status = pjsip_tls_transport_start(_endpt, tls_setting, &local_addr, &a_name, 1, &tls); if (status != PJ_SUCCESS) { @@ -3144,7 +3223,7 @@ bool setCallAudioLocal (SIPCall* call, std::string localIP, bool stun, std::stri if (stun) { // If use Stun server - if (Manager::instance().behindNat (server, callLocalAudioPort)) { + if (Manager::instance().isBehindNat (server, callLocalAudioPort)) { callLocalExternAudioPort = Manager::instance().getFirewallPort(); } } diff --git a/sflphone-common/src/sip/sipvoiplink.h b/sflphone-common/src/sip/sipvoiplink.h index 14311d65bb..3b35f9edf0 100644 --- a/sflphone-common/src/sip/sipvoiplink.h +++ b/sflphone-common/src/sip/sipvoiplink.h @@ -339,8 +339,33 @@ class SIPVoIPLink : public VoIPLink /** Create SIP UDP Listener */ int createUDPServer(); - /** Create SIP TLS Listener */ - int createTLSServer(AccountID id); + /** + * Try to create a new TLS transport + * with the settings defined in the corresponding + * SIPAccount with id "id". If creatation fails + * for whatever reason, it will try to start + * it again on a randomly chosen port. + * + * A better idea would be to list all the transports + * registered to the transport manager in order to find + * an available port. Note that creation might also fail + * for other reason than just a wrong port. + * + * @param id The account id for which a tranport must + * be created. + * @return pj_status_t PJ_SUCCESS on success + */ + pj_status_t createTlsTransportRetryOnFailure(AccountID id); + + /** + * Try to create a TLS transport with the settings + * defined in the corresponding SIPAccount with id + * "id". + * @param id The account id for which a transport must + * be created. + * @return pj_status_t PJ_SUCCESS on success + */ + pj_status_t createTlsTransport(AccountID id); bool loadSIPLocalIP(); -- GitLab