diff --git a/daemon/src/account.h b/daemon/src/account.h index c8db6fbbeb36a070ea8963faca2ee97ef89d5c79..f2898227cde8e857d81975418f68f7893c4da967 100644 --- a/daemon/src/account.h +++ b/daemon/src/account.h @@ -193,19 +193,17 @@ class Account : public Serializable return link_; } - virtual void setVoIPLink () = 0; - /** * Register the underlying VoIPLink. Launch the event listener. * This should update the getRegistrationState() return value. */ - virtual int registerVoIPLink() = 0; + virtual void registerVoIPLink() = 0; /** * Unregister the underlying VoIPLink. Stop the event listener. * This should update the getRegistrationState() return value. */ - virtual int unregisterVoIPLink() = 0; + virtual void unregisterVoIPLink() = 0; /** * Tell if the account is enable or not. diff --git a/daemon/src/config/yamlparser.cpp b/daemon/src/config/yamlparser.cpp index 77bf56f3ebd7089adbd0a6adb6d0770ff511514e..d4462b77a66f43787278387d47dfde3286ab0cfd 100644 --- a/daemon/src/config/yamlparser.cpp +++ b/daemon/src/config/yamlparser.cpp @@ -39,7 +39,6 @@ namespace Conf { YamlParser::YamlParser (const char *file) : filename (file) - , fd(NULL) , events() , eventNumber (0) , doc (NULL) @@ -53,7 +52,6 @@ YamlParser::YamlParser (const char *file) : filename (file) , shortcutNode (NULL) { fd = fopen (filename.c_str(), "rb"); - if (!fd) throw YamlParserException ("Could not open file descriptor"); @@ -65,11 +63,7 @@ YamlParser::YamlParser (const char *file) : filename (file) YamlParser::~YamlParser() { - if (!fd) - throw YamlParserException ("File descriptor not valid"); - - if (fclose (fd)) - throw YamlParserException ("Error closing file descriptor"); + fclose (fd); yaml_parser_delete (&parser); @@ -79,7 +73,6 @@ YamlParser::~YamlParser() if (doc) { doc->deleteChildNodes(); delete doc; - doc = NULL; } } diff --git a/daemon/src/eventthread.cpp b/daemon/src/eventthread.cpp index d80c4423c891cbdb628361cf7bb3bcbf46b2194e..39db9f4087bed54042fe550d7b926503e38b95b2 100644 --- a/daemon/src/eventthread.cpp +++ b/daemon/src/eventthread.cpp @@ -33,7 +33,7 @@ /********************************** Voiplink thread *************************************/ EventThread::EventThread (VoIPLink *link) - : Thread(), _linkthread (link) + : Thread(), _link (link) { setCancel (cancelDeferred); } @@ -44,9 +44,7 @@ EventThread::EventThread (VoIPLink *link) */ void EventThread::run (void) { - while (!testCancel()) { - if (_linkthread) - _linkthread->getEvent(); - } + while (!testCancel()) + _link->getEvent(); } diff --git a/daemon/src/eventthread.h b/daemon/src/eventthread.h index 3553f59f61a4952223d7f1f6a1ecbdc5f0ea1e4e..e73a577bbba8f1a3c205f4ea2b1696d3bb6a3fbf 100644 --- a/daemon/src/eventthread.h +++ b/daemon/src/eventthread.h @@ -61,7 +61,7 @@ class EventThread : public ost::Thread EventThread& operator= (const EventThread& rh); // assignment operator /** VoIPLink is the object being called by getEvents() method */ - VoIPLink* _linkthread; + VoIPLink* _link; }; #endif // __EVENT_THREAD_H__ diff --git a/daemon/src/hooks/urlhook.cpp b/daemon/src/hooks/urlhook.cpp index d871b145bf76960a361c52c72988ae1b623238c2..eeecb581267cf1b066dfed2b20407b6e4d4f60f4 100644 --- a/daemon/src/hooks/urlhook.cpp +++ b/daemon/src/hooks/urlhook.cpp @@ -29,47 +29,13 @@ */ #include "urlhook.h" -#include <iostream> -#include <vector> +#include <cstdlib> -UrlHook::UrlHook () { } - -UrlHook::~UrlHook () { } - -int UrlHook::addAction (std::string field_value, std::string command) +void UrlHook::runAction (std::string command, std::string args) { - - std::string command_bg; - std::string temp; - std::vector <std::string> args; - size_t pos; - unsigned int i; - - /* Escape the '&' char to not discard $_GET parameters in the URL - #2659 */ - while ( (pos = field_value.find ("&", 0)) != std::string::npos) { - temp = field_value.substr (0, pos); - field_value.erase (0, pos + 1); - args.push_back (temp); - } - - command_bg = command + " "; - - pos = args.size (); - - for (i=0; i<pos; i++) { - // Escape the "&" - command_bg += args[i] + "\\&"; - } - - // Retrieve the last argument - command_bg += field_value; - - /* Execute the command in the background to not block the application */ - command_bg += "&"; - - /* Execute a system call */ - return RUN_COMMAND (command_bg.c_str()); - + //FIXME : use fork and execve, so no need to escape shell arguments + std::string cmd = command + "\"" + args + "\" &"; + system(cmd.c_str()); } diff --git a/daemon/src/hooks/urlhook.h b/daemon/src/hooks/urlhook.h index 80e33817acc207f684262a7c971d2fb8e6e36e51..c29637db32f9345357a36293e45a415219917b14 100644 --- a/daemon/src/hooks/urlhook.h +++ b/daemon/src/hooks/urlhook.h @@ -32,27 +32,11 @@ #define URL_HOOK_H #include <string> -#include <stdlib.h> - -#define RUN_COMMAND(command) system(command); class UrlHook { - - public: - /** - * Constructor - */ - UrlHook (); - - /** - * Destructor - */ - ~UrlHook (); - - int addAction (std::string, std::string); - - private: +public: + static void runAction (std::string, std::string); }; #endif // URL_HOOK_H diff --git a/daemon/src/iax/iaxaccount.cpp b/daemon/src/iax/iaxaccount.cpp index c93eff2f9fdd328b9b38309301e2486e26c891ff..71ddb8d68a24b58df77cd27cc1dff1ea48ff54c4 100644 --- a/daemon/src/iax/iaxaccount.cpp +++ b/daemon/src/iax/iaxaccount.cpp @@ -143,38 +143,27 @@ std::map<std::string, std::string> IAXAccount::getAccountDetails() const return a; } - -void IAXAccount::setVoIPLink() -{ -} - -int IAXAccount::registerVoIPLink() +void IAXAccount::registerVoIPLink() { try { link_->init(); - link_->sendRegister (this); } catch (const VoipLinkException &e) { _error("IAXAccount: %s", e.what()); } - - return 0; } -int +void IAXAccount::unregisterVoIPLink() { try { link_->sendUnregister (this); link_->terminate(); - return 0; } catch (const VoipLinkException &e) { _error("IAXAccount: %s", e.what()); } - - return 0; } void diff --git a/daemon/src/iax/iaxaccount.h b/daemon/src/iax/iaxaccount.h index b3121d948a98fc20c204295eea0253c03e07bc13..2b14744898ac2f3fd6eacf65e8f50f7f30bcfc1a 100644 --- a/daemon/src/iax/iaxaccount.h +++ b/daemon/src/iax/iaxaccount.h @@ -52,8 +52,6 @@ class IAXAccount : public Account std::map<std::string, std::string> getAccountDetails() const; - void setVoIPLink (); - /** * Actually useless, since config loading is done in init() */ @@ -62,12 +60,12 @@ class IAXAccount : public Account /** * Register an account */ - int registerVoIPLink(); + void registerVoIPLink(); /** * Unregister an account */ - int unregisterVoIPLink(); + void unregisterVoIPLink(); std::string getPassword (void) const { return password_; diff --git a/daemon/src/iax/iaxvoiplink.cpp b/daemon/src/iax/iaxvoiplink.cpp index 9d5dc005e47c335fa559754cad8aebb3eae14897..faadde68d2c00102a25483ffe92444b5d7d6907c 100644 --- a/daemon/src/iax/iaxvoiplink.cpp +++ b/daemon/src/iax/iaxvoiplink.cpp @@ -64,7 +64,6 @@ IAXVoIPLink::IAXVoIPLink (const std::string& accountID) : VoIPLink () , audiolayer (NULL) , converter (NULL) , converterSamplingRate (0) - , urlhook (NULL) , _accountID(accountID) { _evThread = new EventThread (this); @@ -73,7 +72,6 @@ IAXVoIPLink::IAXVoIPLink (const std::string& accountID) : VoIPLink () srand (time (NULL)); converter = new SamplerateConverter (44100); - urlhook = new UrlHook (); } @@ -611,17 +609,10 @@ IAXVoIPLink::iaxFindCallBySession (struct iax_session* session) // access to callMap shoud use that // the code below is like findSIPCallWithCid() ost::MutexLock m (_callMapMutex); - IAXCall* call = NULL; - CallMap::iterator iter = _callMap.begin(); - - while (iter != _callMap.end()) { - call = dynamic_cast<IAXCall*> (iter->second); - - if (call && call->getSession() == session) { + for (CallMap::iterator iter = _callMap.begin(); iter != _callMap.end(); ++iter) { + IAXCall* call = dynamic_cast<IAXCall*> (iter->second); + if (call && call->getSession() == session) return call; - } - - iter++; } return NULL; // not found @@ -740,9 +731,9 @@ IAXVoIPLink::iaxHandleCallEvent (iax_event* event, IAXCall* call) case IAX_EVENT_URL: if (Manager::instance().getConfigString (HOOKS, URLHOOK_IAX2_ENABLED) == "1") { - if (strcmp ( (char*) event->data, "") != 0) { + if (*event->data) { _debug ("> IAX_EVENT_URL received: %s", event->data); - urlhook->addAction ( (char*) event->data, Manager::instance().getConfigString (HOOKS, URLHOOK_COMMAND)); + UrlHook::runAction (Manager::instance().getConfigString (HOOKS, URLHOOK_COMMAND), (char*) event->data); } } diff --git a/daemon/src/iax/iaxvoiplink.h b/daemon/src/iax/iaxvoiplink.h index 1cacf6b243f7d8f6925face6b5f0dbee6d19c6f5..1370387bb9e30b872b752af34b7f0f0acc5f074e 100644 --- a/daemon/src/iax/iaxvoiplink.h +++ b/daemon/src/iax/iaxvoiplink.h @@ -296,8 +296,11 @@ class IAXVoIPLink : public VoIPLink int converterSamplingRate; - /* URL hook */ - UrlHook *urlhook; + /** Whether init() was called already or not + * This should be used in init() and terminate(), to + * indicate that init() was called, or reset by terminate(). + */ + bool _initDone; const std::string _accountID; }; diff --git a/daemon/src/logger.h b/daemon/src/logger.h index 371f9d39190ec12c8de92d6b254e900f483c0906..8ea3909581d4d28c052be359a39d74092059577a 100644 --- a/daemon/src/logger.h +++ b/daemon/src/logger.h @@ -47,8 +47,8 @@ void setDebugMode (bool); #define _debug(...) Logger::log(LOG_DEBUG, __VA_ARGS__) #define _debugException(...) Logger::log(LOG_DEBUG, __VA_ARGS__) -#define _debugInit(...) Logger::log(LOG_DEBUG, __VA_ARGS__) -#define _debugAlsa(...) Logger::log(LOG_DEBUG, __VA_ARGS__) +#define _debugInit(...) Logger::log(LOG_DEBUG, __VA_ARGS__) +#define _debugAlsa(...) Logger::log(LOG_DEBUG, __VA_ARGS__) #define BLACK "\033[22;30m" #define RED "\033[22;31m" diff --git a/daemon/src/main.cpp b/daemon/src/main.cpp index 63fb68b4734620a45c815eea344bf64e5b73bcbe..b63375421a58e5e557bcb23bc87b2fc504b24b39 100644 --- a/daemon/src/main.cpp +++ b/daemon/src/main.cpp @@ -58,123 +58,87 @@ ost::CommandOptionNoArg help ( "help", "h", "Print help" ); +// returns true if directory exists +static bool check_dir(const char *path) +{ + DIR *dir = opendir (path); + + if (!dir) { // doesn't exist + if (mkdir (path, 0755) != 0) { // couldn't create the dir + perror(path); + return false; + } + } else { + closedir(dir); + } + + return true; +} + int main (int argc, char **argv) { set_program_dir(argv[0]); - - Logger::setConsoleLog (false); - Logger::setDebugMode (false); - // makeCommandOptionParse allocates the object with operator new, so // auto_ptr is fine in this context. // TODO: This should eventually be replaced with std::unique_ptr for C++0x std::auto_ptr<ost::CommandOptionParse> args(ost::makeCommandOptionParse (argc, argv, "")); - printf ("SFLphone Daemon %s, by Savoir-Faire Linux 2004-2011\n", VERSION); - printf ("http://www.sflphone.org/\n"); + printf ("SFLphone Daemon "VERSION", by Savoir-Faire Linux 2004-2011\n" \ + "http://www.sflphone.org/\n"); if (help.numSet) { std::cerr << args->printUsage(); return 0; - } - else if (args->argsHaveError()) { + } else if (args->argsHaveError()) { std::cerr << args->printErrors(); std::cerr << args->printUsage(); return 1; } - if (console.numSet) - Logger::setConsoleLog (true); - - if (debug.numSet) - Logger::setDebugMode (true); - - FILE *fp; - char homepid[128]; - char sfldir[128]; - - unsigned int iPid = getpid(); - char cPid[64], cOldPid[64]; - snprintf (cPid, sizeof (cPid), "%d", iPid); - std::string xdg_cache, xdg_env, path; - - xdg_cache = std::string (HOMEDIR) + DIR_SEPARATOR_STR + ".cache/"; - - if (XDG_CACHE_HOME != NULL) { - xdg_env = std::string (XDG_CACHE_HOME); - (xdg_env.length() > 0) ? path = xdg_env - : path = xdg_cache; - } else - path = xdg_cache; - - // Use safe sprintf (Contribution #4952, Brendan Smith) - snprintf (sfldir, sizeof (sfldir), "%s", path.c_str ()); - - path = path + "sflphone"; - - // Use safe sprintf (Contribution #4952, Brendan Smith) - snprintf (homepid, sizeof (homepid), "%s/%s", path.c_str (), PIDFILE); - - if ( (fp = fopen (homepid,"r")) == NULL) { - // Check if $XDG_CACHE_HOME directory exists or not. - DIR *dir; - - if ( (dir = opendir (sfldir)) == NULL) { - //Create it - if (mkdir (sfldir, 0755) != 0) { - fprintf (stderr, "Creating directory %s failed. Exited.", sfldir); - return 1; - } - } - - // Then create the sflphone directory inside the $XDG_CACHE_HOME dir - snprintf (sfldir, sizeof (sfldir), "%s", path.c_str ()); - - if ( (dir = opendir (sfldir)) == NULL) { - //Create it - if (mkdir (sfldir, 0755) != 0) { - fprintf (stderr, "Creating directory %s failed. Exited.", sfldir); - return 1; - } - } - - // PID file doesn't exists, create and write pid in it - if ( (fp = fopen (homepid,"w")) == NULL) { - fprintf (stderr, "Creating PID file %s failed. Exited.", homepid); - return 1; - } else { - fputs (cPid , fp); - fclose (fp); - } + Logger::setConsoleLog (console.numSet); + Logger::setDebugMode (debug.numSet); + + const char *xdg_env = XDG_CACHE_HOME; + std::string path = xdg_env ? xdg_env : std::string(HOMEDIR) + DIR_SEPARATOR_STR ".cache/"; + + if (!check_dir(path.c_str())) + return 1; + path = path + "sflphone"; + if (!check_dir(path.c_str())) + return 1; + + std::string pidfile = path + "/" PIDFILE; + FILE *fp = fopen (pidfile.c_str(),"r"); + if (fp) { // PID file exists. Check the former process still alive or not. If alive, give user a hint. + int oldPid; + if (fscanf(fp, "%d", &oldPid) != 1) { + fprintf(stderr, "Couldn't read pidfile %s\n", pidfile.c_str()); + return 1; + } + + fclose (fp); + + if (kill (oldPid, 0) == 0) { + fprintf (stderr, "There is already a sflphoned daemon running in the system. Starting Failed."); + return 1; + } + } + + // write pid file + fp = fopen (pidfile.c_str(),"w"); + if (!fp) { + perror(pidfile.c_str()); + return 1; } else { - // PID file exists. Check the former process still alive or not. If alive, give user a hint. - char *res; - res = fgets (cOldPid, 64, fp); - - if (res == NULL) perror ("Error getting string from stream"); - - else { - fclose (fp); - - if (kill (atoi (cOldPid), 0) == 0) { - fprintf (stderr, "There is already a sflphoned daemon running in the system. Starting Failed."); - return 1; - } else { - if ( (fp = fopen (homepid,"w")) == NULL) { - fprintf (stderr, "Writing to PID file %s failed. Exited.", homepid); - return 1; - } else { - fputs (cPid , fp); - fclose (fp); - } - } - } + std::ostringstream pidstr; + pidstr << getpid(); + + fputs (pidstr.str().c_str() , fp); + fclose (fp); } try { - // TODO Use $XDG_CONFIG_HOME to save the config file (which default to $HOME/.config) - Manager::instance().initConfigFile(); Manager::instance().init(); } catch (std::exception &e) { std::cerr << e.what() << std::endl; @@ -189,4 +153,3 @@ main (int argc, char **argv) return 0; } - diff --git a/daemon/src/managerimpl.cpp b/daemon/src/managerimpl.cpp index 965192fde454680ad16179215eff5eeb7a75f9ea..04eaeea4bba937bb8cc92e8ce8da93a9562ec7c6 100644 --- a/daemon/src/managerimpl.cpp +++ b/daemon/src/managerimpl.cpp @@ -69,11 +69,10 @@ ManagerImpl::ManagerImpl (void) : _telephoneTone (0), _audiofile (0), _spkr_volume (0), _mic_volume (0), _waitingCall(), _waitingCallMutex(), _nbIncomingWaitingCall (0), _path (""), - _setupLoaded (false), _callAccountMap(), + _callAccountMap(), _callAccountMapMutex(), _callConfigMap(), _accountMap(), - _directIpAccount (0), _cleaner (new NumberCleaner), - _history (new HistoryManager), _imModule(new sfl::InstantMessaging), - parser_(0) + _cleaner (new NumberCleaner), + _history (new HistoryManager), _imModule(new sfl::InstantMessaging) { // initialize random generator for call id srand (time (NULL)); @@ -88,10 +87,30 @@ ManagerImpl::~ManagerImpl (void) delete _audiofile; } -void ManagerImpl::init () +void ManagerImpl::init (std::string config_file) { - // Load accounts, init map - buildConfiguration(); + if (config_file.empty()) + config_file = getConfigFile(); + _path = config_file; + + _debug ("Manager: configuration file path: %s", _path.c_str()); + + Conf::YamlParser *parser; + + try { + parser = new Conf::YamlParser (_path.c_str()); + parser->serializeEvents(); + parser->composeEvents(); + parser->constructNativeData(); + } catch (Conf::YamlParserException &e) { + _error ("Manager: %s", e.what()); + delete parser; + parser = NULL; + } + + loadAccountMap(parser); + delete parser; + initVolume(); initAudioDriver(); selectAudioDriver(); @@ -124,7 +143,7 @@ void ManagerImpl::init () _imModule->init(); // Register accounts - initRegisterAccounts(); //getEvents(); + registerAccounts(); } void ManagerImpl::terminate () @@ -132,30 +151,24 @@ void ManagerImpl::terminate () _debug ("Manager: Terminate "); std::vector<std::string> callList(getCallList()); - _debug ("Manager: Hangup %d remaining call", callList.size()); - std::vector<std::string>::iterator iter = callList.begin(); + _debug ("Manager: Hangup %zu remaining call", callList.size()); - while (iter != callList.end()) { + std::vector<std::string>::iterator iter; + for (iter = callList.begin(); iter != callList.end(); ++iter) hangupCall (*iter); - iter++; - } unloadAccountMap(); - _debug ("Manager: Unload DTMF key"); delete _dtmfKey; - _debug ("Manager: Unload telephone tone"); delete _telephoneTone; _telephoneTone = NULL; audioLayerMutexLock(); - _debug ("Manager: Unload audio driver"); delete _audiodriver; _audiodriver = NULL; - _debug ("Manager: Unload audio codecs "); _audioCodecFactory.deleteHandlePointer(); audioLayerMutexUnlock(); } @@ -1468,7 +1481,7 @@ void ManagerImpl::removeStream (const std::string& call_id) } //THREAD=Main -bool ManagerImpl::saveConfig (void) +void ManagerImpl::saveConfig (void) { _debug ("Manager: Saving Configuration to XDG directory %s", _path.c_str()); audioPreference.setVolumemic (getMicVolume()); @@ -1505,8 +1518,6 @@ bool ManagerImpl::saveConfig (void) } catch (Conf::YamlEmitterException &e) { _error ("ConfigTree: %s", e.what()); } - - return _setupLoaded; } //THREAD=Main @@ -2190,75 +2201,6 @@ std::string ManagerImpl::getConfigFile (void) const return configdir + DIR_SEPARATOR_STR + PROGNAME + ".yml"; } -/** - * Initialization: Main Thread - */ -void ManagerImpl::initConfigFile (std::string alternate) -{ - _debug ("Manager: Init config file"); - - // Loads config from ~/.sflphone/sflphoned.yml or so.. - _path = (alternate != "") ? alternate : getConfigFile(); - _debug ("Manager: configuration file path: %s", _path.c_str()); - - - bool fileExists = true; - - if (_path.empty()) { - _error ("Manager: Error: XDG config file path is empty!"); - fileExists = false; - } - - std::fstream file; - - file.open (_path.data(), std::fstream::in); - - if (!file.is_open()) { - - _debug ("Manager: File %s not opened, create new one", _path.c_str()); - file.open (_path.data(), std::fstream::out); - - if (!file.is_open()) { - _error ("Manager: Error: could not create empty configurationfile!"); - fileExists = false; - } - - file.close(); - - fileExists = false; - } - - // get length of file: - file.seekg (0, std::ios::end); - int length = file.tellg(); - - file.seekg (0, std::ios::beg); - - if (length <= 0) { - _debug ("Manager: Configuration file length is empty", length); - file.close(); - fileExists = false; // should load config - } - - if (fileExists) { - try { - parser_ = new Conf::YamlParser (_path.c_str()); - - parser_->serializeEvents(); - - parser_->composeEvents(); - - parser_->constructNativeData(); - - _setupLoaded = true; - - _debug ("Manager: Configuration file parsed successfully"); - } catch (Conf::YamlParserException &e) { - _error ("Manager: %s", e.what()); - } - } -} - std::vector<std::string> ManagerImpl::unserialize (std::string s) { std::vector<std::string> list; @@ -3251,7 +3193,6 @@ std::string ManagerImpl::addAccount ( Account* newAccount = NULL; if (accountType == "SIP") { newAccount = new SIPAccount(newAccountID); - newAccount->setVoIPLink(); } else if (accountType == "IAX") { newAccount = new IAXAccount(newAccountID); } else { @@ -3280,8 +3221,6 @@ std::string ManagerImpl::addAccount ( _debug ("AccountMap: %s", account_list.c_str()); - newAccount->setVoIPLink(); - newAccount->registerVoIPLink(); saveConfig(); @@ -3374,130 +3313,81 @@ std::vector<std::string> ManagerImpl::loadAccountOrder (void) const return unserialize (account_list); } -short ManagerImpl::buildConfiguration () -{ - _debug ("Manager: Loading account map"); - - loadIptoipProfile(); - - int nbAccount = loadAccountMap(); - - return nbAccount; -} - -void ManagerImpl::loadIptoipProfile() +void ManagerImpl::loadAccountMap(Conf::YamlParser *parser) { - _debug ("Manager: Create default \"account\" (used as default UDP transport)"); + SIPVoIPLink *link = SIPVoIPLink::instance(); // build a default IP2IP account with default parameters - _directIpAccount = new SIPAccount(IP2IP_PROFILE); - _accountMap[IP2IP_PROFILE] = _directIpAccount; + Account *ip2ip = new SIPAccount(IP2IP_PROFILE); + _accountMap[IP2IP_PROFILE] = ip2ip; // If configuration file parsed, load saved preferences - if (_setupLoaded) { - - _debug ("Manager: Loading IP2IP profile preferences from config"); - - Conf::SequenceNode *seq = parser_->getAccountSequence(); - - // Iterate over every account maps - for (Conf::Sequence::const_iterator iterIP2IP = seq->getSequence()->begin(); iterIP2IP != seq->getSequence()->end(); ++iterIP2IP) { - - Conf::MappingNode *map = (Conf::MappingNode *) (*iterIP2IP); - + if (parser) { + Conf::Sequence *seq = parser->getAccountSequence()->getSequence(); + for (Conf::Sequence::const_iterator iter = seq->begin(); iter != seq->end(); ++iter) { + Conf::MappingNode *map = (Conf::MappingNode *) (*iter); std::string accountid; map->getValue ("id", &accountid); - // if ID is IP2IP, unserialize if (accountid == "IP2IP") { - _directIpAccount->unserialize (map); + ip2ip->unserialize (map); break; } } } - // Force IP2IP settings to be loaded to be loaded - // No registration in the sense of the REGISTER method is performed. - _directIpAccount->registerVoIPLink(); - // SIPVoIPlink is used as a singleton, it is the first call to instance here - // The SIP library initialization is done in the SIPVoIPLink constructor - // We need the IP2IP settings to be loaded at this time as they are used - // for default sip transport + // Initialize default UDP transport according to + // IP to IP settings (most likely using port 5060) + link->createDefaultSipUdpTransport(); - _directIpAccount->setVoIPLink(); + // Call this method to create TLS listener + link->createDefaultSipTlsListener(); -} -short ManagerImpl::loadAccountMap() -{ - _debug ("Manager: Load account map"); + // Force IP2IP settings to be loaded to be loaded + // No registration in the sense of the REGISTER method is performed. + ip2ip->registerVoIPLink(); - if (!_setupLoaded) { - _error("Manager: Error: Configuration file not loaded yet, could not load config"); - return 0; - } + if (!parser) + return; - // build preferences - preferences.unserialize (parser_->getPreferenceNode()); - voipPreferences.unserialize (parser_->getVoipPreferenceNode()); - addressbookPreference.unserialize (parser_->getAddressbookNode()); - hookPreference.unserialize (parser_->getHookNode()); - audioPreference.unserialize (parser_->getAudioNode()); - shortcutPreferences.unserialize (parser_->getShortcutNode()); + // build preferences + preferences.unserialize (parser->getPreferenceNode()); + voipPreferences.unserialize (parser->getVoipPreferenceNode()); + addressbookPreference.unserialize (parser->getAddressbookNode()); + hookPreference.unserialize (parser->getHookNode()); + audioPreference.unserialize (parser->getAudioNode()); + shortcutPreferences.unserialize (parser->getShortcutNode()); - Conf::SequenceNode *seq = parser_->getAccountSequence(); + Conf::Sequence *seq = parser->getAccountSequence()->getSequence(); // Each element in sequence is a new account to create - Conf::Sequence::iterator iterSeq; - int nbAccount = 0; - for (iterSeq = seq->getSequence()->begin(); iterSeq != seq->getSequence()->end(); ++iterSeq) { + for (Conf::Sequence::const_iterator iter = seq->begin(); iter != seq->end(); ++iter) { + Conf::MappingNode *map = (Conf::MappingNode *) (*iter); - // Pointer to the account and account preferences map - Account *tmpAccount = NULL; - Conf::MappingNode *map = (Conf::MappingNode *) (*iterSeq); - - // Search for account types (IAX/IP2IP) - std::string accountType = "SIP"; // Assume type is SIP if not specified + std::string accountType; map->getValue ("type", &accountType); - // search for account id std::string accountid; map->getValue ("id", &accountid); - // search for alias (to get rid of the "ghost" account) std::string accountAlias; map->getValue ("alias", &accountAlias); - // do not insert in account map if id or alias is empty - if (accountid.empty() or accountAlias.empty()) + if (accountid.empty() or accountAlias.empty() or accountid == IP2IP_PROFILE) continue; - // Create a default account for specific type - if (accountType == "SIP" && accountid != "IP2IP") - tmpAccount = new SIPAccount(accountid); - else if (accountType == "IAX" and accountid != "IP2IP") - tmpAccount = new IAXAccount(accountid); + Account *a; + if (accountType == "IAX") + a = new IAXAccount(accountid); + else // assume SIP + a = new SIPAccount(accountid); - // Fill account with configuration preferences - if (tmpAccount != NULL) { - tmpAccount->unserialize (map); - _accountMap[accountid] = tmpAccount; + _accountMap[accountid] = a; - tmpAccount->setVoIPLink(); - nbAccount++; - } + a->unserialize (map); } - - try { - delete parser_; - } catch (Conf::YamlParserException &e) { - _error ("Manager: %s", e.what()); - } - - parser_ = NULL; - - return nbAccount; } void ManagerImpl::unloadAccountMap () @@ -3512,6 +3402,8 @@ void ManagerImpl::unloadAccountMap () } _accountMap.clear(); + + delete SIPVoIPLink::instance(); } bool ManagerImpl::accountExists (const std::string& accountID) @@ -3527,7 +3419,7 @@ ManagerImpl::getAccount (const std::string& accountID) const return iter->second; _debug ("Manager: Did not found account %s, returning IP2IP account", accountID.c_str()); - return _directIpAccount; + return getAccount(IP2IP_PROFILE); } std::string ManagerImpl::getAccountIdFromNameAndServer ( diff --git a/daemon/src/managerimpl.h b/daemon/src/managerimpl.h index 0cbb78b37e3da0eb9733968f69b4a03f58c3b2ba..d5077d3c06d2a90b48610e827956899e6f0f5d76 100644 --- a/daemon/src/managerimpl.h +++ b/daemon/src/managerimpl.h @@ -148,16 +148,11 @@ class ManagerImpl */ ShortcutPreferences shortcutPreferences; - /** - * Method to build preferences from configuration - */ - short buildConfiguration(); - /** * Initialisation of thread (sound) and map. * Init a new VoIPLink, audio codec and audio driver */ - void init (void); + void init (std::string config_file=""); /** * Terminate all thread (sound, link) and unload AccountMap @@ -362,10 +357,8 @@ class ManagerImpl /** * Save config to file - * @return true on success - * false otherwise */ - bool saveConfig (void); + void saveConfig (void); /** * @return true if we tried to register once @@ -964,22 +957,6 @@ class ManagerImpl */ void setMicVolume (unsigned short mic_vol); - /** - * Init default values for the different fields in the config file. - * Fills the local _config (Conf::ConfigTree) with the default contents. - * Called in main.cpp, just before Manager::init(). - */ - void initConfigFile (std::string alternate=""); - - /** - * Tell if the setup was already loaded - * @return bool True if yes - * false otherwise - */ - bool hasLoadedSetup() { - return _setupLoaded; - } - /** * Return a new random callid that is not present in the list * @return std::string A brand new callid @@ -999,14 +976,6 @@ class ManagerImpl */ bool isCurrentCall (const std::string& callId); - - /** - * Send registration to all enabled accounts - * @return 0 on registration success - * 1 otherelse - */ - int registerAccounts(); - /* * Initialize audiodriver */ @@ -1134,8 +1103,6 @@ class ManagerImpl */ std::string _path; - int _setupLoaded; - #ifdef USE_ZEROCONF // DNSService contain every zeroconf services // configuration detected on the network @@ -1160,15 +1127,10 @@ class ManagerImpl *Contains a list of account (sip, aix, etc) and their respective voiplink/calls */ AccountMap _accountMap; - Account * _directIpAccount; - - void loadIptoipProfile(); - /** * Load the account from configuration - * @return short Number of account */ - short loadAccountMap(); + void loadAccountMap(Conf::YamlParser *parser); /** * Unload the account (delete them) @@ -1295,6 +1257,11 @@ class ManagerImpl // Map containing conference pointers ConferenceMap _conferencemap; + /** + * Send registration to all enabled accounts + */ + void registerAccounts(); + private: // Copy Constructor @@ -1303,13 +1270,6 @@ class ManagerImpl // Assignment Operator ManagerImpl& operator= (const ManagerImpl& rh); - /** - * Send registration to all enabled accounts - * @return 0 on registration success - * 1 otherelse - */ - int initRegisterAccounts(); - NumberCleaner *_cleaner; /** @@ -1328,7 +1288,6 @@ class ManagerImpl */ void checkCallConfiguration (const std::string& id, const std::string& to, Call::CallConfiguration *callConfig); - Conf::YamlParser *parser_; Conf::YamlEmitter *emitter; friend class SIPTest; diff --git a/daemon/src/managerimpl_registration.cpp b/daemon/src/managerimpl_registration.cpp index dfa66f8120b2fd3ecaea4d39c8243242db746d02..73f94cc55f65f2db6a8d40485ed253355a225a21 100644 --- a/daemon/src/managerimpl_registration.cpp +++ b/daemon/src/managerimpl_registration.cpp @@ -38,115 +38,41 @@ #include "account.h" #include "dbus/callmanager.h" #include "global.h" -#include "sip/sipaccount.h" #include "audio/audiolayer.h" #include "sip/sipvoiplink.h" #include "manager.h" #include "dbus/configurationmanager.h" -#include "conference.h" - -#include <errno.h> #include <cstdlib> -int +void ManagerImpl::registerAccounts() { - int status; - bool flag = true; AccountMap::iterator iter; - _debugInit ("Manager: Initiate VoIP Links Registration"); - iter = _accountMap.begin(); - - /* Loop on the account map previously loaded */ - - while (iter != _accountMap.end()) { - if (iter->second) { - - if (iter->second->isEnabled()) { - - _debug ("Register account %s", iter->first.c_str()); - - status = iter->second->registerVoIPLink(); - - if (status != 0) { - flag = false; - } - } - } - - iter++; - } - - audioLayerMutexLock(); - // calls the client notification here in case of errors at startup... - if (_audiodriver->getErrorMessage() != -1) { - notifyErrClient (_audiodriver->getErrorMessage()); - } - audioLayerMutexUnlock(); - - if (flag) - return 0; - else - return 1; -} - -//THREAD=Main -int -ManagerImpl::initRegisterAccounts() -{ - int status; - bool flag = true; - AccountMap::iterator iter; - - _debugInit ("Manager: Initiate VoIP Links Registration"); - iter = _accountMap.begin(); - - /* Loop on the account map previously loaded */ - - while (iter != _accountMap.end()) { + for (iter = _accountMap.begin(); iter != _accountMap.end(); ++iter) { 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 != 0) { - flag = false; - } - } + if (iter->second->isEnabled()) + iter->second->registerVoIPLink(); } - - iter++; } audioLayerMutexLock(); - // calls the client notification here in case of errors at startup... - if (_audiodriver->getErrorMessage() != -1) { + + if (_audiodriver->getErrorMessage() != -1) notifyErrClient (_audiodriver->getErrorMessage()); - } - audioLayerMutexUnlock(); - if (flag) - return 0; - else - return 1; + audioLayerMutexUnlock(); } VoIPLink* ManagerImpl::getAccountLink (const std::string& accountID) const { - if (not accountID.empty()) { - Account* acc = getAccount (accountID); - - if (acc) - return acc->getVoIPLink(); - - return 0; - } else + if (not accountID.empty()) + return getAccount (accountID)->getVoIPLink(); + else return SIPVoIPLink::instance (); } @@ -154,7 +80,6 @@ VoIPLink* ManagerImpl::getAccountLink (const std::string& accountID) const void ManagerImpl::sendRegister (const std::string& accountID , const int32_t& enable) { - // Update the active field Account* acc = getAccount (accountID); acc->setEnabled (enable); @@ -162,14 +87,8 @@ ManagerImpl::sendRegister (const std::string& accountID , const int32_t& enable) Manager::instance().saveConfig(); - // Test on the freshly updated value - if (acc->isEnabled()) { - // Verify we aren't already registered, then register - _debug ("Send register for account %s\n" , accountID.c_str()); + if (acc->isEnabled()) acc->registerVoIPLink(); - } else { - // Verify we are already registered, then unregister - _debug ("Send unregister for account %s\n" , accountID.c_str()); + else acc->unregisterVoIPLink(); - } } diff --git a/daemon/src/preferences.cpp b/daemon/src/preferences.cpp index 9e1e0c98f005fc037e4d85addea505e604d42a09..7f63de7b416b25ef49055e8204bc069651ac7ddb 100644 --- a/daemon/src/preferences.cpp +++ b/daemon/src/preferences.cpp @@ -64,12 +64,6 @@ Preferences::~Preferences() {} void Preferences::serialize (Conf::YamlEmitter *emiter) { - - if(emiter == NULL) { - _error("Preference: Error: emitter is NULL while serializing"); - return; - } - Conf::MappingNode preferencemap (NULL); Conf::ScalarNode order (_accountOrder); @@ -146,11 +140,6 @@ VoipPreference::~VoipPreference() {} void VoipPreference::serialize (Conf::YamlEmitter *emitter) { - if(emitter == NULL) { - _error("VoipPreference: Error: emitter is NULL while serializing"); - return; - } - Conf::MappingNode preferencemap (NULL); Conf::ScalarNode playDtmf (_playDtmf); @@ -201,11 +190,6 @@ AddressbookPreference::~AddressbookPreference() {} void AddressbookPreference::serialize (Conf::YamlEmitter *emitter) { - if(emitter == NULL) { - _error("AddressbookPreference: Error: emitter is NULL while serializing"); - return; - } - Conf::MappingNode preferencemap (NULL); Conf::ScalarNode photo (_photo); @@ -261,11 +245,6 @@ HookPreference::~HookPreference() {} void HookPreference::serialize (Conf::YamlEmitter *emitter) { - if(emitter == NULL) { - _error("HookPreference: Error: emitter is NULL while serializing"); - return; - } - Conf::MappingNode preferencemap (NULL); Conf::ScalarNode iax2Enabled (_iax2Enabled); @@ -327,11 +306,6 @@ AudioPreference::~AudioPreference() {} void AudioPreference::serialize (Conf::YamlEmitter *emitter) { - if(emitter == NULL) { - _error("AudioPreference: Error: emitter is NULL while serializing"); - return; - } - Conf::MappingNode preferencemap (NULL); Conf::MappingNode alsapreferencemap (NULL); Conf::MappingNode pulsepreferencemap (NULL); @@ -476,11 +450,6 @@ void ShortcutPreferences::setShortcuts (std::map<std::string, std::string> map) void ShortcutPreferences::serialize (Conf::YamlEmitter *emitter) { - if(emitter == NULL) { - _error("ShortcutPreferences: Error: emitter is NULL while serializing"); - return; - } - Conf::MappingNode preferencemap (NULL); Conf::ScalarNode hangup (_hangup); diff --git a/daemon/src/sip/sipaccount.cpp b/daemon/src/sip/sipaccount.cpp index 3d968a8866e055c8ff77e7714e7384c429b8bb13..9bc7c808d44995ecb8d8e66ea161491fe13c81fb 100644 --- a/daemon/src/sip/sipaccount.cpp +++ b/daemon/src/sip/sipaccount.cpp @@ -61,7 +61,7 @@ SIPAccount::SIPAccount (const std::string& accountID) , transport_ (NULL) , resolveOnce_ (false) , cred_ (NULL) - , tlsSetting_ (NULL) + , stunPort_(0) , dtmfType_ (OVERRTP) , tlsEnable_ ("false") , tlsPort_ (DEFAULT_SIP_TLS_PORT) @@ -89,28 +89,16 @@ SIPAccount::SIPAccount (const std::string& accountID) { stunServerName_.ptr = NULL; stunServerName_.slen = 0; - stunPort_ = 0; + link_ = SIPVoIPLink::instance (); } SIPAccount::~SIPAccount() { - /* One SIP account less connected to the sip voiplink */ - if (accountID_ != "default") - dynamic_cast<SIPVoIPLink*> (link_)->decrementClients(); - - /* Delete accounts-related information */ - regc_ = NULL; delete[] cred_; - delete tlsSetting_; } void SIPAccount::serialize (Conf::YamlEmitter *emitter) { - if(emitter == NULL) { - _error("SIPAccount: Error: emitter is NULL in serialize"); - return; - } - Conf::MappingNode accountmap (NULL); Conf::MappingNode srtpmap (NULL); Conf::MappingNode zrtpmap (NULL); @@ -534,19 +522,10 @@ std::map<std::string, std::string> SIPAccount::getAccountDetails() const return a; } - -void SIPAccount::setVoIPLink() +void SIPAccount::registerVoIPLink() { - link_ = SIPVoIPLink::instance (); - dynamic_cast<SIPVoIPLink*> (link_)->incrementClients(); -} - - -int SIPAccount::registerVoIPLink() -{ - if (hostname_.length() >= PJ_MAX_HOSTNAME) { - return 1; - } + if (hostname_.length() >= PJ_MAX_HOSTNAME) + return; // Init TLS settings if the user wants to use TLS if (tlsEnable_ == "true") { @@ -563,35 +542,30 @@ int SIPAccount::registerVoIPLink() stunServerName_ = pj_str ( (char*) stunServer_.c_str()); } + // In our definition of the ip2ip profile (aka Direct IP Calls), + // no registration should be performed + if (accountID_ == IP2IP_PROFILE) + return; + try { - // In our definition of the ip2ip profile (aka Direct IP Calls), - // no registration should be performed - if (accountID_ != IP2IP_PROFILE) - link_->sendRegister (this); + link_->sendRegister (this); } catch (const VoipLinkException &e) { _error("SIPAccount: %s", e.what()); } - - return 0; } -int SIPAccount::unregisterVoIPLink() +void SIPAccount::unregisterVoIPLink() { - if (accountID_ == IP2IP_PROFILE) { - return true; - } + if (accountID_ == IP2IP_PROFILE) + return; try { - link_->sendUnregister (this); - setRegistrationInfo (NULL); + link_->sendUnregister (this); } catch (const VoipLinkException &e) { _error("SIPAccount: %s", e.what()); - return false; } - - return true; } pjsip_ssl_method SIPAccount::sslMethodStringToPjEnum (const std::string& method) @@ -619,25 +593,22 @@ void SIPAccount::initTlsConfiguration (void) // TLS listener is unique and should be only modified through IP2IP_PROFILE tlsListenerPort_ = tlsPort_; - delete tlsSetting_; - tlsSetting_ = new pjsip_tls_setting; - - pjsip_tls_setting_default (tlsSetting_); + pjsip_tls_setting_default (&tlsSetting_); - pj_cstr (&tlsSetting_->ca_list_file, tlsCaListFile_.c_str()); - pj_cstr (&tlsSetting_->cert_file, tlsCertificateFile_.c_str()); - pj_cstr (&tlsSetting_->privkey_file, tlsPrivateKeyFile_.c_str()); - pj_cstr (&tlsSetting_->password, tlsPassword_.c_str()); - tlsSetting_->method = sslMethodStringToPjEnum (tlsMethod_); - pj_cstr (&tlsSetting_->ciphers, tlsCiphers_.c_str()); - pj_cstr (&tlsSetting_->server_name, tlsServerName_.c_str()); + pj_cstr (&tlsSetting_.ca_list_file, tlsCaListFile_.c_str()); + pj_cstr (&tlsSetting_.cert_file, tlsCertificateFile_.c_str()); + pj_cstr (&tlsSetting_.privkey_file, tlsPrivateKeyFile_.c_str()); + pj_cstr (&tlsSetting_.password, tlsPassword_.c_str()); + tlsSetting_.method = sslMethodStringToPjEnum (tlsMethod_); + pj_cstr (&tlsSetting_.ciphers, tlsCiphers_.c_str()); + pj_cstr (&tlsSetting_.server_name, tlsServerName_.c_str()); - tlsSetting_->verify_server = tlsVerifyServer_ ? PJ_TRUE: PJ_FALSE; - tlsSetting_->verify_client = tlsVerifyClient_ ? PJ_TRUE: PJ_FALSE; - tlsSetting_->require_client_cert = tlsRequireClientCertificate_ ? PJ_TRUE: PJ_FALSE; + tlsSetting_.verify_server = tlsVerifyServer_ ? PJ_TRUE: PJ_FALSE; + tlsSetting_.verify_client = tlsVerifyClient_ ? PJ_TRUE: PJ_FALSE; + tlsSetting_.require_client_cert = tlsRequireClientCertificate_ ? PJ_TRUE: PJ_FALSE; - tlsSetting_->timeout.sec = atol (tlsNegotiationTimeoutSec_.c_str()); - tlsSetting_->timeout.msec = atol (tlsNegotiationTimeoutMsec_.c_str()); + tlsSetting_.timeout.sec = atol (tlsNegotiationTimeoutSec_.c_str()); + tlsSetting_.timeout.msec = atol (tlsNegotiationTimeoutMsec_.c_str()); } void SIPAccount::initStunConfiguration (void) diff --git a/daemon/src/sip/sipaccount.h b/daemon/src/sip/sipaccount.h index 3463a63d68f55da1d1196dafd5468a0a5abf07da..09036624fdc4131074b80309954fb8913a34210a 100644 --- a/daemon/src/sip/sipaccount.h +++ b/daemon/src/sip/sipaccount.h @@ -132,11 +132,6 @@ class SIPAccount : public Account std::map<std::string, std::string> getTlsSettings (void) const; void setTlsSettings (const std::map<std::string, std::string>& details); - /** - * Special setVoIPLink which increment SipVoIPLink's number of client. - */ - void setVoIPLink(); - /** * Actually useless, since config loading is done in init() */ @@ -145,12 +140,12 @@ class SIPAccount : public Account /** * Initialize the SIP voip link with the account parameters and send registration */ - int registerVoIPLink(); + void registerVoIPLink(); /** * Send unregistration and clean all related stuff ( calls , thread ) */ - int unregisterVoIPLink(); + void unregisterVoIPLink(); pjsip_cred_info *getCredInfo() const { return cred_; @@ -231,8 +226,8 @@ class SIPAccount : public Account * file, that can be used directly by PJSIP to initialize * TLS transport. */ - pjsip_tls_setting * getTlsSetting (void) const { - return tlsSetting_; + const pjsip_tls_setting * getTlsSetting (void) const { + return &tlsSetting_; } /** @@ -372,7 +367,17 @@ class SIPAccount : public Account * Get the local port for TLS listener. * @return pj_uint16 The port used for that account */ - pj_uint16_t getTlsListenerPort (void) const { return (pj_uint16_t) tlsListenerPort_; } + pj_uint16_t getTlsListenerPort (void) const { + return tlsListenerPort_; + } + + /** + * Set the local port for TLS listener. + * @pram port The port used for TLS listener. + */ + void setTlsListenerPort (pj_uint16_t port) { + tlsListenerPort_ = port; + } /** * Get the public IP address set by the user for this account. @@ -514,7 +519,7 @@ class SIPAccount : public Account // The TLS settings, if tls is chosen as // a sip transport. - pjsip_tls_setting * tlsSetting_; + pjsip_tls_setting tlsSetting_; // The STUN server name, if applicable for internal use only pj_str_t stunServerName_; diff --git a/daemon/src/sip/sipvoiplink.cpp b/daemon/src/sip/sipvoiplink.cpp index 4ae88ec6c782193e031e121467c8e5bb5e33ec6e..931198c3e87838b1469b859401c42dc2209598ca 100644 --- a/daemon/src/sip/sipvoiplink.cpp +++ b/daemon/src/sip/sipvoiplink.cpp @@ -76,26 +76,26 @@ using namespace sfl; -static char * invitationStateMap[] = { - (char*) "PJSIP_INV_STATE_NULL", - (char*) "PJSIP_INV_STATE_CALLING", - (char*) "PJSIP_INV_STATE_INCOMING", - (char*) "PJSIP_INV_STATE_EARLY", - (char*) "PJSIP_INV_STATE_CONNECTING", - (char*) "PJSIP_INV_STATE_CONFIRMED", - (char*) "PJSIP_INV_STATE_DISCONNECTED" +static const char * invitationStateMap[] = { + "PJSIP_INV_STATE_NULL", + "PJSIP_INV_STATE_CALLING", + "PJSIP_INV_STATE_INCOMING", + "PJSIP_INV_STATE_EARLY", + "PJSIP_INV_STATE_CONNECTING", + "PJSIP_INV_STATE_CONFIRMED", + "PJSIP_INV_STATE_DISCONNECTED" }; -static char * transactionStateMap[] = { - (char*) "PJSIP_TSX_STATE_NULL" , - (char*) "PJSIP_TSX_STATE_CALLING", - (char*) "PJSIP_TSX_STATE_TRYING", - (char*) "PJSIP_TSX_STATE_PROCEEDING", - (char*) "PJSIP_TSX_STATE_COMPLETED", - (char*) "PJSIP_TSX_STATE_CONFIRMED", - (char*) "PJSIP_TSX_STATE_TERMINATED", - (char*) "PJSIP_TSX_STATE_DESTROYED", - (char*) "PJSIP_TSX_STATE_MAX" +static const char * transactionStateMap[] = { + "PJSIP_TSX_STATE_NULL" , + "PJSIP_TSX_STATE_CALLING", + "PJSIP_TSX_STATE_TRYING", + "PJSIP_TSX_STATE_PROCEEDING", + "PJSIP_TSX_STATE_COMPLETED", + "PJSIP_TSX_STATE_CONFIRMED", + "PJSIP_TSX_STATE_TERMINATED", + "PJSIP_TSX_STATE_DESTROYED", + "PJSIP_TSX_STATE_MAX" }; struct result { @@ -164,11 +164,6 @@ pjsip_module _mod_ua; pj_thread_t *thread; pj_thread_desc desc; -/* - * Url hook instance - */ -UrlHook *urlhook; - /** * Get the number of voicemail waiting in a SIP message */ @@ -266,31 +261,31 @@ SIPVoIPLink* SIPVoIPLink::_instance = NULL; SIPVoIPLink::SIPVoIPLink () - : VoIPLink () - , _nbTryListenAddr (2) // number of times to try to start SIP listener + : _nbTryListenAddr (2) // number of times to try to start SIP listener , _regPort (DEFAULT_SIP_PORT) - , _clients (0) { + srand (time (NULL)); // to get random number for RANDOM_PORT - _debug ("SIPVOIPLINK"); - // to get random number for RANDOM_PORT - srand (time (NULL)); + /* Start pjsip initialization step */ + // TODO This port should be the one configured for the IP profile + // and not the global one + _regPort = Manager::instance().getLocalIp2IpPort(); - urlhook = new UrlHook (); + /* Instanciate the C++ thread */ + _evThread = new EventThread (this); - /* Start pjsip initialization step */ - init(); + /* Initialize the pjsip library */ + pjsipInit(); } SIPVoIPLink::~SIPVoIPLink() { - terminate(); - + delete _evThread; + pjsipShutdown(); } SIPVoIPLink* SIPVoIPLink::instance () { - if (!_instance) { _debug ("UserAgent: Create new SIPVoIPLink instance"); _instance = new SIPVoIPLink; @@ -299,53 +294,9 @@ SIPVoIPLink* SIPVoIPLink::instance () return _instance; } -void SIPVoIPLink::decrementClients (void) -{ - if (--_clients == 0) { - _debug ("UserAgent: No SIP account anymore, terminate SIPVoIPLink"); - delete SIPVoIPLink::_instance; - } -} - -void SIPVoIPLink::init() -{ - if (_initDone) - return; - - // TODO This port should be the one configured for the IP profile - // and not the global one - _regPort = Manager::instance().getLocalIp2IpPort(); - - /* Instanciate the C++ thread */ - _evThread = new EventThread (this); - - /* Initialize the pjsip library */ - pjsipInit(); - - _initDone = true; -} - -void -SIPVoIPLink::terminate() -{ - _debug ("UserAgent: Terminating SIPVoIPLink"); - - if (_evThread) { - _debug ("UserAgent: Deleting sip eventThread"); - delete _evThread; - _evThread = NULL; - } - +void SIPVoIPLink::init() {} - /* Clean shutdown of pjsip library */ - if (_initDone) { - _debug ("UserAgent: Shutting down PJSIP"); - pjsipShutdown(); - } - - _initDone = false; - -} +void SIPVoIPLink::terminate() {} void SIPVoIPLink::getEvent() @@ -442,9 +393,7 @@ void SIPVoIPLink::sendRegister (Account *a) account->setRegistrationState (Trying); // Create the registration according to the account ID - status = pjsip_regc_create (_endpt, (void *) account, ®istration_cb, ®c); - - if (status != PJ_SUCCESS) { + if (pjsip_regc_create (_endpt, (void *) account, ®istration_cb, ®c) != PJ_SUCCESS) { _mutexSIP.leaveMutex(); throw VoipLinkException("UserAgent: Unable to create regc structure."); } @@ -478,14 +427,13 @@ void SIPVoIPLink::sendRegister (Account *a) pj_cstr (&pjSrv, srvUri.c_str()); // Initializes registration - status = pjsip_regc_init (regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, expire_value); - if (status != PJ_SUCCESS) { + if (pjsip_regc_init (regc, &pjSrv, &pjFrom, &pjFrom, 1, &pjContact, expire_value) != PJ_SUCCESS) { _mutexSIP.leaveMutex(); throw VoipLinkException("Unable to initialize account registration structure"); } // Fill route set - if (! (account->getServiceRoute().empty())) { + if (!account->getServiceRoute().empty()) { pjsip_route_hdr *route_set = createRouteSet(account, _pool); pjsip_regc_set_route_set (regc, route_set); } @@ -505,7 +453,7 @@ void SIPVoIPLink::sendRegister (Account *a) pjsip_regc_add_headers (regc, &hdr_list); - if ((status = pjsip_regc_register (regc, PJ_TRUE, &tdata)) != PJ_SUCCESS) { + if (pjsip_regc_register (regc, PJ_TRUE, &tdata) != PJ_SUCCESS) { _mutexSIP.leaveMutex(); throw VoipLinkException("Unable to initialize transaction data for account registration"); } @@ -551,13 +499,10 @@ void SIPVoIPLink::sendRegister (Account *a) account->setRegistrationInfo (regc); - if (account->getAccountTransport()) { - + pjsip_transport *transport = account->getAccountTransport(); + if (transport) _debug ("Sent account registration using transport: %s %s (refcnt=%d)", - account->getAccountTransport()->obj_name, - account->getAccountTransport()->info, - (int) pj_atomic_get (account->getAccountTransport()->ref_cnt)); - } + transport->obj_name, transport->info, (int) pj_atomic_get(transport->ref_cnt)); } void SIPVoIPLink::sendUnregister (Account *a) throw(VoipLinkException) @@ -1670,13 +1615,6 @@ bool SIPVoIPLink::pjsipInit() return false; } - // Initialize default UDP transport according to - // IP to IP settings (most likely using port 5060) - createDefaultSipUdpTransport(); - - // Call this method to create TLS listener - createDefaultSipTlsListener(); - // Initialize transaction layer status = pjsip_tsx_layer_init_module (_endpt); PJ_ASSERT_RETURN (status == PJ_SUCCESS, 1); @@ -1869,28 +1807,22 @@ bool SIPVoIPLink::createDefaultSipUdpTransport() account->setAccountTransport (transport); } return true; - } void SIPVoIPLink::createDefaultSipTlsListener() { - SIPAccount * account = dynamic_cast<SIPAccount *> (Manager::instance().getAccount (IP2IP_PROFILE)); - if (account->isTlsEnabled()) { + if (account->isTlsEnabled()) createTlsListener (account); - } } void SIPVoIPLink::createTlsListener (SIPAccount *account) { - pjsip_tpfactory *tls; pj_sockaddr_in local_addr; pjsip_host_port a_name; - pj_status_t status; - pj_status_t success; _debug ("Create TLS listener"); @@ -1905,7 +1837,7 @@ void SIPVoIPLink::createTlsListener (SIPAccount *account) pj_str_t pjAddress; pj_cstr (&pjAddress, PJ_INADDR_ANY); - success = pj_sockaddr_in_set_str_addr (&local_addr, &pjAddress); + pj_sockaddr_in_set_str_addr (&local_addr, &pjAddress); // Init published address for this listener (Local IP address on port 5061) @@ -1915,33 +1847,25 @@ void SIPVoIPLink::createTlsListener (SIPAccount *account) pj_cstr (&a_name.host, publishedAddress.c_str()); a_name.port = account->getTlsListenerPort(); - /* Get TLS settings. Expected to be filled */ - pjsip_tls_setting * tls_setting = account->getTlsSetting(); - - _debug ("UserAgent: TLS transport to be initialized with published address %.*s," " published port %d,\n local address %.*s, local port %d", (int) a_name.host.slen, a_name.host.ptr, - (int) a_name.port, pjAddress.slen, pjAddress.ptr, (int) localTlsPort); + a_name.port, pjAddress.slen, pjAddress.ptr, (int) localTlsPort); - status = pjsip_tls_transport_start (_endpt, tls_setting, &local_addr, &a_name, 1, &tls); + pj_status_t status = pjsip_tls_transport_start (_endpt, account->getTlsSetting(), &local_addr, &a_name, 1, &tls); if (status != PJ_SUCCESS) { _debug ("UserAgent: Error creating SIP TLS listener (%d)", status); } else { _localTlsListener = tls; } - - // return PJ_SUCCESS; - } bool SIPVoIPLink::createSipTransport (SIPAccount *account) { if (account->isTlsEnabled()) { - if (_localTlsListener == NULL) createTlsListener (account); @@ -1985,12 +1909,7 @@ bool SIPVoIPLink::createSipTransport (SIPAccount *account) pjsip_transport *SIPVoIPLink::createUdpTransport (SIPAccount *account, bool local) { - pj_status_t status; pj_sockaddr_in bound_addr; - pjsip_host_port a_name; - // char tmpIP[32]; - pjsip_transport *transport; - int listeningPort = _regPort; /* Use my local address as default value */ std::string listeningAddress = loadSIPLocalIP (); @@ -2001,20 +1920,18 @@ pjsip_transport *SIPVoIPLink::createUdpTransport (SIPAccount *account, bool loca if (account->getLocalInterface () != "default") listeningAddress = getInterfaceAddrFromName (account->getLocalInterface()); - listeningPort = account->getLocalPort (); + int listeningPort = account->getLocalPort (); pj_memset (&bound_addr, 0, sizeof (bound_addr)); - pj_str_t temporary_address; - if (account->getLocalInterface () == "default") { // Init bound address to ANY bound_addr.sin_addr.s_addr = pj_htonl (PJ_INADDR_ANY); listeningAddress = loadSIPLocalIP (); } else { - // bind this account to a specific interface + pj_str_t temporary_address; pj_strdup2 (_pool, &temporary_address, listeningAddress.c_str()); bound_addr.sin_addr = pj_inet_addr (&temporary_address); } @@ -2042,12 +1959,13 @@ pjsip_transport *SIPVoIPLink::createUdpTransport (SIPAccount *account, bool loca } /* Init published name */ + pjsip_host_port a_name; pj_bzero (&a_name, sizeof (pjsip_host_port)); pj_cstr (&a_name.host, listeningAddress.c_str()); a_name.port = listeningPort; - status = pjsip_udp_transport_start (_endpt, &bound_addr, &a_name, 1, &transport); - if (status != PJ_SUCCESS) + pjsip_transport *transport; + if (pjsip_udp_transport_start (_endpt, &bound_addr, &a_name, 1, &transport) != PJ_SUCCESS) transport = NULL; // Print info from transport manager associated to endpoint @@ -2443,25 +2361,25 @@ pjsip_route_hdr *SIPVoIPLink::createRouteSet(Account *account, pj_pool_t *hdr_po } -void SIPVoIPLink::busySleep (unsigned msec) +void SIPVoIPLink::pjsipShutdown (void) { - + if (_endpt) { + _debug ("UserAgent: Shutting down..."); #if defined(PJ_SYMBIAN) && PJ_SYMBIAN != 0 /* Ideally we shouldn't call pj_thread_sleep() and rather * CActiveScheduler::WaitForAnyRequest() here, but that will * drag in Symbian header and it doesn't look pretty. */ - pj_thread_sleep (msec); + pj_thread_sleep (1000); #else pj_time_val timeout, now, tv; pj_gettimeofday (&timeout); - timeout.msec += msec; + timeout.msec += 1000; pj_time_val_normalize (&timeout); tv.sec = 0; tv.msec = 10; - pj_time_val_normalize (&tv); do { pjsip_endpt_handle_events (_endpt, &tv); @@ -2469,13 +2387,6 @@ void SIPVoIPLink::busySleep (unsigned msec) } while (PJ_TIME_VAL_LT (now, timeout)); #endif -} - -void SIPVoIPLink::pjsipShutdown (void) -{ - if (_endpt) { - _debug ("UserAgent: Shutting down..."); - busySleep (1000); } pj_thread_join (thread); @@ -3166,13 +3077,11 @@ transaction_request_cb (pjsip_rx_data *rdata) if (Manager::instance().hookPreference.getSipEnabled()) { _debug ("UserAgent: Set sip url hooks"); - std::string header_value(fetchHeaderValue (rdata->msg_info.msg, - Manager::instance().hookPreference.getUrlSipField())); + std::string header_value(fetchHeaderValue (rdata->msg_info.msg, Manager::instance().hookPreference.getUrlSipField())); if (header_value.size () < header_value.max_size()) { if (not header_value.empty()) { - urlhook->addAction (header_value, - Manager::instance().hookPreference.getUrlCommand()); + UrlHook::runAction (Manager::instance().hookPreference.getUrlCommand(), header_value); } } else throw std::length_error ("UserAgent: Url exceeds std::string max_size"); @@ -3644,16 +3553,14 @@ std::vector<std::string> SIPVoIPLink::getAllIpInterfaceByName (void) std::string SIPVoIPLink::getInterfaceAddrFromName (std::string ifaceName) { - struct ifreq ifr; - int fd; - - if ( (fd = socket (AF_INET, SOCK_DGRAM,0)) < 0) { - _error ("UserAgent: Error: could not open socket"); + int fd = socket (AF_INET, SOCK_DGRAM,0); + if (fd < 0) { + _error ("UserAgent: Error: could not open socket: %m"); return ""; } + struct ifreq ifr; memset (&ifr, 0, sizeof (struct ifreq)); - strcpy (ifr.ifr_name, ifaceName.c_str()); ifr.ifr_addr.sa_family = AF_INET; diff --git a/daemon/src/sip/sipvoiplink.h b/daemon/src/sip/sipvoiplink.h index 219e199e351e1500d61466b8312a6b97770ca5e8..3536cdee1d39fccf81a12e0bc3125bb5c442dffc 100644 --- a/daemon/src/sip/sipvoiplink.h +++ b/daemon/src/sip/sipvoiplink.h @@ -74,16 +74,10 @@ class SIPVoIPLink : public VoIPLink { public: - /* Copy Constructor */ - SIPVoIPLink (const SIPVoIPLink& rh); - - /** - * Destructor - */ - ~SIPVoIPLink(); - - /* Assignment Operator */ - SIPVoIPLink& operator= (const SIPVoIPLink& rh); + /** + * Destructor + */ + ~SIPVoIPLink(); /** * Singleton method. Enable to retrieve the unique static instance @@ -91,18 +85,6 @@ class SIPVoIPLink : public VoIPLink */ static SIPVoIPLink* instance (); - /** - * Increment the number of SIP account connected to this link - */ - void incrementClients (void) { - _clients++; - } - - /** - * Decrement the number of SIP account connected to this link - */ - void decrementClients (void); - /** * Try to initiate the pjsip engine/thread and set config */ @@ -358,14 +340,30 @@ class SIPVoIPLink : public VoIPLink */ int _nbTryListenAddr; + /** + * Create the default UDP transport according ot Ip2Ip profile settings + */ + bool createDefaultSipUdpTransport(); + + + /** + * Create the default TLS litener using IP2IP_PROFILE settings + */ + void createDefaultSipTlsListener(); + private: + + /* Assignment Operator */ + SIPVoIPLink& operator= (const SIPVoIPLink& rh); + + /* Copy Constructor */ + SIPVoIPLink (const SIPVoIPLink& rh); + SIPVoIPLink (); /* The singleton instance */ static SIPVoIPLink* _instance; - void busySleep (unsigned msec); - /** * Initialize the PJSIP library * Must be called before any other calls to the SIP layer @@ -396,19 +394,6 @@ class SIPVoIPLink : public VoIPLink */ bool acquireTransport (SIPAccount *account); - - /** - * Create the default UDP transport according ot Ip2Ip profile settings - */ - bool createDefaultSipUdpTransport(); - - - /** - * Create the default TLS litener using IP2IP_PROFILE settings - */ - void createDefaultSipTlsListener(); - - /** * Create the default TLS litener according to account settings. */ diff --git a/daemon/src/voiplink.cpp b/daemon/src/voiplink.cpp index ac6c92a223fe23d37674b2d63933920d3ca467cc..f292907b92ba0a9304f503e7c0a252f39d4572fc 100644 --- a/daemon/src/voiplink.cpp +++ b/daemon/src/voiplink.cpp @@ -34,7 +34,7 @@ #include "voiplink.h" #include "manager.h" -VoIPLink::VoIPLink () : _localPort (0), _initDone (false) +VoIPLink::VoIPLink () : _localPort (0) { } diff --git a/daemon/src/voiplink.h b/daemon/src/voiplink.h index bec3cdcce75f1a9cfff2ec426a0803a0b65cc486..c7a96994a4a75e604b55b7c2c71f701bd97fb57f 100644 --- a/daemon/src/voiplink.h +++ b/daemon/src/voiplink.h @@ -229,12 +229,6 @@ class VoIPLink /** Get local listening port (5060 for SIP, ...) */ unsigned int _localPort; - - /** Whether init() was called already or not - * This should be used in [IAX|SIP]VoIPLink::init() and terminate(), to - * indicate that init() was called, or reset by terminate(). - */ - bool _initDone; }; #endif // __VOIP_LINK_H__ diff --git a/daemon/test/Makefile.am b/daemon/test/Makefile.am index add6996ead92b4a46b3658d0eb99b94294e122f0..28d0f9ff8943894ddfa56c0906e2205b202340d0 100644 --- a/daemon/test/Makefile.am +++ b/daemon/test/Makefile.am @@ -5,6 +5,8 @@ TESTS_ENVIRONMENT = CODECS_PATH="$(top_builddir)/src/audio/codecs" \ FAKE_PLUGIN_NAME="$(top_builddir)/src/plug-in/test/libplugintest.so" check_PROGRAMS = test +TESTS = run_tests.sh + test_CXXFLAGS = -I . test_LDADD = $(top_builddir)/src/libsflphone.la @LIBCRYPTO_LIBS@ @CPPUNIT_LIBS@ diff --git a/daemon/test/configurationtest.cpp b/daemon/test/configurationtest.cpp index b2b8a122c16d1c8206ddb1e0cae84345b9a65426..24da34990ad775cf2867b8757557855f7244eb92 100644 --- a/daemon/test/configurationtest.cpp +++ b/daemon/test/configurationtest.cpp @@ -67,53 +67,6 @@ void ConfigurationTest::testDefaultValueSignalisation() CPPUNIT_ASSERT (Manager::instance().voipPreferences.getPulseLength() == 250); } -void ConfigurationTest::testLoadSIPAccount() -{ - _debug ("-------------------- ConfigurationTest::testLoadSIPAccount --------------------\n"); - - AccountMap accounts; - Account *current; - std::ostringstream ss; - int nb_account; // Must be 1 - - // Load the account from the user file - nb_account = Manager::instance().loadAccountMap(); - CPPUNIT_ASSERT_EQUAL (1, nb_account); - // Save the account information - accounts = Manager::instance()._accountMap; - - AccountMap::iterator iter = accounts.begin(); - CPPUNIT_ASSERT (Manager::instance().accountExists (iter->first) == true); - - while (iter != accounts.end()) { - current = iter->second; - CPPUNIT_ASSERT (iter->first == current->getAccountID()); - CPPUNIT_ASSERT (0 == current->getVoIPLink()); - iter++; - } -} - -void ConfigurationTest::testUnloadSIPAccount() -{ - _debug ("-------------------- ConfigurationTest::testUnloadSIPAccount --------------------\n"); - - AccountMap accounts; - - // Load the accounts from the user file - Manager::instance().loadAccountMap(); - // Unload the accounts - Manager::instance().unloadAccountMap(); - // Save the account information - accounts = Manager::instance()._accountMap; - - AccountMap::iterator iter = accounts.begin(); - CPPUNIT_ASSERT (Manager::instance().accountExists (iter->first) == false); - - if (iter != accounts.end()) { - CPPUNIT_FAIL ("Unload account map failed\n"); - } -} - void ConfigurationTest::testInitVolume() { _debug ("-------------------- ConfigurationTest::testInitVolume --------------------\n"); @@ -148,29 +101,20 @@ void ConfigurationTest::testInitAudioDriver() void ConfigurationTest::testYamlParser() { - - Conf::YamlParser *parser; - try { - - parser = new Conf::YamlParser ("ymlParser.yml"); + Conf::YamlParser *parser = new Conf::YamlParser ("ymlParser.yml"); parser->serializeEvents(); parser->composeEvents(); parser->constructNativeData(); delete parser; - parser = NULL; - } catch (Conf::YamlParserException &e) { _error ("ConfigTree: %s", e.what()); } - } void ConfigurationTest::testYamlEmitter() { - Conf::YamlEmitter *emitter; - Conf::MappingNode accountmap (NULL); Conf::MappingNode credentialmap (NULL); Conf::MappingNode srtpmap (NULL); @@ -290,7 +234,7 @@ void ConfigurationTest::testYamlEmitter() tlsmap.setKeyValue (verifyServerKey, &verifyserver); try { - emitter = new Conf::YamlEmitter ("/tmp/ymlEmiter.txt"); + Conf::YamlEmitter *emitter = new Conf::YamlEmitter ("/tmp/ymlEmiter.txt"); emitter->serializeAccount (&accountmap); emitter->serializeAccount (&accountmap); @@ -300,5 +244,4 @@ void ConfigurationTest::testYamlEmitter() } catch (Conf::YamlEmitterException &e) { _error ("ConfigTree: %s", e.what()); } - } diff --git a/daemon/test/main.cpp b/daemon/test/main.cpp index ba5fa4e639e4abb85fc7778627c756c6fb9424df..825101e65aae94c03dec41b1aff02f8511e4241e 100644 --- a/daemon/test/main.cpp +++ b/daemon/test/main.cpp @@ -91,8 +91,7 @@ int main (int argc, char* argv[]) printf ("\n\n=== SFLphone initialization ===\n\n"); system("cp " CONFIG_SAMPLE " " CONFIG_SAMPLE ".bak"); - Manager::instance().initConfigFile (CONFIG_SAMPLE); - Manager::instance().init(); + Manager::instance().init(CONFIG_SAMPLE); // Get the top level suite from the registry printf ("\n\n=== Test Suite: %s ===\n\n", testSuiteName.c_str());