diff --git a/sflphone-common/src/accountcreator.cpp b/sflphone-common/src/accountcreator.cpp index 8a4b1c748078c4d1c35d95cb3bd88997ed831160..b45792a8f49be4ff3f31f8d0a97d506e667e6164 100644 --- a/sflphone-common/src/accountcreator.cpp +++ b/sflphone-common/src/accountcreator.cpp @@ -19,6 +19,8 @@ */ #include "accountcreator.h" #include "sip/sipaccount.h" +#include "user_cfg.h" + #ifdef USE_IAX #include "iax/iaxaccount.h" #endif @@ -36,16 +38,17 @@ Account* AccountCreator::createAccount (AccountType type, AccountID accountID) { switch (type) { - case SIP_ACCOUNT: return new SIPAccount (accountID); break; -#ifdef USE_IAX - + case SIP_DIRECT_IP_ACCOUNT: + return new SIPAccount (IP2IP_PROFILE); + break; + #ifdef USE_IAX case IAX_ACCOUNT: return new IAXAccount (accountID); break; -#endif + #endif } return 0; diff --git a/sflphone-common/src/accountcreator.h b/sflphone-common/src/accountcreator.h index c91b3f7220567779cffa54505ce38209a19bbce6..6add7a7ac690a47ce4607a6b43453a23ca874124 100644 --- a/sflphone-common/src/accountcreator.h +++ b/sflphone-common/src/accountcreator.h @@ -34,7 +34,7 @@ public: /** * Public account type */ - enum AccountType {SIP_ACCOUNT, IAX_ACCOUNT }; + enum AccountType {SIP_ACCOUNT, SIP_DIRECT_IP_ACCOUNT, IAX_ACCOUNT }; /** * Create a new account or null diff --git a/sflphone-common/src/managerimpl.cpp b/sflphone-common/src/managerimpl.cpp index dd6c312d98230e12fca66611c3e244a2569b7ef5..a70fc654d4a25bea101aabe0a6901b432790f3d6 100644 --- a/sflphone-common/src/managerimpl.cpp +++ b/sflphone-common/src/managerimpl.cpp @@ -28,6 +28,7 @@ #include "user_cfg.h" #include "global.h" #include "sip/sipaccount.h" + #include "audio/audiolayer.h" #include "audio/alsa/alsalayer.h" #include "audio/pulseaudio/pulselayer.h" @@ -47,10 +48,6 @@ #include <sys/types.h> // mkdir(2) #include <sys/stat.h> // mkdir(2) -//#include <cc++/file.h> - - - #define fill_config_str(name, value) \ (_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_str))) @@ -90,6 +87,7 @@ ManagerImpl::ManagerImpl (void) , _accountMap() , _cleaner (NULL) , _history (NULL) + , _directIpAccount (NULL) { // initialize random generator for call id @@ -2496,7 +2494,7 @@ ManagerImpl::getAccountList() iter = _accountMap.begin (); while (iter != _accountMap.end()) { - if (iter->second != 0) { + if (iter->second != NULL) { v.push_back (iter->first.data()); } @@ -3064,6 +3062,20 @@ ManagerImpl::loadAccountMap() iter++; } + // Those calls that are placed to an uri that cannot be + // associated to an account are using that special account. + // An account, that is not account, in the sense of + // 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(); + } + _debug ("nbAccount loaded %i \n",nbAccount); return nbAccount; @@ -3102,9 +3114,15 @@ ManagerImpl::accountExists (const AccountID& accountID) Account* ManagerImpl::getAccount (const AccountID& accountID) { + // In our definition, + // this is the "direct ip calls account" + if (accountID == AccountNULL) { + return _directIpAccount; + } + AccountMap::iterator iter = _accountMap.find (accountID); if (iter == _accountMap.end()) { - return 0; + return NULL; } return iter->second; } diff --git a/sflphone-common/src/managerimpl.h b/sflphone-common/src/managerimpl.h index a6daacba79de5d9c4f74aa86b79cb6b02168c061..394696961f214247b1117ddea2ede4d7650a810f 100644 --- a/sflphone-common/src/managerimpl.h +++ b/sflphone-common/src/managerimpl.h @@ -48,6 +48,7 @@ class GuiFramework; class TelephoneTone; class VoIPLink; class HistoryManager; +class SIPAccount; /** Define a type for a AccountMap container */ typedef std::map<AccountID, Account*> AccountMap; @@ -1147,6 +1148,8 @@ class ManagerImpl { /** *Contains a list of account (sip, aix, etc) and their respective voiplink/calls */ AccountMap _accountMap; + + Account * _directIpAccount; /** * Load the account from configuration diff --git a/sflphone-common/src/sip/sipaccount.cpp b/sflphone-common/src/sip/sipaccount.cpp index f63fd0bfff073098e79556fcc172a95a8767b1ab..5c5f24c364e5f40ab1eef287945feff7735dcc17 100644 --- a/sflphone-common/src/sip/sipaccount.cpp +++ b/sflphone-common/src/sip/sipaccount.cpp @@ -22,6 +22,7 @@ #include "sipaccount.h" #include "manager.h" #include "user_cfg.h" +#include <pwd.h> SIPAccount::SIPAccount (const AccountID& accountID) : Account (accountID, "sip") @@ -43,7 +44,7 @@ SIPAccount::SIPAccount (const AccountID& accountID) /* Represents the number of SIP accounts connected the same link */ dynamic_cast<SIPVoIPLink*> (_link)->incrementClients(); - + } SIPAccount::~SIPAccount() @@ -120,27 +121,13 @@ int SIPAccount::initCredential(void) int SIPAccount::registerVoIPLink() { - if (Manager::instance().getConfigString (_accountID, HOSTNAME).length() >= PJ_MAX_HOSTNAME) { - return !SUCCESS; - } + // Init general settings + loadConfig(); - // Init general account settings - setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); - 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; - - if (Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE).empty()) { - _registrationExpire = DFT_EXPIRE_VALUE; - } else { - _registrationExpire = Manager::instance().getConfigString (_accountID, CONFIG_ACCOUNT_REGISTRATION_EXPIRE); + if (_hostname.length() >= PJ_MAX_HOSTNAME) { + return !SUCCESS; } - _port = Manager::instance().getSipPort(); - _transportType = PJSIP_TRANSPORT_UDP; - // Init set of additional credentials, if supplied by the user initCredential(); @@ -152,10 +139,11 @@ int SIPAccount::registerVoIPLink() initTlsConfiguration(); } - // Start registration - int status = _link->sendRegister (_accountID); - - ASSERT (status , SUCCESS); + if (_accountID != IP2IP_PROFILE) { + // Start registration + int status = _link->sendRegister (_accountID); + ASSERT (status , SUCCESS); + } return SUCCESS; } @@ -164,6 +152,10 @@ int SIPAccount::unregisterVoIPLink() { _debug ("unregister account %s\n" , getAccountID().c_str()); + if (_accountID == IP2IP_PROFILE) { + return true; + } + if (_link->sendUnregister (_accountID)) { setRegistrationInfo (NULL); return true; @@ -229,7 +221,25 @@ void SIPAccount::initTlsConfiguration(void) } void SIPAccount::loadConfig() -{ +{ + // Init general account settings + setHostname (Manager::instance().getConfigString (_accountID, HOSTNAME)); + 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; + + 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(); + _transportType = PJSIP_TRANSPORT_UDP; + // Account generic Account::loadConfig(); } @@ -252,26 +262,61 @@ bool SIPAccount::hostnameMatch (const std::string& hostname) return (hostname == getHostname()); } +std::string SIPAccount::getMachineName(void) +{ + std::string hostname; + hostname = std::string(pj_gethostname()->ptr, pj_gethostname()->slen); + return hostname; +} + +std::string SIPAccount::getLoginName(void) +{ + std::string username; + + uid_t uid = getuid(); + struct passwd * user_info = NULL; + user_info = getpwuid(uid); + if (user_info != NULL) { + username = user_info->pw_name; + } + + return username; +} + + std::string SIPAccount::getFromUri(void) { char uri[PJSIP_MAX_URL_SIZE]; std::string scheme; std::string transport; + std::string username = _username; + std::string hostname = _hostname; // UDP does not require the transport specification - if (_transportType != PJSIP_TRANSPORT_UDP) { - scheme = "sips"; + if (_transportType == PJSIP_TRANSPORT_TLS) { + scheme = "sips:"; transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); } else { - scheme = "sip"; + scheme = "sip:"; + transport = ""; + } + + // Get login name if username is not specified + if (_username.empty()) { + username = getLoginName(); } + + // Get machine hostname if not provided + if (_hostname.empty()) { + hostname = getMachineName(); + } int len = pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE, - "<%s:%s@%s%s>", + "<%s%s@%s%s>", scheme.c_str(), - _username.c_str(), - _hostname.c_str(), + username.c_str(), + hostname.c_str(), transport.c_str()); return std::string(uri, len); @@ -283,20 +328,33 @@ std::string SIPAccount::getToUri(const std::string& username) std::string scheme; std::string transport; + std::string hostname = _hostname; // UDP does not require the transport specification - if (_transportType != PJSIP_TRANSPORT_UDP) { - scheme = "sips"; + if (_transportType == PJSIP_TRANSPORT_TLS) { + scheme = "sips:"; transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); } else { - scheme = "sip"; + scheme = "sip:"; + transport = ""; + } + + // Check if scheme is already specified + if (username.find("sip") == 0) { + scheme = ""; } + // Check if hostname is already specified + if (username.find("@") != std::string::npos) { + hostname = ""; + } + int len = pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE, - "<%s:%s@%s%s>", + "<%s%s%s%s%s>", scheme.c_str(), username.c_str(), - _hostname.c_str(), + (hostname.empty()) ? "" : "@", + hostname.c_str(), transport.c_str()); return std::string(uri, len); @@ -310,15 +368,16 @@ std::string SIPAccount::getServerUri(void) std::string transport; // UDP does not require the transport specification - if (_transportType != PJSIP_TRANSPORT_UDP) { - scheme = "sips"; + if (_transportType == PJSIP_TRANSPORT_TLS) { + scheme = "sips:"; transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); } else { - scheme = "sip"; + scheme = "sip:"; + transport = ""; } int len = pj_ansi_snprintf(uri, PJSIP_MAX_URL_SIZE, - "<%s:%s%s>", + "<%s%s%s>", scheme.c_str(), _hostname.c_str(), transport.c_str()); @@ -337,15 +396,17 @@ std::string SIPAccount::getContactHeader(const std::string& address, const std:: // if IPV6, should be set to [] beginquote = endquote = ""; - if (_transportType != PJSIP_TRANSPORT_UDP) { - scheme = "sips"; + // UDP does not require the transport specification + if (_transportType == PJSIP_TRANSPORT_TLS) { + scheme = "sips:"; transport = ";transport=" + std::string(pjsip_transport_get_type_name(_transportType)); } else { - scheme = "sip"; + scheme = "sip:"; + transport = ""; } int len = pj_ansi_snprintf(contact, PJSIP_MAX_URL_SIZE, - "%s%s<%s:%s%s%s%s%s:%d%s>", + "%s%s<%s%s%s%s%s%s:%d%s>", _displayName.c_str(), (_displayName.empty() ? "" : " "), scheme.c_str(), diff --git a/sflphone-common/src/sip/sipaccount.h b/sflphone-common/src/sip/sipaccount.h index aee8c0e4badbbe372a9377183e2ecc4d160c29b4..7412b7170c935bc5896e1e81b9344dc0656d0875 100644 --- a/sflphone-common/src/sip/sipaccount.h +++ b/sflphone-common/src/sip/sipaccount.h @@ -4,7 +4,8 @@ * Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com> * Author: Alexandre Bourget <alexandre.bourget@savoirfairelinux.com> * Author: Yan Morin <yan.morin@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 @@ -138,7 +139,8 @@ class SIPAccount : public Account */ std::string getContactHeader(const std::string& address, const std::string& port); - private: + protected: + /* Maps a string description of the SSL method * to the corresponding enum value in pjsip_ssl_method. * @param method The string representation @@ -162,11 +164,6 @@ class SIPAccount : public Account */ pjsip_cred_info *_cred; - /** - * The pjsip client registration information - */ - pjsip_regc *_regc; - std::string _port; pjsip_transport_type_e _transportType; @@ -175,22 +172,54 @@ class SIPAccount : public Account * The TLS settings, if tls is chosen as * a sip transport. */ - pjsip_tls_setting * _tlsSetting; - + pjsip_tls_setting * _tlsSetting; + /** - * To check if the account is registered + * Special hack that is not here to stay + * See #1852 */ - bool _bRegister; - 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 + * onto. + * @return std::string The machine hostname as returned by pj_gethostname() + */ + std::string getMachineName(void); + + /** + * If username is not provided, as it happens for Direct ip calls, + * fetch the Real Name field of the user that is currently + * running this program. + * @return std::string The login name under which SFLPhone is running. + */ + std::string getLoginName(void); + + private: + /** + * The pjsip client registration information + */ + pjsip_regc *_regc; + + /** + * To check if the account is registered + */ + bool _bRegister; /* * SIP address */ std::string _contact; - std::string _displayName; - std::string _registrationExpire; std::string _authenticationUsername; diff --git a/sflphone-common/src/sip/sipvoiplink.cpp b/sflphone-common/src/sip/sipvoiplink.cpp index e7587790ed55ff4c4f822e76dddc8e6f0a7e3c70..29e928c17ae88c2287645fa2c5072cb1aa27e920 100644 --- a/sflphone-common/src/sip/sipvoiplink.cpp +++ b/sflphone-common/src/sip/sipvoiplink.cpp @@ -498,7 +498,7 @@ int SIPVoIPLink::sendRegister (AccountID id) status = pjsip_regc_init (regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, expire_value); if (status != PJ_SUCCESS) { - _debug ("UserAgent: Unable to initialize regc. %d\n", status); + _debug ("UserAgent: Unable to initialize account %d in sendRegister\n", status); _mutexSIP.leaveMutex(); return false; } @@ -1372,16 +1372,18 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) setCallAudioLocal (call, getLocalIPAddress(), useStun(), getStunServer()); call->initRecFileName(); + AccountID accountId = Manager::instance().getAccountFromCall(id); SIPAccount * account = NULL; - account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(id)); + account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(accountId)); if (account == NULL) { - _debug("Account is null. Returning"); + _debug("Account is null. Returning\n"); return !PJ_SUCCESS; } - + + _debug("toUri received in new_ip_to_ip call %s\n", to.c_str()); std::string toUri = account->getToUri(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()->create_initial_offer(); @@ -1420,7 +1422,7 @@ bool SIPVoIPLink::new_ip_to_ip_call (const CallID& id, const std::string& to) pj_cstr(&pjContact, contactUri.c_str()); // Create the dialog (UAC) - // (Parameters are "strduped" inside the function) + // (Parameters are "strduped" inside this function) status = pjsip_dlg_create_uac (pjsip_ua_instance(), &pjFrom, &pjContact, &pjTo, NULL, &dialog); PJ_ASSERT_RETURN (status == PJ_SUCCESS, false);