diff --git a/apps/dsm/mods/mod_dlg/Makefile b/apps/dsm/mods/mod_dlg/Makefile new file mode 100644 index 00000000..aa8beb04 --- /dev/null +++ b/apps/dsm/mods/mod_dlg/Makefile @@ -0,0 +1,18 @@ +plug_in_name = mod_dlg + +DSMPATH ?= ../.. + +module_ldflags = +module_cflags = -DMOD_NAME=\"$(plug_in_name)\" -I$(DSMPATH) + +COREPATH ?=$(DSMPATH)/../../core +lib_full_name = $(DSMPATH)/mods/lib/$(lib_name) +include $(COREPATH)/plug-in/Makefile.app_module + +.PHONY: install +install: all $(extra_install) + mkdir -p $(lib-prefix)/$(lib-dir)/dsm + if [ -f "$(lib_name)" ]; then \ + $(INSTALL-TOUCH) $(lib-prefix)/$(lib-dir)/dsm/; \ + $(INSTALL-MODULES) $(lib_name) $(lib-prefix)/$(lib-dir)/dsm/; \ + fi diff --git a/apps/dsm/mods/mod_dlg/ModDlg.cpp b/apps/dsm/mods/mod_dlg/ModDlg.cpp new file mode 100644 index 00000000..1c02077a --- /dev/null +++ b/apps/dsm/mods/mod_dlg/ModDlg.cpp @@ -0,0 +1,166 @@ +/* + * $Id$ + * + * 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 + * + * 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 + +#include "DSMCoreModule.h" + +SC_EXPORT(DLGModule); + +DLGModule::DLGModule() { +} + +DLGModule::~DLGModule() { +} + +void splitCmd(const string& from_str, + string& cmd, string& params) { + size_t b_pos = from_str.find('('); + if (b_pos != string::npos) { + cmd = from_str.substr(0, b_pos); + params = from_str.substr(b_pos + 1, from_str.rfind(')') - b_pos -1); + } else + cmd = from_str; +} + +DSMAction* DLGModule::getAction(const string& from_str) { + string cmd; + string params; + splitCmd(from_str, cmd, params); + +#define DEF_CMD(cmd_name, class_name) \ + \ + if (cmd == cmd_name) { \ + class_name * a = \ + new class_name(params); \ + a->name = from_str; \ + return a; \ + } + + DEF_CMD("dlg.reply", DLGReplyAction); + DEF_CMD("dlg.acceptInvite", DLGAcceptInviteAction); + + return NULL; +} + +DSMCondition* DLGModule::getCondition(const string& from_str) { + return NULL; +} + +bool DLGModule::onInvite(const AmSipRequest& req, DSMSession* sess) { + // save inivital invite to last_req + sess->last_req.reset(new AmSipRequest(req)); + return true; +} + +#define GET_SCSESSION() \ + DSMSession* sc_sess = dynamic_cast(sess); \ + if (!sc_sess) { \ + ERROR("wrong session type\n"); \ + return false; \ + } + +CONST_TwoParAction(DLGReplyAction, ",", true); + +bool DLGReplyAction::execute(AmSession* sess, + DSMCondition::EventType event, + map* event_params) { + GET_SCSESSION(); + + 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 false; + } + + if (!sc_sess->last_req.get()) { + ERROR("no last request to reply\n"); + sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); + return false; + } + + if (sess->dlg.reply(*sc_sess->last_req.get(), code_i, reason)) + sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); + else + sc_sess->SET_ERRNO(DSM_ERRNO_OK); + + return false; +} + +CONST_TwoParAction(DLGAcceptInviteAction, ",", true); + +bool DLGAcceptInviteAction::execute(AmSession* sess, + DSMCondition::EventType event, + map* event_params) { + GET_SCSESSION(); + + // defaults to 200 OK + unsigned int code_i=200; + string reason = "OK"; + string code = resolveVars(par1, sess, sc_sess, event_params); + DBG("GOT CODE %s\n", code.c_str()); + if (code.length()) { + reason = resolveVars(par2, sess, sc_sess, event_params); + if (str2i(code, code_i)) { + ERROR("decoding reply code '%s'\n", code.c_str()); + sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG); + return false; + } + } + + if (!sc_sess->last_req.get()) { + ERROR("no last request to reply\n"); + sc_sess->SET_ERRNO(DSM_ERRNO_GENERAL); + return false; + } + + try { + string sdp_reply; + + 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) != 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(); + AmSipDialog::reply_error(*sc_sess->last_req.get(),e.code,e.reason); + } + + return false; +} diff --git a/apps/dsm/mods/mod_dlg/ModDlg.h b/apps/dsm/mods/mod_dlg/ModDlg.h new file mode 100644 index 00000000..211ae8f2 --- /dev/null +++ b/apps/dsm/mods/mod_dlg/ModDlg.h @@ -0,0 +1,46 @@ +/* + * $Id$ + * + * 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 + * + * 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_DLG_H +#define _MOD_DLG_H +#include "DSMModule.h" + +class DLGModule +: public DSMModule { + + public: + DLGModule(); + ~DLGModule(); + + DSMAction* getAction(const string& from_str); + DSMCondition* getCondition(const string& from_str); + + bool onInvite(const AmSipRequest& req, DSMSession* sess); +}; + +DEF_TwoParAction(DLGReplyAction); +DEF_TwoParAction(DLGAcceptInviteAction); +#endif diff --git a/apps/dsm/mods/mod_dlg/Readme.mod_uri.txt b/apps/dsm/mods/mod_dlg/Readme.mod_uri.txt new file mode 100644 index 00000000..b523b2cb --- /dev/null +++ b/apps/dsm/mods/mod_dlg/Readme.mod_uri.txt @@ -0,0 +1,13 @@ +* mod_dlg saves the initial INVITE to DSMSession::last_req + + +dlg.reply(code,reason); + reply to the request in DSMSession::last_req + (usually INVITE, if not yet replied) with code and reason + +dlg.acceptInvite([code, reason]); + e.g. dlg.acceptInvite(183, progress); + + accept audio stream from last_req (INVITE), and reply with 200 OK (default) + or code, reason +