From 3af67ec695e9ca69346deda4b80b5b0dfae9b7cb Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 27 Sep 2010 12:54:03 +0200 Subject: [PATCH 1/5] adds AmDynInvoke pointer to the supported payloads in AmArg. --- core/AmArg.cpp | 8 ++++++++ core/AmArg.h | 25 +++++++++++++++++++++---- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/core/AmArg.cpp b/core/AmArg.cpp index 18c8c257..1940f21c 100644 --- a/core/AmArg.cpp +++ b/core/AmArg.cpp @@ -37,6 +37,7 @@ const char* AmArg::t2str(int type) { case AmArg::Double: return "Double"; case AmArg::CStr: return "CStr"; case AmArg::AObject: return "AObject"; + case AmArg::ADynInv: return "ADynInv"; case AmArg::Blob: return "Blob"; case AmArg::Array: return "Array"; case AmArg::Struct: return "Struct"; @@ -62,6 +63,7 @@ AmArg& AmArg::operator=(const AmArg& v) { case Double: { v_double = v.v_double; } break; case CStr: { v_cstr = strdup(v.v_cstr); } break; case AObject:{ v_obj = v.v_obj; } break; + case ADynInv:{ v_inv = v.v_inv; } break; case Array: { v_array = new ValueArray(*v.v_array); } break; case Struct: { v_struct = new ValueStruct(*v.v_struct); } break; case Blob: { v_blob = new ArgBlob(*v.v_blob); } break; @@ -306,6 +308,7 @@ bool operator==(const AmArg& lhs, const AmArg& rhs) { case AmArg::Double: { return lhs.v_double == rhs.v_double; } break; case AmArg::CStr: { return !strcmp(lhs.v_cstr,rhs.v_cstr); } break; case AmArg::AObject:{ return lhs.v_obj == rhs.v_obj; } break; + case AmArg::ADynInv:{ return lhs.v_inv == rhs.v_inv; } break; case AmArg::Array: { return lhs.v_array == rhs.v_array; } break; case AmArg::Struct: { return lhs.v_struct == rhs.v_struct; } break; case AmArg::Blob: { return (lhs.v_blob->len == rhs.v_blob->len) && @@ -363,6 +366,7 @@ void AmArg::assertArrayFmt(const char* format) const { case 'f': assertArgDouble(get(i)); got+='f'; break; case 's': assertArgCStr(get(i)); got+='s'; break; case 'o': assertArgAObject(get(i)); got+='o'; break; + case 'd': assertArgADynInv(get(i)); got+='d'; break; case 'a': assertArgArray(get(i)); got+='a'; break; case 'b': assertArgBlob(get(i)); got+='b'; break; case 'u': assertArgStruct(get(i)); got+='u'; break; @@ -415,6 +419,10 @@ string AmArg::print(const AmArg &a) { return double2str(a.asDouble()); case CStr: return "'" + string(a.asCStr()) + "'"; + case AObject: + return ""; + case ADynInv: + return ""; case Array: s = "["; for (size_t i = 0; i < a.size(); i ++) diff --git a/core/AmArg.h b/core/AmArg.h index 0848e0b5..6d6a4101 100644 --- a/core/AmArg.h +++ b/core/AmArg.h @@ -49,11 +49,13 @@ class ArgObject { virtual ~ArgObject() { } }; -struct ArgBlob { char* data; +struct ArgBlob { + + char* data; int len; -ArgBlob() -: data(NULL),len(0) + ArgBlob() + : data(NULL),len(0) { } @@ -74,6 +76,8 @@ ArgBlob() ~ArgBlob() { if (data) free(data); } }; +class AmDynInvoke; + /** \brief variable type argument for DynInvoke APIs */ class AmArg : public ArgObject @@ -87,7 +91,8 @@ class AmArg Bool, Double, CStr, - AObject, // for passing pointers to objects not owned by AmArg + AObject, // pointer to an object not owned by AmArg + ADynInv, // pointer to a AmDynInvoke (useful for call backs) Blob, Array, @@ -116,6 +121,7 @@ class AmArg double v_double; const char* v_cstr; ArgObject* v_obj; + AmDynInvoke* v_inv; ArgBlob* v_blob; ValueArray* v_array; ValueStruct* v_struct; @@ -169,6 +175,11 @@ class AmArg v_obj(v) { } + AmArg(AmDynInvoke* v) + : type(ADynInv), + v_inv(v) + { } + // convenience constructors AmArg(vector& v); AmArg(const vector& v ); @@ -196,6 +207,7 @@ class AmArg #define isArgBool(a) (AmArg::Bool == a.getType()) #define isArgCStr(a) (AmArg::CStr == a.getType()) #define isArgAObject(a) (AmArg::AObject == a.getType()) +#define isArgADynInv(a) (AmArg::ADynInv == a.getType()) #define isArgBlob(a) (AmArg::Blob == a.getType()) #define _THROW_TYPE_MISMATCH(exp,got) \ @@ -222,6 +234,9 @@ class AmArg #define assertArgAObject(a) \ if (!isArgAObject(a)) \ _THROW_TYPE_MISMATCH(AObject,a); +#define assertArgADynInv(a) \ + if (!isArgADynInv(a)) \ + _THROW_TYPE_MISMATCH(ADynInv,a); #define assertArgBlob(a) \ if (!isArgBlob(a)) \ _THROW_TYPE_MISMATCH(Blob,a); @@ -240,6 +255,7 @@ class AmArg double asDouble() const { return v_double; } const char* asCStr() const { return v_cstr; } ArgObject* asObject() const { return v_obj; } + AmDynInvoke* asDynInv() const { return v_inv; } ArgBlob* asBlob() const { return v_blob; } ValueStruct* asStruct() const { return v_struct; } @@ -304,6 +320,7 @@ class AmArg * f - double * s - cstr * o - object + * d - dyninvoke * b - blob * a - array * u - struct From 7349c5356a1b96dd7a25fe9a50f025a53a108a93 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 27 Sep 2010 17:29:34 +0200 Subject: [PATCH 2/5] Adds notification capabilities to msg_storage. The msg_storage plug-in has been extended to send notifications to a AmDynInvoke instance in following cases: - new message - message marked as read - message has been deleted --- apps/msg_storage/MsgStorage.cpp | 71 +++++++++++++++++++++++++++++++-- apps/msg_storage/MsgStorage.h | 15 +++++++ 2 files changed, 83 insertions(+), 3 deletions(-) diff --git a/apps/msg_storage/MsgStorage.cpp b/apps/msg_storage/MsgStorage.cpp index d0da5dc4..55026636 100644 --- a/apps/msg_storage/MsgStorage.cpp +++ b/apps/msg_storage/MsgStorage.cpp @@ -21,7 +21,9 @@ MsgStorage* MsgStorage::_instance = 0; EXPORT_PLUGIN_CLASS_FACTORY(MsgStorage, MOD_NAME); MsgStorage::MsgStorage(const string& name) - : AmDynInvokeFactory(name) { + : AmDynInvokeFactory(name), + listeners() +{ _instance = this; } @@ -52,7 +54,7 @@ int MsgStorage::onLoad() { status = mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (status && (errno != EEXIST)) { - ERROR("creating test path in storage '%s': %s\n", + ERROR("Write permission check failed. Could not create '%s': %s\n", path.c_str(),strerror(errno)); return -1; } @@ -91,6 +93,7 @@ void MsgStorage::invoke(const string& method, userdir_open(args.get(0).asCStr(), args.get(1).asCStr(), ret); +#if 0 } else if(method == "userdir_close"){ ret.push(userdir_close(args.get(0).asCStr(), args.get(1).asCStr())); @@ -98,6 +101,12 @@ void MsgStorage::invoke(const string& method, userdir_getcount(args.get(0).asCStr(), args.get(1).asCStr(), ret); +#endif + } else if(method == "events_subscribe"){ + events_subscribe(args.get(0).asDynInv(), + args.get(1).asCStr()); + } else if(method == "events_unsubscribe"){ + events_unsubscribe(args.get(0).asDynInv()); } else if(method == "_list"){ ret.push("msg_new"); ret.push("msg_get"); @@ -105,8 +114,13 @@ void MsgStorage::invoke(const string& method, ret.push("msg_delete"); ret.push("userdir_open"); +#if 0 ret.push("userdir_close"); ret.push("userdir_getcount"); +#endif + + ret.push("events_subscribe"); + ret.push("events_unsubscribe"); } else throw AmDynInvoke::NotImplemented(method); @@ -146,6 +160,9 @@ int MsgStorage::msg_new(string domain, string user, if (data) filecopy(data, fp); fclose(fp); + + event_notify(domain,user,"msg_new"); + return MSG_OK; } @@ -185,6 +202,8 @@ int MsgStorage::msg_markread(string domain, string user, string msg_name) { return MSG_EREADERROR; } + event_notify(domain,user,"msg_markread"); + return MSG_OK; } @@ -196,6 +215,9 @@ int MsgStorage::msg_delete(string domain, string user, string msg_name) { path.c_str(),strerror(errno)); return MSG_EMSGNOTFOUND; } + + event_notify(domain,user,"msg_delete"); + return MSG_OK; } @@ -246,12 +268,55 @@ void MsgStorage::userdir_open(string domain, string user, AmArg& ret) { ret.push(msglist); } +#if 0 int MsgStorage::userdir_close(string domain, string user) { // TODO: unblock the directory from delete (decrease lock) return 0; } -void MsgStorage::userdir_getcount(string domain, string user, AmArg& ret) { } +void MsgStorage::userdir_getcount(string domain, string user, AmArg& ret) { + // TODO: return some useful value +} +#endif + +void MsgStorage::events_subscribe(AmDynInvoke* event_sink, string method) +{ + listeners_mut.lock(); + listeners.insert(make_pair(event_sink,method)); + listeners_mut.unlock(); +} + +void MsgStorage::events_unsubscribe(AmDynInvoke* event_sink) +{ + listeners_mut.lock(); + listeners.erase(event_sink); + listeners_mut.unlock(); +} + +void MsgStorage::event_notify(const string& domain, + const string& user, + const string& event) +{ + AmArg args,ret; + args.push(domain); + args.push(user); + args.push(event); + + listeners_mut.lock(); + + for(Listeners::iterator it = listeners.begin(); + it != listeners.end(); ++it) { + try { + it->first->invoke(it->second, args, ret); + } + catch(...){ + DBG("Unexpected exception while notifying event subscribers"); + } + ret.clear(); + } + + listeners_mut.unlock(); +} // copies ifp to ofp, blockwise void MsgStorage::filecopy(FILE* ifp, FILE* ofp) { diff --git a/apps/msg_storage/MsgStorage.h b/apps/msg_storage/MsgStorage.h index 67c12661..88aadfe3 100644 --- a/apps/msg_storage/MsgStorage.h +++ b/apps/msg_storage/MsgStorage.h @@ -3,6 +3,9 @@ #include "AmApi.h" +#include +using std::map; + class MsgStorage : public AmDynInvokeFactory, public AmDynInvoke { @@ -11,6 +14,10 @@ class MsgStorage : public AmDynInvokeFactory, string msg_dir; + typedef map Listeners; + Listeners listeners; + AmMutex listeners_mut; + int msg_new(string domain, string user, string msg_name, FILE* data); void msg_get(string domain, string user, string msg_name, AmArg& ret); int msg_markread(string domain, string user, string msg_name); @@ -20,7 +27,15 @@ class MsgStorage : public AmDynInvokeFactory, int userdir_close(string domain, string user); void userdir_getcount(string domain, string user, AmArg& ret); + void events_subscribe(AmDynInvoke* event_sink, string method); + void events_unsubscribe(AmDynInvoke* event_sink); + + void event_notify(const string& domain, + const string& user, + const string& event); + inline void filecopy(FILE* ifp, FILE* ofp); + public: MsgStorage(const string& name); ~MsgStorage(); From 96b1e816e4ccf9f588f790525f331245c0653a3c Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Mon, 27 Sep 2010 17:29:59 +0200 Subject: [PATCH 3/5] adds MWI support through PUBLISH The mwi plug-in uses the event notification from the msg_storage plug-in and sends PUBLISH requests to a presence server. Thanks to Anton Zagorskiy for this contribution. --- apps/mwi/CMakeLists.txt | 7 +++ apps/mwi/Makefile | 7 +++ apps/mwi/etc/mwi.conf | 2 + apps/mwi/mwi.cpp | 126 ++++++++++++++++++++++++++++++++++++++++ apps/mwi/mwi.h | 41 +++++++++++++ 5 files changed, 183 insertions(+) create mode 100644 apps/mwi/CMakeLists.txt create mode 100644 apps/mwi/Makefile create mode 100644 apps/mwi/etc/mwi.conf create mode 100644 apps/mwi/mwi.cpp create mode 100644 apps/mwi/mwi.h diff --git a/apps/mwi/CMakeLists.txt b/apps/mwi/CMakeLists.txt new file mode 100644 index 00000000..80dd6a25 --- /dev/null +++ b/apps/mwi/CMakeLists.txt @@ -0,0 +1,7 @@ +set (mwi_SRCS +mwi.cpp +) + +SET(sems_module_name mwi) +INCLUDE(${CMAKE_SOURCE_DIR}/cmake/module.rules.txt) +INCLUDE(${CMAKE_SOURCE_DIR}/cmake/config.rules.txt) diff --git a/apps/mwi/Makefile b/apps/mwi/Makefile new file mode 100644 index 00000000..cec8b8de --- /dev/null +++ b/apps/mwi/Makefile @@ -0,0 +1,7 @@ +plug_in_name = mwi + +module_ldflags = +module_cflags = -DMOD_NAME=\"$(plug_in_name)\" + +COREPATH ?=../../core +include $(COREPATH)/plug-in/Makefile.app_module diff --git a/apps/mwi/etc/mwi.conf b/apps/mwi/etc/mwi.conf new file mode 100644 index 00000000..13fcce62 --- /dev/null +++ b/apps/mwi/etc/mwi.conf @@ -0,0 +1,2 @@ +# Presence Server: +presence_server=127.0.0.1 \ No newline at end of file diff --git a/apps/mwi/mwi.cpp b/apps/mwi/mwi.cpp new file mode 100644 index 00000000..85972345 --- /dev/null +++ b/apps/mwi/mwi.cpp @@ -0,0 +1,126 @@ +/* + Copyright (C) Anton Zagorskiy amberovsky@gmail.com + Oyster-Telecom Laboratory + + Published under BSD License +*/ + +#include "AmPlugIn.h" +#include "AmSession.h" +#include "AmConfigReader.h" +#include "AmUtils.h" +#include "log.h" +#include "mwi.h" +#include + +MWI* MWI::_instance = 0; +AmDynInvoke* MWI::MessageStorage = 0; + +EXPORT_PLUGIN_CLASS_FACTORY(MWI, MOD_NAME); + +MWI::MWI(const string& name) + : AmDynInvokeFactory(name) { + _instance = this; +}; + +MWI::~MWI() { }; + + +int MWI::onLoad() +{ + AmDynInvokeFactory* ms_fact = + AmPlugIn::instance()->getFactory4Di("msg_storage"); + + if(!ms_fact || !(MessageStorage = ms_fact->getInstance())) { + ERROR("could not load msg_storage. Load a msg_storage implementation module.\n"); + return -1; + }; + + // register the publish method as event sink for msg_storage events + AmArg es_args,ret; + es_args.push(this); + es_args.push("publish"); + MessageStorage->invoke("events_subscribe",es_args,ret); + + AmConfigReader cfg; + if(cfg.loadFile(AmConfig::ModConfigPath + "mwi.conf")) { + ERROR("can not load configuration file\n"); + return -1; + }; + + presence_server = cfg.getParameter("presence_server"); + if (presence_server.length()) + DBG("set presence server '%s'\n", presence_server.c_str()); + else { + ERROR("parameter 'presence_server' did not found in the configuration file\n"); + return -1; + } + + DBG("MWI module loaded.\n"); + return 0; +}; + + +void MWI::publish(const string& user, const string& domain) +{ + int new_msgs = 0; + int all_msgs = 0; + string headers, body; + + AmArg di_args, ret; + di_args.push(domain.c_str()); + di_args.push(user.c_str()); + + MessageStorage->invoke("userdir_open",di_args,ret); + + if (!ret.size() || !isArgInt(ret.get(0))) { + ERROR("userdir_open for user '%s' domain '%s' returned no (valid) result.\n", user.c_str(), domain.c_str()); + return; + }; + + all_msgs = ret.get(1).size(); + for (size_t i = 0; i < ret.get(1).size(); i++) { + AmArg& elem = ret.get(1).get(i); + + if (elem.get(2).asInt()) // skip empty messages + new_msgs += elem.get(1).asInt(); + else + all_msgs--; + }; + + DBG("Found %d new and %d old messages\n", new_msgs, all_msgs - new_msgs); + string vm_buf = int2str(new_msgs) + "/" + int2str(all_msgs - new_msgs); + + headers = "Event: message-summary\r\n"; + headers += "Subscription-State: active\r\n"; + + if (new_msgs > 0) + body = "Messages-Waiting: yes\r\n"; + else + body = "Messages-Waiting: no\r\n"; + + body += "Message-Account: sip:" + user + "@" + domain + "\r\n"; + body += "Voice-Message: " + vm_buf + " (" + vm_buf + ")\r\n"; + + AmSipDialog tmp_d(NULL); + tmp_d.local_party = string(""; + tmp_d.remote_party = domain.c_str(); + tmp_d.route = "sip:" + presence_server; + tmp_d.remote_uri = "sip:" + user + "@" + domain; + tmp_d.callid = AmSession::getNewId() + "@" + presence_server; + tmp_d.local_tag = AmSession::getNewId(); + tmp_d.sendRequest("PUBLISH", "application/simple-message-summary", body, headers); +}; + +void MWI::invoke(const string& method, const AmArg& args, AmArg& ret) +{ + if (method == "publish") { + string user, domain; + user = args.get(1).asCStr(); + domain = args.get(0).asCStr(); + publish(user, domain); + ret.push(0); + } + else + throw AmDynInvoke::NotImplemented(method); +}; diff --git a/apps/mwi/mwi.h b/apps/mwi/mwi.h new file mode 100644 index 00000000..c1d7f1d6 --- /dev/null +++ b/apps/mwi/mwi.h @@ -0,0 +1,41 @@ +/* + Copyright (C) Anton Zagorskiy amberovsky@gmail.com + Oyster-Telecom Laboratory + + Published under BSD License +*/ + +#ifndef _MWI_H +#define _MWI_H + +#include "AmApi.h" +#include + +class MWI : public AmDynInvokeFactory, public AmDynInvoke +{ +private: + static MWI* _instance; + static AmDynInvoke* MessageStorage; + + string presence_server; + + typedef struct + { + unsigned int new_msgs; + unsigned int saved_msgs; + } msg_info_struct; + + void getMsgInfo (const string& name, const string& domain, msg_info_struct& msg_info); + void publish (const string& name, const string& domain); + +public: + MWI(const string& name); + ~MWI(); + + AmDynInvoke* getInstance(){ return _instance; } + + int onLoad(); + void invoke(const string& method, const AmArg& args, AmArg& ret); +}; + +#endif From 61bb42dc19d7a7640f4b40d7444189080e343f05 Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Tue, 5 Oct 2010 15:15:29 +0200 Subject: [PATCH 4/5] renamed the tracked config so that it does not conflict with the one used during tests. --- core/etc/{app_mapping.conf => app_mapping.conf.sample} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/etc/{app_mapping.conf => app_mapping.conf.sample} (100%) diff --git a/core/etc/app_mapping.conf b/core/etc/app_mapping.conf.sample similarity index 100% rename from core/etc/app_mapping.conf rename to core/etc/app_mapping.conf.sample From 791132ad7866d99bb54853081393f81d670ea1fa Mon Sep 17 00:00:00 2001 From: Raphael Coeffic Date: Thu, 7 Oct 2010 11:08:51 +0200 Subject: [PATCH 5/5] changed: SEMS won't stop anymore on the first error in config file. changed: the stderr option in config file is now read as the first option, to enable better debug/error log while reading the file. --- core/AmConfig.cpp | 88 ++++++++++++++++++++++++----------------------- core/sems.cpp | 6 +++- 2 files changed, 50 insertions(+), 44 deletions(-) diff --git a/core/AmConfig.cpp b/core/AmConfig.cpp index 4c3ee191..b6485863 100644 --- a/core/AmConfig.cpp +++ b/core/AmConfig.cpp @@ -221,6 +221,7 @@ int AmConfig::readConfiguration() DBG("Reading configuration...\n"); AmConfigReader cfg; + int ret=0; if(cfg.loadFile(AmConfig::ConfigurationFile.c_str())){ ERROR("while loading main configuration file\n"); @@ -230,6 +231,15 @@ int AmConfig::readConfiguration() // take values from global configuration file // they will be overwritten by command line args + // stderr + if(cfg.hasParameter("stderr")){ + if(!setLogStderr(cfg.getParameter("stderr"), true)){ + ERROR("invalid stderr value specified," + " valid are only yes or no\n"); + ret = -1; + } + } + #ifndef DISABLE_SYSLOG_LOG if (cfg.hasParameter("syslog_facility")) { set_syslog_facility(cfg.getParameter("syslog_facility").c_str()); @@ -251,7 +261,7 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("sip_port")){ if(!setSIPPort(cfg.getParameter("sip_port").c_str())){ ERROR("invalid sip port specified\n"); - return -1; + ret = -1; } } if(cfg.hasParameter("media_ip")) { @@ -313,7 +323,7 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("loglevel")){ if(!setLogLevel(cfg.getParameter("loglevel"))){ ERROR("invalid log level specified\n"); - return -1; + ret = -1; } } @@ -350,29 +360,30 @@ int AmConfig::readConfiguration() if (!appcfg.good()) { ERROR("could not load application mapping file at '%s'\n", appcfg_fname.c_str()); - return -1; + ret = -1; } - - while (!appcfg.eof()) { - string entry; - getline (appcfg,entry); - if (!entry.length() || entry[0] == '#') - continue; - vector re_v = explode(entry, "=>"); - if (re_v.size() != 2) { - ERROR("Incorrect line '%s' in %s: expected format 'regexp=>app_name'\n", - entry.c_str(), appcfg_fname.c_str()); - return -1; + else { + while (!appcfg.eof()) { + string entry; + getline (appcfg,entry); + if (!entry.length() || entry[0] == '#') + continue; + vector re_v = explode(entry, "=>"); + if (re_v.size() != 2) { + ERROR("Incorrect line '%s' in %s: expected format 'regexp=>app_name'\n", + entry.c_str(), appcfg_fname.c_str()); + ret = -1; + } + regex_t app_re; + if (regcomp(&app_re, re_v[0].c_str(), REG_EXTENDED | REG_NOSUB)) { + ERROR("compiling regex '%s' in %s.\n", + re_v[0].c_str(), appcfg_fname.c_str()); + ret = -1; + } + DBG("adding application mapping '%s' => '%s'\n", + re_v[0].c_str(),re_v[1].c_str()); + AppMapping.push_back(make_pair(app_re, re_v[1])); } - regex_t app_re; - if (regcomp(&app_re, re_v[0].c_str(), REG_EXTENDED | REG_NOSUB)) { - ERROR("compiling regex '%s' in %s.\n", - re_v[0].c_str(), appcfg_fname.c_str()); - return -1; - } - DBG("adding application mapping '%s' => '%s'\n", - re_v[0].c_str(),re_v[1].c_str()); - AppMapping.push_back(make_pair(app_re, re_v[1])); } } else { AppSelect = App_SPECIFIED; @@ -385,7 +396,7 @@ int AmConfig::readConfiguration() if(!setDaemonMode(cfg.getParameter("fork"))){ ERROR("invalid fork value specified," " valid are only yes or no\n"); - return -1; + ret = -1; } } @@ -394,7 +405,7 @@ int AmConfig::readConfiguration() if(!setDaemonMode(cfg.getParameter("daemon"))){ ERROR("invalid daemon value specified," " valid are only yes or no\n"); - return -1; + ret = -1; } } @@ -408,15 +419,6 @@ int AmConfig::readConfiguration() #endif /* !DISABLE_DAEMON_MODE */ - // stderr - if(cfg.hasParameter("stderr")){ - if(!setLogStderr(cfg.getParameter("stderr"), false)){ - ERROR("invalid stderr value specified," - " valid are only yes or no\n"); - return -1; - } - } - MaxShutdownTime = cfg.getParameterInt("max_shutdown_time", DEFAULT_MAX_SHUTDOWN_TIME); @@ -424,7 +426,7 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("rtp_low_port")){ if(!setRtpLowPort(cfg.getParameter("rtp_low_port"))){ ERROR("invalid rtp low port specified\n"); - return -1; + ret = -1; } } @@ -432,7 +434,7 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("rtp_high_port")){ if(!setRtpHighPort(cfg.getParameter("rtp_high_port"))){ ERROR("invalid rtp high port specified\n"); - return -1; + ret = -1; } } @@ -440,12 +442,12 @@ int AmConfig::readConfiguration() #ifdef SESSION_THREADPOOL if(!setSessionProcessorThreads(cfg.getParameter("session_processor_threads"))){ ERROR("invalid session_processor_threads value specified\n"); - return -1; + ret = -1; } if (SessionProcessorThreads<1) { ERROR("invalid session_processor_threads value specified." " need at least one thread\n"); - return -1; + ret = -1; } #else WARN("session_processor_threads specified in sems.conf,\n"); @@ -458,14 +460,14 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("media_processor_threads")){ if(!setMediaProcessorThreads(cfg.getParameter("media_processor_threads"))){ ERROR("invalid media_processor_threads value specified"); - return -1; + ret = -1; } } if(cfg.hasParameter("sip_server_threads")){ if(!setSIPServerThreads(cfg.getParameter("sip_server_threads"))){ ERROR("invalid sip_server_threads value specified"); - return -1; + ret = -1; } } @@ -486,7 +488,7 @@ int AmConfig::readConfiguration() if(cfg.hasParameter("dead_rtp_time")){ if(!setDeadRtpTime(cfg.getParameter("dead_rtp_time"))){ ERROR("invalid dead_rtp_time value specified"); - return -1; + ret = -1; } } @@ -534,11 +536,11 @@ int AmConfig::readConfiguration() } else { ERROR("unknown setting for '100rel' config option: '%s'.\n", rel100s.c_str()); - return -1; + ret = -1; } } INFO("100rel: %d.\n", AmConfig::rel100); - return 0; + return ret; } diff --git a/core/sems.cpp b/core/sems.cpp index 98fd9938..0555f11a 100644 --- a/core/sems.cpp +++ b/core/sems.cpp @@ -435,7 +435,11 @@ int main(int argc, char* argv[]) init_logging(); /* load and apply configuration file */ - AmConfig::readConfiguration(); + if(AmConfig::readConfiguration()){ + ERROR("Errors occured while reading configuration file: exiting."); + return -1; + } + log_level = AmConfig::LogLevel; log_stderr = AmConfig::LogStderr;