mirror of https://github.com/sipwise/sems.git
Development of this module was sponsored by TelTech Systems Inc. The groups module implements a group event broadcast system. DSM calls can join and leave groups, and post events to groups. Events are passed to all members of the group that the event is posted to. Events can, just like the `postEvent` function of DSM, contain either some variables, or all variables. If a call ends, it is automatically removed from all groups it belongs to. Actions: groups.join(groupname) - Join a group groups.leave(groupname) - Leave a group groups.leaveAll() - Leave all groups groups.postEvent(groupname, var1;var2) - post event to groupname with var1 and var2 groups.postEvent(groupname, var) - post event to groupname with all variablessayer/1.4-spce2.6
parent
aee8585091
commit
cad6589d67
@ -0,0 +1,7 @@
|
||||
set (mod_groups_SRCS
|
||||
ModGroups.cpp
|
||||
)
|
||||
|
||||
SET(sems_dsm_module_name mod_groups)
|
||||
INCLUDE(${CMAKE_SOURCE_DIR}/cmake/dsm.lib.rules.txt)
|
||||
|
||||
@ -0,0 +1,10 @@
|
||||
plug_in_name = mod_groups
|
||||
|
||||
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
|
||||
@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stefan Sayer
|
||||
*
|
||||
* Development of this module was sponsored by TelTech Systems Inc
|
||||
*
|
||||
* 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 "ModGroups.h"
|
||||
#include "log.h"
|
||||
#include "AmUtils.h"
|
||||
|
||||
#include "DSMSession.h"
|
||||
#include "AmSession.h"
|
||||
#include "AmSessionContainer.h"
|
||||
|
||||
SC_EXPORT(MOD_CLS_NAME);
|
||||
|
||||
AmMutex GroupsModule::groups_mut;
|
||||
GroupMap GroupsModule::groups;
|
||||
GroupMap GroupsModule::groups_rev;
|
||||
|
||||
|
||||
MOD_ACTIONEXPORT_BEGIN(MOD_CLS_NAME) {
|
||||
|
||||
DEF_CMD("groups.join", GroupsJoinAction);
|
||||
DEF_CMD("groups.leave", GroupsLeaveAction);
|
||||
DEF_CMD("groups.leaveAll", GroupsLeaveAllAction);
|
||||
// DEF_CMD("groups.get", GroupsGetAction);
|
||||
// DEF_CMD("groups.getMembers", GroupsGetMembersAction);
|
||||
DEF_CMD("groups.postEvent", GroupsPostEventAction);
|
||||
|
||||
} MOD_ACTIONEXPORT_END;
|
||||
|
||||
MOD_CONDITIONEXPORT_NONE(MOD_CLS_NAME);
|
||||
|
||||
void GroupsModule::onBeforeDestroy(DSMSession* sc_sess, AmSession* sess) {
|
||||
leave_all_groups(sess->getLocalTag());
|
||||
}
|
||||
|
||||
void GroupsModule::leave_all_groups(const string& ltag) {
|
||||
GroupsModule::groups_mut.lock();
|
||||
|
||||
GroupMap::iterator it = GroupsModule::groups_rev.find(ltag);
|
||||
if (it != GroupsModule::groups_rev.end()) {
|
||||
set<string>& active_groups = it->second;
|
||||
for (set<string>::iterator ag_it =
|
||||
active_groups.begin(); ag_it != active_groups.end(); ag_it++) {
|
||||
GroupsModule::groups[*ag_it].erase(ltag);
|
||||
if (GroupsModule::groups[*ag_it].empty()) {
|
||||
DBG("clearing empty group '%s'\n", ag_it->c_str());
|
||||
GroupsModule::groups.erase(*ag_it);
|
||||
}
|
||||
}
|
||||
GroupsModule::groups_rev.erase(it);
|
||||
}
|
||||
|
||||
GroupsModule::groups_mut.unlock();
|
||||
}
|
||||
|
||||
EXEC_ACTION_START(GroupsJoinAction) {
|
||||
string groupname = resolveVars(arg, sess, sc_sess, event_params);
|
||||
DBG("call '%s' joining group '%s'\n",
|
||||
sess->getLocalTag().c_str(), groupname.c_str());
|
||||
|
||||
GroupsModule::groups_mut.lock();
|
||||
GroupsModule::groups[groupname].insert(sess->getLocalTag());
|
||||
GroupsModule::groups_rev[sess->getLocalTag()].insert(groupname);
|
||||
GroupsModule::groups_mut.unlock();
|
||||
} EXEC_ACTION_END;
|
||||
|
||||
EXEC_ACTION_START(GroupsLeaveAction) {
|
||||
string groupname = resolveVars(arg, sess, sc_sess, event_params);
|
||||
string ltag = sess->getLocalTag();
|
||||
DBG("call '%s' leaving group '%s'\n",
|
||||
ltag.c_str(), groupname.c_str());
|
||||
|
||||
GroupsModule::groups_mut.lock();
|
||||
|
||||
GroupMap::iterator it = GroupsModule::groups.find(groupname);
|
||||
if (it != GroupsModule::groups.end()) {
|
||||
it->second.erase(ltag);
|
||||
if (it->second.empty()) {
|
||||
DBG("clearing empty group '%s'\n", groupname.c_str());
|
||||
GroupsModule::groups.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
it = GroupsModule::groups_rev.find(ltag);
|
||||
if (it != GroupsModule::groups_rev.end()) {
|
||||
it->second.erase(groupname);
|
||||
if (it->second.empty()) {
|
||||
DBG("call '%s' in no group any more\n", ltag.c_str());
|
||||
GroupsModule::groups_rev.erase(it);
|
||||
}
|
||||
}
|
||||
GroupsModule::groups_mut.unlock();
|
||||
} EXEC_ACTION_END;
|
||||
|
||||
EXEC_ACTION_START(GroupsLeaveAllAction) {
|
||||
string ltag = sess->getLocalTag();
|
||||
DBG("call '%s' leaving all groups\n", ltag.c_str());
|
||||
|
||||
GroupsModule::leave_all_groups(ltag);
|
||||
} EXEC_ACTION_END;
|
||||
|
||||
CONST_ACTION_2P(GroupsPostEventAction, ',', true);
|
||||
EXEC_ACTION_START(GroupsPostEventAction) {
|
||||
string groupname = resolveVars(par1, sess, sc_sess, event_params);
|
||||
string var = resolveVars(par2, sess, sc_sess, event_params);
|
||||
map<string, string> ev_params;
|
||||
|
||||
if (!var.empty()) {
|
||||
if (var == "var")
|
||||
ev_params = sc_sess->var;
|
||||
else {
|
||||
vector<string> vars = explode(var, ";");
|
||||
for (vector<string>::iterator it =
|
||||
vars.begin(); it != vars.end(); it++)
|
||||
ev_params[*it] = sc_sess->var[*it];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DBG("posting event to group '%s'\n", groupname.c_str());
|
||||
GroupsModule::groups_mut.unlock();
|
||||
GroupMap::iterator grp = GroupsModule::groups.find(groupname);
|
||||
bool posted = false;
|
||||
if (grp != GroupsModule::groups.end()) {
|
||||
for (set<string>::iterator it =
|
||||
grp->second.begin(); it != grp->second.end(); it++) {
|
||||
if (*it == sess->getLocalTag())
|
||||
continue; // don't post to myself
|
||||
|
||||
DSMEvent* ev = new DSMEvent();
|
||||
ev->params = ev_params;
|
||||
if (!AmSessionContainer::instance()->postEvent(*it, ev)) {
|
||||
DBG("could not post to call '%s'\n", it->c_str());
|
||||
} else {
|
||||
DBG("posted event to call '%s'\n", it->c_str());
|
||||
posted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
GroupsModule::groups_mut.unlock();
|
||||
|
||||
if (posted) {
|
||||
sc_sess->CLR_ERRNO;
|
||||
} else {
|
||||
sc_sess->SET_ERRNO(DSM_ERRNO_UNKNOWN_ARG);
|
||||
sc_sess->SET_STRERROR("event could not be posted\n");
|
||||
}
|
||||
|
||||
} EXEC_ACTION_END;
|
||||
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2010 Stefan Sayer
|
||||
*
|
||||
* Development of this module was sponsored by TelTech Systems Inc
|
||||
*
|
||||
* 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
|
||||
*/
|
||||
#ifndef _MOD_MYSQL_H
|
||||
#define _MOD_MYSQL_H
|
||||
#include "DSMModule.h"
|
||||
#include "DSMSession.h"
|
||||
#include "AmThread.h"
|
||||
|
||||
#define MOD_CLS_NAME GroupsModule
|
||||
|
||||
#include <set>
|
||||
using std::set;
|
||||
#include <map>
|
||||
using std::map;
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
||||
typedef map<string, set<string> > GroupMap;
|
||||
|
||||
DECLARE_MODULE_BEGIN(MOD_CLS_NAME);
|
||||
|
||||
static AmMutex groups_mut;
|
||||
// group name ltags
|
||||
|
||||
static GroupMap groups;
|
||||
// ltags groups
|
||||
static GroupMap groups_rev;
|
||||
|
||||
static void leave_all_groups(const string& ltag);
|
||||
void onBeforeDestroy(DSMSession* sc_sess, AmSession* sess);
|
||||
|
||||
DECLARE_MODULE_END;
|
||||
|
||||
DEF_ACTION_1P(GroupsJoinAction);
|
||||
DEF_ACTION_1P(GroupsLeaveAction);
|
||||
DEF_ACTION_1P(GroupsLeaveAllAction);
|
||||
/* DEF_ACTION_1P(GroupsGetAction); */
|
||||
/* DEF_ACTION_1P(GroupsGetMembersAction); */
|
||||
DEF_ACTION_2P(GroupsPostEventAction);
|
||||
|
||||
#endif
|
||||
@ -0,0 +1,56 @@
|
||||
mod_groups - Group event passing
|
||||
|
||||
Copyright (C) 2010 Stefan Sayer
|
||||
|
||||
Development of this module was sponsored by TelTech Systems Inc
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The groups module implements a group event broadcast system. DSM calls can
|
||||
join and leave groups, and post events to groups. Events are passed to all
|
||||
members of the group that the event is posted to. Events can, just like the
|
||||
`postEvent` function of DSM, contain either some variables, or all variables.
|
||||
If a call ends, it is automatically removed from all groups it belongs to.
|
||||
|
||||
Actions:
|
||||
|
||||
groups.join(groupname) - Join a group
|
||||
groups.leave(groupname) - Leave a group
|
||||
groups.leaveAll() - Leave all groups
|
||||
groups.postEvent(groupname, var1;var2) - post event to groupname with var1 and var2
|
||||
groups.postEvent(groupname, var) - post event to groupname with all variables
|
||||
|
||||
|
||||
Example:
|
||||
import(mod_groups);
|
||||
initial state START
|
||||
enter {
|
||||
groups.join("yeah");
|
||||
repost();
|
||||
};
|
||||
|
||||
transition "in the call" START --> IN_CALL;
|
||||
|
||||
state IN_CALL;
|
||||
|
||||
transition "got key" IN_CALL - key / {
|
||||
set($event="key_press");
|
||||
set($key=#key);
|
||||
set($duration=#duration);
|
||||
set($type=groups);
|
||||
logVars(1);
|
||||
groups.postEvent("yeah", event;key;duration;type);
|
||||
} -> IN_CALL;
|
||||
|
||||
transition "got group event" IN_CALL - event(#type==groups) / {
|
||||
logParams();
|
||||
} -> IN_CALL;
|
||||
|
||||
transition "hangup" IN_CALL - hangup / {
|
||||
-- groups.leave("yeah");
|
||||
groups.leaveAll();
|
||||
stop(false);
|
||||
} -> END;
|
||||
|
||||
state END;
|
||||
Loading…
Reference in new issue