Commit 9aa98b7b authored by Emmanuel Milou's avatar Emmanuel Milou

Migrate to 1->N relationship between voiplink and accounts

parent 54dd1aec
......@@ -22,9 +22,10 @@
#include "account.h"
#include "manager.h"
Account::Account(const AccountID& accountID) :
_accountID(accountID), _link(NULL), _enabled(false)
Account::Account(const AccountID& accountID, std::string type) :
_accountID(accountID), _link(NULL), _enabled(false), _type(type)
{
setRegistrationState(VoIPLink::Unregistered);
}
Account::~Account()
......
......@@ -38,6 +38,19 @@ class VoIPLink;
typedef std::string AccountID;
/** Contains all the state an Voip can be in */
typedef enum RegistrationState {
Unregistered,
Trying,
Registered,
Error,
ErrorAuth ,
ErrorNetwork ,
ErrorHost,
ErrorExistStun,
ErrorConfStun
} RegistrationState;
#define AccountNULL ""
// Common account parameters
......@@ -59,7 +72,7 @@ class Account{
public:
Account(const AccountID& accountID);
Account(const AccountID& accountID, std::string type);
/**
* Virtual destructor
......@@ -106,10 +119,31 @@ class Account{
* Get the registration state of the specified link
* @return RegistrationState The registration state of underlying VoIPLink
*/
VoIPLink::RegistrationState getRegistrationState() { return _link->getRegistrationState(); }
inline RegistrationState getRegistrationState() { return _registrationState; }
private:
inline void setRegistrationState( RegistrationState state ) {
_registrationState = state;
// Notify the client
Manager::instance().connectionStatusNotification( );
}
inline std::string getUsername( void ) { return _username; }
inline void setUsername( std::string username) { _username = username; }
inline std::string getHostname( void ) { return _hostname; }
inline void setHostname( std::string hostname) { _hostname = hostname; }
inline std::string getPassword( void ) { return _password; }
inline void setPassword( std::string password ) { _password = password; }
inline std::string getAlias( void ) { return _alias; }
inline void setAlias( std::string alias ) { _alias = alias; }
inline std::string getType( void ) { return _type; }
inline void setType( std::string type ) { _type = type; }
private:
// copy constructor
Account(const Account& rh);
......@@ -122,6 +156,32 @@ class Account{
*/
AccountID _accountID;
/**
* Account login information: username
*/
std::string _username;
/**
* Account login information: hostname
*/
std::string _hostname;
/**
* Account login information: password
*/
std::string _password;
/**
* Account login information: Alias
*/
std::string _alias;
/*
* The account type
* IAX2 or SIP
*/
std::string _type;
/**
* Voice over IP Link contains a listener thread and calls
*/
......@@ -134,6 +194,11 @@ class Account{
*/
bool _enabled;
/*
* The registration state of the account
*/
RegistrationState _registrationState;
};
#endif
......@@ -20,31 +20,22 @@
#include "eventthread.h"
#include "voiplink.h"
/********************************** IAX Voiplink thread *************************************/
/**
* Reimplementation of run()
*/
void IAXEventThread::run (void)
/********************************** Voiplink thread *************************************/
EventThread::EventThread( VoIPLink *link )
: Thread(), _linkthread(link)
{
while(!testCancel()) {
_linkthread->getEvent();
}
}
/********************************************************************************************/
setCancel( cancelDeferred );
}
/********************************** SIP Voiplink thread *************************************/
/**
* Reimplementation of run()
*/
void SIPEventThread::run (void)
void EventThread::run (void)
{
while(!testCancel()) {
_linkthread->getEvent();
}
}
}
/********************************************************************************************/
......@@ -31,23 +31,17 @@ class VoIPLink;
class EventThread : public ost::Thread {
friend class SIPEventThread;
friend class IAXEventThread;
public:
/**
* Thread constructor
*/
EventThread (VoIPLink* link) : Thread(), _linkthread(link){
setCancel( cancelDeferred );
}
EventThread (VoIPLink* link);
virtual ~EventThread (void){
~EventThread (void){
terminate();
}
virtual void run () = 0;
virtual void run () ;
private:
EventThread(const EventThread& rh); // copy constructor
......@@ -57,25 +51,5 @@ class EventThread : public ost::Thread {
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__
......@@ -23,7 +23,7 @@
#include "iaxvoiplink.h"
IAXAccount::IAXAccount(const AccountID& accountID)
: Account(accountID)
: Account(accountID, "iax2")
{
_link = new IAXVoIPLink(accountID);
}
......@@ -35,8 +35,7 @@ IAXAccount::~IAXAccount()
_link = NULL;
}
int
IAXAccount::registerVoIPLink()
int IAXAccount::registerVoIPLink()
{
IAXVoIPLink *thislink;
......
......@@ -45,7 +45,7 @@
IAXVoIPLink::IAXVoIPLink(const AccountID& accountID)
: VoIPLink(accountID)
{
_evThread = new IAXEventThread(this);
_evThread = new EventThread(this);
_regSession = NULL;
_nextRefreshStamp = 0;
......@@ -207,7 +207,7 @@ IAXVoIPLink::getEvent()
// Refresh registration.
if (_nextRefreshStamp && _nextRefreshStamp - 2 < time(NULL)) {
sendRegister();
sendRegister(-1);
}
// thread wait 3 millisecond
......@@ -308,7 +308,7 @@ IAXVoIPLink::getIAXCall(const CallID& id)
int
IAXVoIPLink::sendRegister()
IAXVoIPLink::sendRegister(AccountID id UNUSED)
{
bool result = false;
if (_host.empty()) {
......
......@@ -76,7 +76,7 @@ class IAXVoIPLink : public VoIPLink
* Send out registration
* @return bool The new registration state (are we registered ?)
*/
int sendRegister (void);
int sendRegister (AccountID id);
/**
* Destroy registration session
......
......@@ -680,7 +680,7 @@ ManagerImpl::startVoiceMessageNotification(const AccountID& accountId, int nb_ms
if (_dbus) _dbus->getCallManager()->voiceMailNotify(accountId, nb_msg) ;
}
void ManagerImpl::connectionStatusNotification( void )
void ManagerImpl::connectionStatusNotification( )
{
if (_dbus)
_dbus->getConfigurationManager()->accountsChanged();
......@@ -1701,88 +1701,6 @@ int ManagerImpl::getSipPort( void )
}
/**
* configuration function requests
* Main Thread
*/
bool
ManagerImpl::getZeroconf(const std::string& sequenceId)
{
bool returnValue = false;
#ifdef USE_ZEROCONF
int useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
if (useZeroconf && _dbus != NULL) {
TokenList arg;
TokenList argTXT;
std::string newService = "new service";
std::string newTXT = "new txt record";
if (!_DNSService->isStart()) { _DNSService->startScanServices(); }
DNSServiceMap services = _DNSService->getServices();
DNSServiceMap::iterator iter = services.begin();
arg.push_back(newService);
while(iter!=services.end()) {
arg.push_front(iter->first);
//_gui->sendMessage("100",sequenceId,arg);
arg.pop_front(); // remove the first, the name
TXTRecordMap record = iter->second.getTXTRecords();
TXTRecordMap::iterator iterTXT = record.begin();
while(iterTXT!=record.end()) {
argTXT.clear();
argTXT.push_back(iter->first);
argTXT.push_back(iterTXT->first);
argTXT.push_back(iterTXT->second);
argTXT.push_back(newTXT);
// _gui->sendMessage("101",sequenceId,argTXT);
iterTXT++;
}
iter++;
}
returnValue = true;
}
#else
(void)sequenceId;
#endif
return returnValue;
}
/**
* Main Thread
*/
bool
ManagerImpl::attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer)
{
bool returnValue = false;
// don't need the _gui like getZeroconf function
// because Observer is here
#ifdef USE_ZEROCONF
int useZeroconf = getConfigInt(PREFERENCES, CONFIG_ZEROCONF);
if (useZeroconf) {
if (!_DNSService->isStart()) { _DNSService->startScanServices(); }
_DNSService->attach(observer);
returnValue = true;
}
#else
(void)sequenceId;
(void)observer;
#endif
return returnValue;
}
bool
ManagerImpl::detachZeroconfEvents(Pattern::Observer& observer)
{
bool returnValue = false;
#ifdef USE_ZEROCONF
if (_DNSService) {
_DNSService->detach(observer);
returnValue = true;
}
#else
(void)observer;
#endif
return returnValue;
}
// TODO: rewrite this
/**
* Main Thread
......@@ -2227,8 +2145,25 @@ ManagerImpl::getAccountIdFromNameAndServer(const std::string& userName, const st
return AccountNULL;
}
VoIPLink*
ManagerImpl::getAccountLink(const AccountID& accountID)
AccountMap ManagerImpl::getSipAccountMap( void )
{
AccountMap::iterator iter;
AccountMap sipaccounts;
AccountID id;
Account *account;
for(iter = _accountMap.begin(); iter != _accountMap.end(); ++iter) {
if( iter->second->getType() == "sip" ){
//id = iter->first;
//account = iter->second;
//sipaccounts.insert( std::pair<id, account> );
}
}
return sipaccounts;
}
VoIPLink* ManagerImpl::getAccountLink(const AccountID& accountID)
{
Account* acc = getAccount(accountID);
if ( acc ) {
......
......@@ -271,9 +271,6 @@ class ManagerImpl {
*/
void sendRegister( const ::std::string& accountId , const int32_t& expire );
bool getZeroconf(const std::string& sequenceId);
bool attachZeroconfEvents(const std::string& sequenceId, Pattern::Observer& observer);
bool detachZeroconfEvents(Pattern::Observer& observer);
bool getCallStatus(const std::string& sequenceId);
/**
......@@ -798,6 +795,11 @@ class ManagerImpl {
void registerCurSIPAccounts();
/**
* Returns a map with only the existing SIP accounts
*/
AccountMap getSipAccountMap( void );
private:
/**
......
......@@ -25,9 +25,7 @@
#include "user_cfg.h"
SIPAccount::SIPAccount(const AccountID& accountID)
: Account(accountID)
, _userName("")
, _server("")
: Account(accountID, "sip")
, _cred(NULL)
, _contact("")
{
......@@ -46,56 +44,51 @@ SIPAccount::~SIPAccount()
int SIPAccount::registerVoIPLink()
{
int status, useStun;
SIPVoIPLink *thislink;
/* Retrieve the account information */
_link->setHostname(Manager::instance().getConfigString(_accountID,HOSTNAME));
useStun = Manager::instance().getConfigInt(_accountID,SIP_USE_STUN);
/* Stuff needed for SIP registration */
setHostname(Manager::instance().getConfigString(_accountID,HOSTNAME));
setUsername(Manager::instance().getConfigString(_accountID, USERNAME));
setPassword(Manager::instance().getConfigString(_accountID, PASSWORD));
/* Retrieve STUN stuff */
/* STUN configuration is attached to a voiplink because it is applied to every accounts (PJSIP limitation)*/
thislink = dynamic_cast<SIPVoIPLink*> (_link);
thislink->setStunServer(Manager::instance().getConfigString(_accountID,SIP_STUN_SERVER));
thislink->setUseStun( useStun!=0 ? true : false);
if (thislink) {
useStun = Manager::instance().getConfigInt(_accountID,SIP_USE_STUN);
thislink->setStunServer(Manager::instance().getConfigString(_accountID,SIP_STUN_SERVER));
thislink->setUseStun( useStun!=0 ? true : false);
}
/* Link initialization */
_link->init();
// Stuff needed for SIP registration.
thislink->setUsername(Manager::instance().getConfigString(_accountID, USERNAME));
thislink->setPassword(Manager::instance().getConfigString(_accountID, PASSWORD));
thislink->setHostname(Manager::instance().getConfigString(_accountID, HOSTNAME));
// Start registration
status = _link->sendRegister();
/* Start registration */
status = _link->sendRegister( _accountID );
ASSERT( status , SUCCESS );
return SUCCESS;
}
int
SIPAccount::unregisterVoIPLink()
int SIPAccount::unregisterVoIPLink()
{
_debug("SIPAccount: unregister account %s\n" , getAccountID().c_str());
_link->sendUnregister();
return SUCCESS;
return _link->sendUnregister();
}
void
SIPAccount::loadConfig()
void SIPAccount::loadConfig()
{
// Account generic
Account::loadConfig();
}
bool
SIPAccount::fullMatch(const std::string& userName, const std::string& server)
bool SIPAccount::fullMatch(const std::string& username, const std::string& hostname)
{
return (userName == _userName && server == _server);
return (username == getUsername() && hostname == getHostname());
}
bool
SIPAccount::userMatch(const std::string& userName)
bool SIPAccount::userMatch(const std::string& username)
{
return (userName == _userName);
return (username == getUsername());
}
......@@ -33,69 +33,75 @@ class SIPVoIPLink;
/**
* @file sipaccount.h
* @brief A SIP Account specify SIP specific functions and object (SIPCall/SIPVoIPLink)
*/
*/
class SIPAccount : public Account
{
public:
/**
* Constructor
* @param accountID The account identifier
*/
SIPAccount(const AccountID& accountID);
/* Copy Constructor */
SIPAccount(const SIPAccount& rh);
public:
/**
* Constructor
* @param accountID The account identifier
*/
SIPAccount(const AccountID& accountID);
/* Assignment Operator */
SIPAccount& operator=( const SIPAccount& rh);
/**
* Virtual destructor
*/
virtual ~SIPAccount();
/* Copy Constructor */
SIPAccount(const SIPAccount& rh);
/**
* Actually unuseful, since config loading is done in init()
*/
void loadConfig();
/* Assignment Operator */
SIPAccount& operator=( const SIPAccount& rh);
/**
* Initialize the SIP voip link with the account parameters and send registration
*/
int registerVoIPLink();
/**
* Virtual destructor
*/
virtual ~SIPAccount();
/**
* Send unregistration and clean all related stuff ( calls , thread )
*/
int unregisterVoIPLink();
/**
* Actually unuseful, since config loading is done in init()
*/
void loadConfig();
/**
* Initialize the SIP voip link with the account parameters and send registration
*/
int registerVoIPLink();
void setUserName(const std::string &name) {_userName = name;}
/**
* Send unregistration and clean all related stuff ( calls , thread )
*/
int unregisterVoIPLink();
std::string getUserName() {return _userName;}
inline void setCredInfo(pjsip_cred_info *cred) {_cred = cred;}
inline pjsip_cred_info *getCredInfo() {return _cred;}
void setServer(const std::string &server) {_server = server;}
inline void setContact(const std::string &contact) {_contact = contact;}
inline std::string getContact() {return _contact;}
std::string getServer() {return _server;}
bool fullMatch(const std::string& username, const std::string& hostname);
bool userMatch(const std::string& username);
void setCredInfo(pjsip_cred_info *cred) {_cred = cred;}
inline std::string getHostname( void ) { return _hostname; }
inline void setHostname( std::string hostname) { _hostname = hostname; }
pjsip_cred_info *getCredInfo() {return _cred;}
inline std::string getPassword( void ) { return _password; }
inline void setPassword( std::string password ) { _password = password; }
void setContact(const std::string contact) {_contact = contact;}
inline std::string getAlias( void ) { return _alias; }
inline void setAlias( std::string alias ) { _alias = alias; }
std::string getContact() {return _contact;}
inline std::string getType( void ) { return _type; }
inline void setType( std::string type ) { _type = type; }
bool fullMatch(const std::string& userName, const std::string& server);
bool userMatch(const std::string& userName);
private:
/**
* Credential information
*/
pjsip_cred_info *_cred;
private:
std::string _userName;
std::string _server;
pjsip_cred_info *_cred;
std::string _contact;
/*
* SIP address
*/
std::string _contact;
};
#endif
......@@ -2,8 +2,7 @@
* Copyright (C) 2004-2009 Savoir-Faire Linux inc.
*
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
* Author: Yan Morin <yan.morin@savoirfairelinux.com>
* Author : Laurielle Lea <laurielle.lea@savoirfairelinux.com>
* Author: Yun Liu <yun.liu@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
......@@ -75,26 +74,23 @@ void xfer_svr_cb(pjsip_evsub *sub, pjsip_event *event);
void onCallTransfered(pjsip_inv_session *inv, pjsip_rx_data *rdata);
/*******************************/
SIPVoIPLink::SIPVoIPLink(const AccountID& accountID)
: VoIPLink(accountID)
, _initDone(false)
, _nbTryListenAddr(2) // number of times to try to start SIP listener
, _stunServer("")
, _localExternAddress("")
, _stunServer("")
, _localExternAddress("")
, _localExternPort(0)
, _audiortp(new AudioRtp())
, _regc()
, _bRegister(false)
,_regPort(DEFAULT_SIP_PORT)
,_regPort(DEFAULT_SIP_PORT)
{
// to get random number for RANDOM_PORT
srand (time(NULL));
_useStun = false;
_localIPAddress = "127.0.0.1";
_evThread = new SIPEventThread(this);
_evThread = new EventThread(this);
}
SIPVoIPLink::~SIPVoIPLink()
......@@ -113,13 +109,14 @@ SIPVoIPLink* SIPVoIPLink::instance( const AccountID& id){
bool SIPVoIPLink::init()
{
if(_initDone)
return false;
/* Initialize the pjsip library */
if( !isInitDone() ){
_regc = NULL;
pjsip_init();
}
_regc = NULL;
if(!pjsip_init())
return false;
setInitState(true);
_initDone = true;
return true;
}
......@@ -127,7 +124,8 @@ bool SIPVoIPLink::init()
SIPVoIPLink::terminate()
{
/* Clean shutdown of pjsip library */
pjsip_shutdown();
if( _initDone )
pjsip_shutdown();
_initDone = false;
}
......@@ -167,10 +165,8 @@ SIPVoIPLink::getEvent()
_mutexSIP.leaveMutex();
}
int SIPVoIPLink::sendRegister()
int SIPVoIPLink::sendRegister( AccountID id )
{
AccountID id;
pj_status_t status;
int expire_value;
char contactTmp[256];
......@@ -179,11 +175,10 @@ int SIPVoIPLink::sendRegister()
std::string tmp, hostname, username, password;
SIPAccount *account;
/* Get the current account ID */
id = getAccountID();
hostname = getHostname();
username = getUsername();
password = getPassword();
account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(id));
hostname = account->getHostname();
username = account->getUsername();
password = account->getPassword();
_mutexSIP.enterMutex();
......@@ -209,6 +204,7 @@ int SIPVoIPLink::sendRegister()
return false;
}
/* Create the registration according to the account ID */
status = pjsip_regc_create(_endpt, (void*)new AccountID(id), &regc_cb, &_regc);
if (status != PJ_SUCCESS) {
_debug("UserAgent: Unable to create regc.\n");
......@@ -224,6 +220,7 @@ int SIPVoIPLink::sendRegister()
sprintf(contactTmp, "<sip:%s@%s:%d>", username.data(), _localExternAddress.data(), _localExternPort);
pj_strdup2(_pool, &contact, contactTmp);
account->setContact(contactTmp);
status = pjsip_regc_init(_regc, &svr, &aor, &aor, 1, &contact, 600); //timeout);
if (status != PJ_SUCCESS) {
......@@ -232,7 +229,6 @@ int SIPVoIPLink::sendRegister()
return false;
}
account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount(id));
pjsip_cred_info *cred = account->getCredInfo();
if(!cred)
......@@ -261,46 +257,18 @@ int SIPVoIPLink::sendRegister()
_mutexSIP.leaveMutex();
return false;
}
account->setUserName(username);
account->setServer(hostname);
account->setContact(contactTmp);