// todo: convert errors to exceptions void replyRequest(DSMSession* sc_sess, AmSession* sess, EventParamT* event_params, const string& par1, const string& par2, const AmSipRequest& req) { string code = resolveVars(par1, sess, sc_sess, event_params); string reason = resolveVars(par2, sess, sc_sess, event_params); unsigned int code_i; if (str2i(code, code_i)) { ERROR("decoding reply code '%s'\n", code.c_str()); sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); return; } 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)) { sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); sc_sess->SET_STRERROR("error sending reply"); } else sc_sess->CLR_ERRNO; }
bool TestDSMCondition::match(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { if (ttype == None || (type != DSMCondition::Any && type != event)) return false; if (ttype == Always) return true; DSMSession* sc_sess = dynamic_cast<DSMSession*>(sess); if (!sc_sess) { ERROR("wrong session type\n"); return false; } string l; string r; if (lhs.length() > 5 && (lhs.substr(0, 4) == "len(") && lhs[lhs.length()-1] == ')') { l = int2str(resolveVars(lhs.substr(4, lhs.length()-5), sess, sc_sess, event_params).length()); } else { l = resolveVars(lhs, sess, sc_sess, event_params); } if (rhs.length() > 5 && rhs.substr(0, 4) == "len(" && rhs[rhs.length()-1] == ')') { r = resolveVars(rhs.substr(4, rhs.length()-5), sess, sc_sess, event_params).length(); } else { r = resolveVars(rhs, sess, sc_sess, event_params); } // string r = resolveVars(rhs, sess, sc_sess, event_params); DBG("test '%s' vs '%s'\n", l.c_str(), r.c_str()); switch (ttype) { case Eq: return l == r; case Neq: return l != r; case Less: { char* endptr = NULL; long l_i = strtol(l.c_str(), &endptr, 10); if (endptr && *endptr == '\0') { long r_i = strtol(r.c_str(), &endptr, 10); if (endptr && *endptr == '\0') return l_i < r_i; } return l < r; } case Gt: { char* endptr = NULL; long l_i = strtol(l.c_str(), &endptr, 10); if (endptr && *endptr == '\0') { long r_i = strtol(r.c_str(), &endptr, 10); if (endptr && *endptr == '\0') return l_i > r_i; } return l > r; } default: return false; } }
bool MonLogAddAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); string prop = resolveVars(par1, sess, sc_sess, event_params); string val = resolveVars(par2, sess, sc_sess, event_params); MONITORING_LOG_ADD(sess->getLocalTag().c_str(), prop.c_str(), val.c_str()); return false; }
bool SCPlayFileAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); bool loop = resolveVars(par2, sess, sc_sess, event_params) == "true"; DBG("par1 = '%s', par2 = %s\n", par1.c_str(), par2.c_str()); sc_sess->playFile(resolveVars(par1, sess, sc_sess, event_params), loop); return false; }
bool SCLogAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); unsigned int lvl; if (str2i(resolveVars(par1, sess, sc_sess, event_params), lvl)) { ERROR("unknown log level '%s'\n", par1.c_str()); return false; } string l_line = resolveVars(par2, sess, sc_sess, event_params).c_str(); _LOG((int)lvl, "FSM: %s %s\n", (par2 != l_line)?par2.c_str():"", l_line.c_str()); return false; }
DSMAction::SEAction SCCallFSMAction::getSEAction(string& param, AmSession* sess, DSMSession* sc_sess, DSMCondition::EventType event, map<string,string>* event_params) { param = resolveVars(arg, sess, sc_sess, event_params); return Call; }
bool SCRecordFileAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); sc_sess->recordFile(resolveVars(arg, sess, sc_sess, event_params)); return false; }
string replaceParams(const string& q, AmSession* sess, DSMSession* sc_sess, map<string,string>* event_params) { string res = q; size_t repl_pos = 0; while (repl_pos<res.length()) { size_t rstart = res.find_first_of("$#@", repl_pos); repl_pos = rstart+1; if (rstart == string::npos) break; if (rstart && res[rstart-1] == '\\') // escaped continue; size_t rend; if (res.length() > rstart+1 && (res[rstart+1] == '(' || res[rstart+1] == '"' || res[rstart+1] == '\'' )) rend = res.find_first_of(" ,()[]$#@\t;:'\"", rstart+2); else rend = res.find_first_of(" ,()[]$#@\t;:'\"", rstart+1); if (rend==string::npos) rend = res.length(); string keyname = res.substr(rstart+1, rend-rstart-1); if (keyname.length()>2) { if ((keyname[0] == '(' && res[rend] == ')') || (keyname[0] == res[rend] && (keyname[0] == '"' ||keyname[0] == '\''))) { keyname = keyname.substr(1); if (rend != res.length()) rend++; } } // todo: simply use resolveVars (?) switch(res[rstart]) { case '$': { if (sc_sess->var.find(keyname) == sc_sess->var.end()) res.erase(rstart, rend-rstart); else res.replace(rstart, rend-rstart, sc_sess->var[keyname]); } break; case '#': if (NULL!=event_params) { if (event_params->find(keyname) != event_params->end()) res.replace(rstart, rend-rstart, (*event_params)[keyname]); else res.erase(rstart, rend-rstart); } break; case '@': { // todo: optimize res.replace(rstart, rend-rstart, resolveVars("@"+keyname, sess, sc_sess, event_params)); } break; default: break; } } return res; }
bool SCClosePlaylistAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); bool notify = resolveVars(arg, sess, sc_sess, event_params) == "true"; sc_sess->closePlaylist(notify); return false; }
bool SCStopAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); if (resolveVars(arg, sess, sc_sess, event_params) == "true") { DBG("sending bye\n"); sess->dlg.bye(); } sess->setStopped(); return false; }
bool SCSetAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); string var_name = (par1.length() && par1[0] == '$')? par1.substr(1) : par1; sc_sess->var[var_name] = resolveVars(par2, sess, sc_sess, event_params); DBG("set variable '%s'='%s'\n", var_name.c_str(), sc_sess->var[var_name].c_str()); return false; }
bool SCSetTimerAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); unsigned int timerid; if (str2i(resolveVars(par1, sess, sc_sess, event_params), timerid)) { ERROR("timer id '%s' not decipherable\n", resolveVars(par1, sess, sc_sess, event_params).c_str()); return false; } unsigned int timeout; if (str2i(resolveVars(par2, sess, sc_sess, event_params), timeout)) { ERROR("timeout value '%s' not decipherable\n", resolveVars(par2, sess, sc_sess, event_params).c_str()); return false; } DBG("setting timer %u with timeout %u\n", timerid, timeout); AmDynInvokeFactory* user_timer_fact = AmPlugIn::instance()->getFactory4Di("user_timer"); if(!user_timer_fact) { ERROR("load sess_timer module for timers.\n"); return false; } AmDynInvoke* user_timer = user_timer_fact->getInstance(); if(!user_timer) { ERROR("load sess_timer module for timers.\n"); return false; } AmArg di_args,ret; di_args.push((int)timerid); di_args.push((int)timeout); // in seconds di_args.push(sess->getLocalTag().c_str()); user_timer->invoke("setTimer", di_args, ret); return false; }
void log_vars(const string& l_arg, AmSession* sess, DSMSession* sc_sess, map<string,string>* event_params) { unsigned int lvl; if (str2i(resolveVars(l_arg, sess, sc_sess, event_params), lvl)) { ERROR("unknown log level '%s'\n", l_arg.c_str()); return; } _LOG((int)lvl, "FSM: variables set ---\n"); for (map<string, string>::iterator it = sc_sess->var.begin(); it != sc_sess->var.end(); it++) { _LOG((int)lvl, "FSM: $%s='%s'\n", it->first.c_str(), it->second.c_str()); } _LOG((int)lvl, "FSM: variables end ---\n"); }
void log_selects(const string& l_arg, AmSession* sess, DSMSession* sc_sess, map<string,string>* event_params) { unsigned int lvl; if (str2i(resolveVars(l_arg, sess, sc_sess, event_params), lvl)) { ERROR("unknown log level '%s'\n", l_arg.c_str()); return; } _LOG((int)lvl, "FSM: selects set ---\n"); #define SELECT_LOG(select_name) \ _LOG((int)lvl, "FSM: @%s='%s'\n", select_name, \ resolveVars("@" select_name, sess, sc_sess, event_params).c_str()); SELECT_LOG("local_tag"); SELECT_LOG("user"); SELECT_LOG("domain"); SELECT_LOG("remote_tag"); SELECT_LOG("callid"); SELECT_LOG("local_uri"); SELECT_LOG("remote_uri"); #undef SELECT_LOG _LOG((int)lvl, "FSM: selects end ---\n"); }
string resolveVars(const string ts, AmSession* sess, DSMSession* sc_sess, map<string,string>* event_params, bool eval_ops) { string s = ts; if (s.length()) { if(eval_ops) { // remove all spaces string::size_type p; for (p = s.find (" ", 0 ); p != string::npos; p = s.find(" ", p)) { s.erase (p, 1); } // evaluate operators string a,b; if((p = s.find("-")) != string::npos) { a = resolveVars(s.substr(0, p), sess, sc_sess, event_params, true); b = resolveVars(s.substr(p+1, string::npos), sess, sc_sess, event_params, true); if(isNumber(a) && isNumber(b)) { std::stringstream res; res << atoi(a.c_str()) - atoi(b.c_str()); return res.str(); } } else if((p = s.find("+")) != string::npos) { a = resolveVars(s.substr(0, p), sess, sc_sess, event_params, true); b = resolveVars(s.substr(p+1, string::npos), sess, sc_sess, event_params, true); if(isNumber(a) && isNumber(b)) { std::stringstream res; res << atoi(a.c_str()) + atoi(b.c_str()); return res.str(); } } } switch(s[0]) { case '$': { if (s.substr(1, 1)=="$") return "$"; map<string, string>::iterator it = sc_sess->var.find(s.substr(1)); if (it != sc_sess->var.end()) return it->second; return ""; } case '#': if (s.substr(1, 1)=="#") return "#"; if (event_params) { map<string, string>::iterator it = event_params->find(s.substr(1)); if (it != event_params->end()) return it->second; return ""; }else return string(); case '@': { if (s.substr(1, 1)=="@") return "@"; if (s.length() < 2) return "@"; string s1 = s.substr(1); if (s1 == "local_tag") return sess->getLocalTag(); else if (s1 == "user") return sess->dlg->getUser(); else if (s1 == "domain") return sess->dlg->getDomain(); else if (s1 == "remote_tag") return sess->getRemoteTag(); else if (s1 == "callid") return sess->getCallID(); else if (s1 == "local_uri") return sess->dlg->getLocalUri(); else if (s1 == "local_party") return sess->dlg->getLocalParty(); else if (s1 == "remote_uri") return sess->dlg->getRemoteUri(); else if (s1 == "remote_party") return sess->dlg->getRemoteParty(); else return string(); } default: return trim(s, "\""); } } return s; }
bool SCDIAction::execute(AmSession* sess, DSMCondition::EventType event, map<string,string>* event_params) { GET_SCSESSION(); if (params.size() < 2) { ERROR("DI needs at least: mod_name, " "function_name (in '%s'\n", name.c_str()); return false; } vector<string>::iterator p_it=params.begin(); string fact_name = trim(*p_it, " \""); AmDynInvokeFactory* fact = AmPlugIn::instance()->getFactory4Di(fact_name); if(!fact) { ERROR("load module for factory '%s'.\n", fact_name.c_str()); return false; } AmDynInvoke* di_inst = fact->getInstance(); if(!di_inst) { ERROR("load module for factory '%s'\n", fact_name.c_str()); return false; } p_it++; string func_name = trim(*p_it, " \""); p_it++; AmArg di_args; while (p_it != params.end()) { string p = trim(*p_it, " \t"); if (p.length() && p[0] == '"') { di_args.push(trim(p,"\"").c_str()); } else if (p.length() > 5 && p.substr(0, 5) =="(int)") { p = resolveVars(p.substr(5), sess, sc_sess, event_params); char* endptr = NULL; long p_i = strtol(p.c_str(), &endptr, 10); if (endptr && *endptr == '\0') { di_args.push((int)p_i); } else { ERROR("converting value '%s' to int\n", p.c_str()); return false; } } else { di_args.push(resolveVars(p, sess, sc_sess, event_params).c_str()); } p_it++; } sc_sess->di_res.clear(); DBG("executing DI function '%s'\n", func_name.c_str()); try { di_inst->invoke(func_name, di_args, sc_sess->di_res); } catch (const AmDynInvoke::NotImplemented& ni) { ERROR("not implemented DI function '%s'\n", ni.what.c_str()); return false; } catch (const AmArg::OutOfBoundsException& oob) { ERROR("out of bounds in DI call '%s'\n", name.c_str()); return false; } catch (const AmArg::TypeMismatchException& oob) { ERROR("type mismatch in DI call '%s'\n", name.c_str()); return false; } catch (...) { ERROR("unexpected Exception in DI call '%s'\n", name.c_str()); return false; } if (get_res) { // rudimentary variables conversion... if (isArgCStr(sc_sess->di_res)) sc_sess->var["DI_res"] = sc_sess->di_res.asCStr(); else if (isArgInt(sc_sess->di_res)) sc_sess->var["DI_res"] = int2str(sc_sess->di_res.asInt()); else if (isArgArray(sc_sess->di_res)) { // copy results to $DI_res0..$DI_resn for (size_t i=0;i<sc_sess->di_res.size();i++) { switch (sc_sess->di_res.get(i).getType()) { case AmArg::CStr: { sc_sess->var["DI_res"+int2str(i)] = sc_sess->di_res.get(i).asCStr(); } break; case AmArg::Int: { sc_sess->var["DI_res"+int2str(i)] = int2str(sc_sess->di_res.get(i).asInt()); } break; default: { ERROR("unsupported AmArg return type!"); } } } } else { ERROR("unsupported AmArg return type!"); } } return false; }