Commit 78f86339 authored by pierre-luc's avatar pierre-luc
Browse files

[#812] Fix various segmentation faults related to Direct IP kind of calls.

parent 73800ff3
......@@ -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;
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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
......
......@@ -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(),
......
......@@ -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;
......
......@@ -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);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment