Commit 54dd1aec authored by Emmanuel Milou's avatar Emmanuel Milou
Browse files

Use c++ thread in SIP, move everything in sipvoiplink;

Seems to fix or reduce deadlocks
parent 35641ddb
......@@ -39,8 +39,7 @@ sflphoned_SOURCES = \
call.cpp \
account.cpp \
sipcall.cpp \
$(IAXSOURCES) \
useragent.cpp
$(IAXSOURCES)
sflphoned_CXXFLAGS = \
-DPREFIX=\"$(prefix)\" -DPROGSHAREDIR=\"${datadir}/sflphone\" \
......@@ -80,8 +79,7 @@ noinst_HEADERS = \
accountcreator.h \
sipvoiplink.h \
call.h \
sipcall.h \
useragent.h
sipcall.h
libsflphone_la_LIBADD = \
$(src)/libs/stund/libstun.la \
......
/*
* Copyright (C) 2004, 2005, 2006 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
*
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Emmanuel Milou <emmanuel.milou@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
......@@ -21,43 +20,31 @@
#include "eventthread.h"
#include "voiplink.h"
EventThread::EventThread (VoIPLink* link) : Thread (), _linkthread(link), stopIt(false)
{
setCancel(cancelDeferred);
}
EventThread::~EventThread (void)
{
terminate();
}
/********************************** IAX Voiplink thread *************************************/
/**
* Reimplementation of run()
*/
void
EventThread::run (void)
void IAXEventThread::run (void)
{
//stopIt = false;
while(!testCancel()) {
_linkthread->getEvent();
}
}
}
void
EventThread::stop( void )
{
stopIt = true;
}
/********************************************************************************************/
void
EventThread::startLoop( void )
{
stopIt = false;
//start();
}
bool
EventThread::isStopped( void )
/********************************** SIP Voiplink thread *************************************/
/**
* Reimplementation of run()
*/
void SIPEventThread::run (void)
{
return stopIt;
while(!testCancel()) {
_linkthread->getEvent();
}
}
/********************************************************************************************/
/*
* Copyright (C) 2004-2005 Savoir-Faire Linux inc.
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
* Copyright (C) 2009 Savoir-Faire Linux inc.
* Emmanuel Milou <emmanuel.milou@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
......@@ -31,24 +30,52 @@ class VoIPLink;
*/
class EventThread : public ost::Thread {
public:
/**
* Build a thread that call getEvents
*/
EventThread (VoIPLink*);
~EventThread (void);
virtual void run ();
virtual void stop();
virtual void startLoop();
bool isStopped();
private:
friend class SIPEventThread;
friend class IAXEventThread;
public:
/**
* Thread constructor
*/
EventThread (VoIPLink* link) : Thread(), _linkthread(link){
setCancel( cancelDeferred );
}
virtual ~EventThread (void){
terminate();
}
virtual void run () = 0;
private:
EventThread(const EventThread& rh); // copy constructor
EventThread& operator=(const EventThread& rh); // assignment operator
/** VoIPLink is the object being called by getEvents() method */
VoIPLink* _linkthread;
bool stopIt;
VoIPLink* _linkthread;
};
class IAXEventThread : public EventThread {
public:
IAXEventThread( VoIPLink* voiplink )
: EventThread( voiplink ){
}
virtual void run();
};
class SIPEventThread : public EventThread {
public:
SIPEventThread( VoIPLink* voiplink )
: EventThread( voiplink ){
}
virtual void run();
};
#endif // __EVENT_THREAD_H__
......@@ -45,7 +45,7 @@
IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
: VoIPLink(accountID)
{
_evThread = new EventThread(this);
_evThread = new IAXEventThread(this);
_regSession = NULL;
_nextRefreshStamp = 0;
......@@ -917,6 +917,8 @@ IAXVoIPLink::iaxCodecMapToFormat(IAXCall* call)
void IAXVoIPLink::updateAudiolayer( void )
{
_mutexIAX.enterMutex();
audiolayer = NULL;
audiolayer = Manager::instance().getAudioDriver();
_mutexIAX.leaveMutex();
}
......@@ -46,15 +46,8 @@
#include "accountcreator.h" // create new account
#include "sipvoiplink.h"
#include "useragent.h"
#include "user_cfg.h"
#ifdef USE_ZEROCONF
#include "zeroconf/DNSService.h"
#include "zeroconf/DNSServiceTXTRecord.h"
#endif
#define fill_config_str(name, value) \
(_config.addConfigTreeItem(section, Conf::ConfigTreeItem(std::string(name), std::string(value), type_str)))
#define fill_config_int(name, value) \
......@@ -88,26 +81,10 @@ ManagerImpl::ManagerImpl (void)
, _callAccountMap()
//, _callAccountMapMutex()
, _accountMap()
, _userAgent(NULL)
, _userAgentInitlized(false)
, _sipThreadStop()
{
/* Init private variables
setup: _path, _exist, _setupLoaded , _dbus
sound: _audiodriver, _dtmfKey,
_spkr_volume,_mic_volume = 0; // Initialize after by init() -> initVolume()
Call: _nbIncomingWaitingCall, _hasTriedToRegister
SIP Link: _userAgent, _userAgentInitlized
*/
#ifdef USE_ZEROCONF
_hasZeroconf = true;
_DNSService = new DNSService();
#endif
// initialize random generator for call id
srand (time(NULL));
// initialize random generator for call id
srand (time(NULL));
#ifdef TEST
testAccountMap();
......@@ -123,82 +100,60 @@ ManagerImpl::ManagerImpl (void)
// never call if we use only the singleton...
ManagerImpl::~ManagerImpl (void)
{
terminate();
#ifdef USE_ZEROCONF
delete _DNSService; _DNSService = 0;
#endif
_debug("%s stop correctly.\n", PROGNAME);
terminate();
_debug("%s stop correctly.\n", PROGNAME);
}
void
ManagerImpl::init()
{
// Load accounts, init map
loadAccountMap();
// Load accounts, init map
loadAccountMap();
//Initialize sip manager
if(_userAgentInitlized) {
_userAgent->sipCreate();
_userAgent->sipInit();
}
initVolume();
initVolume();
if (_exist == 0) {
_debug("Cannot create config file in your home directory\n");
}
initAudioDriver();
selectAudioDriver();
if (_exist == 0) {
_debug("Cannot create config file in your home directory\n");
}
// Initialize the list of supported audio codecs
initAudioCodec();
initAudioDriver();
selectAudioDriver();
getAudioInputDeviceList();
// Initialize the list of supported audio codecs
initAudioCodec();
AudioLayer *audiolayer = getAudioDriver();
if (audiolayer!=0) {
unsigned int sampleRate = audiolayer->getSampleRate();
getAudioInputDeviceList();
_debugInit("Load Telephone Tone");
std::string country = getConfigString(PREFERENCES, ZONE_TONE);
_telephoneTone = new TelephoneTone(country, sampleRate);
AudioLayer *audiolayer = getAudioDriver();
if (audiolayer!=0) {
unsigned int sampleRate = audiolayer->getSampleRate();
_debugInit("Loading DTMF key");
_dtmfKey = new DTMF(sampleRate);
}
_debugInit("Load Telephone Tone");
std::string country = getConfigString(PREFERENCES, ZONE_TONE);
_telephoneTone = new TelephoneTone(country, sampleRate);
// initRegisterAccounts was here, but we doing it after the gui loaded...
// the stun detection is long, so it's a better idea to do it after getEvents
initZeroconf();
_debugInit("Loading DTMF key");
_dtmfKey = new DTMF(sampleRate);
}
}
void ManagerImpl::terminate()
{
saveConfig();
saveConfig();
unloadAccountMap();
unloadAccountMap();
if(_userAgentInitlized) {
delete _userAgent;
_userAgent = NULL;
_userAgentInitlized = false;
}
_debug("Unload DTMF Key\n");
delete _dtmfKey;
_debug("Unload DTMF Key\n");
delete _dtmfKey;
_debug("Unload Audio Driver\n");
delete _audiodriver; _audiodriver = NULL;
_debug("Unload Audio Driver\n");
delete _audiodriver; _audiodriver = NULL;
_debug("Unload Telephone Tone\n");
delete _telephoneTone; _telephoneTone = NULL;
_debug("Unload Telephone Tone\n");
delete _telephoneTone; _telephoneTone = NULL;
_debug("Unload Audio Codecs\n");
_codecDescriptorMap.deleteHandlePointer();
_debug("Unload Audio Codecs\n");
_codecDescriptorMap.deleteHandlePointer();
}
bool
......@@ -443,25 +398,29 @@ ManagerImpl::saveConfig (void)
int
ManagerImpl::initRegisterAccounts()
{
int status;
//TODO What the flag is for ??
bool flag = true;
AccountMap::iterator iter;
_debugInit("Initiate VoIP Links Registration");
iter = _accountMap.begin();
/* Loop on the account map previously loaded */
while( iter != _accountMap.end() ) {
if ( iter->second ) {
iter->second->loadConfig();
if ( iter->second->isEnabled() ) {
status = iter->second->registerVoIPLink();
if (status != SUCCESS)
flag = false;
if ( iter->second ) {
iter->second->loadConfig();
/* If the account is set as enabled, try to register */
if ( iter->second->isEnabled() ) {
status = iter->second->registerVoIPLink();
if (status != SUCCESS){
flag = false;
}
}
}
}
iter++;
iter++;
}
// calls the client notification here in case of errors at startup...
if( _audiodriver -> getErrorMessage() != -1 )
notifyErrClient( _audiodriver -> getErrorMessage() );
......@@ -1694,24 +1653,6 @@ ManagerImpl::switchAudioManager( void )
notifyErrClient( _audiodriver -> getErrorMessage());
}
/**
* Initialize the Zeroconf scanning services loop
* Informations will be store inside a map DNSService->_services
* Initialization: Main Thread
*/
void
ManagerImpl::initZeroconf(void)
{
#ifdef USE_ZEROCONF
_debugInit("Zeroconf Initialization");
int useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
if (useZeroconf) {
_DNSService->startScanServices();
}
#endif
}
/**
* Init the volume for speakers/micro from 0 to 100 value
* Initialization: Main Thread
......@@ -1750,6 +1691,16 @@ void ManagerImpl::setMicVolume(unsigned short mic_vol)
//}
}
void ManagerImpl::setSipPort( int port )
{
}
int ManagerImpl::getSipPort( void )
{
return 5060;
}
/**
* configuration function requests
* Main Thread
......@@ -2021,26 +1972,17 @@ void ManagerImpl::setAccountDetails( const std::string& accountID, const std::ma
if (accountType == "SIP") {
setConfig(accountID, SIP_STUN_SERVER,(*details.find(SIP_STUN_SERVER)).second);
setConfig(accountID, SIP_USE_STUN, (*details.find(SIP_USE_STUN)).second == "TRUE" ? "1" : "0");
if(!_userAgentInitlized) {
_userAgentInitlized = true;
if((*details.find(SIP_USE_STUN)).second == "TRUE")
_userAgent->setStunServer((*details.find(SIP_STUN_SERVER)).second.data());
else
_userAgent->setStunServer(NULL);
_userAgent->sipCreate();
_userAgent->sipInit();
} else {
if((*details.find(SIP_USE_STUN)).second == "TRUE")
_userAgent->setStunServer((*details.find(SIP_STUN_SERVER)).second.data());
else
_userAgent->setStunServer(NULL);
restartPjsip();
}
}
if((*details.find(SIP_USE_STUN)).second == "TRUE")
{
//TODO Replace: _userAgent->setStunServer((*details.find(SIP_STUN_SERVER)).second.data());
}
else
{
//TODO: replace: _userAgent->setStunServer(NULL);
}
//restartPjsip();
}
saveConfig();
......@@ -2082,38 +2024,30 @@ ManagerImpl::sendRegister( const std::string& accountID , const int32_t& expire
ManagerImpl::addAccount(const std::map< std::string, std::string >& details)
{
/** @todo Deal with both the _accountMap and the Configuration */
std::string accountType = (*details.find(CONFIG_ACCOUNT_TYPE)).second;
Account* newAccount;
std::stringstream accountID;
accountID << "Account:" << time(NULL);
AccountID newAccountID = accountID.str();
/** @todo Verify the uniqueness, in case a program adds accounts, two in a row. */
/** @todo Deal with both the _accountMap and the Configuration */
std::string accountType = (*details.find(CONFIG_ACCOUNT_TYPE)).second;
Account* newAccount;
std::stringstream accountID;
accountID << "Account:" << time(NULL);
AccountID newAccountID = accountID.str();
/** @todo Verify the uniqueness, in case a program adds accounts, two in a row. */
if (accountType == "SIP") {
if(!_userAgentInitlized) {
// Initialize the SIP Manager
_userAgent = new UserAgent();
_userAgent->setSipPort(Manager::instance().getConfigInt(PREFERENCES , CONFIG_SIP_PORT));
}
newAccount = AccountCreator::createAccount(AccountCreator::SIP_ACCOUNT, newAccountID);
}
else if (accountType == "IAX") {
newAccount = AccountCreator::createAccount(AccountCreator::IAX_ACCOUNT, newAccountID);
}
else {
_debug("Unknown %s param when calling addAccount(): %s\n", CONFIG_ACCOUNT_TYPE, accountType.c_str());
return;
}
_accountMap[newAccountID] = newAccount;
setAccountDetails(accountID.str(), details);
saveConfig();
if (accountType == "SIP") {
newAccount = AccountCreator::createAccount(AccountCreator::SIP_ACCOUNT, newAccountID);
}
else if (accountType == "IAX") {
newAccount = AccountCreator::createAccount(AccountCreator::IAX_ACCOUNT, newAccountID);
}
else {
_debug("Unknown %s param when calling addAccount(): %s\n", CONFIG_ACCOUNT_TYPE, accountType.c_str());
return;
}
_accountMap[newAccountID] = newAccount;
setAccountDetails(accountID.str(), details);
if (_dbus) _dbus->getConfigurationManager()->accountsChanged();
saveConfig();
//restartPjsip();
if (_dbus) _dbus->getConfigurationManager()->accountsChanged();
}
void
......@@ -2192,20 +2126,6 @@ ManagerImpl::getNewCallID()
return random_id.str();
}
void
ManagerImpl::restartPjsip()
{
if ( _userAgentInitlized ){
unregisterCurSIPAccounts();
_userAgent->sipDestory();
//_userAgent->setSipPort(Manager::instance().getConfigInt(PREFERENCES , CONFIG_SIP_PORT));
_userAgent->sipCreate();
_userAgent->sipInit();
registerCurSIPAccounts();
}
}
short
ManagerImpl::loadAccountMap()
{
......@@ -2214,7 +2134,6 @@ ManagerImpl::loadAccountMap()
TokenList sections = _config.getSections();
std::string accountType;
Account* tmpAccount;
std::string port;
TokenList::iterator iter = sections.begin();
while(iter != sections.end()) {
......@@ -2226,28 +2145,7 @@ ManagerImpl::loadAccountMap()
accountType = getConfigString(*iter, CONFIG_ACCOUNT_TYPE);
if (accountType == "SIP") {
if(!_userAgentInitlized) {
// Initialize the SIP Manager
_userAgent = new UserAgent();
_userAgentInitlized = true;
_userAgent->setSipPort(Manager::instance().getConfigInt(PREFERENCES , CONFIG_SIP_PORT));
}
tmpAccount = AccountCreator::createAccount(AccountCreator::SIP_ACCOUNT, *iter);
// Determine whether to use stun for the current account or not
int useStun = Manager::instance().getConfigInt(tmpAccount->getAccountID(),SIP_USE_STUN);
if(useStun == 1) {
_userAgent->setStunServer(Manager::instance().getConfigString(tmpAccount->getAccountID(), SIP_STUN_SERVER).data());
}
/*// Set registration port for all accounts, The last non-5060 port will be recorded in _userAgent.
port = Manager::instance().getConfigString(tmpAccount->getAccountID(), SIP_PORT);
std::istringstream is(port);
is >> iPort;
if (iPort != DEFAULT_SIP_PORT)
_userAgent->setRegPort(iPort); */
}
else if (accountType == "IAX") {
tmpAccount = AccountCreator::createAccount(AccountCreator::IAX_ACCOUNT, *iter);
......@@ -2262,8 +2160,6 @@ ManagerImpl::loadAccountMap()
nbAccount++;
}
_debug("\n");
iter++;
}
......@@ -2351,37 +2247,6 @@ pjsip_regc
return NULL;
}
/**
* Return the instance of sip manager
*/
UserAgent *ManagerImpl::getUserAgent()
{
return _userAgent;
}
int
ManagerImpl::getSipPort()
{
if( _userAgent )
return _userAgent->getSipPort();
else
{
// It means that no SIP accounts are configured, so return a default value
return 0;
}
}
void
ManagerImpl::setSipPort(int portNum)
{
if(portNum != _userAgent->getSipPort()) {
_userAgent->setSipPort(portNum);
restartPjsip();
setConfig( PREFERENCES , CONFIG_SIP_PORT , portNum );
}
}
void ManagerImpl::unregisterCurSIPAccounts()
{
AccountMap::iterator iter = _accountMap.begin();
......
......@@ -47,7 +47,6 @@ class CodecDescriptor;
class GuiFramework;
class TelephoneTone;
class VoIPLink;
class UserAgent;
#ifdef USE_ZEROCONF