1 /* 2 * Copyright (C) 2008 iptego GmbH 3 * 4 * This file is part of SEMS, a free SIP media server. 5 * 6 * SEMS is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. This program is released under 10 * the GPL with the additional exemption that compiling, linking, 11 * and/or using OpenSSL is allowed. 12 * 13 * For a license to use the SEMS software under conditions 14 * other than those described here, or to purchase support for this 15 * software, please contact iptel.org by e-mail at the following addresses: 16 * info@iptel.org 17 * 18 * SEMS is distributed in the hope that it will be useful, 19 * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 * GNU General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License 24 * along with this program; if not, write to the Free Software 25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 26 */ 27 #ifndef _DSM_MODULE_H 28 #define _DSM_MODULE_H 29 #include "DSMStateEngine.h" 30 #include "AmSipMsg.h" 31 #include "AmArg.h" 32 #include "AmSession.h" 33 34 class DSMSession; 35 36 #include <string> 37 using std::string; 38 39 #include <typeinfo> 40 41 // script modules interface 42 // factory only: it produces actions and conditions from script statements. 43 class DSMModule { 44 45 public: 46 DSMModule(); 47 virtual ~DSMModule(); 48 49 virtual DSMAction* getAction(const string& from_str) = 0; 50 virtual DSMCondition* getCondition(const string& from_str) = 0; 51 preload()52 virtual int preload() { return 0; } onInvite(const AmSipRequest & req,DSMSession * sess)53 virtual bool onInvite(const AmSipRequest& req, DSMSession* sess) { return true; } onBeforeDestroy(DSMSession * sc_sess,AmSession * sess)54 virtual void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) { } processSdpOffer(AmSdp & offer)55 virtual void processSdpOffer(AmSdp& offer) { } processSdpAnswer(const AmSdp & offer,AmSdp & answer)56 virtual void processSdpAnswer(const AmSdp& offer, AmSdp& answer) { } 57 }; 58 59 typedef map<string,string> EventParamT; 60 61 typedef void* (*SCFactoryCreate)(); 62 63 #define SCSTR(x) #x 64 #define SCXSTR(x) SCSTR(x) 65 66 #define SC_FACTORY_EXPORT sc_factory_create 67 #define SC_FACTORY_EXPORT_STR SCXSTR(SC_FACTORY_EXPORT) 68 69 #if __GNUC__ < 3 70 #define EXPORT_SC_FACTORY(fctname,class_name,args...) \ 71 extern "C" void* fctname() \ 72 { \ 73 return new class_name(##args); \ 74 } 75 #else 76 #define EXPORT_SC_FACTORY(fctname,class_name,...) \ 77 extern "C" void* fctname() \ 78 { \ 79 return new class_name(__VA_ARGS__); \ 80 } 81 #endif 82 83 #define SC_EXPORT(class_name) \ 84 EXPORT_SC_FACTORY(SC_FACTORY_EXPORT,class_name) 85 86 class SCStrArgAction 87 : public DSMAction { 88 protected: 89 string arg; 90 public: 91 SCStrArgAction(const string& m_arg); 92 }; 93 94 #define DEF_ACTION_1P(CL_Name) \ 95 class CL_Name \ 96 : public SCStrArgAction { \ 97 public: \ 98 CL_Name(const string& arg) : SCStrArgAction(arg) { } \ 99 bool execute(AmSession* sess, DSMSession* sc_sess, \ 100 DSMCondition::EventType event, \ 101 map<string,string>* event_params); \ 102 }; \ 103 104 105 #define DEF_SCModSEStrArgAction(CL_Name) \ 106 class CL_Name \ 107 : public SCStrArgAction { \ 108 bool is_evaluated; \ 109 public: \ 110 CL_Name(const string& arg) : SCStrArgAction(arg), \ 111 is_evaluated(false) { } \ 112 bool execute(AmSession* sess, DSMSession* sc_sess, \ 113 DSMCondition::EventType event, \ 114 map<string,string>* event_params); \ 115 SEAction getSEAction(std::string&, \ 116 AmSession* sess, DSMSession* sc_sess, \ 117 DSMCondition::EventType event, \ 118 map<string,string>* event_params); \ 119 }; \ 120 121 #define DEF_ACTION_2P(CL_Name) \ 122 class CL_Name \ 123 : public DSMAction { \ 124 string par1; \ 125 string par2; \ 126 public: \ 127 CL_Name(const string& arg); \ 128 bool execute(AmSession* sess, DSMSession* sc_sess, \ 129 DSMCondition::EventType event, \ 130 map<string,string>* event_params); \ 131 }; \ 132 133 /* bool xsplit(const string& arg, char sep, bool optional, string& par1, string& par2); */ 134 135 #define SPLIT_ARGS(sep, optional) \ 136 size_t p = 0; \ 137 char last_c = ' '; \ 138 bool quot=false; \ 139 char quot_c = ' '; \ 140 bool sep_found = false; \ 141 while (p<arg.size()) { \ 142 if (quot) { \ 143 if (last_c != '\\' && arg[p]==quot_c) \ 144 quot=false; \ 145 } else { \ 146 if (last_c != '\\' && (arg[p]=='\'' || arg[p]=='\"')) { \ 147 quot = true; \ 148 quot_c = arg[p]; \ 149 } else { \ 150 if (arg[p] == sep) { \ 151 sep_found = true; \ 152 break; \ 153 } \ 154 } \ 155 } \ 156 p++; \ 157 last_c = arg[p]; \ 158 } \ 159 \ 160 if ((!optional) && (!sep_found)) { \ 161 ERROR("expected two parameters separated with '%c' in expression '%s' for %s\n", \ 162 sep,arg.c_str(),typeid(this).name()); \ 163 return; \ 164 } \ 165 \ 166 par1 = trim(arg.substr(0,p), " \t"); \ 167 if (sep_found) \ 168 par2 = trim(arg.substr(p+1), " \t"); \ 169 \ 170 if (par1.length() && par1[0]=='\'') { \ 171 par1 = trim(par1, "\'"); \ 172 size_t rpos = 0; \ 173 while ((rpos=par1.find("\\\'")) != string::npos) \ 174 par1.erase(rpos, 1); \ 175 } else if (par1.length() && par1[0]=='\"') { \ 176 par1 = trim(par1, "\""); \ 177 size_t rpos = 0; \ 178 while ((rpos=par1.find("\\\"")) != string::npos) \ 179 par1.erase(rpos, 1); \ 180 } \ 181 \ 182 if (par2.length() && par2[0]=='\'') { \ 183 par2 = trim(par2, "\'"); \ 184 size_t rpos = 0; \ 185 while ((rpos=par2.find("\\\'")) != string::npos) \ 186 par2.erase(rpos, 1); \ 187 } else if (par2.length() && par2[0]=='\"') { \ 188 par2 = trim(par2, "\""); \ 189 size_t rpos = 0; \ 190 while ((rpos=par2.find("\\\"")) != string::npos) \ 191 par2.erase(rpos, 1); \ 192 } \ 193 \ 194 if ((!optional) && ((par1.empty())||(par2.empty()))) { \ 195 ERROR("expected two parameters separated with '%c' in expression '%s' for %s\n", \ 196 sep,arg.c_str(),typeid(this).name()); \ 197 return; \ 198 } 199 200 201 #define CONST_ACTION_2P(CL_name, _sep, _optional) \ 202 CL_name::CL_name(const string& arg) { \ 203 SPLIT_ARGS(_sep, _optional); \ 204 } 205 206 207 #define EXEC_ACTION_START(act_name) \ 208 bool act_name::execute(AmSession* sess, DSMSession* sc_sess, \ 209 DSMCondition::EventType event, \ 210 map<string,string>* event_params) { 211 212 213 #define EXEC_ACTION_END \ 214 return false; \ 215 } 216 217 #define EXEC_ACTION_STOP \ 218 return false; 219 220 string resolveVars(const string s, AmSession* sess, 221 DSMSession* sc_sess, map<string,string>* event_params, 222 bool eval_ops = false); 223 224 void splitCmd(const string& from_str, 225 string& cmd, string& params); 226 227 228 #define DEF_CMD(cmd_name, class_name) \ 229 \ 230 if (cmd == cmd_name) { \ 231 class_name * a = \ 232 new class_name(params); \ 233 a->name = from_str; \ 234 return a; \ 235 } 236 237 #define DEF_SCCondition(cond_name) \ 238 class cond_name \ 239 : public DSMCondition { \ 240 string arg; \ 241 bool inv; \ 242 \ 243 public: \ 244 \ 245 cond_name(const string& arg, bool inv) \ 246 : arg(arg), inv(inv) { } \ 247 bool match(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, \ 248 map<string,string>* event_params); \ 249 }; 250 251 #define DEF_CONDITION_2P(cond_name) \ 252 class cond_name \ 253 : public DSMCondition { \ 254 string par1; \ 255 string par2; \ 256 bool inv; \ 257 public: \ 258 cond_name(const string& arg, bool inv); \ 259 bool match(AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, \ 260 map<string,string>* event_params); \ 261 }; 262 263 #define CONST_CONDITION_2P(cond_name, _sep, _optional) \ 264 cond_name::cond_name(const string& arg, bool inv) \ 265 : inv(inv) { \ 266 SPLIT_ARGS(_sep, _optional); \ 267 } 268 269 #define MATCH_CONDITION_START(cond_clsname) \ 270 bool cond_clsname::match(AmSession* sess, DSMSession* sc_sess, \ 271 DSMCondition::EventType event, \ 272 map<string,string>* event_params) { 273 274 #define MATCH_CONDITION_END } 275 276 #define DECLARE_MODULE(mod_cls_name) \ 277 class mod_cls_name \ 278 : public DSMModule { \ 279 \ 280 public: \ 281 mod_cls_name() { } \ 282 ~mod_cls_name() { } \ 283 \ 284 DSMAction* getAction(const string& from_str); \ 285 DSMCondition* getCondition(const string& from_str); \ 286 }; 287 288 #define DECLARE_MODULE_BEGIN(mod_cls_name) \ 289 class mod_cls_name \ 290 : public DSMModule { \ 291 \ 292 public: \ 293 mod_cls_name() { } \ 294 ~mod_cls_name() { } \ 295 \ 296 DSMAction* getAction(const string& from_str); \ 297 DSMCondition* getCondition(const string& from_str); 298 299 300 301 #define DECLARE_MODULE_END \ 302 } 303 304 #define MOD_ACTIONEXPORT_BEGIN(mod_cls_name) \ 305 DSMAction* mod_cls_name::getAction(const string& from_str) { \ 306 string cmd; \ 307 string params; \ 308 splitCmd(from_str, cmd, params); 309 310 #define MOD_ACTIONEXPORT_END \ 311 return NULL; \ 312 } 313 314 #define MOD_CONDITIONEXPORT_NONE(mod_cls_name) \ 315 DSMCondition* mod_cls_name::getCondition(const string& from_str) { \ 316 return NULL; \ 317 } 318 319 320 #define MOD_CONDITIONEXPORT_BEGIN(mod_cls_name) \ 321 DSMCondition* mod_cls_name::getCondition(const string& from_str) { \ 322 string cmd; \ 323 string params; \ 324 splitCmd(from_str, cmd, params); 325 326 #define MOD_CONDITIONEXPORT_END \ 327 return NULL; \ 328 } \ 329 330 331 #endif 332