Commit 7a39f0c6 authored by Rafaël Carré's avatar Rafaël Carré
Browse files

* #6554 : simplify sipvoiplink

Now it's created before accounts
parent 8c124d57
......@@ -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.
......
......@@ -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;
}
}
......
......@@ -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();
}
......@@ -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__
......@@ -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());
}
......@@ -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
......@@ -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
......
......@@ -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_;
......
......@@ -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);
}
}
......
......@@ -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;
};
......
......@@ -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"
......
......@@ -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;
}
......@@ -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..