mirror of https://github.com/sipwise/sems.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
623 lines
20 KiB
623 lines
20 KiB
/*
|
|
* Copyright (C) 2008 iptego 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 "ModDlg.h"
|
|
#include "log.h"
|
|
#include "AmUtils.h"
|
|
|
|
#include "DSMSession.h"
|
|
#include "AmSession.h"
|
|
#include "AmB2BSession.h"
|
|
#include <string.h>
|
|
#include "AmSipHeaders.h"
|
|
|
|
#include "AmUAC.h"
|
|
#include "ampi/UACAuthAPI.h"
|
|
|
|
SC_EXPORT(MOD_CLS_NAME);
|
|
|
|
|
|
MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
|
|
|
|
DEF_CMD("dlg.reply", DLGReplyAction);
|
|
DEF_CMD("dlg.replyRequest", DLGReplyRequestAction);
|
|
DEF_CMD("dlg.acceptInvite", DLGAcceptInviteAction);
|
|
DEF_CMD("dlg.bye", DLGByeAction);
|
|
DEF_CMD("dlg.connectCalleeRelayed", DLGConnectCalleeRelayedAction);
|
|
DEF_CMD("dlg.dialout", DLGDialoutAction);
|
|
|
|
DEF_CMD("dlg.getRequestBody", DLGGetRequestBodyAction)
|
|
DEF_CMD("dlg.getReplyBody", DLGGetReplyBodyAction)
|
|
|
|
DEF_CMD("dlg.getOtherId", DLGGetOtherIdAction)
|
|
DEF_CMD("dlg.getRtpRelayMode", DLGGetRtpRelayModeAction)
|
|
|
|
DEF_CMD("dlg.refer", DLGReferAction);
|
|
DEF_CMD("dlg.info", DLGInfoAction);
|
|
DEF_CMD("dlg.relayError", DLGB2BRelayErrorAction);
|
|
|
|
DEF_CMD("dlg.addReplyBodyPart", DLGAddReplyBodyPartAction);
|
|
DEF_CMD("dlg.deleteReplyBodyPart", DLGDeleteReplyBodyPartAction);
|
|
|
|
} MOD_ACTIONEXPORT_END;
|
|
|
|
//MOD_CONDITIONEXPORT_NONE(MOD_CLS_NAME);
|
|
|
|
|
|
MOD_CONDITIONEXPORT_BEGIN(MOD_CLS_NAME) {
|
|
if (cmd == "dlg.replyHasContentType")
|
|
return new DLGReplyHasContentTypeCondition(params, false);
|
|
|
|
if (cmd == "dlg.requestHasContentType")
|
|
return new DLGRequestHasContentTypeCondition(params, false);
|
|
|
|
} MOD_CONDITIONEXPORT_END;
|
|
|
|
bool DLGModule::onInvite(const AmSipRequest& req, DSMSession* sess) {
|
|
// save inivital invite to last_req
|
|
// todo: save this in avar
|
|
sess->last_req.reset(new AmSipRequest(req));
|
|
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,
|
|
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);
|
|
string hdrs = replaceLineEnds(resolveVars("$dlg.reply.hdrs", sess, sc_sess, event_params));
|
|
unsigned int code_i;
|
|
if (str2int(code, code_i)) {
|
|
ERROR("decoding reply code '%s'\n", code.c_str());
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
|
|
return;
|
|
}
|
|
|
|
DBG("replying with %i %s, hdrs='%s'\n", code_i, reason.c_str(), hdrs.c_str());
|
|
|
|
if (sess->dlg->reply(req, code_i, reason, NULL, hdrs)) {
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
|
|
sc_sess->SET_STRERROR("error sending reply");
|
|
} else
|
|
sc_sess->CLR_ERRNO;
|
|
}
|
|
|
|
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");
|
|
return false;
|
|
}
|
|
|
|
replyRequest(sc_sess, sess, event_params, par1, par2, *sc_sess->last_req.get());
|
|
} EXEC_ACTION_END;
|
|
|
|
// todo (?) move replyRequest to core module (?)
|
|
CONST_ACTION_2P(DLGReplyRequestAction, ',', true);
|
|
EXEC_ACTION_START(DLGReplyRequestAction) {
|
|
DSMSipRequest* sip_req;
|
|
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REQUEST);
|
|
if (it == sc_sess->avar.end() ||
|
|
!isArgAObject(it->second) ||
|
|
!(sip_req = dynamic_cast<DSMSipRequest*>(it->second.asObject()))) {
|
|
throw DSMException("dlg", "cause", "no request");
|
|
}
|
|
|
|
replyRequest(sc_sess, sess, event_params, par1, par2, *sip_req->req);
|
|
} EXEC_ACTION_END;
|
|
|
|
CONST_ACTION_2P(DLGAcceptInviteAction, ',', true);
|
|
EXEC_ACTION_START(DLGAcceptInviteAction) {
|
|
// defaults to 200 OK
|
|
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));
|
|
|
|
if (code.length()) {
|
|
reason = resolveVars(par2, sess, sc_sess, event_params);
|
|
if (str2int(code, code_i)) {
|
|
ERROR("decoding reply code '%s'\n", code.c_str());
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
|
|
sc_sess->SET_STRERROR("decoding reply code '"+
|
|
code+"%s'\n");
|
|
return false;
|
|
}
|
|
}
|
|
|
|
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 false;
|
|
}
|
|
|
|
try {
|
|
AmMimeBody sdp_body;
|
|
/* save generated SDP body for this session as `established_body` */
|
|
if(sess->dlg->reply(*sc_sess->last_req.get(),
|
|
code_i,
|
|
reason,
|
|
sdp_body.addPart(SIP_APPLICATION_SDP),
|
|
hdrs,
|
|
SIP_FLAGS_SAVE_ESTB_SDP) != 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;
|
|
|
|
EXEC_ACTION_START(DLGByeAction) {
|
|
string hdrs = resolveVars(arg, sess, sc_sess, event_params);
|
|
|
|
if (sess->dlg->bye(hdrs)) {
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
|
|
sc_sess->SET_STRERROR("Error sending bye");
|
|
} else {
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_OK);
|
|
}
|
|
} EXEC_ACTION_END;
|
|
|
|
|
|
CONST_ACTION_2P(DLGConnectCalleeRelayedAction,',', false);
|
|
EXEC_ACTION_START(DLGConnectCalleeRelayedAction) {
|
|
string remote_party = resolveVars(par1, sess, sc_sess, event_params);
|
|
string remote_uri = resolveVars(par2, sess, sc_sess, event_params);
|
|
|
|
// if (sc_sess->last_req.get()) {
|
|
// sc_sess->B2BaddReceivedRequest(*sc_sess->last_req.get());
|
|
// } else {
|
|
// WARN("internal error: initial INVITE request missing.\n");
|
|
// }
|
|
// AmB2BSession* b2b_sess = dynamic_cast<AmB2BSession*>(sess);
|
|
// if (b2b_sess)
|
|
// b2b_sess->set_sip_relay_only(true);
|
|
// else
|
|
// ERROR("getting B2B session.\n");
|
|
|
|
sc_sess->B2BconnectCallee(remote_party, remote_uri, true);
|
|
} EXEC_ACTION_END;
|
|
|
|
EXEC_ACTION_START(DLGDialoutAction) {
|
|
string arrayname = resolveVars(arg, sess, sc_sess, event_params);
|
|
|
|
#define GET_VARIABLE_MANDATORY(varname_suffix, outvar) \
|
|
it = sc_sess->var.find(arrayname+varname_suffix); \
|
|
if (it == sc_sess->var.end()) { \
|
|
WARN("%s", std::string("need " + arrayname + varname_suffix " set for dlg.dialoutSimple("+arrayname+")").c_str()); \
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); \
|
|
return false; \
|
|
} \
|
|
outvar = it->second;
|
|
|
|
#define GET_VARIABLE_OPTIONAL(varname_suffix, outvar) \
|
|
it = sc_sess->var.find(arrayname+varname_suffix); \
|
|
if (it != sc_sess->var.end()) \
|
|
outvar = it->second;
|
|
|
|
map<string, string>::iterator it;
|
|
|
|
string v_from;
|
|
GET_VARIABLE_MANDATORY("_caller", v_from);
|
|
string v_to;
|
|
GET_VARIABLE_MANDATORY("_callee", v_to);
|
|
string v_domain;
|
|
GET_VARIABLE_MANDATORY("_domain", v_domain);
|
|
string app_name;
|
|
GET_VARIABLE_MANDATORY("_app", app_name);
|
|
|
|
string user = v_from;
|
|
string r_uri = "sip:"+v_to+"@"+v_domain;
|
|
|
|
GET_VARIABLE_OPTIONAL("_r_uri", r_uri);
|
|
|
|
string from = "<sip:"+v_from+"@"+v_domain+">";
|
|
GET_VARIABLE_OPTIONAL("_from", from);
|
|
|
|
string from_uri = "sip:"+v_from+"@"+v_domain;
|
|
GET_VARIABLE_OPTIONAL("_from_uri", from_uri);
|
|
|
|
string to = "<sip:"+v_to+"@"+v_domain+">";
|
|
GET_VARIABLE_OPTIONAL("_to", to);
|
|
|
|
string auth_user;
|
|
GET_VARIABLE_OPTIONAL("_auth_user", auth_user);
|
|
|
|
string auth_pwd;
|
|
GET_VARIABLE_OPTIONAL("_auth_pwd", auth_pwd);
|
|
|
|
string ltag;
|
|
GET_VARIABLE_OPTIONAL("_ltag", ltag);
|
|
|
|
string hdrs;
|
|
GET_VARIABLE_OPTIONAL("_hdrs", hdrs);
|
|
|
|
if (hdrs.length()) {
|
|
size_t crpos;
|
|
while ((crpos=hdrs.find("\\r\\n")) != string::npos) {
|
|
hdrs.replace(crpos, 4, "\r\n");
|
|
}
|
|
}
|
|
|
|
#undef GET_VARIABLE_MANDATORY
|
|
#undef GET_VARIABLE_OPTIONAL
|
|
|
|
DBG("placing UAC call: user <%s>, app <%s>, ruri <%s>, from <%s> "
|
|
"from_uri <%s>, to <%s>, ltag <%s>, hdrs <%s>, auth_user <%s>, auth_pwd <not shown>\n",
|
|
user.c_str(), app_name.c_str(), r_uri.c_str(), from.c_str(),
|
|
from_uri.c_str(), to.c_str(), ltag.c_str(), hdrs.c_str(), auth_user.c_str());
|
|
|
|
AmArg* sess_params = new AmArg();
|
|
bool has_auth = false;
|
|
if (!auth_user.empty() && !auth_pwd.empty()) {
|
|
AmArg auth_param;
|
|
auth_param.setBorrowedPointer(new UACAuthCred("", auth_user,auth_pwd));
|
|
sess_params->push(auth_param);
|
|
has_auth = true;
|
|
}
|
|
AmArg var_struct;
|
|
string varprefix = arrayname+"_var.";
|
|
bool has_vars = false;
|
|
map<string, string>::iterator lb = sc_sess->var.lower_bound(varprefix);
|
|
while (lb != sc_sess->var.end()) {
|
|
if ((lb->first.length() < varprefix.length()) ||
|
|
strncmp(lb->first.c_str(), varprefix.c_str(),varprefix.length()))
|
|
break;
|
|
string varname = lb->first.substr(varprefix.length());
|
|
if (!has_auth) // sess_params is variable struct
|
|
(*sess_params)[std::move(varname)] = lb->second;
|
|
else // variable struct is in sess_params array
|
|
var_struct[std::move(varname)] = lb->second;
|
|
|
|
lb++;
|
|
has_vars = true;
|
|
}
|
|
|
|
if (has_vars && has_auth)
|
|
sess_params->push(var_struct);
|
|
|
|
DBG("sess_params: '%s'\n", AmArg::print(*sess_params).c_str());
|
|
|
|
string new_sess_tag = AmUAC::dialout(user, app_name, r_uri, from, from_uri, to, ltag, hdrs, sess_params);
|
|
|
|
if (!new_sess_tag.empty()) {
|
|
sc_sess->var[arrayname + "_ltag"] = std::move(new_sess_tag);
|
|
} else {
|
|
sc_sess->var[arrayname + "_ltag"] = "";
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL);
|
|
}
|
|
|
|
} EXEC_ACTION_END;
|
|
|
|
MATCH_CONDITION_START(DLGReplyHasContentTypeCondition) {
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REPLY);
|
|
if (it == sc_sess->avar.end()) {
|
|
ERROR("DSM script error: dlg.replyHasContentType condition used for "
|
|
"other event than sipReply event\n");
|
|
return false;
|
|
}
|
|
|
|
DSMSipReply* dsm_reply = NULL;
|
|
if (!isArgAObject(sc_sess->avar[DSM_AVAR_REPLY]) ||
|
|
(NULL ==
|
|
(dsm_reply = dynamic_cast<DSMSipReply*>(sc_sess->avar[DSM_AVAR_REPLY].asObject())))) {
|
|
ERROR("internal: DSM could not get DSMSipReply\n");
|
|
return false;
|
|
}
|
|
|
|
bool res = dsm_reply->reply->body.hasContentType(arg);
|
|
|
|
DBG("checking for content_type '%s': %s\n", arg.c_str(), res?"has it":"doesn't have it");
|
|
return res;
|
|
} MATCH_CONDITION_END;
|
|
|
|
MATCH_CONDITION_START(DLGRequestHasContentTypeCondition) {
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REQUEST);
|
|
if (it == sc_sess->avar.end()) {
|
|
ERROR("DSM script error: dlg.requestHasContentType condition used for "
|
|
"other event than sipRequest event\n");
|
|
return false;
|
|
}
|
|
|
|
DSMSipRequest* dsm_req = NULL;
|
|
if (!isArgAObject(sc_sess->avar[DSM_AVAR_REQUEST]) ||
|
|
(NULL ==
|
|
(dsm_req = dynamic_cast<DSMSipRequest*>(sc_sess->avar[DSM_AVAR_REQUEST].asObject())))) {
|
|
ERROR("internal: DSM could not get DSMSipRequest\n");
|
|
return false;
|
|
}
|
|
|
|
bool res = dsm_req->req->body.hasContentType(arg);
|
|
|
|
DBG("checking for content_type '%s': %s\n", arg.c_str(), res?"has it":"doesn't have it");
|
|
return res;
|
|
} MATCH_CONDITION_END;
|
|
|
|
CONST_ACTION_2P(DLGGetRequestBodyAction, ',', false);
|
|
EXEC_ACTION_START(DLGGetRequestBodyAction) {
|
|
DSMSipRequest* sip_req;
|
|
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REQUEST);
|
|
if (it == sc_sess->avar.end() ||
|
|
!isArgAObject(it->second) ||
|
|
!(sip_req = dynamic_cast<DSMSipRequest*>(it->second.asObject()))) {
|
|
throw DSMException("dlg", "cause", "no request");
|
|
}
|
|
|
|
string content_type = resolveVars(par1, sess, sc_sess, event_params);
|
|
string dstvar = resolveVars(par2, sess, sc_sess, event_params);
|
|
|
|
const AmMimeBody* msg_body = sip_req->req->body.hasContentType(content_type);
|
|
if (NULL == msg_body) {
|
|
DBG("body with content_type %s not found\n", content_type.c_str());
|
|
sc_sess->var.erase(dstvar);
|
|
} else {
|
|
sc_sess->var[dstvar] = msg_body->getPayload();
|
|
DBG("set $%s='%s'\n", dstvar.c_str(), sc_sess->var[dstvar].c_str());
|
|
}
|
|
} EXEC_ACTION_END;
|
|
|
|
CONST_ACTION_2P(DLGGetReplyBodyAction, ',', false);
|
|
EXEC_ACTION_START(DLGGetReplyBodyAction) {
|
|
DSMSipReply* sip_req;
|
|
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REPLY);
|
|
if (it == sc_sess->avar.end() ||
|
|
!isArgAObject(it->second) ||
|
|
!(sip_req = dynamic_cast<DSMSipReply*>(it->second.asObject()))) {
|
|
throw DSMException("dlg", "cause", "no reply");
|
|
}
|
|
|
|
string content_type = resolveVars(par1, sess, sc_sess, event_params);
|
|
string dstvar = resolveVars(par2, sess, sc_sess, event_params);
|
|
|
|
const AmMimeBody* msg_body = sip_req->reply->body.hasContentType(content_type);
|
|
if (NULL == msg_body) {
|
|
DBG("body with content_type %s not found\n", content_type.c_str());
|
|
sc_sess->var.erase(dstvar);
|
|
} else {
|
|
sc_sess->var[dstvar] = msg_body->getPayload();
|
|
DBG("set $%s='%s'\n", dstvar.c_str(), sc_sess->var[dstvar].c_str());
|
|
}
|
|
} EXEC_ACTION_END;
|
|
|
|
EXEC_ACTION_START(DLGGetOtherIdAction) {
|
|
string varname = arg;
|
|
AmB2BSession* b2b_sess = dynamic_cast<AmB2BSession*>(sess);
|
|
if (NULL == b2b_sess) {
|
|
DBG("script writer error: dlg.getOtherId used without B2B session object.\n");
|
|
EXEC_ACTION_STOP;
|
|
}
|
|
|
|
if (varname.size() && varname[0] == '$')
|
|
varname.erase(0, 1);
|
|
sc_sess->var[varname] = b2b_sess->getOtherId();
|
|
} EXEC_ACTION_END;
|
|
|
|
EXEC_ACTION_START(DLGGetRtpRelayModeAction) {
|
|
string varname = arg;
|
|
AmB2BSession* b2b_sess = dynamic_cast<AmB2BSession*>(sess);
|
|
if (NULL == b2b_sess) {
|
|
DBG("script writer error: dlg.getOtherId used without B2B session object.\n");
|
|
EXEC_ACTION_STOP;
|
|
}
|
|
|
|
if (varname.size() && varname[0] == '$')
|
|
varname.erase(0, 1);
|
|
switch (b2b_sess->getRtpRelayMode()) {
|
|
case AmB2BSession::RTP_Direct: sc_sess->var[varname] = "RTP_Direct"; break;
|
|
case AmB2BSession::RTP_Relay: sc_sess->var[varname] = "RTP_Relay"; break;
|
|
case AmB2BSession::RTP_Transcoding: sc_sess->var[varname] = "RTP_Transcoding"; break;
|
|
default: sc_sess->var[varname] = "Unknown"; break;
|
|
}
|
|
|
|
DBG("get RTP relay mode: %s='%s'\n", varname.c_str(), sc_sess->var[varname].c_str());
|
|
} EXEC_ACTION_END;
|
|
|
|
CONST_ACTION_2P(DLGReferAction, ',', true);
|
|
EXEC_ACTION_START(DLGReferAction) {
|
|
|
|
AmSession* b2b_sess = dynamic_cast<AmSession*>(sess);
|
|
if (NULL == b2b_sess) {
|
|
throw DSMException("sbc", "type", "param", "cause",
|
|
"dlg.refer used on non-session");
|
|
}
|
|
|
|
string refer_to = resolveVars(par1, sess, sc_sess, event_params);
|
|
string expires_s = resolveVars(par2, sess, sc_sess, event_params);
|
|
|
|
int expires = -1;
|
|
if (!expires_s.empty()) {
|
|
if (!str2int(expires_s, expires)) {
|
|
throw DSMException("sbc", "type", "param", "cause",
|
|
"expires "+expires_s+" not valid");
|
|
}
|
|
}
|
|
|
|
if (NULL == b2b_sess->dlg) {
|
|
throw DSMException("sbc", "type", "param", "cause",
|
|
"call doesn't have SIP dialog (OOPS!)");
|
|
}
|
|
|
|
if (b2b_sess->dlg->refer(refer_to, expires)) {
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_DLG);
|
|
sc_sess->SET_STRERROR("sending REFER failed");
|
|
} else {
|
|
sc_sess->CLR_ERRNO;
|
|
}
|
|
} EXEC_ACTION_END;
|
|
|
|
CONST_ACTION_2P(DLGInfoAction, ',', true);
|
|
EXEC_ACTION_START(DLGInfoAction) {
|
|
|
|
AmSession* b2b_sess = dynamic_cast<AmSession*>(sess);
|
|
if (NULL == b2b_sess) {
|
|
throw DSMException("sbc", "type", "param", "cause",
|
|
"dlg.info used on non-session");
|
|
}
|
|
|
|
string content_type = resolveVars(par1, sess, sc_sess, event_params);
|
|
string body_str = resolveVars(par2, sess, sc_sess, event_params);
|
|
|
|
if (NULL == b2b_sess->dlg) {
|
|
throw DSMException("sbc", "type", "param", "cause",
|
|
"call doesn't have SIP dialog (OOPS!)");
|
|
}
|
|
|
|
string body_crlf = std::move(body_str);
|
|
AmMimeBody *body = new AmMimeBody();
|
|
if (!content_type.empty()) {
|
|
DBG("body_crlf is '%s'\n", body_crlf.c_str());
|
|
while (true) {
|
|
size_t p = body_crlf.find("\\r\\n");
|
|
if (p==string::npos)
|
|
break;
|
|
body_crlf.replace(p, 4, "\r\n");
|
|
}
|
|
DBG("-> body_crlf is '%s'\n", body_crlf.c_str());
|
|
if (body->parse(content_type,
|
|
body_crlf.c_str(),
|
|
body_crlf.length())) {
|
|
throw DSMException("sbc", "type", "param", "cause",
|
|
"parsing of INFO body failed");
|
|
}
|
|
}
|
|
|
|
if (b2b_sess->dlg->info("", body)) {
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_DLG);
|
|
sc_sess->SET_STRERROR("sending INFO failed");
|
|
} else {
|
|
sc_sess->CLR_ERRNO;
|
|
}
|
|
|
|
} EXEC_ACTION_END;
|
|
|
|
#define GET_B2B_SESSION(action) \
|
|
AmB2BSession* b2b_sess = dynamic_cast<AmB2BSession*>(sess); \
|
|
if (NULL == b2b_sess) { \
|
|
throw DSMException("sbc", "type", "param", "cause", \
|
|
#action " used on non-b2b-session"); \
|
|
}
|
|
|
|
CONST_ACTION_2P(DLGB2BRelayErrorAction, ',', false);
|
|
EXEC_ACTION_START(DLGB2BRelayErrorAction) {
|
|
DSMSipRequest* sip_req;
|
|
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REQUEST);
|
|
if (it == sc_sess->avar.end() ||
|
|
!isArgAObject(it->second) ||
|
|
!(sip_req = dynamic_cast<DSMSipRequest*>(it->second.asObject()))) {
|
|
throw DSMException("dlg", "cause", "no request");
|
|
}
|
|
GET_B2B_SESSION(dlg.refer);
|
|
|
|
string code = resolveVars(par1, sess, sc_sess, event_params);
|
|
string reason = resolveVars(par2, sess, sc_sess, event_params);
|
|
unsigned int code_i;
|
|
if (str2int(code, code_i)) {
|
|
ERROR("decoding reply code '%s'\n", code.c_str());
|
|
sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
|
|
EXEC_ACTION_STOP;
|
|
}
|
|
|
|
b2b_sess->relayError(sip_req->req->method, sip_req->req->cseq, true, code_i, reason.c_str());
|
|
} EXEC_ACTION_END;
|
|
|
|
CONST_ACTION_2P(DLGAddReplyBodyPartAction, ',', false);
|
|
EXEC_ACTION_START(DLGAddReplyBodyPartAction) {
|
|
DSMMutableSipReply* sip_reply;
|
|
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REPLY);
|
|
if (it == sc_sess->avar.end() ||
|
|
!isArgAObject(it->second) ||
|
|
!(sip_reply = dynamic_cast<DSMMutableSipReply*>(it->second.asObject()))) {
|
|
throw DSMException("dlg", "cause", "no reply");
|
|
}
|
|
|
|
string content_type = resolveVars(par1, sess, sc_sess, event_params);
|
|
string body_part = resolveVars(par2, sess, sc_sess, event_params);
|
|
|
|
AmMimeBody* new_part;
|
|
|
|
new_part = sip_reply->mutable_reply->body.addPart(content_type);
|
|
new_part->setPayload(body_part.c_str(),
|
|
body_part.length());
|
|
DBG("added to reply body part %s='%s'\n",
|
|
content_type.c_str(), body_part.c_str());
|
|
} EXEC_ACTION_END;
|
|
|
|
EXEC_ACTION_START(DLGDeleteReplyBodyPartAction) {
|
|
DSMMutableSipReply* sip_reply;
|
|
|
|
AVarMapT::iterator it = sc_sess->avar.find(DSM_AVAR_REPLY);
|
|
if (it == sc_sess->avar.end() ||
|
|
!isArgAObject(it->second) ||
|
|
!(sip_reply = dynamic_cast<DSMMutableSipReply*>(it->second.asObject()))) {
|
|
throw DSMException("dlg", "cause", "no reply");
|
|
}
|
|
|
|
if (sip_reply->mutable_reply->body.deletePart(arg)) {
|
|
DBG("failed to delete reply body part '%s'\n", arg.c_str());
|
|
} else {
|
|
DBG("deleted reply body part '%s'\n", arg.c_str());
|
|
}
|
|
} EXEC_ACTION_END;
|