Module: sems Branch: master Commit: 21ddd3ca67ee4fdc643ed26516a6c710842803bb URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sems/?a=commit;h=21ddd3ca67ee4fdc643ed26516a6c710842803bb
Author: Stefan Sayer <[email protected]> Committer: Stefan Sayer <[email protected]> Date: Thu Mar 8 14:26:01 2012 +0100 dsm: mod_regex module for regular expressions in DSM --- apps/dsm/mods/mod_regex/CMakeLists.txt | 7 ++ apps/dsm/mods/mod_regex/Makefile | 10 ++ apps/dsm/mods/mod_regex/ModRegex.cpp | 163 ++++++++++++++++++++++++++++ apps/dsm/mods/mod_regex/ModRegex.h | 65 +++++++++++ apps/dsm/mods/mod_regex/etc/mod_regex.conf | 6 + doc/dsm/mods/Readme.mod_regex.txt | 30 +++++ 6 files changed, 281 insertions(+), 0 deletions(-) diff --git a/apps/dsm/mods/mod_regex/CMakeLists.txt b/apps/dsm/mods/mod_regex/CMakeLists.txt new file mode 100644 index 0000000..007a582 --- /dev/null +++ b/apps/dsm/mods/mod_regex/CMakeLists.txt @@ -0,0 +1,7 @@ +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 new file mode 100644 index 0000000..8cd44a4 --- /dev/null +++ b/apps/dsm/mods/mod_regex/Makefile @@ -0,0 +1,10 @@ +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 new file mode 100644 index 0000000..0e562e0 --- /dev/null +++ b/apps/dsm/mods/mod_regex/ModRegex.cpp @@ -0,0 +1,163 @@ +/* + * 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: + * [email protected] + * + * 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<string, TsRegex> 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.loadPluginConf(MOD_NAME)) { + INFO("no module configuration for '%s' found, not preloading regular expressions\n", + MOD_NAME); + return 0; + } + + bool failed = false; + for (std::map<string,string>::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<string, TsRegex>::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 new file mode 100644 index 0000000..f553389 --- /dev/null +++ b/apps/dsm/mods/mod_regex/ModRegex.h @@ -0,0 +1,65 @@ +/* + * 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: + * [email protected] + * + * 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 <sys/types.h> +#include <regex.h> +#include <map> + +// 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<string, TsRegex> 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 new file mode 100644 index 0000000..91503da --- /dev/null +++ b/apps/dsm/mods/mod_regex/etc/mod_regex.conf @@ -0,0 +1,6 @@ +# 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/doc/dsm/mods/Readme.mod_regex.txt b/doc/dsm/mods/Readme.mod_regex.txt new file mode 100644 index 0000000..bf74068 --- /dev/null +++ b/doc/dsm/mods/Readme.mod_regex.txt @@ -0,0 +1,30 @@ +mod_regex - regular expressions + +This module uses regex(3) for regular expressions. + +Regular expressions are referenced by a regex name. They are compiled using +regex.compile action or by adding a line to mod_regex.conf and preloading +mod_regex. The compiled regular expressions can be used with the action +regex.match or the condition regex.match. + +Actions: +regex.compile(name, reg_ex) + Compile a regular expressions in reg_ex to be referenced by name. + REG_NOSUB | REG_EXTENDED is used. + +regex.match(name, match_string) + Match match_string on regex referenced by name. + $regex.match is set to 1 if matched, 0 if not matched. + +regex.clear(name) + Clear the regex referenced by name. + +Conditions: + regex.match(name, match_string) + Match match_string on regex referenced by name. + + + +TODO: + - implement substring adressing + - find a better way for $regex.match side-effect _______________________________________________ Semsdev mailing list [email protected] http://lists.iptel.org/mailman/listinfo/semsdev
