diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 6713f662..00000000 --- a/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -*.a -*.d -*.o -*.pyc -*.pyo -*.so -*~ -apps/py_sems/sip/*.cpp -apps/py_sems/sip/*.h -apps/py_sems/sip/Makefile.gen -core/etc/*.conf -core/etc/*.template -getarch -getos -sems -sems-stats -sems-logfile-callextract - -cscope.out -cscope.files -semantic.cache diff --git a/Makefile b/Makefile index a5cecf04..1d023400 100644 --- a/Makefile +++ b/Makefile @@ -23,11 +23,11 @@ clean: .PHONY: modules modules: - @for r in $(subdirs) "" ; do \ + -@for r in $(subdirs) "" ; do \ if [ -n "$$r" ]; then \ echo "" ; \ echo "making $$r" ; \ - $(MAKE) -C $$r all || exit 1; \ + $(MAKE) -C $$r all; \ fi ; \ done diff --git a/Makefile.defs b/Makefile.defs index 24b9091b..0d2ea587 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -3,25 +3,25 @@ else makefile_defs=1 export makefile_defs -GIT = $(shell which git) -SVNVERSION = $(shell which svnversion) - -ifneq ($(GIT),) - SCM_REV = $(shell if git --help describe |grep dirty 2>&1 >/dev/null ; \ - then git describe --always --dirty 2>/dev/null; \ - else git describe --always 2>/dev/null; fi) -endif - -ifeq ($(SCM_REV),) -ifneq ($(SVNVERSION),) - SCM_REV = r$(shell svnversion -n .) -endif -endif +#GIT = $(shell which git) +#SVNVERSION = $(shell which svnversion) +# +#ifneq ($(GIT),) +# SCM_REV = $(shell if git --help describe |grep dirty 2>&1 >/dev/null ; \ +# then git describe --always --dirty 2>/dev/null; \ +# else git describe --always 2>/dev/null; fi) +#endif +# +#ifeq ($(SCM_REV),) +#ifneq ($(SVNVERSION),) +# SCM_REV = r$(shell svnversion -n .) +#endif +#endif #version number VERSION = 1 PATCHLEVEL = 4 -SUBLEVEL = 3 +SUBLEVEL = 3 ifneq ($(SCM_REV),) RELEASE = $(SCM_REV) @@ -50,7 +50,7 @@ CPPFLAGS += -D_DEBUG \ # if compiled without thread pool support, every # session will have its own thread. # -USE_THREADPOOL = yes +#USE_THREADPOOL = yes # compile with spandsp DTMF detection? see soft-switch.org # this needs a fairly new version of spandsp - tested with 0.0.4pre11 diff --git a/apps/Makefile b/apps/Makefile index 6f91d016..f9470590 100644 --- a/apps/Makefile +++ b/apps/Makefile @@ -23,7 +23,7 @@ else ifneq ($(local_exclude_app_modules),) exclude_app_modules = $(local_exclude_app_modules) else - exclude_app_modules += mp3 examples py_sems xmlrpc2di gateway jsonrpc twit mobile_push + exclude_app_modules += mp3 examples py_sems xmlrpc2di gateway jsonrpc twit ifneq ($(USE_MONITORING), yes) exclude_app_modules += monitoring @@ -58,16 +58,16 @@ clean: .PHONY: modules modules: - @for r in $(app_modules) "" ; do \ - if [ -n "$$r" -a -f "$$r"/Makefile ]; then \ + -@for r in $(app_modules) "" ; do \ + if [ -n "$$r" ]; then \ echo "" ; \ echo "" ; \ - COREPATH=../$(COREPATH) $(MAKE) -C $$r all || exit 1; \ + COREPATH=../$(COREPATH) $(MAKE) -C $$r all; \ fi ; \ done .PHONY: install -install: install-bin +install: install-bin install-cfg .PHONY: install-bin install-bin: diff --git a/apps/db_reg_agent/DBRegAgent.cpp b/apps/db_reg_agent/DBRegAgent.cpp deleted file mode 100644 index 3904163a..00000000 --- a/apps/db_reg_agent/DBRegAgent.cpp +++ /dev/null @@ -1,1340 +0,0 @@ -/* - * Copyright (C) 2011 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * For a license to use the sems software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "DBRegAgent.h" -#include "AmSession.h" -#include "AmEventDispatcher.h" - -#include -#include - -EXPORT_MODULE_FACTORY(DBRegAgent); -DEFINE_MODULE_INSTANCE(DBRegAgent, MOD_NAME); - -mysqlpp::Connection DBRegAgent::MainDBConnection(mysqlpp::use_exceptions); -mysqlpp::Connection DBRegAgent::ProcessorDBConnection(mysqlpp::use_exceptions); - -string DBRegAgent::joined_query; -string DBRegAgent::registrations_table = "registrations"; - -double DBRegAgent::reregister_interval = 0.5; -double DBRegAgent::minimum_reregister_interval = -1; - -bool DBRegAgent::enable_ratelimiting = false; -unsigned int DBRegAgent::ratelimit_rate = 0; -unsigned int DBRegAgent::ratelimit_per = 0; -bool DBRegAgent::ratelimit_slowstart = false; - -bool DBRegAgent::delete_removed_registrations = true; -bool DBRegAgent::delete_failed_deregistrations = false; -bool DBRegAgent::save_contacts = true; -bool DBRegAgent::db_read_contact = false; -string DBRegAgent::contact_hostport; -string DBRegAgent::outbound_proxy; -bool DBRegAgent::save_auth_replies = false; - -unsigned int DBRegAgent::error_retry_interval = 300; - -static void _timer_cb(RegTimer* timer, long subscriber_id, int data2) { - DBRegAgent::instance()->timer_cb(timer, subscriber_id, data2); -} - -DBRegAgent::DBRegAgent(const string& _app_name) - : AmDynInvokeFactory(_app_name), - AmEventQueue(this), - uac_auth_i(NULL) -{ -} - -DBRegAgent::~DBRegAgent() { -} - -int DBRegAgent::onLoad() -{ - - DBG("loading db_reg_agent....\n"); - - AmDynInvokeFactory* uac_auth_f = AmPlugIn::instance()->getFactory4Di("uac_auth"); - if (uac_auth_f == NULL) { - WARN("unable to get a uac_auth factory. " - "registrations will not be authenticated.\n"); - WARN("(do you want to load uac_auth module?)\n"); - } else { - uac_auth_i = uac_auth_f->getInstance(); - } - - AmConfigReader cfg; - if(cfg.loadFile(add2path(AmConfig::ModConfigPath,1, MOD_NAME ".conf"))) - return -1; - - expires = cfg.getParameterInt("expires", 7200); - DBG("requesting registration expires of %u seconds\n", expires); - - if (cfg.hasParameter("reregister_interval")) { - reregister_interval = -1; - reregister_interval = atof(cfg.getParameter("reregister_interval").c_str()); - if (reregister_interval <= 0 || reregister_interval > 1) { - ERROR("configuration value 'reregister_interval' could not be read. " - "needs to be 0 .. 1.0 (recommended: 0.5)\n"); - return -1; - } - } - - if (cfg.hasParameter("minimum_reregister_interval")) { - minimum_reregister_interval = -1; - minimum_reregister_interval = atof(cfg.getParameter("minimum_reregister_interval").c_str()); - if (minimum_reregister_interval <= 0 || minimum_reregister_interval > 1) { - ERROR("configuration value 'minimum_reregister_interval' could not be read. " - "needs to be 0 .. reregister_interval (recommended: 0.4)\n"); - return -1; - } - - if (minimum_reregister_interval >= reregister_interval) { - ERROR("configuration value 'minimum_reregister_interval' must be smaller " - "than reregister_interval (recommended: 0.4)\n"); - return -1; - } - } - - enable_ratelimiting = cfg.getParameter("enable_ratelimiting") == "yes"; - if (enable_ratelimiting) { - if (!cfg.hasParameter("ratelimit_rate") || !cfg.hasParameter("ratelimit_per")) { - ERROR("if ratelimiting is enabled, ratelimit_rate and ratelimit_per must be set\n"); - return -1; - } - ratelimit_rate = cfg.getParameterInt("ratelimit_rate", 0); - ratelimit_per = cfg.getParameterInt("ratelimit_per", 0); - if (!ratelimit_rate || !ratelimit_per) { - ERROR("ratelimit_rate and ratelimit_per must be > 0\n"); - return -1; - } - ratelimit_slowstart = cfg.getParameter("ratelimit_slowstart") == "yes"; - - } - - delete_removed_registrations = - cfg.getParameter("delete_removed_registrations", "yes") == "yes"; - - delete_failed_deregistrations = - cfg.getParameter("delete_failed_deregistrations", "no") == "yes"; - - save_contacts = - cfg.getParameter("save_contacts", "yes") == "yes"; - - db_read_contact = - cfg.getParameter("db_read_contact", "no") == "yes"; - - save_auth_replies = - cfg.getParameter("save_auth_replies", "no") == "yes"; - - contact_hostport = cfg.getParameter("contact_hostport"); - - outbound_proxy = cfg.getParameter("outbound_proxy"); - - error_retry_interval = cfg.getParameterInt("error_retry_interval", 300); - if (!error_retry_interval) { - WARN("disabled retry on errors!\n"); - } - - string mysql_server, mysql_user, mysql_passwd, mysql_db; - - mysql_server = cfg.getParameter("mysql_server", "localhost"); - - mysql_user = cfg.getParameter("mysql_user"); - if (mysql_user.empty()) { - ERROR(MOD_NAME ".conf parameter 'mysql_user' is missing.\n"); - return -1; - } - - mysql_passwd = cfg.getParameter("mysql_passwd"); - if (mysql_passwd.empty()) { - ERROR(MOD_NAME ".conf parameter 'mysql_passwd' is missing.\n"); - return -1; - } - - mysql_db = cfg.getParameter("mysql_db", "sems"); - - try { - - MainDBConnection.set_option(new mysqlpp::ReconnectOption(true)); - // matched instead of changed rows in result, so we know when to create DB entry - MainDBConnection.set_option(new mysqlpp::FoundRowsOption(true)); - MainDBConnection.connect(mysql_db.c_str(), mysql_server.c_str(), - mysql_user.c_str(), mysql_passwd.c_str()); - if (!MainDBConnection) { - ERROR("Database connection failed: %s\n", MainDBConnection.error()); - return -1; - } - - ProcessorDBConnection.set_option(new mysqlpp::ReconnectOption(true)); - // matched instead of changed rows in result, so we know when to create DB entry - ProcessorDBConnection.set_option(new mysqlpp::FoundRowsOption(true)); - ProcessorDBConnection.connect(mysql_db.c_str(), mysql_server.c_str(), - mysql_user.c_str(), mysql_passwd.c_str()); - if (!ProcessorDBConnection) { - ERROR("Database connection failed: %s\n", ProcessorDBConnection.error()); - return -1; - } - - } catch (const mysqlpp::Exception& er) { - // Catch-all for any MySQL++ exceptions - ERROR("MySQL++ error: %s\n", er.what()); - return -1; - } - - // register us as SIP event receiver for MOD_NAME - AmEventDispatcher::instance()->addEventQueue(MOD_NAME,this); - - if (!AmPlugIn::registerDIInterface(MOD_NAME, this)) { - ERROR("registering "MOD_NAME" DI interface\n"); - return -1; - } - - joined_query = cfg.getParameter("joined_query"); - if (joined_query.empty()) { - // todo: name! - ERROR("joined_query must be set\n"); - return -1; - } - - if (cfg.hasParameter("registrations_table")) { - registrations_table = cfg.getParameter("registrations_table"); - } - DBG("using registrations table '%s'\n", registrations_table.c_str()); - - if (!loadRegistrations()) { - ERROR("loading registrations from DB\n"); - return -1; - } - - DBG("starting registration timer thread...\n"); - registration_scheduler.start(); - - // run_tests(); - - start(); - - return 0; -} - -void DBRegAgent::onUnload() { - if (running) { - running = false; - registration_scheduler._timer_thread_running = false; - DBG("unclean shutdown. Waiting for processing thread to stop.\n"); - for (int i=0;i<400;i++) { - if (shutdown_finished && registration_scheduler._shutdown_finished) - break; - usleep(2000); // 2ms - } - - if (!shutdown_finished || !registration_scheduler._shutdown_finished) { - WARN("processing thread could not be stopped, process will probably crash\n"); - } - } - - DBG("closing main DB connection\n"); - MainDBConnection.disconnect(); - DBG("closing auxiliary DB connection\n"); - ProcessorDBConnection.disconnect(); -} - -bool DBRegAgent::loadRegistrations() { - try { - time_t now_time = time(NULL); - - mysqlpp::Query query = DBRegAgent::MainDBConnection.query(); - - string query_string, table; - - query_string = joined_query; - - DBG("querying all registrations with : '%s'\n", - query_string.c_str()); - - query << query_string; - mysqlpp::UseQueryResult res = query.use(); - - // mysqlpp::Row::size_type row_count = res.num_rows(); - // DBG("got %zd subscriptions\n", row_count); - - while (mysqlpp::Row row = res.fetch_row()) { - int status = 0; - long subscriber_id = row[COLNAME_SUBSCRIBER_ID]; - - string contact_uri; - if (db_read_contact && row[COLNAME_CONTACT] != mysqlpp::null) { - contact_uri = (string) row[COLNAME_CONTACT]; - } - - if (row[COLNAME_STATUS] != mysqlpp::null) - status = row[COLNAME_STATUS]; - else { - DBG("registration status entry for id %ld does not exist, creating...\n", - subscriber_id); - createDBRegistration(subscriber_id, ProcessorDBConnection); - } - - DBG("got subscriber '%s@%s' status %i\n", - string(row[COLNAME_USER]).c_str(), string(row[COLNAME_REALM]).c_str(), - status); - - switch (status) { - case REG_STATUS_INACTIVE: - case REG_STATUS_PENDING: // try again - case REG_STATUS_FAILED: // try again - { - createRegistration(subscriber_id, - (string)row[COLNAME_USER], - (string)row[COLNAME_PASS], - (string)row[COLNAME_REALM], - contact_uri - ); - scheduleRegistration(subscriber_id); - }; break; - - case REG_STATUS_ACTIVE: - { - createRegistration(subscriber_id, - (string)row[COLNAME_USER], - (string)row[COLNAME_PASS], - (string)row[COLNAME_REALM], - contact_uri - ); - - time_t dt_expiry = now_time; - if (row[COLNAME_EXPIRY] != mysqlpp::null) { - dt_expiry = (time_t)((mysqlpp::DateTime)row[COLNAME_EXPIRY]); - } - - time_t dt_registration_ts = now_time; - if (row[COLNAME_REGISTRATION_TS] != mysqlpp::null) { - dt_registration_ts = (time_t)((mysqlpp::DateTime)row[COLNAME_REGISTRATION_TS]); - } - - DBG("got expiry '%ld, registration_ts %ld, now %ld'\n", - dt_expiry, dt_registration_ts, now_time); - - if (dt_registration_ts > now_time) { - WARN("needed to sanitize last_registration timestamp TS from the %ld (now %ld) - " - "DB host time mismatch?\n", dt_registration_ts, now_time); - dt_registration_ts = now_time; - } - - // if expired add to pending registrations, else schedule re-regstration - if (dt_expiry <= now_time) { - DBG("scheduling imminent re-registration for subscriber %ld\n", subscriber_id); - scheduleRegistration(subscriber_id); - } else { - setRegistrationTimer(subscriber_id, dt_expiry, dt_registration_ts, now_time); - } - - }; break; - case REG_STATUS_REMOVED: - { - DBG("ignoring removed registration %ld %s@%s", subscriber_id, - ((string)row[COLNAME_USER]).c_str(), ((string)row[COLNAME_REALM]).c_str()); - } break; - - case REG_STATUS_TO_BE_REMOVED: - { - DBG("Scheduling Deregister of registration %ld %s@%s", subscriber_id, - ((string)row[COLNAME_USER]).c_str(), ((string)row[COLNAME_REALM]).c_str()); - createRegistration(subscriber_id, - (string)row[COLNAME_USER], - (string)row[COLNAME_PASS], - (string)row[COLNAME_REALM], - contact_uri - ); - scheduleDeregistration(subscriber_id); - }; - } - } - - - } catch (const mysqlpp::Exception& er) { - // Catch-all for any MySQL++ exceptions - ERROR("MySQL++ error: %s\n", er.what()); - return false; - } - - return true; -} - -/** create registration in our list */ -void DBRegAgent::createRegistration(long subscriber_id, - const string& user, - const string& pass, - const string& realm, - const string& contact) { - - string contact_uri = contact; - if (contact_uri.empty() && !contact_hostport.empty()) { - contact_uri = "sip:"+ user + "@" + contact_hostport; - } - - string handle = AmSession::getNewId(); - SIPRegistrationInfo reg_info(realm, user, - user, // name - user, // auth_user - pass, - outbound_proxy, // proxy - contact_uri // contact - ); - - registrations_mut.lock(); - try { - if (registrations.find(subscriber_id) != registrations.end()) { - registrations_mut.unlock(); - WARN("registration with ID %ld already exists, removing\n", subscriber_id); - removeRegistration(subscriber_id); - clearRegistrationTimer(subscriber_id); - registrations_mut.lock(); - } - - AmSIPRegistration* reg = new AmSIPRegistration(handle, reg_info, "" /*MOD_NAME*/); - reg->setExpiresInterval(expires); - - registrations[subscriber_id] = reg; - registration_ltags[handle] = subscriber_id; - - if (NULL != uac_auth_i) { - DBG("enabling UAC Auth for new registration.\n"); - - // get a sessionEventHandler from uac_auth - AmArg di_args,ret; - AmArg a; - a.setBorrowedPointer(reg); - di_args.push(a); - di_args.push(a); - - uac_auth_i->invoke("getHandler", di_args, ret); - if (!ret.size()) { - ERROR("Can not add auth handler to new registration!\n"); - } else { - ArgObject* p = ret.get(0).asObject(); - if (p != NULL) { - AmSessionEventHandler* h = dynamic_cast(p); - if (h != NULL) - reg->setSessionEventHandler(h); - } - } - } - } catch (const AmArg::OutOfBoundsException& e) { - ERROR("OutOfBoundsException"); - } catch (const AmArg::TypeMismatchException& e) { - ERROR("TypeMismatchException"); - } catch (...) { - ERROR("unknown exception occured\n"); - } - - registrations_mut.unlock(); - - // register us as SIP event receiver for this ltag - AmEventDispatcher::instance()->addEventQueue(handle,this); - - DBG("created new registration with ID %ld and ltag '%s'\n", - subscriber_id, handle.c_str()); -} - -void DBRegAgent::updateRegistration(long subscriber_id, - const string& user, - const string& pass, - const string& realm, - const string& contact) { - - registrations_mut.lock(); - map::iterator it=registrations.find(subscriber_id); - if (it == registrations.end()) { - registrations_mut.unlock(); - WARN("updateRegistration - registration %ld %s@%s unknown, creating\n", - subscriber_id, user.c_str(), realm.c_str()); - createRegistration(subscriber_id, user, pass, realm, contact); - scheduleRegistration(subscriber_id); - return; - } - - bool need_reregister = it->second->getInfo().domain != realm - || it->second->getInfo().user != user - || it->second->getInfo().pwd != pass - || it->second->getInfo().contact != contact; - - string old_realm = it->second->getInfo().domain; - string old_user = it->second->getInfo().user; - it->second->setRegistrationInfo(SIPRegistrationInfo(realm, user, - user, // name - user, // auth_user - pass, - outbound_proxy, // proxy - contact)); // contact - registrations_mut.unlock(); - if (need_reregister) { - DBG("user/realm for registration %ld changed (%s@%s -> %s@%s). " - "Triggering immediate re-registration\n", - subscriber_id, old_user.c_str(), old_realm.c_str(), user.c_str(), realm.c_str()); - scheduleRegistration(subscriber_id); - } -} - -/** remove registration from our list */ -void DBRegAgent::removeRegistration(long subscriber_id) { - bool res = false; - string handle; - registrations_mut.lock(); - map::iterator it = registrations.find(subscriber_id); - if (it != registrations.end()) { - handle = it->second->getHandle(); - registration_ltags.erase(handle); - delete it->second; - registrations.erase(it); - res = true; - } - registrations_mut.unlock(); - - if (res) { - // deregister us as SIP event receiver for this ltag - AmEventDispatcher::instance()->delEventQueue(handle); - - DBG("removed registration with ID %ld\n", subscriber_id); - } else { - DBG("registration with ID %ld not found for removing\n", subscriber_id); - } -} - -/** schedule this registration to REGISTER (immediately) */ -void DBRegAgent::scheduleRegistration(long subscriber_id) { - if (enable_ratelimiting) { - registration_processor. - postEvent(new RegistrationActionEvent(RegistrationActionEvent::Register, - subscriber_id)); - } else { - // use our own thread - postEvent(new RegistrationActionEvent(RegistrationActionEvent::Register, - subscriber_id)); - } - DBG("added to pending actions: REGISTER of %ld\n", subscriber_id); -} - -/** schedule this registration to de-REGISTER (immediately) */ -void DBRegAgent::scheduleDeregistration(long subscriber_id) { - if (enable_ratelimiting) { - registration_processor. - postEvent(new RegistrationActionEvent(RegistrationActionEvent::Deregister, - subscriber_id)); - } else { - // use our own thread - postEvent(new RegistrationActionEvent(RegistrationActionEvent::Deregister, - subscriber_id)); - } - DBG("added to pending actions: DEREGISTER of %ld\n", subscriber_id); -} - -void DBRegAgent::process(AmEvent* ev) { - - if (ev->event_id == RegistrationActionEventID) { - RegistrationActionEvent* reg_action_ev = - dynamic_cast(ev); - if (reg_action_ev) { - onRegistrationActionEvent(reg_action_ev); - return; - } - } - - AmSipReplyEvent* sip_rep = dynamic_cast(ev); - if (sip_rep) { - onSipReplyEvent(sip_rep); - return; - } - - if (ev->event_id == E_SYSTEM) { - AmSystemEvent* sys_ev = dynamic_cast(ev); - if(sys_ev){ - DBG("Session received system Event\n"); - if (sys_ev->sys_event == AmSystemEvent::ServerShutdown) { - running = false; - registration_scheduler._timer_thread_running = false; - } - return; - } - } - - ERROR("unknown event received!\n"); -} - -// uses ProcessorDBConnection -void DBRegAgent::onRegistrationActionEvent(RegistrationActionEvent* reg_action_ev) { - switch (reg_action_ev->action) { - case RegistrationActionEvent::Register: - { - DBG("REGISTER of registration %i\n", reg_action_ev->subscriber_id); - registrations_mut.lock(); - map::iterator it= - registrations.find(reg_action_ev->subscriber_id); - if (it==registrations.end()) { - DBG("ignoring scheduled REGISTER of unknown registration %i\n", - reg_action_ev->subscriber_id); - } else { - if (!it->second->doRegistration()) { - updateDBRegistration(ProcessorDBConnection, - reg_action_ev->subscriber_id, - 480, ERR_REASON_UNABLE_TO_SEND_REQUEST, - true, REG_STATUS_FAILED); - if (error_retry_interval) { - // schedule register-refresh after error_retry_interval - setRegistrationTimer(reg_action_ev->subscriber_id, error_retry_interval, - RegistrationActionEvent::Register); - } - } - } - registrations_mut.unlock(); - } break; - case RegistrationActionEvent::Deregister: - { - DBG("De-REGISTER of registration %i\n", reg_action_ev->subscriber_id); - registrations_mut.lock(); - map::iterator it= - registrations.find(reg_action_ev->subscriber_id); - if (it==registrations.end()) { - DBG("ignoring scheduled De-REGISTER of unknown registration %i\n", - reg_action_ev->subscriber_id); - } else { - if (!it->second->doUnregister()) { - if (delete_removed_registrations && delete_failed_deregistrations) { - DBG("sending de-Register failed - deleting registration %i " - "(delete_failed_deregistrations=yes)\n", reg_action_ev->subscriber_id); - deleteDBRegistration(reg_action_ev->subscriber_id, ProcessorDBConnection); - } else { - DBG("failed sending de-register, updating DB with REG_STATUS_TO_BE_REMOVED " - ERR_REASON_UNABLE_TO_SEND_REQUEST "for subscriber %i\n", - reg_action_ev->subscriber_id); - updateDBRegistration(ProcessorDBConnection, - reg_action_ev->subscriber_id, - 480, ERR_REASON_UNABLE_TO_SEND_REQUEST, - true, REG_STATUS_TO_BE_REMOVED); - // don't re-try de-registrations if sending failed - // if (error_retry_interval) { - // // schedule register-refresh after error_retry_interval - // setRegistrationTimer(reg_action_ev->subscriber_id, error_retry_interval, - // RegistrationActionEvent::Deregister); - // } - } - } - } - registrations_mut.unlock(); - } break; - } -} - -void DBRegAgent::createDBRegistration(long subscriber_id, mysqlpp::Connection& conn) { - string insert_query = "insert into "+registrations_table+ - " (subscriber_id) values ("+ - long2str(subscriber_id)+");"; - - try { - mysqlpp::Query query = conn.query(); - query << insert_query; - - mysqlpp::SimpleResult res = query.execute(); - if (!res) { - WARN("creating registration in DB with query '%s' failed: '%s'\n", - insert_query.c_str(), res.info()); - } - } catch (const mysqlpp::Exception& er) { - // Catch-all for any MySQL++ exceptions - ERROR("MySQL++ error: %s\n", er.what()); - return; - } -} - -void DBRegAgent::deleteDBRegistration(long subscriber_id, mysqlpp::Connection& conn) { - string insert_query = "delete from "+registrations_table+ - " where subscriber_id=" + long2str(subscriber_id)+";"; - - try { - mysqlpp::Query query = conn.query(); - query << insert_query; - - mysqlpp::SimpleResult res = query.execute(); - if (!res) { - WARN("removing registration in DB with query '%s' failed: '%s'\n", - insert_query.c_str(), res.info()); - } - } catch (const mysqlpp::Exception& er) { - // Catch-all for any MySQL++ exceptions - ERROR("MySQL++ error: %s\n", er.what()); - return; - } -} - -void DBRegAgent::updateDBRegistration(mysqlpp::Connection& db_connection, - long subscriber_id, int last_code, - const string& last_reason, - bool update_status, int status, - bool update_ts, unsigned int expiry, - bool update_contacts, const string& contacts) { - try { - - mysqlpp::Query query = db_connection.query(); - - query << "update "+registrations_table+" set last_code="+ int2str(last_code) +", "; - query << "last_reason="; - query << mysqlpp::quote << last_reason; - - if (update_status) { - query << ", registration_status="+int2str(status); - } - - if (update_ts) { - query << ", last_registration=NOW(), " - "expiry=TIMESTAMPADD(SECOND,"+int2str(expiry)+", NOW())"; - } - - if (update_contacts) { - query << ", contacts=" << mysqlpp::quote << contacts; - } - - query << " where " COLNAME_SUBSCRIBER_ID "="+long2str(subscriber_id) + ";"; - string query_str = query.str(); - DBG("updating registration in DB with query '%s'\n", query_str.c_str()); - - mysqlpp::SimpleResult res = query.execute(); - if (!res) { - WARN("updating registration in DB with query '%s' failed: '%s'\n", - query_str.c_str(), res.info()); - } else { - if (!res.rows()) { - // should not happen - DB entry is created on load or on createRegistration - DBG("creating registration DB entry for subscriber %ld\n", subscriber_id); - createDBRegistration(subscriber_id, db_connection); - query.reset(); - query << query_str; - - mysqlpp::SimpleResult res = query.execute(); - if (!res || !res.rows()) { - WARN("updating registration in DB with query '%s' failed: '%s'\n", - query_str.c_str(), res.info()); - } - } - } - - } catch (const mysqlpp::Exception& er) { - // Catch-all for any MySQL++ exceptions - ERROR("MySQL++ error: %s\n", er.what()); - return; - } - -} - -// uses MainDBConnection -void DBRegAgent::onSipReplyEvent(AmSipReplyEvent* ev) { - if (!ev) return; - - DBG("received SIP reply event for '%s'\n", -#ifdef HAS_OFFER_ANSWER - ev->reply.from_tag.c_str() -#else - ev->reply.local_tag.c_str() -#endif - ); - registrations_mut.lock(); - - string local_tag = -#ifdef HAS_OFFER_ANSWER - ev->reply.from_tag; -#else - ev->reply.local_tag; -#endif - - map::iterator it=registration_ltags.find(local_tag); - if (it!=registration_ltags.end()) { - long subscriber_id = it->second; - map::iterator r_it=registrations.find(subscriber_id); - if (r_it != registrations.end()) { - AmSIPRegistration* registration = r_it->second; - if (!registration) { - ERROR("Internal error: registration object missing\n"); - return; - } - unsigned int cseq_before = registration->getDlg()->cseq; - -#ifdef HAS_OFFER_ANSWER - registration->getDlg()->onRxReply(ev->reply); -#else - registration->getDlg()->updateStatus(ev->reply); -#endif - - //update registrations set - bool update_status = false; - int status = 0; - bool update_ts = false; - unsigned int expiry = 0; - bool delete_status = false; - bool auth_pending = false; - - if (ev->reply.code >= 300) { - // REGISTER or de-REGISTER failed - if ((ev->reply.code == 401 || ev->reply.code == 407) && - // auth response codes - // processing reply triggered sending request: resent by auth - (cseq_before != registration->getDlg()->cseq)) { - DBG("received negative reply, but still in pending state (auth).\n"); - auth_pending = true; - } else { - if (!registration->getUnregistering()) { - // REGISTER failed - mark in DB - DBG("registration failed - mark in DB\n"); - update_status = true; - status = REG_STATUS_FAILED; - if (error_retry_interval) { - // schedule register-refresh after error_retry_interval - setRegistrationTimer(subscriber_id, error_retry_interval, - RegistrationActionEvent::Register); - } - } else { - // de-REGISTER failed - if (delete_removed_registrations && delete_failed_deregistrations) { - DBG("de-Register failed - deleting registration %ld " - "(delete_failed_deregistrations=yes)\n", subscriber_id); - delete_status = true; - } else { - update_status = true; - status = REG_STATUS_TO_BE_REMOVED; - } - } - } - } else if (ev->reply.code >= 200) { - // positive reply - if (!registration->getUnregistering()) { - time_t now_time = time(0); - setRegistrationTimer(subscriber_id, registration->getExpiresTS(), - now_time, now_time); - - update_status = true; - status = REG_STATUS_ACTIVE; - - update_ts = true; - expiry = registration->getExpiresLeft(); - } else { - if (delete_removed_registrations) { - delete_status = true; - } else { - update_status = true; - status = REG_STATUS_REMOVED; - } - } - } - - // skip provisional replies & auth - if (ev->reply.code >= 200 && !auth_pending) { - // remove unregistered - if (registration->getUnregistering()) { - registrations_mut.unlock(); - removeRegistration(subscriber_id); - registrations_mut.lock(); - } - } - - if (!delete_status) { - if (auth_pending && !save_auth_replies) { - DBG("not updating DB with auth reply %u %s\n", - ev->reply.code, ev->reply.reason.c_str()); - } else { - DBG("update DB with reply %u %s\n", ev->reply.code, ev->reply.reason.c_str()); - updateDBRegistration(MainDBConnection, - subscriber_id, ev->reply.code, ev->reply.reason, - update_status, status, update_ts, expiry, - save_contacts, ev->reply.contact); - } - } else { - DBG("delete DB registration of subscriber %ld\n", subscriber_id); - deleteDBRegistration(subscriber_id, MainDBConnection); - } - - } else { - ERROR("internal: inconsistent registration list\n"); - } - } else { - DBG("ignoring reply for unknown registration\n"); - } - registrations_mut.unlock(); -} - -void DBRegAgent::run() { - running = shutdown_finished = true; - - DBG("DBRegAgent thread: waiting 2 sec for server startup ...\n"); - sleep(2); - - mysqlpp::Connection::thread_start(); - - if (enable_ratelimiting) { - DBG("starting processor thread\n"); - registration_processor.start(); - } - - DBG("running DBRegAgent thread...\n"); - shutdown_finished = false; - while (running) { - processEvents(); - - usleep(1000); // 1ms - } - - DBG("DBRegAgent done, removing all registrations from Event Dispatcher...\n"); - registrations_mut.lock(); - for (map::iterator it=registration_ltags.begin(); - it != registration_ltags.end(); it++) { - AmEventDispatcher::instance()->delEventQueue(it->first); - } - registrations_mut.unlock(); - - DBG("removing "MOD_NAME" registrations from Event Dispatcher...\n"); - AmEventDispatcher::instance()->delEventQueue(MOD_NAME); - - mysqlpp::Connection::thread_end(); - - DBG("DBRegAgent thread stopped.\n"); - shutdown_finished = true; -} - -void DBRegAgent::on_stop() { - DBG("DBRegAgent on_stop()...\n"); - running = false; -} - -void DBRegAgent::setRegistrationTimer(long subscriber_id, unsigned int timeout, - RegistrationActionEvent::RegAction reg_action) { - DBG("setting Register timer for subscription %ld, timeout %u, reg_action %u\n", - subscriber_id, timeout, reg_action); - - RegTimer* timer = NULL; - map::iterator it=registration_timers.find(subscriber_id); - if (it==registration_timers.end()) { - DBG("timer object for subscription %ld not found\n", subscriber_id); - timer = new RegTimer(); - timer->data1 = subscriber_id; - timer->cb = _timer_cb; - DBG("created timer object [%p] for subscription %ld\n", timer, subscriber_id); - } else { - timer = it->second; - DBG("removing scheduled timer...\n"); - registration_scheduler.remove_timer(timer); - } - - timer->data2 = reg_action; - timer->expires = time(0) + timeout; - - DBG("placing timer for %ld in T-%u\n", subscriber_id, timeout); - registration_scheduler.insert_timer(timer); - - registration_timers.insert(std::make_pair(subscriber_id, timer)); - -} - -void DBRegAgent::setRegistrationTimer(long subscriber_id, - time_t expiry, time_t reg_start_ts, - time_t now_time) { - DBG("setting re-Register timer for subscription %ld, expiry %ld, reg_start_t %ld\n", - subscriber_id, expiry, reg_start_ts); - - RegTimer* timer = NULL; - map::iterator it=registration_timers.find(subscriber_id); - if (it==registration_timers.end()) { - DBG("timer object for subscription %ld not found\n", subscriber_id); - timer = new RegTimer(); - timer->data1 = subscriber_id; - timer->cb = _timer_cb; - DBG("created timer object [%p] for subscription %ld\n", timer, subscriber_id); - registration_timers.insert(std::make_pair(subscriber_id, timer)); - } else { - timer = it->second; - DBG("removing scheduled timer...\n"); - registration_scheduler.remove_timer(timer); - } - - timer->data2 = RegistrationActionEvent::Register; - - if (minimum_reregister_interval>0.0) { - time_t t_expiry_max = reg_start_ts; - time_t t_expiry_min = reg_start_ts; - if (expiry > reg_start_ts) - t_expiry_max+=(expiry - reg_start_ts) * reregister_interval; - if (expiry > reg_start_ts) - t_expiry_min+=(expiry - reg_start_ts) * minimum_reregister_interval; - - if (t_expiry_max < now_time) { - // calculated interval completely in the past - immediate re-registration - // by setting the timer to now - t_expiry_max = now_time; - } - - if (t_expiry_min > t_expiry_max) - t_expiry_min = t_expiry_max; - - timer->expires = t_expiry_max; - - if (t_expiry_max == now_time) { - // immediate re-registration - DBG("calculated re-registration at TS (%ld)" - "(reg_start_ts=%ld, reg_expiry=%ld, reregister_interval=%f, " - "minimum_reregister_interval=%f)\n", - t_expiry_max, reg_start_ts, expiry, - reregister_interval, minimum_reregister_interval); - registration_scheduler.insert_timer(timer); - } else { - DBG("calculated re-registration at TS %ld .. %ld" - "(reg_start_ts=%ld, reg_expiry=%ld, reregister_interval=%f, " - "minimum_reregister_interval=%f)\n", - t_expiry_min, t_expiry_max, reg_start_ts, expiry, - reregister_interval, minimum_reregister_interval); - - registration_scheduler.insert_timer_leastloaded(timer, t_expiry_min, t_expiry_max); - } - } else { - time_t t_expiry = reg_start_ts; - if (expiry > reg_start_ts) - t_expiry+=(expiry - reg_start_ts) * reregister_interval; - - if (t_expiry < now_time) { - t_expiry = now_time; - DBG("re-registering at TS (%ld)\n", now_time); - } - - DBG("calculated re-registration at TS %ld " - "(reg_start_ts=%ld, reg_expiry=%ld, reregister_interval=%f)\n", - t_expiry, reg_start_ts, expiry, reregister_interval); - - timer->expires = t_expiry; - registration_scheduler.insert_timer(timer); - } -} - -void DBRegAgent::clearRegistrationTimer(long subscriber_id) { - DBG("removing timer for subscription %ld", subscriber_id); - - map::iterator it=registration_timers.find(subscriber_id); - if (it==registration_timers.end()) { - DBG("timer object for subscription %ld not found\n", subscriber_id); - return; - } - DBG("removing timer [%p] from scheduler\n", it->second); - registration_scheduler.remove_timer(it->second); - - DBG("deleting timer object [%p]\n", it->second); - delete it->second; - - registration_timers.erase(it); -} - -void DBRegAgent::removeRegistrationTimer(long subscriber_id) { - DBG("removing timer object for subscription %ld", subscriber_id); - - map::iterator it=registration_timers.find(subscriber_id); - if (it==registration_timers.end()) { - DBG("timer object for subscription %ld not found\n", subscriber_id); - return; - } - - DBG("deleting timer object [%p]\n", it->second); - delete it->second; - - registration_timers.erase(it); -} - -void DBRegAgent::timer_cb(RegTimer* timer, long subscriber_id, int reg_action) { - DBG("re-registration timer expired: subscriber %ld, timer=[%p], action %d\n", - subscriber_id, timer, reg_action); - - registrations_mut.lock(); - removeRegistrationTimer(subscriber_id); - registrations_mut.unlock(); - switch (reg_action) { - case RegistrationActionEvent::Register: - scheduleRegistration(subscriber_id); break; - case RegistrationActionEvent::Deregister: - scheduleDeregistration(subscriber_id); break; - default: ERROR("internal: unknown reg_action %d for subscriber %ld timer event\n", - reg_action, subscriber_id); - }; -} - - -void DBRegAgent::DIcreateRegistration(int subscriber_id, const string& user, - const string& pass, const string& realm, - const string& contact, - AmArg& ret) { - DBG("DI method: createRegistration(%i, %s, %s, %s, %s)\n", - subscriber_id, user.c_str(), - pass.c_str(), realm.c_str(), contact.c_str()); - - createRegistration(subscriber_id, user, pass, realm, contact); - scheduleRegistration(subscriber_id); - ret.push(200); - ret.push("OK"); -} - -void DBRegAgent::DIupdateRegistration(int subscriber_id, const string& user, - const string& pass, const string& realm, - const string& contact, - AmArg& ret) { - DBG("DI method: updateRegistration(%i, %s, %s, %s)\n", - subscriber_id, user.c_str(), - pass.c_str(), realm.c_str()); - - string contact_uri = contact; - if (contact_uri.empty() && !contact_hostport.empty()) { - contact_uri = "sip:"+ user + "@" + contact_hostport; - } - - updateRegistration(subscriber_id, user, pass, realm, contact_uri); - - ret.push(200); - ret.push("OK"); -} - -void DBRegAgent::DIremoveRegistration(int subscriber_id, AmArg& ret) { - DBG("DI method: removeRegistration(%i)\n", - subscriber_id); - scheduleDeregistration(subscriber_id); - - registrations_mut.lock(); - clearRegistrationTimer(subscriber_id); - registrations_mut.unlock(); - - ret.push(200); - ret.push("OK"); -} - -void DBRegAgent::DIrefreshRegistration(int subscriber_id, AmArg& ret) { - DBG("DI method: refreshRegistration(%i)\n", subscriber_id); - scheduleRegistration(subscriber_id); - - ret.push(200); - ret.push("OK"); -} - -// ///////// DI API /////////////////// - -void DBRegAgent::invoke(const string& method, - const AmArg& args, AmArg& ret) -{ - if (method == "createRegistration"){ - args.assertArrayFmt("isss"); // subscriber_id, user, pass, realm - string contact; - if (args.size() > 4) { - assertArgCStr(args.get(4)); - contact = args.get(4).asCStr(); - } - DIcreateRegistration(args.get(0).asInt(), args.get(1).asCStr(), - args.get(2).asCStr(),args.get(3).asCStr(), - contact, ret); - } else if (method == "updateRegistration"){ - args.assertArrayFmt("isss"); // subscriber_id, user, pass, realm - string contact; - if (args.size() > 4) { - assertArgCStr(args.get(4)); - contact = args.get(4).asCStr(); - } - DIupdateRegistration(args.get(0).asInt(), args.get(1).asCStr(), - args.get(2).asCStr(),args.get(3).asCStr(), - contact, ret); - } else if (method == "removeRegistration"){ - args.assertArrayFmt("i"); // subscriber_id - DIremoveRegistration(args.get(0).asInt(), ret); - } else if (method == "refreshRegistration"){ - args.assertArrayFmt("i"); // subscriber_id - DIrefreshRegistration(args.get(0).asInt(), ret); - } else if(method == "_list"){ - ret.push(AmArg("createRegistration")); - ret.push(AmArg("updateRegistration")); - ret.push(AmArg("removeRegistration")); - ret.push(AmArg("refreshRegistration")); - } else - throw AmDynInvoke::NotImplemented(method); -} - -// /////////////// processor thread ///////////////// - -DBRegAgentProcessorThread::DBRegAgentProcessorThread() - : AmEventQueue(this), stopped(false) { -} - -DBRegAgentProcessorThread::~DBRegAgentProcessorThread() { -} - -void DBRegAgentProcessorThread::on_stop() { -} - -void DBRegAgentProcessorThread::rateLimitWait() { - DBG("applying rate limit %u initial requests per %us\n", - DBRegAgent::ratelimit_rate, DBRegAgent::ratelimit_per); - - DBG("allowance before ratelimit: %f\n", allowance); - - struct timeval current; - struct timeval time_passed; - gettimeofday(¤t, 0); - timersub(¤t, &last_check, &time_passed); - memcpy(&last_check, ¤t, sizeof(struct timeval)); - double seconds_passed = (double)time_passed.tv_sec + - (double)time_passed.tv_usec / 1000000.0; - allowance += seconds_passed * - (double) DBRegAgent::ratelimit_rate / (double)DBRegAgent::ratelimit_per; - - if (allowance > (double)DBRegAgent::ratelimit_rate) - allowance = (double)DBRegAgent::ratelimit_rate; // enough time passed, but limit to max - if (allowance < 1.0) { - useconds_t sleep_time = 1000000.0 * (1.0 - allowance) * - ((double)DBRegAgent::ratelimit_per/(double)DBRegAgent::ratelimit_rate); - DBG("not enough allowance (%f), sleeping %d useconds\n", allowance, sleep_time); - usleep(sleep_time); - allowance=0.0; - gettimeofday(&last_check, 0); - } else { - allowance -= 1.0; - } - - DBG("allowance left: %f\n", allowance); -} - -void DBRegAgentProcessorThread::run() { - DBG("DBRegAgentProcessorThread thread started\n"); - - // register us as SIP event receiver for MOD_NAME_processor - AmEventDispatcher::instance()->addEventQueue(MOD_NAME "_processor",this); - - mysqlpp::Connection::thread_start(); - - // initialize ratelimit - gettimeofday(&last_check, NULL); - if (DBRegAgent::ratelimit_slowstart) - allowance = 0.0; - else - allowance = DBRegAgent::ratelimit_rate; - - reg_agent = DBRegAgent::instance(); - while (!stopped) { - waitForEvent(); - while (eventPending()) { - rateLimitWait(); - processSingleEvent(); - } - } - - mysqlpp::Connection::thread_end(); - - DBG("DBRegAgentProcessorThread thread stopped\n"); -} - -void DBRegAgentProcessorThread::process(AmEvent* ev) { - - if (ev->event_id == E_SYSTEM) { - AmSystemEvent* sys_ev = dynamic_cast(ev); - if(sys_ev){ - DBG("Session received system Event\n"); - if (sys_ev->sys_event == AmSystemEvent::ServerShutdown) { - DBG("stopping processor thread\n"); - stopped = true; - } - return; - } - } - - - if (ev->event_id == RegistrationActionEventID) { - RegistrationActionEvent* reg_action_ev = - dynamic_cast(ev); - if (reg_action_ev) { - reg_agent->onRegistrationActionEvent(reg_action_ev); - return; - } - } - - ERROR("unknown event received!\n"); -} -#if 0 -void test_cb(RegTimer* tr, long data1, void* data2) { - DBG("cb called: [%p], data %ld / [%p]\n", tr, data1, data2); -} - -void DBRegAgent::run_tests() { - - registration_timer.start(); - - struct timeval now; - gettimeofday(&now, 0); - - RegTimer rt; - rt.expires = now.tv_sec + 10; - rt.cb=test_cb; - registration_scheduler.insert_timer(&rt); - - RegTimer rt2; - rt2.expires = now.tv_sec + 5; - rt2.cb=test_cb; - registration_scheduler.insert_timer(&rt2); - - RegTimer rt3; - rt3.expires = now.tv_sec + 15; - rt3.cb=test_cb; - registration_scheduler.insert_timer(&rt3); - - RegTimer rt4; - rt4.expires = now.tv_sec - 1; - rt4.cb=test_cb; - registration_scheduler.insert_timer(&rt4); - - RegTimer rt5; - rt5.expires = now.tv_sec + 100000; - rt5.cb=test_cb; - registration_scheduler.insert_timer(&rt5); - - RegTimer rt6; - rt6.expires = now.tv_sec + 100; - rt6.cb=test_cb; - registration_scheduler.insert_timer_leastloaded(&rt6, now.tv_sec+5, now.tv_sec+50); - - - sleep(30); - gettimeofday(&now, 0); - - RegTimer rt7; - rt6.expires = now.tv_sec + 980; - rt6.cb=test_cb; - registration_scheduler.insert_timer_leastloaded(&rt6, now.tv_sec+9980, now.tv_sec+9990); - - vector rts; - - for (int i=0;i<1000;i++) { - RegTimer* t = new RegTimer(); - rts.push_back(t); - t->expires = now.tv_sec + i; - t->cb=test_cb; - registration_scheduler.insert_timer_leastloaded(t, now.tv_sec, now.tv_sec+1000); - } - - sleep(200); -} -#endif diff --git a/apps/db_reg_agent/DBRegAgent.h b/apps/db_reg_agent/DBRegAgent.h deleted file mode 100644 index bbb0861e..00000000 --- a/apps/db_reg_agent/DBRegAgent.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright (C) 2011 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * For a license to use the sems software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _DB_REGAgent_h_ -#define _DB_REGAgent_h_ -#include - -#include - - -#include -using std::map; -#include -using std::queue; - -#include "AmApi.h" -#include "AmSipRegistration.h" - -#include "RegistrationTimer.h" - -#define REG_STATUS_INACTIVE 0 -#define REG_STATUS_PENDING 1 -#define REG_STATUS_ACTIVE 2 -#define REG_STATUS_FAILED 3 -#define REG_STATUS_REMOVED 4 -#define REG_STATUS_TO_BE_REMOVED 5 - -#define REG_STATUS_INACTIVE_S "0" -#define REG_STATUS_PENDING_S "1" -#define REG_STATUS_ACTIVE_S "2" -#define REG_STATUS_FAILED_S "3" -#define REG_STATUS_REMOVED_S "4" -#define REG_STATUS_TO_BE_REMOVED_S "5" - -#define COLNAME_SUBSCRIBER_ID "subscriber_id" -#define COLNAME_USER "user" -#define COLNAME_PASS "pass" -#define COLNAME_REALM "realm" -#define COLNAME_CONTACT "contact" - -#define COLNAME_STATUS "registration_status" -#define COLNAME_EXPIRY "expiry" -#define COLNAME_REGISTRATION_TS "last_registration" -#define COLNAME_LAST_CODE "last_code" -#define COLNAME_LAST_REASON "last_reason" - -#define RegistrationActionEventID 117 - -#define ERR_REASON_UNABLE_TO_SEND_REQUEST "unable to send request" - -struct RegistrationActionEvent : public AmEvent { - - enum RegAction { Register=0, Deregister }; - -RegistrationActionEvent(RegAction action, int subscriber_id) - : AmEvent(RegistrationActionEventID), - action(action), subscriber_id(subscriber_id) { } - - RegAction action; - int subscriber_id; -}; - -class DBRegAgent; - -// separate thread for REGISTER sending, which can block for rate limiting -class DBRegAgentProcessorThread -: public AmThread, - public AmEventQueue, - public AmEventHandler -{ - - DBRegAgent* reg_agent; - bool stopped; - - void rateLimitWait(); - - double allowance; - struct timeval last_check; - - protected: - void process(AmEvent* ev); - - public: - DBRegAgentProcessorThread(); - ~DBRegAgentProcessorThread(); - - void run(); - void on_stop(); - -}; - -class DBRegAgent -: public AmDynInvokeFactory, - public AmDynInvoke, - public AmThread, - public AmEventQueue, - public AmEventHandler -{ - - static string joined_query; - static string registrations_table; - - static double reregister_interval; - static double minimum_reregister_interval; - - static bool enable_ratelimiting; - static unsigned int ratelimit_rate; - static unsigned int ratelimit_per; - static bool ratelimit_slowstart; - - static bool delete_removed_registrations; - static bool delete_failed_deregistrations; - static bool save_contacts; - - static bool db_read_contact; - - static string contact_hostport; - - static string outbound_proxy; - - static bool save_auth_replies; - - static unsigned int error_retry_interval; - - map registrations; - map registration_ltags; - map registration_timers; - AmMutex registrations_mut; - - // connection used in main DBRegAgent thread - static mysqlpp::Connection MainDBConnection; - - // connection used in other thread (processor thread) - static mysqlpp::Connection ProcessorDBConnection; - - int onLoad(); - - void onUnload(); - - RegistrationTimer registration_scheduler; - DBRegAgentProcessorThread registration_processor; - - bool loadRegistrations(); - - void createDBRegistration(long subscriber_id, mysqlpp::Connection& conn); - void deleteDBRegistration(long subscriber_id, mysqlpp::Connection& conn); - void updateDBRegistration(mysqlpp::Connection& db_connection, - long subscriber_id, int last_code, - const string& last_reason, - bool update_status = false, int status = 0, - bool update_ts=false, unsigned int expiry = 0, - bool update_contacts=false, const string& contacts = ""); - - /** create registration in our list */ - void createRegistration(long subscriber_id, - const string& user, - const string& pass, - const string& realm, - const string& contact); - /** update registration in our list */ - void updateRegistration(long subscriber_id, - const string& user, - const string& pass, - const string& realm, - const string& contact); - - /** remove registration */ - void removeRegistration(long subscriber_id); - - /** schedule this subscriber to REGISTER imminently */ - void scheduleRegistration(long subscriber_id); - - /** schedule this subscriber to de-REGISTER imminently*/ - void scheduleDeregistration(long subscriber_id); - - /** create a timer for the registration - fixed expiry + action */ - void setRegistrationTimer(long subscriber_id, unsigned int timeout, - RegistrationActionEvent::RegAction reg_action); - - /** create a registration refresh timer for that registration - @param subscriber_id - ID of subscription - @param expiry - SIP registration expiry time - @param reg_start_ts - start TS of the SIP registration - @param now_time - current time - */ - void setRegistrationTimer(long subscriber_id, - time_t expiry, time_t reg_start_ts, time_t now_time); - - /** clear re-registration timer and remove timer object */ - void clearRegistrationTimer(long subscriber_id); - - /** remove timer object */ - void removeRegistrationTimer(long subscriber_id); - - // void run_tests(); - - // amThread - void run(); - void on_stop(); - - // AmEventHandler - void process(AmEvent* ev); - - void onSipReplyEvent(AmSipReplyEvent* ev); - - void onRegistrationActionEvent(RegistrationActionEvent* reg_action_ev); - - - unsigned int expires; - - /** processing thread running? */ - bool running; - - /** processing thread shutdown finished? */ - bool shutdown_finished; - - AmDynInvoke* uac_auth_i; - - void DIcreateRegistration(int subscriber_id, const string& user, - const string& pass, const string& realm, - const string& contact, AmArg& ret); - void DIupdateRegistration(int subscriber_id, const string& user, - const string& pass, const string& realm, - const string& contact, AmArg& ret); - void DIremoveRegistration(int subscriber_id, AmArg& ret); - void DIrefreshRegistration(int subscriber_id, AmArg& ret); - - - public: - DBRegAgent(const string& _app_name); - ~DBRegAgent(); - - DECLARE_MODULE_INSTANCE(DBRegAgent); - - // DI - // DI factory - AmDynInvoke* getInstance() { return instance(); } - // DI API - void invoke(const string& method, - const AmArg& args, AmArg& ret); - /** re-registration timer callback */ - void timer_cb(RegTimer* timer, long subscriber_id, int data2); - - friend class DBRegAgentProcessorThread; -}; - -#endif diff --git a/apps/db_reg_agent/Makefile b/apps/db_reg_agent/Makefile deleted file mode 100644 index fc938786..00000000 --- a/apps/db_reg_agent/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -plug_in_name = db_reg_agent - -module_ldflags = -lmysqlpp -module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I/usr/include/mysql++ -I/usr/include/mysql - -COREPATH ?=../../core -include $(COREPATH)/plug-in/Makefile.app_module diff --git a/apps/db_reg_agent/RegistrationTimer.cpp b/apps/db_reg_agent/RegistrationTimer.cpp deleted file mode 100644 index 79d5be36..00000000 --- a/apps/db_reg_agent/RegistrationTimer.cpp +++ /dev/null @@ -1,301 +0,0 @@ -/* - * Copyright (C) 2011 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * For a license to use the sems software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "RegistrationTimer.h" -#include - -RegistrationTimer::RegistrationTimer() - : current_bucket(0) -{ - struct timeval now; - gettimeofday(&now, 0); - current_bucket_start = now.tv_sec; -} - -// unsafe! -int RegistrationTimer::get_bucket_index(time_t tv) { - time_t buckets_start_time = current_bucket_start; - - if (tv < buckets_start_time) - return -1; - - // offset - int bucket_index = (tv - buckets_start_time); - bucket_index /= TIMER_BUCKET_LENGTH; - - if (bucket_index > TIMER_BUCKETS) { // too far in the future - ERROR("requested timer too far in the future (index %d vs %d TIMER_BUCKETS)\n", - bucket_index, TIMER_BUCKETS); - return -2; - } - - bucket_index += current_bucket; - bucket_index %= TIMER_BUCKETS; // circular array - - return bucket_index; -} - -void RegistrationTimer::place_timer(RegTimer* timer, int bucket_index) { - if (bucket_index < 0) { - ERROR("trying to place_timer with negative index (%i)\n", bucket_index); - return; - } - - if (bucket_index > TIMER_BUCKETS) { - ERROR("trying to place_timer with too high index (%i vs %i)\n", - bucket_index, TIMER_BUCKETS); - return; - } - - std::list::iterator it = buckets[bucket_index].timers.begin(); - while (it != buckets[bucket_index].timers.end() && - (timer->expires > (*it)->expires)) - it++; - - buckets[bucket_index].timers.insert(it, timer); - size_t b_size = buckets[bucket_index].timers.size(); - - DBG("inserted timer [%p] in bucket %i (now sized %zd)\n", - timer, bucket_index, b_size); -} - -void RegistrationTimer::fire_timer(RegTimer* timer) { - if (timer && timer->cb) { - DBG("firing timer [%p]\n", timer); - timer->cb(timer, timer->data1, timer->data2); - } -} - -bool RegistrationTimer::insert_timer(RegTimer* timer) { - if (!timer) - return false; - - buckets_mut.lock(); - int bucket_index = get_bucket_index(timer->expires); - - if (bucket_index == -1) { - // already expired, fire timer - buckets_mut.unlock(); - DBG("inserting already expired timer [%p], firing\n", timer); - fire_timer(timer); - return false; - } - - if (bucket_index == -2) { - ERROR("trying to place timer too far in the future\n"); - buckets_mut.unlock(); - return false; - } - - place_timer(timer, bucket_index); - - buckets_mut.unlock(); - - return true; -} - -bool RegistrationTimer::remove_timer(RegTimer* timer) { - if (!timer) - return false; - - bool res = false; - - buckets_mut.lock(); - int bucket_index = get_bucket_index(timer->expires); - - if (bucket_index < 0) { - buckets_mut.unlock(); - return false; - } - - std::list& timerlist = buckets[bucket_index].timers; - - for (std::list::iterator it = timerlist.begin(); - it != timerlist.end(); it++) { - if (*it == timer) { - timerlist.erase(it); - res = true; - break; - } - } - - buckets_mut.unlock(); - - if (res) { - DBG("successfully removed timer [%p]\n", timer); - } else { - DBG("timer [%p] not found for removing\n", timer); - } - return res; -} - -void RegistrationTimer::run_timers() { - std::list timers_tbf; - - struct timeval now; - gettimeofday(&now, 0); - - buckets_mut.lock(); - - // bucket over? - if (now.tv_sec > current_bucket_start + TIMER_BUCKET_LENGTH) { - timers_tbf.insert(timers_tbf.begin(), - buckets[current_bucket].timers.begin(), - buckets[current_bucket].timers.end()); - buckets[current_bucket].timers.clear(); - current_bucket++; - current_bucket %= TIMER_BUCKETS; - current_bucket_start += TIMER_BUCKET_LENGTH; - // DBG("turned bucket to %i\n", current_bucket); - } - - // move timers from current_bucket - RegTimerBucket& bucket = buckets[current_bucket]; - std::list::iterator it = bucket.timers.begin(); - while (it != bucket.timers.end() && - now.tv_sec > (*it)->expires) { - std::list::iterator c_it = it; - it++; - timers_tbf.push_back(*c_it); - bucket.timers.erase(c_it); - } - - buckets_mut.unlock(); - - if (!timers_tbf.empty()) { - DBG("firing %zd timers\n", timers_tbf.size()); - for (std::list::iterator it=timers_tbf.begin(); - it != timers_tbf.end(); it++) { - fire_timer(*it); - } - } -} - -void RegistrationTimer::run() -{ - struct timeval now,next_tick,diff,tick; - _shutdown_finished = false; - - tick.tv_sec = 0; - tick.tv_usec = TIMER_RESOLUTION; - - gettimeofday(&now, NULL); - timeradd(&tick,&now,&next_tick); - - _timer_thread_running = true; - - while(_timer_thread_running){ - - gettimeofday(&now,NULL); - - if(timercmp(&now,&next_tick,<)){ - - struct timespec sdiff,rem; - timersub(&next_tick, &now,&diff); - - sdiff.tv_sec = diff.tv_sec; - sdiff.tv_nsec = diff.tv_usec * 1000; - - if(sdiff.tv_nsec > 2000000) // 2 ms - nanosleep(&sdiff,&rem); - } - //else { - //printf("missed one tick\n"); - //} - - run_timers(); - timeradd(&tick,&next_tick,&next_tick); - } - - DBG("RegistrationTimer thread finishing.\n"); - _shutdown_finished = true; -} - -void RegistrationTimer::on_stop() { -} - -bool RegistrationTimer::insert_timer_leastloaded(RegTimer* timer, - time_t from_time, - time_t to_time) { - - buckets_mut.lock(); - - int from_index = get_bucket_index(from_time); - int to_index = get_bucket_index(to_time); - - if (from_index < 0 && to_index < 0) { - ERROR("could not find timer bucket indices - " - "from_index = %d, to_index = %d, from_time = %ld, to_time %ld, " - "current_bucket_start = %ld\n", - from_index, to_index, from_time, to_time, current_bucket_start); - buckets_mut.unlock(); - return false; - } - - if (from_index < 0) { - // use now .. to_index - DBG("from_time (%ld) in the past - searching load loaded from now()\n", from_time); - from_index = current_bucket; - } - // find least loaded bucket - int res_index = from_index; - size_t least_load = buckets[from_index].timers.size(); - - int i = from_index; - while (i != to_index) { - if (buckets[i].timers.size() <= least_load) { - least_load = buckets[i].timers.size(); - res_index = i; - } - - i++; - i %= TIMER_BUCKETS; - } - DBG("found bucket %i with least load %zd (between %i and %i)\n", - res_index, least_load, from_index, to_index); - - // update expires to some random value inside the selected bucket - int diff = (unsigned)res_index - current_bucket; - - if ((unsigned)res_index < current_bucket) { - diff+=TIMER_BUCKETS; - } - - timer->expires = current_bucket_start + - diff * TIMER_BUCKET_LENGTH + // bucket start - rand() % TIMER_BUCKET_LENGTH; - DBG("setting expires to %ld (between %ld and %ld)\n", - timer->expires, from_time, to_time); - - place_timer(timer, res_index); - - buckets_mut.unlock(); - - return false; -} - - - - diff --git a/apps/db_reg_agent/RegistrationTimer.h b/apps/db_reg_agent/RegistrationTimer.h deleted file mode 100644 index c39fb1e5..00000000 --- a/apps/db_reg_agent/RegistrationTimer.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (C) 2011 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * For a license to use the sems software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef _RegistrationTimer_h_ -#define _RegistrationTimer_h_ - -#include -#include - -#include - -#include "log.h" -#include "AmThread.h" - -#define TIMER_BUCKET_LENGTH 10 // 10 sec -#define TIMER_BUCKETS 40000 // 40000 buckets (400000 sec, 111 hrs) - -// 100 ms == 100000 us -#define TIMER_RESOLUTION 100000 - -class RegTimer; -typedef void (*timer_cb)(RegTimer*, long /*data1*/,int /*data2*/); - -class RegTimerBucket; - -class RegTimer { - public: - time_t expires; - - timer_cb cb; - long data1; - int data2; - - RegTimer() - : expires(0), cb(0), data1(0), data2(0) { } -}; - -class RegTimerBucket { - public: - std::list timers; - - RegTimerBucket() { } -}; - -/** - Additionally to normal timer operation (setting and removing timer, - fire the timer when it is expired), this RegistrationTimer timers - class needs to support insert_timer_leastloaded() which should insert - the timer in some least loaded interval between from_time and to_time - in order to flatten out re-register spikes (due to restart etc). - - Timer granularity is seconds. - - Timers are saved in buckets of TIMER_BUCKET_LENGTH seconds. the buckets - array is a circular one, the current bucket starts from the time - current_bucket_start (in seconds as in time(2)). - - The timer object is owned by the caller, and MUST be valid until it is - fired or removed. - */ - -class RegistrationTimer -: public AmThread -{ - time_t current_bucket_start; - // every bucket contains TIMER_BUCKET_LENGTH seconds of timers - RegTimerBucket buckets[TIMER_BUCKETS]; - unsigned int current_bucket; - AmMutex buckets_mut; - - int get_bucket_index(time_t tv); - void place_timer(RegTimer* timer, int bucket_index); - void fire_timer(RegTimer* timer); - void run_timers(); - - protected: - void run(); - void on_stop(); - - public: - bool insert_timer(RegTimer* timer); - bool remove_timer(RegTimer* timer); - - bool insert_timer_leastloaded(RegTimer* timer, - time_t from_time, - time_t to_time); - - RegistrationTimer(); - bool _timer_thread_running; - bool _shutdown_finished; -}; - -#endif diff --git a/apps/db_reg_agent/etc/db_reg_agent.conf b/apps/db_reg_agent/etc/db_reg_agent.conf deleted file mode 100644 index a77abf07..00000000 --- a/apps/db_reg_agent/etc/db_reg_agent.conf +++ /dev/null @@ -1,99 +0,0 @@ -# Database connection -mysql_user=root -mysql_passwd=mypass123 - -# mysql_server, default: localhost -# mysql_server=localhost - -#mysql_db, default: sems -# mysql_db=sems - -# table for registration status -# default: registrations -# registrations_table="registrations" - -# query joining subscriber info with registration table -joined_query="select subscribers.subscriber_id as subscriber_id, subscribers.user as user, subscribers.pass as pass, subscribers.realm as realm, registrations.registration_status as registration_status, registrations.expiry as expiry, registrations.last_registration as last_registration from subscribers left join registrations on subscribers.subscriber_id=registrations.subscriber_id;" - -#example with contact: -# joined_query="select subscribers.subscriber_id as subscriber_id, subscribers.user as user, subscribers.pass as pass, subscribers.realm as realm, subscribers.contact as contact, registrations.registration_status as registration_status, registrations.expiry as expiry, registrations.last_registration as last_registration from subscribers left join registrations on subscribers.subscriber_id=registrations.subscriber_id;" - -# outbound_proxy= -# set the outbound proxy to send registrations through -# -#outbound_proxy=sip:10.0.0.2:5070 - -# contact_hostport= - overriding contact host:port -# sets the contact host:port portion that is registered -# default: empty -#contact_hostport=10.0.0.50:5080 - -# db_read_contact=[yes, no] : read individual contact to register from DB? -# note: joined_query must select the contact, too -# default: no -#db_read_contact=yes - -#save_contacts=[yes, no] : save contacts? -# for monitoring and troubleshooting, all contacts returned with a positive reply -# may be saved to DB in the registrations.contacts colums -# default: yes -#save_contacts=yes - -#save_auth_replies=[yes, no] : update status on 401 replies (auth)? -# usually, 401 replies which are resent with auth are not saved. if save_auth_replies=yes, -# last_code and last_reason in DB is updated with the 401 -#save_auth_replies=yes - -# expires: desired expires, i.e. expires value that is requested -# default: 7200 -# expires=300 - -# error_retry_interval -# -# default: 300 - -# reregister_interval: fraction of actual expires after which register is refreshed -# default: reregister_interval=0.5 -#reregister_interval=0.5 - -# minimum_reregister_interval: if set, re-register is scheduled in least loaded time -# in minimum_reregister_interval .. reregister_interval i order to smooth load spikes -# must be smaller than reregister_interval -# default: off -# -# example: -# reregister_interval=0.5 -# minimum_reregister_interval=0.4 -# on a registration expiring in 3600s, the least loaded spot between 1440s and 1800s -# is chosen -# -#minimum_reregister_interval=0.4 - -# enable_ratelimiting=yes : Enable ratelimiting? -# default: no -# if enabled, the amount of initial REGISTER requests is limited (not counting re-trans- -# missions and requests re-sent for authentication) -#enable_ratelimiting=yes - -# ratelimit_rate=300 : rate of initial REGISTER requests to send as maximum -#ratelimit_rate=2 - -# ratelimit_per=1 : per time unit (in seconds, e.g. 300 REGISTER in 1 second) -#ratelimit_per=1 - -#ratelimit_slowstart=[yes|no] : on startup send initially ratelimit_rate or 0 requests -#default: no -#ratelimit_slowstart=yes - -# delete_removed_registrations=yes : delete removed registrations from registrations -# table in DB? (otherwise they will stay with STATUS_REMOVED) -# default: yes -# -#delete_removed_registrations=no - -# delete_failed_deregistrations=yes : delete failed de-registrations from registrations -# table in DB? (otherwise they will stay with STATUS_TO_BE_REMOVED) -# only applicable if delete_removed_registrations=yes -# default: no -# -#delete_failed_deregistrations=no diff --git a/apps/dsm/DSMCall.cpp b/apps/dsm/DSMCall.cpp index 63af6742..d48f2fc4 100644 --- a/apps/dsm/DSMCall.cpp +++ b/apps/dsm/DSMCall.cpp @@ -29,9 +29,6 @@ #include "AmUtils.h" #include "AmMediaProcessor.h" #include "DSM.h" -#include "AmConferenceStatus.h" -#include "AmAdvancedAudio.h" -#include "AmSipSubscription.h" #include "../apps/jsonrpc/JsonRPCEvents.h" // todo! @@ -96,7 +93,6 @@ void DSMCall::onInvite(const AmSipRequest& req) { bool run_session_invite = engine.onInvite(req, this); if (run_invite_event) { - avar[DSM_AVAR_REQUEST] = AmArg(&req); if (!engine.init(this, this, startDiagName, DSMCondition::Invite)) run_session_invite =false; @@ -104,7 +100,7 @@ void DSMCall::onInvite(const AmSipRequest& req) { DBG("session choose to not connect media\n"); run_session_invite = false; // don't accept audio } - avar.erase(DSM_AVAR_REQUEST); + } if (run_session_invite) @@ -387,14 +383,6 @@ void DSMCall::process(AmEvent* event) engine.runEvent(this, this, DSMCondition::PlaylistSeparator, ¶ms); } - ConferenceEvent * conf_ev = dynamic_cast(event); - if (conf_ev) { - map params; - params["type"] = "conference_event"; - params["id"] = int2str(conf_ev->event_id); - engine.runEvent(this, this, DSMCondition::DSMEvent, ¶ms); - } - // todo: give modules the possibility to define/process events JsonRpcEvent* jsonrpc_ev = dynamic_cast(event); if (jsonrpc_ev) { @@ -451,33 +439,6 @@ void DSMCall::process(AmEvent* event) } - if (event->event_id == E_SIP_SUBSCRIPTION) { - SIPSubscriptionEvent* sub_ev = dynamic_cast(event); - if (sub_ev) { - DBG("DSM Call received SIP Subscription Event\n"); - map params; - params["status"] = sub_ev->getStatusText(); - params["code"] = int2str(sub_ev->code); - params["reason"] = sub_ev->reason; - params["expires"] = int2str(sub_ev->expires); - params["has_body"] = (!sub_ev->notify_body.empty())?"true":"false"; - if (!sub_ev->notify_body.empty()) { - avar[DSM_AVAR_SIPSUBSCRIPTION_BODY] = AmArg(sub_ev->notify_body); - } - engine.runEvent(this, this, DSMCondition::SIPSubscription, ¶ms); - avar.erase(DSM_AVAR_SIPSUBSCRIPTION_BODY); - } - } - - AmRtpTimeoutEvent* timeout_ev = dynamic_cast(event); - if (timeout_ev) { - map params; - params["type"] = "rtp_timeout"; - params["timeout_value"] = int2str(AmConfig::DeadRtpTime); - engine.runEvent(this, this, DSMCondition::RTPTimeout, ¶ms); - return; - } - AmB2BCallerSession::process(event); } @@ -485,13 +446,13 @@ inline UACAuthCred* DSMCall::getCredentials() { return cred.get(); } -void DSMCall::playPrompt(const string& name, bool loop, bool front) { +void DSMCall::playPrompt(const string& name, bool loop) { DBG("playing prompt '%s'\n", name.c_str()); if (prompts->addToPlaylist(name, (long)this, playlist, - front, loop)) { + /*front =*/ false, loop)) { if ((var["prompts.default_fallback"] != "yes") || default_prompts->addToPlaylist(name, (long)this, playlist, - front, loop)) { + /*front =*/ false, loop)) { DBG("checked [%p]\n", default_prompts); throw DSMException("prompt", "name", name); } else { @@ -508,17 +469,9 @@ void DSMCall::closePlaylist(bool notify) { playlist.close(notify); } -void DSMCall::flushPlaylist() { - DBG("flush playlist\n"); - playlist.close(false); -} - -void DSMCall::addToPlaylist(AmPlaylistItem* item, bool front) { +void DSMCall::addToPlaylist(AmPlaylistItem* item) { DBG("add item to playlist\n"); - if (front) - playlist.addToPlayListFront(item); - else - playlist.addToPlaylist(item); + playlist.addToPlaylist(item); } void DSMCall::playFile(const string& name, bool loop, bool front) { @@ -544,18 +497,6 @@ void DSMCall::playFile(const string& name, bool loop, bool front) { CLR_ERRNO; } -void DSMCall::playSilence(unsigned int length, bool front) { - AmNullAudio* af = new AmNullAudio(); - af->setReadLength(length); - if (front) - playlist.addToPlayListFront(new AmPlaylistItem(af, NULL)); - else - playlist.addToPlaylist(new AmPlaylistItem(af, NULL)); - - audiofiles.push_back(af); - CLR_ERRNO; -} - void DSMCall::recordFile(const string& name) { if (rec_file) stopRecord(); @@ -678,14 +619,10 @@ void DSMCall::addSeparator(const string& name, bool front) { } void DSMCall::transferOwnership(DSMDisposable* d) { - if (d == NULL) - return; gc_trash.insert(d); } void DSMCall::releaseOwnership(DSMDisposable* d) { - if (d == NULL) - return; gc_trash.erase(d); } diff --git a/apps/dsm/DSMCall.h b/apps/dsm/DSMCall.h index 673f1c59..7e7405ac 100644 --- a/apps/dsm/DSMCall.h +++ b/apps/dsm/DSMCall.h @@ -97,12 +97,10 @@ public: void setPromptSets(map& new_prompt_sets); // DSMSession interface - void playPrompt(const string& name, bool loop = false, bool front = false); + void playPrompt(const string& name, bool loop = false); void closePlaylist(bool notify); - void flushPlaylist(); - void addToPlaylist(AmPlaylistItem* item, bool front = false); + void addToPlaylist(AmPlaylistItem* item); void playFile(const string& name, bool loop, bool front=false); - void playSilence(unsigned int length, bool front=false); void recordFile(const string& name); unsigned int getRecordLength(); unsigned int getRecordDataSize(); diff --git a/apps/dsm/DSMCoreModule.cpp b/apps/dsm/DSMCoreModule.cpp index 6768f89a..ae34ac48 100644 --- a/apps/dsm/DSMCoreModule.cpp +++ b/apps/dsm/DSMCoreModule.cpp @@ -55,12 +55,9 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("stop", SCStopAction); DEF_CMD("playPrompt", SCPlayPromptAction); - DEF_CMD("playPromptFront", SCPlayPromptFrontAction); DEF_CMD("playPromptLooped", SCPlayPromptLoopedAction); DEF_CMD("playFile", SCPlayFileAction); DEF_CMD("playFileFront", SCPlayFileFrontAction); - DEF_CMD("playSilence", SCPlaySilenceAction); - DEF_CMD("playSilenceFront", SCPlaySilenceFrontAction); DEF_CMD("recordFile", SCRecordFileAction); DEF_CMD("stopRecord", SCStopRecordAction); DEF_CMD("getRecordLength", SCGetRecordLengthAction); @@ -70,11 +67,6 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("addSeparator", SCAddSeparatorAction); DEF_CMD("connectMedia", SCConnectMediaAction); DEF_CMD("disconnectMedia", SCDisconnectMediaAction); - DEF_CMD("enableReceiving", SCEnableReceivingAction); - DEF_CMD("disableReceiving", SCDisableReceivingAction); - DEF_CMD("enableForceDTMFReceiving", SCEnableForceDTMFReceiving); - DEF_CMD("disableForceDTMFReceiving", SCDisableForceDTMFReceiving); - DEF_CMD("monitorRTPTimeout", SCMonitorRTPTimeoutAction); DEF_CMD("mute", SCMuteAction); DEF_CMD("unmute", SCUnmuteAction); DEF_CMD("enableDTMFDetection", SCEnableDTMFDetection); @@ -131,10 +123,6 @@ DSMAction* DSMCoreModule::getAction(const string& from_str) { DEF_CMD("B2B.clearHeaders", SCB2BClearHeadersAction); DEF_CMD("B2B.setHeaders", SCB2BSetHeadersAction); - DEF_CMD("trackObject", SCTrackObjectAction); - DEF_CMD("releaseObject", SCReleaseObjectAction); - DEF_CMD("freeObject", SCFreeObjectAction); - return NULL; } @@ -205,9 +193,6 @@ DSMCondition* DSMCoreModule::getCondition(const string& from_str) { if (cmd == "jsonRpcResponse") return new TestDSMCondition(params, DSMCondition::JsonRpcResponse); - if (cmd == "subscription") - return new TestDSMCondition(params, DSMCondition::SIPSubscription); - if (cmd == "startup") return new TestDSMCondition(params, DSMCondition::Startup); @@ -217,9 +202,6 @@ DSMCondition* DSMCoreModule::getCondition(const string& from_str) { if (cmd == "system") return new TestDSMCondition(params, DSMCondition::System); - if (cmd == "rtpTimeout") - return new TestDSMCondition(params, DSMCondition::RTPTimeout); - return NULL; } @@ -227,10 +209,6 @@ EXEC_ACTION_START(SCPlayPromptAction) { sc_sess->playPrompt(resolveVars(arg, sess, sc_sess, event_params)); } EXEC_ACTION_END; -EXEC_ACTION_START(SCPlayPromptFrontAction) { - sc_sess->playPrompt(resolveVars(arg, sess, sc_sess, event_params), false, true); -} EXEC_ACTION_END; - EXEC_ACTION_START(SCSetPromptsAction) { sc_sess->setPromptSet(resolveVars(arg, sess, sc_sess, event_params)); } EXEC_ACTION_END; @@ -306,24 +284,6 @@ EXEC_ACTION_START(SCPlayFileFrontAction) { loop, true); } EXEC_ACTION_END; -EXEC_ACTION_START(SCPlaySilenceAction) { - int length; - string length_str = resolveVars(arg, sess, sc_sess, event_params); - if (!str2int(length_str, length)) { - throw DSMException("core", "cause", "cannot parse number"); - } - sc_sess->playSilence(length); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCPlaySilenceFrontAction) { - int length; - string length_str = resolveVars(arg, sess, sc_sess, event_params); - if (!str2int(length_str, length)) { - throw DSMException("core", "cause", "cannot parse number"); - } - sc_sess->playSilence(length, true); -} EXEC_ACTION_END; - EXEC_ACTION_START(SCRecordFileAction) { sc_sess->recordFile(resolveVars(arg, sess, sc_sess, event_params)); } EXEC_ACTION_END; @@ -365,32 +325,6 @@ EXEC_ACTION_START(SCDisconnectMediaAction) { sc_sess->disconnectMedia(); } EXEC_ACTION_END; -EXEC_ACTION_START(SCEnableReceivingAction) { - DBG("enabling RTP receving in session\nb"); - sess->setReceiving(true); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCDisableReceivingAction) { - DBG("disabling RTP receving in session\nb"); - sess->setReceiving(false); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCEnableForceDTMFReceiving) { - DBG("enabling forced DTMF RTP receving in session\nb"); - sess->setForceDtmfReceiving(true); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCDisableForceDTMFReceiving) { - DBG("disabling forced DTMF RTP receving in session\nb"); - sess->setForceDtmfReceiving(false); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCMonitorRTPTimeoutAction) { - string e = resolveVars(arg, sess, sc_sess, event_params); - DBG("setting RTP stream to %smonitor RTP timeout\n", e=="true"?"":"not"); - sess->RTPStream()->setMonitorRTPTimeout(e=="true"); -} EXEC_ACTION_END; - EXEC_ACTION_START(SCMuteAction) { sc_sess->mute(); } EXEC_ACTION_END; @@ -1399,49 +1333,3 @@ EXEC_ACTION_START(SCCreateSystemDSMAction) { } EXEC_ACTION_END; -DSMDisposable* getObjectFromVariable(DSMSession* sc_sess, const string& var_name) { - AVarMapT::iterator it = sc_sess->avar.find(var_name); - if (it == sc_sess->avar.end()) { - DBG("object '%s' not found\n", var_name.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("object '"+var_name+"' not found\n"); - return NULL; - } - - DSMDisposable* disp = dynamic_cast(it->second.asObject()); - if (NULL == disp) { - DBG("object '%s' is not a DSMDisposable\n", var_name.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("object '"+var_name+"' is not a DSMDisposable\n"); - return NULL; - } - return disp; -} - -EXEC_ACTION_START(SCTrackObjectAction) { - string var_name = resolveVars(arg, sess, sc_sess, event_params); - DSMDisposable* disp = getObjectFromVariable(sc_sess, var_name); - if (NULL == disp) { - EXEC_ACTION_STOP; - } - sc_sess->transferOwnership(disp); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCReleaseObjectAction) { - string var_name = resolveVars(arg, sess, sc_sess, event_params); - DSMDisposable* disp = getObjectFromVariable(sc_sess, var_name); - if (NULL == disp) { - EXEC_ACTION_STOP; - } - sc_sess->releaseOwnership(disp); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCFreeObjectAction) { - string var_name = resolveVars(arg, sess, sc_sess, event_params); - DSMDisposable* disp = getObjectFromVariable(sc_sess, var_name); - if (NULL == disp) { - EXEC_ACTION_STOP; - } - delete disp; - sc_sess->avar.erase(var_name); -} EXEC_ACTION_END; diff --git a/apps/dsm/DSMCoreModule.h b/apps/dsm/DSMCoreModule.h index cbb0ffb2..c00c2581 100644 --- a/apps/dsm/DSMCoreModule.h +++ b/apps/dsm/DSMCoreModule.h @@ -48,7 +48,6 @@ class DSMCoreModule }; DEF_ACTION_1P(SCPlayPromptAction); -DEF_ACTION_1P(SCPlayPromptFrontAction); DEF_ACTION_1P(SCPlayPromptLoopedAction); DEF_ACTION_1P(SCRecordFileAction); DEF_ACTION_1P(SCStopRecordAction); @@ -59,11 +58,6 @@ DEF_ACTION_1P(SCSetInOutPlaylistAction); DEF_ACTION_1P(SCStopAction); DEF_ACTION_1P(SCConnectMediaAction); DEF_ACTION_1P(SCDisconnectMediaAction); -DEF_ACTION_1P(SCEnableReceivingAction); -DEF_ACTION_1P(SCDisableReceivingAction); -DEF_ACTION_1P(SCEnableForceDTMFReceiving); -DEF_ACTION_1P(SCDisableForceDTMFReceiving); -DEF_ACTION_1P(SCMonitorRTPTimeoutAction); DEF_ACTION_1P(SCMuteAction); DEF_ACTION_1P(SCUnmuteAction); DEF_ACTION_1P(SCEnableDTMFDetection); @@ -71,7 +65,6 @@ DEF_ACTION_1P(SCDisableDTMFDetection); DEF_ACTION_2P(SCSendDTMFAction); DEF_ACTION_2P(SCSendDTMFSequenceAction); - DEF_ACTION_1P(SCSetPromptsAction); DEF_ACTION_2P(SCAddSeparatorAction); @@ -105,8 +98,6 @@ DEF_ACTION_2P(SCGetParamAction); DEF_ACTION_2P(SCSetVarAction); DEF_ACTION_2P(SCPlayFileAction); DEF_ACTION_2P(SCPlayFileFrontAction); -DEF_ACTION_1P(SCPlaySilenceAction); -DEF_ACTION_1P(SCPlaySilenceFrontAction); DEF_ACTION_2P(SCPostEventAction); DEF_ACTION_2P(SCB2BConnectCalleeAction); @@ -122,10 +113,6 @@ DEF_ACTION_1P(SCUnregisterEventQueueAction); DEF_ACTION_2P(SCCreateSystemDSMAction); -DEF_ACTION_1P(SCTrackObjectAction); -DEF_ACTION_1P(SCReleaseObjectAction); -DEF_ACTION_1P(SCFreeObjectAction); - class SCDIAction : public DSMAction { vector params; diff --git a/apps/dsm/DSMModule.h b/apps/dsm/DSMModule.h index 0153971e..7f7f8e8a 100644 --- a/apps/dsm/DSMModule.h +++ b/apps/dsm/DSMModule.h @@ -52,8 +52,6 @@ class DSMModule { virtual int preload() { return 0; } virtual bool onInvite(const AmSipRequest& req, DSMSession* sess) { return true; } virtual void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { } - virtual void processSdpOffer(AmSdp& offer) { } - virtual void processSdpAnswer(const AmSdp& offer, AmSdp& answer) { } }; typedef map EventParamT; @@ -132,7 +130,8 @@ class SCStrArgAction /* bool xsplit(const string& arg, char sep, bool optional, string& par1, string& par2); */ -#define SPLIT_ARGS(sep, optional) \ +#define CONST_ACTION_2P(CL_name, sep, optional) \ + CL_name::CL_name(const string& arg) { \ size_t p = 0; \ char last_c = ' '; \ bool quot=false; \ @@ -195,14 +194,9 @@ class SCStrArgAction ERROR("expected two parameters separated with '%c' in expression '%s' for %s\n", \ sep,arg.c_str(),typeid(this).name()); \ return; \ - } - - -#define CONST_ACTION_2P(CL_name, _sep, _optional) \ - CL_name::CL_name(const string& arg) { \ - SPLIT_ARGS(_sep, _optional); \ - } - + } \ + } \ + #define EXEC_ACTION_START(act_name) \ bool act_name::execute(AmSession* sess, DSMSession* sc_sess, \ @@ -247,24 +241,7 @@ void splitCmd(const string& from_str, bool match(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, \ map* event_params); \ }; - -#define DEF_CONDITION_2P(cond_name) \ - class cond_name \ - : public DSMCondition { \ - string par1; \ - string par2; \ - bool inv; \ - public: \ - cond_name(const string& arg, bool inv); \ - bool match(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, \ - map* event_params); \ - }; - -#define CONST_CONDITION_2P(cond_name, _sep, _optional) \ - cond_name::cond_name(const string& arg, bool inv) \ - : inv(inv) { \ - SPLIT_ARGS(_sep, _optional); \ - } + #define MATCH_CONDITION_START(cond_clsname) \ bool cond_clsname::match(AmSession* sess, DSMSession* sc_sess, \ diff --git a/apps/dsm/DSMSession.h b/apps/dsm/DSMSession.h index b56879df..a7475b2f 100644 --- a/apps/dsm/DSMSession.h +++ b/apps/dsm/DSMSession.h @@ -66,8 +66,6 @@ using std::map; #define DSM_AVAR_JSONRPCRESPONSEDATA "JsonRpcResponseParameters" #define DSM_AVAR_JSONRPCRESPONSEUDATA "JsonRpcResponseUData" -#define DSM_AVAR_SIPSUBSCRIPTION_BODY "SipSubscriptionBody" - #define DSM_ERRNO_FILE "file" #define DSM_ERRNO_UNKNOWN_ARG "arg" #define DSM_ERRNO_SCRIPT "script" @@ -102,9 +100,8 @@ class DSMSession { DSMSession(); virtual ~DSMSession(); - virtual void playPrompt(const string& name, bool loop = false, bool front = false) = 0; + virtual void playPrompt(const string& name, bool loop = false) = 0; virtual void playFile(const string& name, bool loop, bool front = false) = 0; - virtual void playSilence(unsigned int length, bool front = false) = 0; virtual void recordFile(const string& name) = 0; virtual unsigned int getRecordLength() = 0; virtual unsigned int getRecordDataSize() = 0; @@ -113,9 +110,8 @@ class DSMSession { virtual void setInputPlaylist() = 0; virtual void setOutputPlaylist() = 0; - virtual void addToPlaylist(AmPlaylistItem* item, bool front = false) = 0; + virtual void addToPlaylist(AmPlaylistItem* item) = 0; virtual void closePlaylist(bool notify) = 0; - virtual void flushPlaylist() = 0; virtual void setPromptSet(const string& name) = 0; virtual void addSeparator(const string& name, bool front = false) = 0; virtual void connectMedia() = 0; diff --git a/apps/dsm/DSMStateEngine.cpp b/apps/dsm/DSMStateEngine.cpp index 50c70c2f..f36a2f7e 100644 --- a/apps/dsm/DSMStateEngine.cpp +++ b/apps/dsm/DSMStateEngine.cpp @@ -224,18 +224,6 @@ void DSMStateEngine::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { (*it)->onBeforeDestroy(sc_sess, sess); } -void DSMStateEngine::processSdpOffer(AmSdp& offer) { - for (vector::iterator it = - mods.begin(); it != mods.end(); it++) - (*it)->processSdpOffer(offer); -} - -void DSMStateEngine::processSdpAnswer(const AmSdp& offer, AmSdp& answer) { - for (vector::iterator it = - mods.begin(); it != mods.end(); it++) - (*it)->processSdpAnswer(offer, answer); -} - bool DSMStateEngine::runactions(vector::iterator from, vector::iterator to, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, diff --git a/apps/dsm/DSMStateEngine.h b/apps/dsm/DSMStateEngine.h index 4e3836ff..e3351094 100644 --- a/apps/dsm/DSMStateEngine.h +++ b/apps/dsm/DSMStateEngine.h @@ -30,7 +30,6 @@ #include "DSMElemContainer.h" #include "AmSipMsg.h" #include "AmArg.h" -#include "AmSdp.h" class AmSession; class DSMSession; @@ -91,10 +90,7 @@ class DSMCondition Startup, Reload, - System, - - RTPTimeout, - SIPSubscription + System }; bool invert; @@ -288,9 +284,6 @@ class DSMStateEngine { /** @return whether call should be accepted */ bool onInvite(const AmSipRequest& req, DSMSession* sess); void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess); - - void processSdpOffer(AmSdp& offer); - void processSdpAnswer(const AmSdp& offer, AmSdp& answer); }; extern void varPrintArg(const AmArg& a, map& dst, const string& name); diff --git a/apps/dsm/SystemDSM.cpp b/apps/dsm/SystemDSM.cpp index ef0f9551..ae2dc08b 100644 --- a/apps/dsm/SystemDSM.cpp +++ b/apps/dsm/SystemDSM.cpp @@ -6,7 +6,6 @@ #include "DSMStateDiagramCollection.h" #include "../apps/jsonrpc/JsonRPCEvents.h" // todo! -#include "AmSipSubscription.h" SystemDSM::SystemDSM(const DSMScriptConfig& config, const string& startDiagName, @@ -128,28 +127,10 @@ void SystemDSM::process(AmEvent* event) { } - if (event->event_id == E_SIP_SUBSCRIPTION) { - SIPSubscriptionEvent* sub_ev = dynamic_cast(event); - if (sub_ev) { - DBG("SystemDSM received SIP Subscription Event\n"); - map params; - params["status"] = sub_ev->getStatusText(); - params["code"] = int2str(sub_ev->code); - params["reason"] = sub_ev->reason; - params["expires"] = int2str(sub_ev->expires); - params["has_body"] = (!sub_ev->notify_body.empty())?"true":"false"; - if (!sub_ev->notify_body.empty()) { - avar[DSM_AVAR_SIPSUBSCRIPTION_BODY] = AmArg(sub_ev->notify_body); - } - engine.runEvent(&dummy_session, this, DSMCondition::SIPSubscription, ¶ms); - avar.erase(DSM_AVAR_SIPSUBSCRIPTION_BODY); - } - } - if (event->event_id == E_SYSTEM) { AmSystemEvent* sys_ev = dynamic_cast(event); if(sys_ev){ - DBG("SystemDSM received system Event\n"); + DBG("SystemDSM received system Event\n"); map params; params["type"] = AmSystemEvent::getDescription(sys_ev->sys_event); engine.runEvent(&dummy_session, this, DSMCondition::System, ¶ms); @@ -170,9 +151,8 @@ void SystemDSM::_func { \ throw DSMException("core", "cause", "not implemented"); \ } -NOT_IMPLEMENTED(playPrompt(const string& name, bool loop, bool front)); +NOT_IMPLEMENTED(playPrompt(const string& name, bool loop)); NOT_IMPLEMENTED(playFile(const string& name, bool loop, bool front)); -NOT_IMPLEMENTED(playSilence(unsigned int length, bool front)); NOT_IMPLEMENTED(recordFile(const string& name)); NOT_IMPLEMENTED_UINT(getRecordLength()); NOT_IMPLEMENTED_UINT(getRecordDataSize()); @@ -181,8 +161,7 @@ NOT_IMPLEMENTED(setInOutPlaylist()); NOT_IMPLEMENTED(setInputPlaylist()); NOT_IMPLEMENTED(setOutputPlaylist()); -NOT_IMPLEMENTED(addToPlaylist(AmPlaylistItem* item, bool front)); -NOT_IMPLEMENTED(flushPlaylist()); +NOT_IMPLEMENTED(addToPlaylist(AmPlaylistItem* item)); NOT_IMPLEMENTED(closePlaylist(bool notify)); NOT_IMPLEMENTED(setPromptSet(const string& name)); NOT_IMPLEMENTED(addSeparator(const string& name, bool front)); diff --git a/apps/dsm/SystemDSM.h b/apps/dsm/SystemDSM.h index b4621e30..cb8b2eb7 100644 --- a/apps/dsm/SystemDSM.h +++ b/apps/dsm/SystemDSM.h @@ -52,9 +52,8 @@ class SystemDSM void process(AmEvent* event); // DSMSession interface - void playPrompt(const string& name, bool loop = false, bool front = false); + void playPrompt(const string& name, bool loop = false); void playFile(const string& name, bool loop, bool front = false); - void playSilence(unsigned int length, bool front = false); void recordFile(const string& name); unsigned int getRecordLength(); unsigned int getRecordDataSize(); @@ -63,9 +62,8 @@ class SystemDSM void setInputPlaylist(); void setOutputPlaylist(); - void addToPlaylist(AmPlaylistItem* item, bool front = false); + void addToPlaylist(AmPlaylistItem* item); void closePlaylist(bool notify); - void flushPlaylist(); void setPromptSet(const string& name); void addSeparator(const string& name, bool front = false); void connectMedia(); diff --git a/apps/dsm/mods/Makefile b/apps/dsm/mods/Makefile index bb797a44..7752d49a 100644 --- a/apps/dsm/mods/Makefile +++ b/apps/dsm/mods/Makefile @@ -4,7 +4,7 @@ COREPATH = $(DSMPATH)/../../core include $(COREPATH)/../Makefile.defs -exclude_dsm_modules ?= mod_mysql mod_aws mod_curl mod_xml +exclude_dsm_modules ?= mod_mysql mod_aws ifneq ($(USE_MONITORING), yes) exclude_dsm_modules += mod_monitoring @@ -41,7 +41,7 @@ modules: done .PHONY: install -install: install-bin +install: install-bin install-cfg .PHONY: install-bin install-bin: diff --git a/apps/dsm/mods/mod_curl/Makefile b/apps/dsm/mods/mod_curl/Makefile deleted file mode 100644 index 7031885b..00000000 --- a/apps/dsm/mods/mod_curl/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -plug_in_name = mod_curl - -DSMPATH ?= ../.. - -module_ldflags = `curl-config --libs` -module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH) `curl-config --cflags` - -# for local libcurl: -#module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH) -Icurl-7.15.5/include -#module_ldflags = curl-7.15.5/lib/.libs/libcurl.a - -COREPATH ?=$(DSMPATH)/../../core -lib_full_name = $(DSMPATH)/mods/lib/$(lib_name) -include $(DSMPATH)/mods/Makefile.dsm_module diff --git a/apps/dsm/mods/mod_curl/ModCurl.cpp b/apps/dsm/mods/mod_curl/ModCurl.cpp deleted file mode 100644 index e550f31c..00000000 --- a/apps/dsm/mods/mod_curl/ModCurl.cpp +++ /dev/null @@ -1,415 +0,0 @@ -/* - * Copyright (C) 2009 TelTech Systems Inc. - * Copyright (C) 2011 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * sems is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ModCurl.h" -#include "log.h" -#include "AmUtils.h" - -#include "DSMSession.h" -#include "AmSession.h" - -#include -#include -#include "AmConfigReader.h" - -bool CurlModule::curl_initialized = false; - -SC_EXPORT(CurlModule); - -CurlModule::CurlModule() { - if (!curl_initialized) { - curl_initialized = true; - if (curl_global_init(CURL_GLOBAL_ALL)) { - ERROR("Initializing libcurl\n"); - throw string("Initializing libcurl"); - } - - curl_version_info_data *data = curl_version_info(CURLVERSION_NOW); - if (data && data->version >=0) { - DBG("using libcurl version '%s'\n", - data->version); - if (data->features & CURL_VERSION_SSL) { - DBG("libcurl with SSL version '%s'\n", data->ssl_version); - } else { - DBG("libcurl without SSL support\n"); - } - } - } -} - -CurlModule::~CurlModule() { -} - - -DSMAction* CurlModule::getAction(const string& from_str) { - string cmd; - string params; - splitCmd(from_str, cmd, params); - - DEF_CMD("curl.get", SCJCurlGetAction); - DEF_CMD("curl.getDiscardResult", SCJCurlGetNoresultAction); - DEF_CMD("curl.getFile", SCJCurlGetFileAction); - DEF_CMD("curl.getForm", SCJCurlGetFormAction); - DEF_CMD("curl.post", SCJCurlPOSTGetResultAction); - DEF_CMD("curl.postDiscardResult", SCJCurlPOSTAction); - - return NULL; -} - -DSMCondition* CurlModule::getCondition(const string& from_str) { - return NULL; -} - -size_t debug_output_func(void *ptr, size_t size, size_t - nmemb, void *stream) { - string data((char*)ptr, size*nmemb); - DBG("server out: <<%s>>\n", data.c_str()); - return size*nmemb; -} - -/** append output to $curl.out */ -size_t var_output_func(void *ptr, size_t size, size_t - nmemb, void *stream) { - if (NULL == stream) - return size*nmemb; - - string data((char*)ptr, size*nmemb); - DBG("server out: <<%s>>\n", data.c_str()); - DSMSession* sc_sess = reinterpret_cast(stream); - if (sc_sess) { - sc_sess->var["curl.out"]+=data; - } - return size*nmemb; -} - -bool curl_run_get(DSMSession* sc_sess, const string& url, - bool get_result) { - CURL* m_curl_handle = curl_easy_init(); - if (!m_curl_handle) { - ERROR("getting curl handle\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - return false; - } - - char* enc_url = curl_easy_escape(m_curl_handle, url.c_str(), url.length()); - if (NULL == enc_url) { - ERROR("URL-encoding url '%s'\n", url.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - return false; - } - - if (curl_easy_setopt(m_curl_handle, CURLOPT_URL, url.c_str()) - != CURLE_OK) { - ERROR("setting URL '%s'\n", url.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - free(enc_url); - return false; - } - - if (!sc_sess->var["curl.timeout"].empty()) { - unsigned int curl_timeout = 0; - if (str2i(sc_sess->var["curl.timeout"], curl_timeout)) { - WARN("curl.timeout '%s' not understood\n", sc_sess->var["curl.timeout"].c_str()); - } else { - if ((curl_easy_setopt(m_curl_handle, CURLOPT_TIMEOUT, curl_timeout) != CURLE_OK) || - (curl_easy_setopt(m_curl_handle, CURLOPT_NOSIGNAL, 1L) != CURLE_OK)) { - ERROR("setting timeout '%u'\n", curl_timeout); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - free(enc_url); - return false; - } - } - } - - if (!get_result) { - if (curl_easy_setopt(m_curl_handle, CURLOPT_WRITEFUNCTION, debug_output_func) - != CURLE_OK) { - ERROR("setting curl write function\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - curl_easy_cleanup(m_curl_handle); - free(enc_url); - return false; - } - } else { - if ((curl_easy_setopt(m_curl_handle, CURLOPT_WRITEFUNCTION, var_output_func) - != CURLE_OK)|| - (curl_easy_setopt(m_curl_handle, CURLOPT_WRITEDATA, sc_sess) - != CURLE_OK)) { - ERROR("setting curl write function\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - curl_easy_cleanup(m_curl_handle); - free(enc_url); - return false; - } - } - - char curl_err[CURL_ERROR_SIZE]; - curl_err[0]='\0'; - if (curl_easy_setopt(m_curl_handle, CURLOPT_ERRORBUFFER, curl_err) - != CURLE_OK) { - ERROR("setting curl error buffer\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - curl_easy_cleanup(m_curl_handle); - free(enc_url); - return false; - } - - CURLcode rescode = curl_easy_perform(m_curl_handle); - - if (rescode) { - DBG("Error while trying to retrieve '%s': '%s'\n", - url.c_str(), curl_err); - sc_sess->var["curl.err"] = string(curl_err); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - } else { - sc_sess->SET_ERRNO(DSM_ERRNO_OK); - } - - curl_easy_cleanup(m_curl_handle); - free(enc_url); - return false; -} - - -EXEC_ACTION_START(SCJCurlGetAction) { - sc_sess->var.erase("curl.out"); - return curl_run_get(sc_sess, resolveVars(arg, sess, sc_sess, event_params), true); -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCJCurlGetNoresultAction) { - return curl_run_get(sc_sess, resolveVars(arg, sess, sc_sess, event_params), false); -} EXEC_ACTION_END; - - -CONST_ACTION_2P(SCJCurlGetFormAction, ',', true); -EXEC_ACTION_START(SCJCurlGetFormAction) { - sc_sess->var.erase("curl.out"); - string form_url = resolveVars(par1, sess, sc_sess, event_params);; - bool url_has_qmark = form_url.find('?')!=string::npos; - - vector p_vars=explode(par2, ";"); - for (vector::iterator it= - p_vars.begin();it != p_vars.end();it++) { - string varname = (it->size() && ((*it)[0]=='$')) ? (it->substr(1)) : (*it); - DBG("adding '%s' = '%s'\n", varname.c_str(), sc_sess->var[varname].c_str()); - if (!url_has_qmark && it == p_vars.begin()) - form_url+= "?"; - else - form_url+= "&"; - form_url += varname + "=" + sc_sess->var[varname]; - } - - return curl_run_get(sc_sess, form_url, true); -} EXEC_ACTION_END; - -void curl_run_getfile(DSMSession* sc_sess, const string& url, const string& outfile) { - CURL* m_curl_handle = curl_easy_init(); - if (!m_curl_handle) { - ERROR("getting curl handle\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - return; - } - - if (curl_easy_setopt(m_curl_handle, CURLOPT_URL, url.c_str()) - != CURLE_OK) { - ERROR("setting URL '%s'\n", url.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - return; - } - - if (!sc_sess->var["curl.timeout"].empty()) { - unsigned int curl_timeout = 0; - if (str2i(sc_sess->var["curl.timeout"], curl_timeout)) { - WARN("curl.timeout '%s' not understood\n", sc_sess->var["curl.timeout"].c_str()); - } else { - if ((curl_easy_setopt(m_curl_handle, CURLOPT_TIMEOUT, curl_timeout) != CURLE_OK) || - (curl_easy_setopt(m_curl_handle, CURLOPT_NOSIGNAL, 1L) != CURLE_OK)) { - ERROR("setting timeout '%u'\n", curl_timeout); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - return; - } - } - } - - FILE* f = fopen(outfile.c_str(), "wb"); - if (NULL == f) { - DBG("Error opening file '%s' for writing\n", outfile.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - return; - } - - if (curl_easy_setopt(m_curl_handle, CURLOPT_WRITEDATA, f) - != CURLE_OK) { - ERROR("setting curl data file\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - fclose(f); - return; - } - - char curl_err[CURL_ERROR_SIZE]; - curl_err[0]='\0'; - if (curl_easy_setopt(m_curl_handle, CURLOPT_ERRORBUFFER, curl_err) - != CURLE_OK) { - ERROR("setting URL '%s'\n", url.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - fclose(f); - return; - } - - CURLcode rescode = curl_easy_perform(m_curl_handle); - - if (rescode) { - DBG("Error while trying to retrieve '%s' to '%s': '%s'\n", - url.c_str(), outfile.c_str(), curl_err); - sc_sess->var["curl.err"] = string(curl_err); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - }else { - sc_sess->SET_ERRNO(DSM_ERRNO_OK); - } - - fclose(f); - curl_easy_cleanup(m_curl_handle); -} - - -CONST_ACTION_2P(SCJCurlGetFileAction, ',', true); -EXEC_ACTION_START(SCJCurlGetFileAction) { - curl_run_getfile(sc_sess, - resolveVars(par1, sess, sc_sess, event_params), - resolveVars(par2, sess, sc_sess, event_params)); -} EXEC_ACTION_END; - -bool curl_run_post(DSMSession* sc_sess, const string& par1, const string& par2, - bool get_result) { - CURL* m_curl_handle = curl_easy_init(); - if (!m_curl_handle) { - ERROR("getting curl handle\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - return false; - } - - if (curl_easy_setopt(m_curl_handle, CURLOPT_URL, par1.c_str()) - != CURLE_OK) { - ERROR("setting URL '%s'\n", par1.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - return false; - } - - if (!sc_sess->var["curl.timeout"].empty()) { - unsigned int curl_timeout = 0; - if (str2i(sc_sess->var["curl.timeout"], curl_timeout)) { - WARN("curl.timeout '%s' not understood\n", sc_sess->var["curl.timeout"].c_str()); - } else { - if ((curl_easy_setopt(m_curl_handle, CURLOPT_TIMEOUT, curl_timeout) != CURLE_OK) || - (curl_easy_setopt(m_curl_handle, CURLOPT_NOSIGNAL, 1L) != CURLE_OK)) { - ERROR("setting timeout '%u'\n", curl_timeout); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - curl_easy_cleanup(m_curl_handle); - return false; - } - } - } - - if (!get_result) { - if (curl_easy_setopt(m_curl_handle, CURLOPT_WRITEFUNCTION, debug_output_func) - != CURLE_OK) { - ERROR("setting curl write function\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - curl_easy_cleanup(m_curl_handle); - return false; - } - } else { - if ((curl_easy_setopt(m_curl_handle, CURLOPT_WRITEFUNCTION, var_output_func) - != CURLE_OK)|| - (curl_easy_setopt(m_curl_handle, CURLOPT_WRITEDATA, sc_sess) - != CURLE_OK)) { - ERROR("setting curl write function\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_FILE); - curl_easy_cleanup(m_curl_handle); - return false; - } - } - - char curl_err[CURL_ERROR_SIZE]; - curl_err[0]='\0'; - if (curl_easy_setopt(m_curl_handle, CURLOPT_ERRORBUFFER, curl_err) - != CURLE_OK) { - ERROR("setting curl error buffer\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - curl_easy_cleanup(m_curl_handle); - return false; - } - - struct curl_httppost *post=NULL; - struct curl_httppost *last=NULL; - string post_vars; - vector p_vars=explode(par2, ";"); - for (vector::iterator it= - p_vars.begin();it != p_vars.end();it++) { - string varname = (it->size() && ((*it)[0]=='$')) ? (it->substr(1)) : (*it); - DBG("adding '%s' = '%s'\n", varname.c_str(), sc_sess->var[varname].c_str()); - curl_formadd(&post, &last, - CURLFORM_COPYNAME, varname.c_str(), - CURLFORM_COPYCONTENTS, sc_sess->var[varname].c_str(), CURLFORM_END); - } - - CURLcode rescode = curl_easy_perform(m_curl_handle); - - bool res = false; - if (rescode) { - DBG("Error while trying to POST to '%s': '%s'\n", - par1.c_str(), curl_err); - sc_sess->var["curl.err"] = string(curl_err); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - } else { - sc_sess->SET_ERRNO(DSM_ERRNO_OK); - res = true; - } - curl_formfree(post); - curl_easy_cleanup(m_curl_handle); - return false; -} - -CONST_ACTION_2P(SCJCurlPOSTAction, ',', true); -EXEC_ACTION_START(SCJCurlPOSTAction) { - curl_run_post(sc_sess, resolveVars(par1, sess, sc_sess, event_params), - par2, false); - return false; -} EXEC_ACTION_END; - -CONST_ACTION_2P(SCJCurlPOSTGetResultAction, ',', true); -EXEC_ACTION_START(SCJCurlPOSTGetResultAction) { - sc_sess->var.erase("curl.out"); - curl_run_post(sc_sess, resolveVars(par1, sess, sc_sess, event_params), - par2, true); - return false; -} EXEC_ACTION_END; diff --git a/apps/dsm/mods/mod_curl/ModCurl.h b/apps/dsm/mods/mod_curl/ModCurl.h deleted file mode 100644 index 4f1ec6b2..00000000 --- a/apps/dsm/mods/mod_curl/ModCurl.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * - * Copyright (C) 2009 TelTech Systems - * Copyright (C) 2011 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * sems is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _MOD_CURL_H -#define _MOD_CURL_H -#include "DSMModule.h" -#include "DSMSession.h" - -class CurlModule -: public DSMModule { - - public: - CurlModule(); - ~CurlModule(); - - DSMAction* getAction(const string& from_str); - DSMCondition* getCondition(const string& from_str); - - static bool curl_initialized; -}; - -DEF_ACTION_1P(SCJCurlGetAction); -DEF_ACTION_1P(SCJCurlGetNoresultAction); -DEF_ACTION_2P(SCJCurlGetFileAction); -DEF_ACTION_2P(SCJCurlGetFormAction); -DEF_ACTION_2P(SCJCurlPOSTAction); -DEF_ACTION_2P(SCJCurlPOSTGetResultAction); - -#endif diff --git a/apps/dsm/mods/mod_dlg/ModDlg.cpp b/apps/dsm/mods/mod_dlg/ModDlg.cpp index b470f885..ec0c11c1 100644 --- a/apps/dsm/mods/mod_dlg/ModDlg.cpp +++ b/apps/dsm/mods/mod_dlg/ModDlg.cpp @@ -60,23 +60,6 @@ bool DLGModule::onInvite(const AmSipRequest& req, DSMSession* sess) { return true; } -string replaceLineEnds(string input) -{ - string result; - size_t last = 0; - size_t pos; - while ((pos = input.find("\\r\\n", last)) != string::npos) { - result += input.substr(last, pos-last); - result += "\r\n"; - last = pos + 4; - } - if (!input.substr(last).empty()) { - result += input.substr(last); - result += "\r\n"; - } - return result; -} - // todo: convert errors to exceptions void replyRequest(DSMSession* sc_sess, AmSession* sess, EventParamT* event_params, @@ -84,7 +67,6 @@ void replyRequest(DSMSession* sc_sess, AmSession* sess, const AmSipRequest& req) { string code = resolveVars(par1, sess, sc_sess, event_params); string reason = resolveVars(par2, sess, sc_sess, event_params); - string hdrs = replaceLineEnds(resolveVars("$dlg.reply.hdrs", sess, sc_sess, event_params)); unsigned int code_i; if (str2i(code, code_i)) { ERROR("decoding reply code '%s'\n", code.c_str()); @@ -92,9 +74,14 @@ void replyRequest(DSMSession* sc_sess, AmSession* sess, return; } - DBG("replying with %i %s, hdrs='%s'\n", code_i, reason.c_str(), hdrs.c_str()); + if (!sc_sess->last_req.get()) { + ERROR("no last request to reply\n"); + sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); + sc_sess->SET_STRERROR("no last request to reply"); + return; + } - if (sess->dlg.reply(req, code_i, reason, "","", hdrs)) { + if (sess->dlg.reply(req, code_i, reason)) { sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); sc_sess->SET_STRERROR("error sending reply"); } else @@ -103,13 +90,6 @@ void replyRequest(DSMSession* sc_sess, AmSession* sess, CONST_ACTION_2P(DLGReplyAction, ',', true); EXEC_ACTION_START(DLGReplyAction) { - if (!sc_sess->last_req.get()) { - ERROR("no last request to reply\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - sc_sess->SET_STRERROR("no last request to reply"); - EXEC_ACTION_STOP; - } - replyRequest(sc_sess, sess, event_params, par1, par2, *sc_sess->last_req.get()); } EXEC_ACTION_END; @@ -134,7 +114,7 @@ EXEC_ACTION_START(DLGAcceptInviteAction) { unsigned int code_i=200; string reason = "OK"; string code = resolveVars(par1, sess, sc_sess, event_params); - string hdrs = replaceLineEnds(resolveVars("$dlg.reply.hdrs", sess, sc_sess, event_params)); + DBG("replying with code %s\n", code.c_str()); if (code.length()) { reason = resolveVars(par2, sess, sc_sess, event_params); @@ -147,8 +127,6 @@ EXEC_ACTION_START(DLGAcceptInviteAction) { } } - DBG("replying with %i %s, hdrs='%s'\n", code_i, reason.c_str(), hdrs.c_str()); - if (!sc_sess->last_req.get()) { ERROR("no last request to reply\n"); sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); @@ -162,17 +140,14 @@ EXEC_ACTION_START(DLGAcceptInviteAction) { sess->acceptAudio(sc_sess->last_req.get()->body, sc_sess->last_req.get()->hdrs,&sdp_reply); if(sess->dlg.reply(*sc_sess->last_req.get(),code_i, reason, - "application/sdp",sdp_reply, hdrs) != 0) + "application/sdp",sdp_reply) != 0) throw AmSession::Exception(500,"could not send response"); - + }catch(const AmSession::Exception& e){ ERROR("%i %s\n",e.code,e.reason.c_str()); sess->setStopped(); sess->dlg.reply(*sc_sess->last_req.get(),e.code,e.reason); - - sc_sess->SET_ERRNO(DSM_ERRNO_DLG); - sc_sess->SET_STRERROR("Error accepting call: "+ int2str(e.code) + " "+ e.reason); } } EXEC_ACTION_END; diff --git a/apps/dsm/mods/mod_dlg/ModDlg.h b/apps/dsm/mods/mod_dlg/ModDlg.h index a8535d62..978288b1 100644 --- a/apps/dsm/mods/mod_dlg/ModDlg.h +++ b/apps/dsm/mods/mod_dlg/ModDlg.h @@ -30,8 +30,6 @@ #define MOD_CLS_NAME DLGModule -#define DSM_ERRNO_DLG "dlg" - DECLARE_MODULE_BEGIN(MOD_CLS_NAME); bool onInvite(const AmSipRequest& req, DSMSession* sess); DECLARE_MODULE_END; diff --git a/apps/dsm/mods/mod_mysql/ModMysql.cpp b/apps/dsm/mods/mod_mysql/ModMysql.cpp index 2108a734..6bec11dd 100644 --- a/apps/dsm/mods/mod_mysql/ModMysql.cpp +++ b/apps/dsm/mods/mod_mysql/ModMysql.cpp @@ -61,8 +61,6 @@ DSMAction* SCMysqlModule::getAction(const string& from_str) { DEF_CMD("mysql.saveResult", SCMySaveResultAction); DEF_CMD("mysql.useResult", SCMyUseResultAction); DEF_CMD("mysql.playDBAudio", SCMyPlayDBAudioAction); - DEF_CMD("mysql.playDBAudioFront", SCMyPlayDBAudioFrontAction); - DEF_CMD("mysql.playDBAudioLooped", SCMyPlayDBAudioLoopedAction); DEF_CMD("mysql.getFileFromDB", SCMyGetFileFromDBAction); DEF_CMD("mysql.putFileToDB", SCMyPutFileToDBAction); @@ -452,14 +450,12 @@ EXEC_ACTION_START(SCMyUseResultAction) { } EXEC_ACTION_END; -bool playDBAudio(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, - map* event_params, const string& par1, const string& par2, - bool looped, bool front) { +CONST_ACTION_2P(SCMyPlayDBAudioAction, ',', true); +EXEC_ACTION_START(SCMyPlayDBAudioAction) { mysqlpp::Connection* conn = getMyDSMSessionConnection(sc_sess); - if (NULL == conn) - EXEC_ACTION_STOP; - + if (NULL == conn) + return false; string qstr = replaceQueryParams(par1, sc_sess, event_params); try { @@ -470,14 +466,14 @@ bool playDBAudio(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType e mysqlpp::Row row = res.fetch_row(); if (!row) { sc_sess->SET_ERRNO(DSM_ERRNO_MY_NOROW); - sc_sess->SET_STRERROR("result does not have row"); - EXEC_ACTION_STOP; + sc_sess->SET_STRERROR("result does not have row"); + return false; } FILE *t_file = tmpfile(); if (NULL == t_file) { sc_sess->SET_ERRNO(DSM_ERRNO_FILE); sc_sess->SET_STRERROR("tmpfile() failed: "+string(strerror(errno))); - EXEC_ACTION_STOP; + return false; } fwrite(row.at(0).data(), 1, row.at(0).size(), t_file); @@ -487,12 +483,10 @@ bool playDBAudio(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType e if (a_file->fpopen(par2, AmAudioFile::Read, t_file)) { sc_sess->SET_ERRNO(DSM_ERRNO_FILE); sc_sess->SET_STRERROR("fpopen failed!"); - EXEC_ACTION_STOP; + return false; } - a_file->loop.set(looped); - - sc_sess->addToPlaylist(new AmPlaylistItem(a_file, NULL), front); + sc_sess->addToPlaylist(new AmPlaylistItem(a_file, NULL)); sc_sess->transferOwnership(a_file); sc_sess->CLR_ERRNO; @@ -507,25 +501,6 @@ bool playDBAudio(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType e sc_sess->SET_STRERROR(e.what()); sc_sess->var["db.ereason"] = e.what(); } - return false; -} - -CONST_ACTION_2P(SCMyPlayDBAudioAction, ',', true); -EXEC_ACTION_START(SCMyPlayDBAudioAction) { - playDBAudio(sess, sc_sess, event, event_params, par1, par2, - /*looped = */ false, /*front = */ false); -} EXEC_ACTION_END; - -CONST_ACTION_2P(SCMyPlayDBAudioFrontAction, ',', true); -EXEC_ACTION_START(SCMyPlayDBAudioFrontAction) { - playDBAudio(sess, sc_sess, event, event_params, par1, par2, - /*looped = */ false, /*front = */ true); -} EXEC_ACTION_END; - -CONST_ACTION_2P(SCMyPlayDBAudioLoopedAction, ',', true); -EXEC_ACTION_START(SCMyPlayDBAudioLoopedAction) { - playDBAudio(sess, sc_sess, event, event_params, par1, par2, - /*looped = */ true, /*front = */ false); } EXEC_ACTION_END; CONST_ACTION_2P(SCMyGetFileFromDBAction, ',', true); diff --git a/apps/dsm/mods/mod_mysql/ModMysql.h b/apps/dsm/mods/mod_mysql/ModMysql.h index b93f8f2b..1c7e5d7e 100644 --- a/apps/dsm/mods/mod_mysql/ModMysql.h +++ b/apps/dsm/mods/mod_mysql/ModMysql.h @@ -88,8 +88,6 @@ DEF_SCCondition(MyConnectedCondition); DEF_ACTION_1P(SCMySaveResultAction); DEF_ACTION_1P(SCMyUseResultAction); DEF_ACTION_2P(SCMyPlayDBAudioAction); -DEF_ACTION_2P(SCMyPlayDBAudioFrontAction); -DEF_ACTION_2P(SCMyPlayDBAudioLoopedAction); DEF_ACTION_2P(SCMyGetFileFromDBAction); DEF_ACTION_2P(SCMyPutFileToDBAction); diff --git a/apps/dsm/mods/mod_regex/CMakeLists.txt b/apps/dsm/mods/mod_regex/CMakeLists.txt deleted file mode 100644 index 007a582e..00000000 --- a/apps/dsm/mods/mod_regex/CMakeLists.txt +++ /dev/null @@ -1,7 +0,0 @@ -set (mod_regex_SRCS -ModRegex.cpp -) - -SET(sems_dsm_module_name mod_regex) -INCLUDE(${CMAKE_SOURCE_DIR}/cmake/dsm.lib.rules.txt) - diff --git a/apps/dsm/mods/mod_regex/Makefile b/apps/dsm/mods/mod_regex/Makefile deleted file mode 100644 index 8cd44a40..00000000 --- a/apps/dsm/mods/mod_regex/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -plug_in_name = mod_regex - -DSMPATH ?= ../.. - -module_ldflags = -module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH) - -COREPATH ?=$(DSMPATH)/../../core -lib_full_name = $(DSMPATH)/mods/lib/$(lib_name) -include $(DSMPATH)/mods/Makefile.dsm_module diff --git a/apps/dsm/mods/mod_regex/ModRegex.cpp b/apps/dsm/mods/mod_regex/ModRegex.cpp deleted file mode 100644 index a67d10d2..00000000 --- a/apps/dsm/mods/mod_regex/ModRegex.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Copyright (C) 2012 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. This program is released under - * the GPL with the additional exemption that compiling, linking, - * and/or using OpenSSL is allowed. - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "ModRegex.h" - -#include "log.h" -#include "AmUtils.h" -#include "AmConfigReader.h" - -SC_EXPORT(MOD_CLS_NAME); - -map MOD_CLS_NAME::regexes; - -MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) { - - DEF_CMD("regex.compile", SCCompileRegexAction); - DEF_CMD("regex.match", SCExecRegexAction); - DEF_CMD("regex.clear", SCClearRegexAction); -} MOD_ACTIONEXPORT_END; - -MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) { - - if (cmd == "regex.match") { - return new SCExecRegexCondition(params, false); - } - -} MOD_CONDITIONEXPORT_END; - -int MOD_CLS_NAME::preload() { - AmConfigReader cfg; - if(cfg.loadFile(AmConfig::ModConfigPath + string(MOD_NAME ".conf"))) { - INFO("no module configuration for '%s' found, not preloading regular expressions\n", - MOD_NAME); - return 0; - } - - bool failed = false; - for (std::map::const_iterator it = - cfg.begin(); it != cfg.end(); it++) { - if (add_regex(it->first, it->second)) { - ERROR("compiling regex '%s' for '%s'\n", - it->second.c_str(), it->first.c_str()); - failed = true; - } else { - DBG("compiled regex '%s' as '%s'\n", it->second.c_str(), it->first.c_str()); - } - } - - return failed? -1 : 0; -} - -int MOD_CLS_NAME::add_regex(const string& r_name, const string& r_reg) { - if (regexes[r_name].regcomp(r_reg.c_str(), REG_NOSUB | REG_EXTENDED)) { - ERROR("compiling '%s' for regex '%s'\n", r_reg.c_str(), r_name.c_str()); - regexes.erase(r_name); - return -1; - } - return 0; -} - - -CONST_CONDITION_2P(SCExecRegexCondition, ',', false); -MATCH_CONDITION_START(SCExecRegexCondition) { - DBG("checking condition '%s' '%s'\n", par1.c_str(), par2.c_str()); - return true; -} MATCH_CONDITION_END; - - -CONST_ACTION_2P(SCCompileRegexAction, ',', false); -EXEC_ACTION_START(SCCompileRegexAction) { - string rname = resolveVars(par1, sess, sc_sess, event_params); - string rval = par2; //resolveVars(par2, sess, sc_sess, event_params); - DBG("compiling '%s' for regex '%s'\n", rval.c_str(), rname.c_str()); - - if (MOD_CLS_NAME::add_regex(rname, rval)) { - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - ERROR("compiling '%s' for regex '%s'\n", rval.c_str(), rname.c_str()); - } -} EXEC_ACTION_END; - -CONST_ACTION_2P(SCExecRegexAction, ',', false); -EXEC_ACTION_START(SCExecRegexAction) { - string rname = resolveVars(par1, sess, sc_sess, event_params); - string val = resolveVars(par2, sess, sc_sess, event_params); - DBG("matching '%s' on regex '%s'\n", val.c_str(), rname.c_str()); - map::iterator it=MOD_CLS_NAME::regexes.find(rname); - if (it == MOD_CLS_NAME::regexes.end()) { - ERROR("regex '%s' not found for matching '%s'\n", rname.c_str(), val.c_str()); - EXEC_ACTION_STOP; - } - - int res = it->second.regexec(val.c_str(), 1, NULL, 0); - if (!res) { - // yeah side effects - sc_sess->var["regex.match"] = "1"; - } else { - sc_sess->var["regex.match"] = "0"; - } -} EXEC_ACTION_END; - -EXEC_ACTION_START(SCClearRegexAction) { - string r_name = resolveVars(arg, sess, sc_sess, event_params); - DBG("clearing regex '%s'\n", r_name.c_str()); - MOD_CLS_NAME::regexes.erase(r_name); -} EXEC_ACTION_END; - -TsRegex::TsRegex() - : i(false) { } - -TsRegex::~TsRegex() -{ - if (i) { - regfree(®); - } -} - -int TsRegex::regcomp(const char *regex, int cflags) { - m.lock(); - if (i) { - regfree(®); - } - int res = ::regcomp(®, regex, cflags); - if (!res) - i=true; - m.unlock(); - return res; -} - -int TsRegex::regexec(const char *_string, size_t nmatch, - regmatch_t pmatch[], int eflags) { - if (!i) { - ERROR("uninitialized regex when matching '%s'\n", _string); - return -1; - } - m.lock(); - int res = ::regexec(®, _string, nmatch, pmatch, eflags); - m.unlock(); - return res; -} diff --git a/apps/dsm/mods/mod_regex/ModRegex.h b/apps/dsm/mods/mod_regex/ModRegex.h deleted file mode 100644 index f553389c..00000000 --- a/apps/dsm/mods/mod_regex/ModRegex.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2012 Stefan Sayer - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. This program is released under - * the GPL with the additional exemption that compiling, linking, - * and/or using OpenSSL is allowed. - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _MOD_REGEX_H -#define _MOD_REGEX_H -#include "DSMModule.h" -#include "DSMSession.h" - -#define MOD_CLS_NAME SCRegexModule - -#include -#include -#include - -// in some earlier versions of libc apparently regex were inot thread-safe -class TsRegex { - regex_t reg; - AmMutex m; - bool i; - - public: - TsRegex(); - ~TsRegex(); - int regcomp(const char *regex, int cflags); - int regexec(const char *_string, size_t nmatch, regmatch_t pmatch[], int eflags); - -}; - -DECLARE_MODULE_BEGIN(MOD_CLS_NAME); -int preload(); -static map regexes; -static int add_regex(const string& r_name, const string& r_reg); -DECLARE_MODULE_END; - /* }; */ - - -DEF_ACTION_2P(SCCompileRegexAction); -DEF_ACTION_2P(SCExecRegexAction); -DEF_ACTION_1P(SCClearRegexAction); -DEF_CONDITION_2P(SCExecRegexCondition); - -#endif diff --git a/apps/dsm/mods/mod_regex/etc/mod_regex.conf b/apps/dsm/mods/mod_regex/etc/mod_regex.conf deleted file mode 100644 index 91503daa..00000000 --- a/apps/dsm/mods/mod_regex/etc/mod_regex.conf +++ /dev/null @@ -1,6 +0,0 @@ -# list of regex's to compile on start -# use preload_mods=mod_regex in dsm.conf if you want to use those - -# ex: -#my_r1=^sip: -#my_r2=mydomain\.net \ No newline at end of file diff --git a/apps/dsm/mods/mod_subscription/Makefile b/apps/dsm/mods/mod_subscription/Makefile deleted file mode 100644 index 9381e846..00000000 --- a/apps/dsm/mods/mod_subscription/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -plug_in_name = mod_subscription - -DSMPATH ?= ../.. - -module_ldflags = -module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH) - -COREPATH ?=$(DSMPATH)/../../core -lib_full_name = $(DSMPATH)/mods/lib/$(lib_name) -include $(DSMPATH)/mods/Makefile.dsm_module diff --git a/apps/dsm/mods/mod_subscription/ModSubscription.cpp b/apps/dsm/mods/mod_subscription/ModSubscription.cpp deleted file mode 100644 index 4a05d2fc..00000000 --- a/apps/dsm/mods/mod_subscription/ModSubscription.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (C) 2012 FRAFOS GmbH - * - * Development sponsored by Sipwise GmbH. - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. This program is released under - * the GPL with the additional exemption that compiling, linking, - * and/or using OpenSSL is allowed. - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "ModSubscription.h" -#include "log.h" -#include "AmUtils.h" - -#include "AmSipSubscriptionContainer.h" - -SC_EXPORT(MOD_CLS_NAME); - -MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) { - - DEF_CMD("subscription.create", SIPSUBCreateAction); - DEF_CMD("subscription.refresh", SIPSUBRefreshAction); - DEF_CMD("subscription.remove", SIPSUBRemoveAction); - -} MOD_ACTIONEXPORT_END; - -MOD_CONDITIONEXPORT_NONE(MOD_CLS_NAME); - -CONST_ACTION_2P(SIPSUBCreateAction, ',', true); -EXEC_ACTION_START(SIPSUBCreateAction) { - string params_s = resolveVars(par1, sess, sc_sess, event_params); -// string basedir = resolveVars(par2, sess, sc_sess, event_params); - - AmSipSubscriptionInfo info(sc_sess->var[params_s+".domain"], - sc_sess->var[params_s+".user"], - sc_sess->var[params_s+".from_user"], - sc_sess->var[params_s+".pwd"], - sc_sess->var[params_s+".proxy"], - sc_sess->var[params_s+".event"]); - info.accept = sc_sess->var[params_s+".accept"]; - info.id = sc_sess->var[params_s+".id"]; - unsigned int expires = 0; - - if (sc_sess->var.find(params_s+".expires") != sc_sess->var.end()) { - str2i(sc_sess->var[params_s+".expires"], expires); - } - - string handle = AmSipSubscriptionContainer::instance()-> - createSubscription(info, sess->getLocalTag(), expires); - - DBG("got handle '%s'\n", handle.c_str()); - sc_sess->var[params_s+".handle"] = handle; - if (handle.empty()) { - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("could not create subscription\n"); - } else { - sc_sess->CLR_ERRNO; - } -} EXEC_ACTION_END; - - - -CONST_ACTION_2P(SIPSUBRefreshAction, ',', true); -EXEC_ACTION_START(SIPSUBRefreshAction) { - string handle = resolveVars(par1, sess, sc_sess, event_params); - string expires = resolveVars(par2, sess, sc_sess, event_params); - unsigned int expires_i = 0; - if (!expires.empty()) - str2i(expires, expires_i); - - DBG("refreshing subscription with handle '%s'\n", handle.c_str()); - if (!AmSipSubscriptionContainer::instance()->refreshSubscription(handle, expires_i)) { - sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); - sc_sess->SET_STRERROR("could not refresh subscription\n"); - } else { - sc_sess->CLR_ERRNO; - } -} EXEC_ACTION_END; - -EXEC_ACTION_START(SIPSUBRemoveAction) { - string handle = resolveVars(arg, sess, sc_sess, event_params); - DBG("removing subscription with handle '%s'\n", handle.c_str()); - AmSipSubscriptionContainer::instance()->removeSubscription(handle); -} EXEC_ACTION_END; diff --git a/apps/dsm/mods/mod_subscription/ModSubscription.h b/apps/dsm/mods/mod_subscription/ModSubscription.h deleted file mode 100644 index 4557c229..00000000 --- a/apps/dsm/mods/mod_subscription/ModSubscription.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (C) 2012 FRAFOS GmbH - * - * Development sponsored by Sipwise GmbH. - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. This program is released under - * the GPL with the additional exemption that compiling, linking, - * and/or using OpenSSL is allowed. - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _MOD_SUBSCRIPTION_H -#define _MOD_SUBSCRIPTION_H -#include "DSMModule.h" -#include "DSMSession.h" - -#define MOD_CLS_NAME SCSubscriptionModule - -DECLARE_MODULE(MOD_CLS_NAME); - -DEF_ACTION_2P(SIPSUBCreateAction); -DEF_ACTION_2P(SIPSUBRefreshAction); -DEF_ACTION_1P(SIPSUBRemoveAction); -#endif diff --git a/apps/dsm/mods/mod_xml/Makefile b/apps/dsm/mods/mod_xml/Makefile deleted file mode 100644 index 308df766..00000000 --- a/apps/dsm/mods/mod_xml/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -plug_in_name = mod_xml - -DSMPATH ?= ../.. - -module_ldflags = `xml2-config --libs` -module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH) \ - `xml2-config --cflags` - -COREPATH ?=$(DSMPATH)/../../core -lib_full_name = $(DSMPATH)/mods/lib/$(lib_name) -include $(DSMPATH)/mods/Makefile.dsm_module diff --git a/apps/dsm/mods/mod_xml/ModXml.cpp b/apps/dsm/mods/mod_xml/ModXml.cpp deleted file mode 100644 index 534971f8..00000000 --- a/apps/dsm/mods/mod_xml/ModXml.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2012 FRAFOS GmbH - * - * Development sponsored by Sipwise GmbH. - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. This program is released under - * the GPL with the additional exemption that compiling, linking, - * and/or using OpenSSL is allowed. - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include "ModXml.h" -#include "log.h" -#include "AmUtils.h" - -#include - -SC_EXPORT(MOD_CLS_NAME); - -void xml_err_func(void *ctx, const char *msg, ...); -xmlGenericErrorFunc handler = (xmlGenericErrorFunc)xml_err_func; -int xml_log_level = L_ERR; - -int MOD_CLS_NAME::preload() { - DBG("initializing libxml2...\n"); - xmlInitParser(); - initGenericErrorDefaultFunc(&handler); - handler = (xmlGenericErrorFunc)xml_err_func; - xmlSetGenericErrorFunc(NULL, &xml_err_func); - return 0; -} - -MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) { - DEF_CMD("xml.parse", MODXMLParseAction); - DEF_CMD("xml.parseSIPMsgBody", MODXMLParseSIPMsgBodyAction); - - DEF_CMD("xml.evalXPath", MODXMLEvalXPathAction); - DEF_CMD("xml.XPathResultCount", MODXMLXPathResultNodeCount); - - DEF_CMD("xml.setLoglevel", MODXMLSetLogLevelAction); - -} MOD_ACTIONEXPORT_END; - -MOD_CONDITIONEXPORT_NONE(MOD_CLS_NAME); - -ModXmlDoc::~ModXmlDoc() { - if (NULL != doc) { - DBG("freeing XML document [%p]\n", doc); - xmlFreeDoc(doc); - } -} - -ModXmlXPathObj::~ModXmlXPathObj() { - if (NULL != xpathObj) { - DBG("freeing XML xpath obj [%p]\n", xpathObj); - xmlXPathFreeObject(xpathObj); - } - if (NULL != xpathCtx) { - DBG("freeing XML xpath ctx [%p]\n", xpathCtx); - xmlXPathFreeContext(xpathCtx); - } -} - -#define TMP_BUF_SIZE 256 -void xml_err_func(void *ctx, const char *msg, ...) { - char _string[TMP_BUF_SIZE]; - va_list arg_ptr; - va_start(arg_ptr, msg); - vsnprintf(_string, TMP_BUF_SIZE, msg, arg_ptr); - va_end(arg_ptr); - - _LOG(xml_log_level, "%s", _string); -} - -CONST_ACTION_2P(MODXMLParseSIPMsgBodyAction, ',', false); -EXEC_ACTION_START(MODXMLParseSIPMsgBodyAction) { - string msgbody_var = resolveVars(par1, sess, sc_sess, event_params); - string dstname = resolveVars(par2, sess, sc_sess, event_params); - AVarMapT::iterator it = sc_sess->avar.find(msgbody_var); - if (it==sc_sess->avar.end()) { - DBG("no message body in avar '%s'\n", msgbody_var.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("no message body in avar " + msgbody_var); - EXEC_ACTION_STOP; - } - if (!isArgCStr(it->second)) { - DBG("no SIP MSG body in avar '%s'\n", msgbody_var.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("no SIP MSG body in avar " + msgbody_var); - EXEC_ACTION_STOP; - } - const char* b = it->second.asCStr(); - if (b==NULL) { - DBG("empty SIP MSG body in avar '%s'\n", msgbody_var.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("empty SIP MSG body in avar " + msgbody_var); - EXEC_ACTION_STOP; - } - - xmlSetGenericErrorFunc(NULL, &xml_err_func); - - xmlDocPtr doc = - xmlReadMemory((const char*)b, strlen(b), "noname.xml", NULL, 0); - if (doc == NULL) { - DBG("failed parsing XML document from '%s'\n", msgbody_var.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("failed parsing XML document from " + msgbody_var); - EXEC_ACTION_STOP; - } - - xmlSetGenericErrorFunc(doc, &xml_err_func); - - ModXmlDoc* xml_doc = new ModXmlDoc(doc); - sc_sess->avar[dstname] = xml_doc; - DBG("parsed XML body document to '%s'\n", dstname.c_str()); - -// string basedir = resolveVars(par2, sess, sc_sess, event_params); -} EXEC_ACTION_END; - -CONST_ACTION_2P(MODXMLParseAction, ',', false); -EXEC_ACTION_START(MODXMLParseAction) { - string xml_doc = resolveVars(par1, sess, sc_sess, event_params); - string dstname = resolveVars(par2, sess, sc_sess, event_params); - - xmlSetGenericErrorFunc(NULL, &xml_err_func); - - xmlDocPtr doc = - xmlReadMemory(xml_doc.c_str(), xml_doc.length(), "noname.xml", NULL, 0); - if (doc == NULL) { - DBG("failed parsing XML document from '%s'\n", xml_doc.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("failed parsing XML document from " + xml_doc); - EXEC_ACTION_STOP; - } - xmlSetGenericErrorFunc(doc, &xml_err_func); - - ModXmlDoc* xml_doc_var = new ModXmlDoc(doc); - sc_sess->avar[dstname] = xml_doc_var; - DBG("parsed XML body document to '%s'\n", dstname.c_str()); -} EXEC_ACTION_END; - -template -T* getXMLElemFromVariable(DSMSession* sc_sess, const string& var_name) { - AVarMapT::iterator it = sc_sess->avar.find(var_name); - if (it == sc_sess->avar.end()) { - DBG("object '%s' not found\n", var_name.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("object '"+var_name+"' not found\n"); - return NULL; - } - - T* doc = dynamic_cast(it->second.asObject()); - if (NULL == doc) { - DBG("object '%s' is not the right type\n", var_name.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("object '"+var_name+"' is not the right type\n"); - return NULL; - } - return doc; -} - -CONST_ACTION_2P(MODXMLEvalXPathAction, ',', false); -EXEC_ACTION_START(MODXMLEvalXPathAction) { - string xpath_expr = resolveVars(par1, sess, sc_sess, event_params); - string xml_doc_var = resolveVars(par2, sess, sc_sess, event_params); - - xmlSetGenericErrorFunc(NULL, &xml_err_func); - - ModXmlDoc* xml_doc = getXMLElemFromVariable(sc_sess, xml_doc_var); - if (NULL == xml_doc) - EXEC_ACTION_STOP; - - xmlDocPtr doc = xml_doc->doc; - - xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc); - if(xpathCtx == NULL) { - DBG("unable to create new XPath context\n"); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("unable to create new XPath context"); - EXEC_ACTION_STOP; - } - xmlSetGenericErrorFunc(xpathCtx, &xml_err_func); - - string xml_doc_ns = sc_sess->var[xml_doc_var+".ns"]; - vector ns_entries = explode(xml_doc_ns, " "); - for (vector::iterator it=ns_entries.begin(); it != ns_entries.end(); it++) { - vector ns = explode(*it, "="); - if (ns.size() != 2) { - DBG("script writer error: namespace entry must be prefix=href (got '%s')\n", - it->c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("script writer error: namespace entry must be prefix=href\n"); - xmlXPathFreeContext(xpathCtx); - EXEC_ACTION_STOP; - } - - if(xmlXPathRegisterNs(xpathCtx, (const xmlChar*)ns[0].c_str(), - (const xmlChar*)ns[1].c_str()) != 0) { - DBG("unable to register namespace %s=%s\n", ns[0].c_str(), ns[1].c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("unable to register namespace\n"); - xmlXPathFreeContext(xpathCtx); - EXEC_ACTION_STOP; - } - DBG("registered namespace %s=%s\n", ns[0].c_str(), ns[1].c_str()); - } - - xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression((const xmlChar*)xpath_expr.c_str(), - xpathCtx); - if(xpathObj == NULL) { - DBG("unable to evaluate xpath expression \"%s\"\n", xpath_expr.c_str()); - sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); - sc_sess->SET_STRERROR("unable to evaluate xpath expression"); - xmlXPathFreeContext(xpathCtx); - EXEC_ACTION_STOP; - } - - ModXmlXPathObj* xpath_obj = new ModXmlXPathObj(xpathObj, xpathCtx); - sc_sess->avar[xml_doc_var+".xpath"] = xpath_obj; - DBG("evaluated XPath expression on '%s' to '%s'\n", - xml_doc_var.c_str(), (xml_doc_var+".xpath").c_str()); - -} EXEC_ACTION_END; - -CONST_ACTION_2P(MODXMLXPathResultNodeCount, '=', false); -EXEC_ACTION_START(MODXMLXPathResultNodeCount) { - string cnt_var = par1; - string xpath_res_var = resolveVars(par2, sess, sc_sess, event_params); - - if (cnt_var.size() && cnt_var[0]=='$') { - cnt_var.erase(0,1); - } - - ModXmlXPathObj* xpath_obj = - getXMLElemFromVariable(sc_sess, xpath_res_var); - if (NULL == xpath_obj){ - DBG("no xpath result found in '%s'\n", xpath_res_var.c_str()); - sc_sess->var[cnt_var] = "0"; - EXEC_ACTION_STOP; - } - - unsigned int res = (xpath_obj->xpathObj->nodesetval) ? - xpath_obj->xpathObj->nodesetval->nodeNr : 0; - - sc_sess->var[cnt_var] = int2str(res); - DBG("set count $%s=%u\n", cnt_var.c_str(), res); - -} EXEC_ACTION_END; - -EXEC_ACTION_START(MODXMLSetLogLevelAction) { - string xml_log_level_s = resolveVars(arg, sess, sc_sess, event_params); - if (xml_log_level_s == "error") - xml_log_level = L_ERR; - else if (xml_log_level_s == "warn") - xml_log_level = L_WARN; - else if (xml_log_level_s == "info") - xml_log_level = L_INFO; - else if (xml_log_level_s == "debug") - xml_log_level = L_DBG; - else { - ERROR("script writer error: '%s' is no valid log level (error, warn, info, debug)\n", - xml_log_level_s.c_str()); - } -} EXEC_ACTION_END; diff --git a/apps/dsm/mods/mod_xml/ModXml.h b/apps/dsm/mods/mod_xml/ModXml.h deleted file mode 100644 index f5da41db..00000000 --- a/apps/dsm/mods/mod_xml/ModXml.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (C) 2012 FRAFOS GmbH - * - * Development sponsored by Sipwise GmbH. - * - * This file is part of SEMS, a free SIP media server. - * - * SEMS is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. This program is released under - * the GPL with the additional exemption that compiling, linking, - * and/or using OpenSSL is allowed. - * - * For a license to use the SEMS software under conditions - * other than those described here, or to purchase support for this - * software, please contact iptel.org by e-mail at the following addresses: - * info@iptel.org - * - * SEMS is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#ifndef _MOD_XML_H -#define _MOD_XML_H -#include "DSMModule.h" -#include "DSMSession.h" - - -#include -#include -#include -#include - -#define MOD_CLS_NAME SCXMLModule - -DECLARE_MODULE_BEGIN(MOD_CLS_NAME); -int preload(); -DECLARE_MODULE_END; - -DEF_ACTION_2P(MODXMLParseSIPMsgBodyAction); -DEF_ACTION_2P(MODXMLParseAction); -DEF_ACTION_2P(MODXMLEvalXPathAction); -DEF_ACTION_2P(MODXMLXPathResultNodeCount); -DEF_ACTION_1P(MODXMLSetLogLevelAction); - -class ModXmlDoc -: public DSMDisposable, - public ArgObject { - public: - ModXmlDoc() : doc(NULL) {} - ModXmlDoc(xmlDocPtr doc) : doc(doc) {} - ~ModXmlDoc(); - xmlDocPtr doc; -}; - -class ModXmlXPathObj -: public DSMDisposable, - public ArgObject { - public: - ModXmlXPathObj() : xpathObj(NULL), xpathCtx(NULL) {} - ModXmlXPathObj(xmlXPathObjectPtr xpathObj, xmlXPathContextPtr xpathCtx) - : xpathObj(xpathObj), xpathCtx(xpathCtx) { } - ~ModXmlXPathObj(); - - xmlXPathObjectPtr xpathObj; - xmlXPathContextPtr xpathCtx; -}; - -#endif diff --git a/apps/early_dbprompt/early_dbprompt.dsm b/apps/early_dbprompt/early_dbprompt.dsm deleted file mode 100644 index 9abc4909..00000000 --- a/apps/early_dbprompt/early_dbprompt.dsm +++ /dev/null @@ -1,70 +0,0 @@ --- --- This DSM app --- o plays early media from a file in the DB --- o replies with final reply code/reason from P-App-Param --- --- Parameters (P-App-Param): --- audio_id - indicating audio file in DB; must be wav 16 bit pcm format (with wav header) --- fr_code - final reply code --- fr_reason - final reply reason --- play_looped - "yes" to play the prompt in loop --- --- Example: P-App-Param: audio_id=rbt;play_looped=yes;fr_code=404;fr_reason="Not found" - -import(mod_utils); -import(mod_dlg); -import(mod_mysql); - -initial state START; - -transition "DB exception" START - exception / { - log(1, "Error in initializing :"); - logAll(1); - - -- reply with fr_code/reason immediately - dlg.reply($fr_code, $fr_reason); - - -- alternatively, reply with 500: - -- dlg.reply(500, "Server Internal Error"); - stop(false); -} -> END; - -transition "invite" START - invite / { - if test($audio_id != "") { - mysql.connect(); - throwOnError(); - -- play waiting file from DB - if test($play_looped=="yes") { - mysql.playDBAudioLooped(SELECT data FROM provisioning.audio_files WHERE id="$audio_id", rbt.wav); - } else { - mysql.playDBAudio(SELECT data FROM provisioning.audio_files WHERE id="$audio_id", rbt.wav); - } - throwOnError(); - mysql.disconnect(); - } - - -- send 183 with early media - dlg.acceptInvite(183, "Progress"); - - -- no default 200 OK - set($connect_session=0); - - -- start RTP processing - connectMedia(); -} -> WAITING; - -state WAITING; - -transition "CANCEL received" WAITING - hangup / { - dlg.reply(487, "Request Terminated"); - removeTimers(); - stop(false); -} -> END; - -transition "end of prompt" WAITING - noAudio / { - dlg.reply($fr_code, $fr_reason); - removeTimers(); - stop(false); -} -> END; - -state END; \ No newline at end of file diff --git a/apps/early_dbprompt/etc/early_dbprompt.conf b/apps/early_dbprompt/etc/early_dbprompt.conf deleted file mode 100644 index eb0c5810..00000000 --- a/apps/early_dbprompt/etc/early_dbprompt.conf +++ /dev/null @@ -1,20 +0,0 @@ - -# configuration for early_dbprompt app - -# DSM configuration -diag_path=/usr/lib/sems/early_dbprompt -mod_path=/usr/lib/sems/plug-in/ -load_diags=early_dbprompt -register_apps=early_dbprompt -run_invite_event=yes -set_param_variables=yes - -# application configuration: - -# database connection: -db_url="mysql://root:frafos@localhost/provisioning" - - -# local testing: -#diag_path=../apps/early_dbprompt -#mod_path=../apps/dsm/mods/lib diff --git a/apps/examples/Makefile b/apps/examples/Makefile index 6e32b9da..c0206a0f 100644 --- a/apps/examples/Makefile +++ b/apps/examples/Makefile @@ -33,7 +33,7 @@ modules: done .PHONY: install -install: install-bin +install: install-bin install-cfg .PHONY: install-bin install-bin: diff --git a/apps/examples/tutorial/Makefile b/apps/examples/tutorial/Makefile index 80d8a1d9..f451a1d0 100644 --- a/apps/examples/tutorial/Makefile +++ b/apps/examples/tutorial/Makefile @@ -33,7 +33,7 @@ modules: done .PHONY: install -install: install-bin +install: install-bin install-cfg .PHONY: install-bin install-bin: diff --git a/apps/ivr/IvrDialogBase.cpp b/apps/ivr/IvrDialogBase.cpp index edb14111..63f6bd19 100644 --- a/apps/ivr/IvrDialogBase.cpp +++ b/apps/ivr/IvrDialogBase.cpp @@ -281,46 +281,6 @@ static PyObject* IvrDialogBase_unmute(IvrDialogBase* self, PyObject* args) return Py_None; } -static PyObject* IvrDialogBase_enableReceiving(IvrDialogBase* self, PyObject* args) -{ - assert(self->p_dlg); - - self->p_dlg->setReceiving(true); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* IvrDialogBase_disableReceiving(IvrDialogBase* self, PyObject* args) -{ - assert(self->p_dlg); - - self->p_dlg->setReceiving(false); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* IvrDialogBase_enableDTMFReceiving(IvrDialogBase* self, PyObject* args) -{ - assert(self->p_dlg); - - self->p_dlg->setForceDtmfReceiving(true); - - Py_INCREF(Py_None); - return Py_None; -} - -static PyObject* IvrDialogBase_disableDTMFReceiving(IvrDialogBase* self, PyObject* args) -{ - assert(self->p_dlg); - - self->p_dlg->setForceDtmfReceiving(false); - - Py_INCREF(Py_None); - return Py_None; -} - static PyObject* IvrDialogBase_remove_mediaprocessor(IvrDialogBase* self, PyObject* args) { @@ -597,18 +557,6 @@ static PyMethodDef IvrDialogBase_methods[] = { {"unmute", (PyCFunction)IvrDialogBase_unmute, METH_NOARGS, "unmute the RTP stream (send packets)" }, - {"enableReceiving", (PyCFunction)IvrDialogBase_enableReceiving, METH_NOARGS, - "enable receiving of RTP packets" - }, - {"disableReceiving", (PyCFunction)IvrDialogBase_disableReceiving, METH_NOARGS, - "disable receiving of RTP packets" - }, - {"enableDTMFReceiving", (PyCFunction)IvrDialogBase_enableDTMFReceiving, METH_NOARGS, - "enable receiving of RFC-2833 DTMF packets even if RTP receiving is disabled" - }, - {"disableDTMFReceiving", (PyCFunction)IvrDialogBase_disableDTMFReceiving, METH_NOARGS, - "disable receiving of RFC-2833 DTMF packets when RTP receiving is disabled" - }, {"connectMedia", (PyCFunction)IvrDialogBase_add_mediaprocessor, METH_NOARGS, "enable the processing of audio and RTP" }, diff --git a/apps/mobile_push/etc/mobile_push.conf b/apps/mobile_push/etc/mobile_push.conf deleted file mode 100644 index 088ec27a..00000000 --- a/apps/mobile_push/etc/mobile_push.conf +++ /dev/null @@ -1,45 +0,0 @@ - -# configuration for mobile_push app - -# DSM configuration -diag_path=/usr/lib/sems/mobile_push -load_diags=mobile_push -register_apps=mobile_push -mod_path=/usr/lib/sems/plug-in/ -preload_mods=mod_xml -run_invite_event=yes -set_param_variables=yes -#run_system_dsms= - -# application configuration: - -# enable_rbt=[yes|no] - enable playing of ring-back tone from DB? -enable_rbt=yes - -# database connection: -db_url="mysql://root:frafos@localhost/provisioning" - -# play_looped=[yes|no] - loop file? -play_looped=yes - -# mobile push web app server URL: -push_server_url=http://127.0.0.1:8000/mobilepush/ - -# use_post=[yes|no] - use HTTP POST? (or GET) -use_post=no - -# subscription user/pwd (From in subscription) -subscription_user=sub_user -subscription_pwd=sub_pwd - -# proxy for subscription (outbound-proxy setting) -#proxy=sip:127.0.0.1:5060 - -# extra_3xx_uri_append - append extra string to Contact in 300 (e.g. port) -# extra_3xx_uri_append=":5090" - -# use_subscription_id=[yes|no] - use an ID for SUBSCRIBE? (problems with kamailio :( ) -use_subscription_id=no - - - diff --git a/apps/mobile_push/load_test/call_gen.py b/apps/mobile_push/load_test/call_gen.py deleted file mode 100755 index 49501802..00000000 --- a/apps/mobile_push/load_test/call_gen.py +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env python -from xmlrpclib import * -s = ServerProxy('http://127.0.0.1:8092') -print s.setTarget(100, 1, 0, '4', '192.168.5.110', 2, 0, 30, 40) - diff --git a/apps/mobile_push/load_test/example_server.py b/apps/mobile_push/load_test/example_server.py deleted file mode 100644 index b5643087..00000000 --- a/apps/mobile_push/load_test/example_server.py +++ /dev/null @@ -1,36 +0,0 @@ -import time -import BaseHTTPServer - - -HOST_NAME = '127.0.0.1' # !!!REMEMBER TO CHANGE THIS!!! -PORT_NUMBER = 8000 # Maybe set this to 9000. - - -class MyHandler(BaseHTTPServer.BaseHTTPRequestHandler): - def do_HEAD(s): - s.send_response(200) - s.send_header("Content-type", "text/html") - s.end_headers() - def do_GET(s): - """Respond to a GET request.""" - s.send_response(200) - s.send_header("Content-type", "text/html") - s.end_headers() - s.wfile.write("Title goes here.") - s.wfile.write("

This is a test.

") - # If someone went to "http://something.somewhere.net/foo/bar/", - # then s.path equals "/foo/bar/". - s.wfile.write("

You accessed path: %s

" % s.path) - s.wfile.write("") - -if __name__ == '__main__': - server_class = BaseHTTPServer.HTTPServer - httpd = server_class((HOST_NAME, PORT_NUMBER), MyHandler) - print time.asctime(), "Server Starts - %s:%s" % (HOST_NAME, PORT_NUMBER) - try: - httpd.serve_forever() - except KeyboardInterrupt: - pass - httpd.server_close() - print time.asctime(), "Server Stops - %s:%s" % (HOST_NAME, PORT_NUMBER) - diff --git a/apps/mobile_push/load_test/mobilepush_loadtest.txt b/apps/mobile_push/load_test/mobilepush_loadtest.txt deleted file mode 100644 index ff0d549e..00000000 --- a/apps/mobile_push/load_test/mobilepush_loadtest.txt +++ /dev/null @@ -1,105 +0,0 @@ -this is a small set of scripts and config files to do load tests on the -mobile-push application. It uses another SEMS instance to register/deregister -users using db_reg_agent module, and place calls using call_gen application. - -both sems instances are expected to run on 192.168.5.110 - if that IP is -different, it needs to be changed in some (many) places. - -1. create users 400..499 (pwd 400..499) in kamailio with - for ((i=400;i<500;i++)); do kamctl add $i $i; done - - 1.b for Kamailio from packages (default config), - - enable: - #!define WITH_MYSQL - #!define WITH_PRESENCE - undefine WITH_AUTH - - - add to presence loading section: - #!ifdef WITH_PRESENCE - loadmodule "presence.so" - loadmodule "presence_xml.so" - - # reginfo related - loadmodule "presence_reginfo.so" - loadmodule "pua.so" - loadmodule "pua_reginfo.so" - #!endif - - - add to presence config section: - #!ifdef WITH_PRESENCE - # ----- presence params ----- - modparam("presence", "db_url", DBURL) - - # ----- presence_xml params ----- - modparam("presence_xml", "db_url", DBURL) - modparam("presence_xml", "force_active", 1) - - # reginfo related - modparam("pua_reginfo", "default_domain", "192.168.5.110") - modparam("pua_reginfo", "publish_reginfo", 1) - modparam("pua_reginfo", "server_address", "sip:reginfo@192.168.5.110") - - - remove auth check in request_route (easier) - # authentication - # if (!is_method("SUBSCRIBE|NOTIFY")) { - # route(AUTH); - # } - - - add SERVICES route to route calls to sems: - # dispatch requests to foreign domains - route(SIPOUT); - - route(SERVICES); - - ... - - route[SERVICES] { - - if (method=="INVITE") { - if ((uri=~"sip:38") || (uri=~"sip:4")) - { - - # $ru = "sip:" + $rU + "@" + "192.168.5.110:5080"; - append_hf("P-App-Param: audio_id=connecting;caller=+492222222222;callee=+491111111111;domain=sip.sipwise.com\r\n"); - append_hf("P-hint: services\r\n"); - t_relay_to("192.168.5.110:5080"); - exit(); - } - } - } - - -2. create database tables for sems with: - -CREATE TABLE `registrations` ( - `subscriber_id` int(11) NOT NULL, - `registration_status` tinyint(1) NOT NULL DEFAULT '0', - `last_registration` datetime NOT NULL, - `expiry` datetime NOT NULL, - `last_code` smallint(2) NOT NULL, - `last_reason` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, - `contacts` varchar(512) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, - PRIMARY KEY (`subscriber_id`) -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - -CREATE TABLE `subscribers` ( - `subscriber_id` int(10) NOT NULL AUTO_INCREMENT, - `user` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, - `pass` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, - `realm` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, - `contact` varchar(256) CHARACTER SET ascii COLLATE ascii_bin NOT NULL, - PRIMARY KEY (`subscriber_id`) -) ENGINE=MyISAM AUTO_INCREMENT=20005 DEFAULT CHARSET=latin1; - -3. set mysql pwd in db_reg_agent.conf - -4. start load gen sems instance with the configuration given here. - (git clone git://git.sip-router.org/sems ; cp -R sems_cfg/* sems ; cd sems ; make -C apps/xmlrpc2di ; - make -C apps/examples/call_gen; make -C apps/db_reg_agent; make -C core ; cd core ; - ./sems -f etc/sems.conf -D 3 -E ) - -5. run reg_client.py, which will very quickly register and deregister subscribers - by calling removeRegistration/createRegistration on the load gen sems instance - -6. run call_gen.py to set a target of 100 calls (or run sth like -s.createCalls(1, 1, 0, '4', '192.168.5.110', 2, 0, 30, 40) to create one call for testing first diff --git a/apps/mobile_push/load_test/reg_client.py b/apps/mobile_push/load_test/reg_client.py deleted file mode 100755 index 01a4972b..00000000 --- a/apps/mobile_push/load_test/reg_client.py +++ /dev/null @@ -1,20 +0,0 @@ -#!/usr/bin/env python - -from xmlrpclib import * -from random import * -import time - -s = ServerProxy('http://127.0.0.1:8092') - -r = set() - -while True: - n = randint(400, 499) - if n in r: - print s.removeRegistration(n) - r.remove(n) - else: - print s.createRegistration(n, str(n), str(n), '192.168.5.110') - r.add(n) - - time.sleep(.1) \ No newline at end of file diff --git a/apps/mobile_push/load_test/sems_cfg/core/etc/callgen.conf b/apps/mobile_push/load_test/sems_cfg/core/etc/callgen.conf deleted file mode 100644 index 401615ad..00000000 --- a/apps/mobile_push/load_test/sems_cfg/core/etc/callgen.conf +++ /dev/null @@ -1,3 +0,0 @@ -play_file=wav/default_en.wav -digits_dir=../apps/examples/call_gen/wav/ -from_host=callgen.example.net \ No newline at end of file diff --git a/apps/mobile_push/load_test/sems_cfg/core/etc/db_reg_agent.conf b/apps/mobile_push/load_test/sems_cfg/core/etc/db_reg_agent.conf deleted file mode 100644 index 4f878350..00000000 --- a/apps/mobile_push/load_test/sems_cfg/core/etc/db_reg_agent.conf +++ /dev/null @@ -1,99 +0,0 @@ -# Database connection -mysql_user=root -mysql_passwd=mysqlrootpwd - -# mysql_server, default: localhost -# mysql_server=localhost - -#mysql_db, default: sems -# mysql_db=sems - -# table for registration status -# default: registrations -# registrations_table="registrations" - -# query joining subscriber info with registration table -joined_query="select subscribers.subscriber_id as subscriber_id, subscribers.user as user, subscribers.pass as pass, subscribers.realm as realm, registrations.registration_status as registration_status, registrations.expiry as expiry, registrations.last_registration as last_registration from subscribers left join registrations on subscribers.subscriber_id=registrations.subscriber_id;" - -#example with contact: -# joined_query="select subscribers.subscriber_id as subscriber_id, subscribers.user as user, subscribers.pass as pass, subscribers.realm as realm, subscribers.contact as contact, registrations.registration_status as registration_status, registrations.expiry as expiry, registrations.last_registration as last_registration from subscribers left join registrations on subscribers.subscriber_id=registrations.subscriber_id;" - -# outbound_proxy= -# set the outbound proxy to send registrations through -# -#outbound_proxy=sip:10.0.0.2:5070 - -# contact_hostport= - overriding contact host:port -# sets the contact host:port portion that is registered -# default: empty -#contact_hostport=10.0.0.50:5080 - -# db_read_contact=[yes, no] : read individual contact to register from DB? -# note: joined_query must select the contact, too -# default: no -#db_read_contact=yes - -#save_contacts=[yes, no] : save contacts? -# for monitoring and troubleshooting, all contacts returned with a positive reply -# may be saved to DB in the registrations.contacts colums -# default: yes -#save_contacts=yes - -#save_auth_replies=[yes, no] : update status on 401 replies (auth)? -# usually, 401 replies which are resent with auth are not saved. if save_auth_replies=yes, -# last_code and last_reason in DB is updated with the 401 -#save_auth_replies=yes - -# expires: desired expires, i.e. expires value that is requested -# default: 7200 -# expires=300 - -# error_retry_interval -# -# default: 300 - -# reregister_interval: fraction of actual expires after which register is refreshed -# default: reregister_interval=0.5 -#reregister_interval=0.5 - -# minimum_reregister_interval: if set, re-register is scheduled in least loaded time -# in minimum_reregister_interval .. reregister_interval i order to smooth load spikes -# must be smaller than reregister_interval -# default: off -# -# example: -# reregister_interval=0.5 -# minimum_reregister_interval=0.4 -# on a registration expiring in 3600s, the least loaded spot between 1440s and 1800s -# is chosen -# -#minimum_reregister_interval=0.4 - -# enable_ratelimiting=yes : Enable ratelimiting? -# default: no -# if enabled, the amount of initial REGISTER requests is limited (not counting re-trans- -# missions and requests re-sent for authentication) -#enable_ratelimiting=yes - -# ratelimit_rate=300 : rate of initial REGISTER requests to send as maximum -#ratelimit_rate=2 - -# ratelimit_per=1 : per time unit (in seconds, e.g. 300 REGISTER in 1 second) -#ratelimit_per=1 - -#ratelimit_slowstart=[yes|no] : on startup send initially ratelimit_rate or 0 requests -#default: no -#ratelimit_slowstart=yes - -# delete_removed_registrations=yes : delete removed registrations from registrations -# table in DB? (otherwise they will stay with STATUS_REMOVED) -# default: yes -# -#delete_removed_registrations=no - -# delete_failed_deregistrations=yes : delete failed de-registrations from registrations -# table in DB? (otherwise they will stay with STATUS_TO_BE_REMOVED) -# only applicable if delete_removed_registrations=yes -# default: no -# -#delete_failed_deregistrations=no diff --git a/apps/mobile_push/load_test/sems_cfg/core/etc/sems.conf b/apps/mobile_push/load_test/sems_cfg/core/etc/sems.conf deleted file mode 100644 index a28fa2c8..00000000 --- a/apps/mobile_push/load_test/sems_cfg/core/etc/sems.conf +++ /dev/null @@ -1,544 +0,0 @@ -# $Id$ -# -# sems.conf.sample -# -# Sip Express Media Server (sems) -# -# sample configuration file -# -# -# whitespaces (spaces and tabs) are ignored -# comments start with a "#" and may be used inline -# -# example: option=value # i like this option -# -# @filename includes mod_config_path/filename -# @/absolute/path/to/file includes file - -############################################################ -# Network configuration - -# optional parameter: media_ip=| -# -# - this informs SEMS about the IP address or interface that -# SEMS uses to send and receive media. -# - If neither 'media_ip' nor 'sip_ip' are set, defaults -# to first non-loopback interface. If 'sip_ip' is set, -# 'media_ip' defaults to 'sip_ip. -# -# Examples: -# media_ip=10.0.0.34 -# media_ip=eth0 - -# optional parameter: sip_ip=| -# -# - this informs SEMS about the SIP IP where its SIP stack is -# bound to or should be bound to. This also sets -# the value used for contact header in outgoing calls and -# registrations. -# - If neither 'media_ip' nor 'sip_ip' are set, defaults -# to first non-loopback interface. If 'media_ip' is set, -# 'sip_ip' defaults to 'media_ip. -# -# Example: -# sip_ip=10.0.0.34 -# sip_ip=en0 -# - -# optional parameter: public_ip= -# -# - when running SEMS behind certain simple NAT configurations, -# you can use this parameter to inform SEMS of its public IP -# address. If this parameter is set, SEMS will write this value -# into SDP bodies. -# If this parameter is not set, the local IP address is used. -# N.B., there is no support for port translation; the local -# RTP port is advertised in SDP in either case. -# -# Example: -# public_ip=75.101.219.48 -# - -# optional parameter: sip_port= -# -# - this informs SEMS about the port where its SIP stack is -# bound to or should be bound to. SEMS needs this information -# to correctly set the contact header in outgoing calls -# and registrations. Should be set to equal the 'port' -# configuration option in ser_sems.cfg. -# -# default: 5060 -# -sip_port=5080 - -# optional parameter: outbound_proxy=uri -# -# - this sets an outbound proxy for calls and registrations initiated -# by SEMS. This does not apply to requests in a dialog that -# is initiated by someone else and incoming to SEMS. -# If this is not set (default setting), then for dialogs -# initiated by SEMS the r-uri is resolved and the request -# is sent there directly. -# This is resolved by the SIP stack with DNS if a name is given. -# Warning: If the value set here can not be resolved, no -# requests will be sent out at all! -# -# default: empty -# -# Example: -# outbound_proxy=sip:proxy.mydomain.net - -# optional parameter: force_outbound_proxy={yes|no} -# -# - forces SEMS to send any request to the outbound proxy in any -# situation, by adding an extra first Route to the outbound_proxy. -# This option will only have an effect if the outbound_proxy -# option has been set, and it will break 3261 compatibility -# in some cases; better use next_hop_ip/next_hop_port. -# -# default: no -# -# Example: -# force_outbound_proxy=yes - -# optional parameter: next_hop_ip -# - if this is set, all outgoing requests will be sent to -# this IP, regardless of R-URI etc. -# -#next_hop_ip=192.168.5.106 - -# optional parameter: next_hop_port -# defaults to 5060 -#next_hop_port=5060 - -# optional parameter:next_hop_for_replies -# - use next_hop for replies, too? -# -#next_hop_for_replies=yes - -# optional parameter: rtp_low_port= -# -# - sets lowest for RTP used port -rtp_low_port=10000 - -# optional parameter: rtp_high_port= -# -# - sets highest for RTP used port -rtp_high_port=60000 - -# Additional IFs (optional): -# additional_interfaces = -# -# additional_interfaces must be set if more than one -# interface is to be used for the same purpose (e.g. -# more than one interface for SIP). Configure additional -# interfaces if networks should be bridged or separate -# networks should be served. -# -# For each additional interface, a set of parameters -# suffixed with the interface name should be listed -# with the 'additional_interfaces' parameter. -# -# Please note that for each additional interface, -# 'sip_ip_[if_name]' is mandatory (but can be the interface -# name, then the first assigned IP is used). The other -# parameters are optional. 'media_ip_[if_name]' -# is derived from 'sip_ip_[if_name]' if not set. -# 'public_ip_[ip_name]' is also based on 'sip_ip_[if_name]' -# if not set explicitly. -# -# Example: -# additional_interfaces=intern,extern -# -# sip_ip_intern=192.168.0.5 -# sip_port_intern=5060 -# media_ip_intern=192.168.10.5 -# rtp_low_port_intern=2000 -# rtp_high_port_intern=5000 -# -# sip_ip_extern=213.192.59.73 -# sip_port_extern=5060 -# media_ip_extern=213.192.59.73 -# rtp_low_port_extern=2000 -# rtp_high_port_extern=5000 -# public_ip_extern=213.192.35.73 -# - -############################################################ -# modules and application configuration -# -# Configuration of plugin (module) loading: -# - if load_plugins is set, only those are loaded. -# - if load_plugins is not set, all modules in the plugin_path -# directory are loaded, except those which are listed -# in exclude_plugins. -# - -# optional parameter: plugin_path= -# -# - sets the path to the plug-ins' binaries -# - may be absolute or relative to CWD -plugin_path=/usr/local/lib/sems/plug-in/ - -# optional parameter: load_plugins= -# -# semicolon-separated list of modules to load. -# If empty, all modules in plugin_path are loaded. -# -# example for announcement with only g711 and ilbc codecs -# load_plugins=wav;ilbc;announcement - -# optional parameter: exclude_plugins= -# -# semicolon-separated list of modules to exclude from loading -# ('blacklist'). If empty, all modules in plugin_path are loaded. -# This has only effect it load_plugins is not set. -# -# o precoded_announce: no precoded sample files present -# o py_sems: conflicts with ivr (in some cases) -# o db_reg_agent: needs DB tables -exclude_plugins=precoded_announce;py_sems;db_reg_agent - -# optional: load_plugins_rtld_global= -# -# load these plugins with RTLD_GLOBAL (by default py_sems, -# dsm, ivr, sbc, diameter_client, registrar_client, uac_auth) - -# optional parameter: application -# -# This controls which application is to be executed if there -# is no explicit application requested from the SIP stack -# (i.e. unixsockctrl and second parameter of t_write_unix). -# -# This can be one of -# $(ruri.user) - user part of ruri is taken as application, -# e.g. sip:announcement@host -# $(ruri.param) - uri parameter "app", e.g. -# sip:joe@host.net;app=announcement -# $(apphdr) - the value of the P-App-Name header is used -# -# $(mapping) - regex=>application mapping is read from -# app_mapping.conf (see app_mapping.conf) -# - application name configured here, e.g. -# application=announcement -# -# examples: -# application = conference -# application = $(mapping) -# application = $(ruri.user) -# application = $(ruri.param) -application = $(apphdr) - -# parameter: plugin_config_path= -# -# - in this path configuration files of the applications -# (e.g. announcement.conf) are searched -plugin_config_path=/usr/local/etc/sems/etc/ - -# optional parameter: exclude_payloads= -# -# semicolon-separated list of payloads to exclude from loading -# ('blacklist'). -# -# For example, to only use low bandwidth codecs: -# exclude_payloads=PCMU;PCMA;G726-40;G726-32;G721;L16 -# or, to use only codecs which are not CPU-intensive: -# exclude_payloads=iLBC;speex; -# only use G711 (exclude everything else): -# exclude_payloads=iLBC;speex;G726-40;G726-32;G721;G726-24;G726-16;GSM;L16 - -############################################################ -# logging and running - -# optional parameter: fork={yes|no} -# -# - specifies if sems should run in daemon mode (background) -# (fork=no is the same as -E) -fork=yes - -# optional parameter: stderr={yes|no} -# -# - debug mode: do not fork and log to stderr -# (stderr=yes is the same as -E) -stderr=no - -# optional parameter: loglevel={0|1|2|3} -# -# - sets log level (error=0, warning=1, info=2, debug=3) -# (same as -D) -loglevel=2 - -# optional parameter: syslog_facility={DAEMON|USER|LOCAL[0-7]} -# -# - sets the log facility that is used for syslog. Using this, -# the log can for example be filtered into a special file -# by the syslog daemon. -# -# Default: DAEMON -# -# Example: -# syslog_facility=LOCAL0 - -# optional parameter: log_sessions=[yes|no] -# -# Default: no -# -# If log_sessions=yes is set, INFO level log messages are generated -# for each session when it is started and stopped. -# -# log_sessions=yes - -# optional parameter: log_events=[yes|no] -# -# Default: no -# -# If log_eventy=yes is set, generic DBG level log messages are -# generated for each event that is posted into an event queue. -# -# log_events=yes - -# optional parameter: max_shutdown_time=