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.
227 lines
6.4 KiB
227 lines
6.4 KiB
/*
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2009 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 "ModPy.h"
|
|
#include "log.h"
|
|
#include "AmUtils.h"
|
|
|
|
#include "DSMSession.h"
|
|
#include "AmSession.h"
|
|
#include "PyDSMSession.h"
|
|
#include "PyDSM.h"
|
|
|
|
struct PythonGIL
|
|
{
|
|
PyGILState_STATE gst;
|
|
|
|
PythonGIL() { gst = PyGILState_Ensure(); }
|
|
~PythonGIL(){ PyGILState_Release(gst); }
|
|
};
|
|
#define PYLOCK PythonGIL _py_gil
|
|
|
|
SC_EXPORT(SCPyModule);
|
|
|
|
PyObject* SCPyModule::dsm_module = NULL;
|
|
PyObject* SCPyModule::session_module = NULL;
|
|
|
|
SCPyModule::SCPyModule() {
|
|
|
|
}
|
|
|
|
SCPyModule::~SCPyModule() {
|
|
}
|
|
|
|
int SCPyModule::preload() {
|
|
if(!Py_IsInitialized()){
|
|
Py_Initialize();
|
|
DBG("Python version %s\n", Py_GetVersion());
|
|
}
|
|
|
|
PyEval_InitThreads();
|
|
|
|
PyImport_AddModule("dsm");
|
|
dsm_module = Py_InitModule("dsm",mod_py_methods);
|
|
PyModule_AddIntConstant(dsm_module, "Any", DSMCondition::Any);
|
|
PyModule_AddIntConstant(dsm_module, "Invite", DSMCondition::Invite);
|
|
PyModule_AddIntConstant(dsm_module, "SessionStart", DSMCondition::SessionStart);
|
|
PyModule_AddIntConstant(dsm_module, "Key", DSMCondition::Key);
|
|
PyModule_AddIntConstant(dsm_module, "Timer", DSMCondition::Timer);
|
|
PyModule_AddIntConstant(dsm_module, "NoAudio", DSMCondition::NoAudio);
|
|
PyModule_AddIntConstant(dsm_module, "Hangup", DSMCondition::Hangup);
|
|
PyModule_AddIntConstant(dsm_module, "Hold", DSMCondition::Hold); PyModule_AddIntConstant(dsm_module, "UnHold", DSMCondition::UnHold);
|
|
PyModule_AddIntConstant(dsm_module, "XmlrpcResponse", DSMCondition::XmlrpcResponse);
|
|
PyModule_AddIntConstant(dsm_module, "DSMEvent", DSMCondition::DSMEvent);
|
|
PyModule_AddIntConstant(dsm_module, "PlaylistSeparator", DSMCondition::PlaylistSeparator);
|
|
PyModule_AddIntConstant(dsm_module, "B2BOtherReply", DSMCondition::B2BOtherReply);
|
|
PyModule_AddIntConstant(dsm_module, "B2BOtherBye", DSMCondition::B2BOtherBye);
|
|
|
|
PyImport_AddModule("session");
|
|
session_module = Py_InitModule("session",session_methods);
|
|
|
|
PyEval_ReleaseLock();
|
|
return 0;
|
|
}
|
|
|
|
DSMAction* SCPyModule::getAction(const string& from_str) {
|
|
string cmd;
|
|
string params;
|
|
splitCmd(from_str, cmd, params);
|
|
|
|
if (NULL==dsm_module) {
|
|
ERROR("mod_py must be preloaded! add preload=mod_py to dsm.conf\n");
|
|
return NULL;
|
|
}
|
|
|
|
try {
|
|
DEF_CMD("py", SCPyPyAction);
|
|
} catch (const string& err) {
|
|
ERROR("creating py() action\n");
|
|
return NULL;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
DSMCondition* SCPyModule::getCondition(const string& from_str) {
|
|
string cmd;
|
|
string params;
|
|
splitCmd(from_str, cmd, params);
|
|
|
|
if (NULL==dsm_module) {
|
|
ERROR("mod_py must be preloaded! add preload=mod_py to dsm.conf\n");
|
|
return NULL;
|
|
}
|
|
|
|
if (cmd == "py") {
|
|
try {
|
|
return new PyPyCondition(params);
|
|
} catch (const string& err) {
|
|
ERROR("creating py() condition\n");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
bool py_execute(PyCodeObject* py_func, DSMSession* sc_sess,
|
|
DSMCondition::EventType event, map<string,string>* event_params,
|
|
bool expect_int_result) {
|
|
// acquire the GIL
|
|
PYLOCK;
|
|
|
|
bool py_res = false;
|
|
|
|
PyObject* m = PyImport_AddModule("__main__");
|
|
if (m == NULL) {
|
|
ERROR("getting main module\n");
|
|
return false;
|
|
}
|
|
PyObject*d = PyModule_GetDict(m);
|
|
|
|
PyObject* locals = PyDict_New();
|
|
PyDict_SetItem(locals, PyString_FromString("dsm"), SCPyModule::dsm_module);
|
|
PyDict_SetItem(locals, PyString_FromString("session"), SCPyModule::session_module);
|
|
|
|
PyObject* params = PyDict_New();
|
|
if (NULL != event_params) {
|
|
for (map<string,string>::iterator it=event_params->begin();
|
|
it != event_params->end(); it++) {
|
|
PyDict_SetItemString(params, it->first.c_str(),
|
|
PyString_FromString(it->second.c_str()));
|
|
}
|
|
}
|
|
PyDict_SetItemString(locals, "params", params);
|
|
PyDict_SetItemString(locals, "type", PyInt_FromLong(event));
|
|
|
|
PyObject* py_sc_sess = PyCObject_FromVoidPtr(sc_sess,NULL);
|
|
PyObject* ts_dict = PyThreadState_GetDict();
|
|
PyDict_SetItemString(ts_dict, "_dsm_sess_", py_sc_sess);
|
|
|
|
// call the function
|
|
PyObject* res = PyEval_EvalCode((PyCodeObject*)py_func, d, locals);
|
|
|
|
if(PyErr_Occurred())
|
|
PyErr_Print();
|
|
|
|
ts_dict = PyThreadState_GetDict(); // should be the same as before
|
|
py_sc_sess = PyDict_GetItemString(ts_dict, "_dsm_sess_"); // should be the same as before
|
|
Py_XDECREF(py_sc_sess);
|
|
PyDict_DelItemString(ts_dict, "_dsm_sess_");
|
|
|
|
Py_DECREF(params);
|
|
Py_DECREF(locals);
|
|
if (NULL == res) {
|
|
ERROR("evaluating python code\n");
|
|
} else if (PyBool_Check(res)) {
|
|
py_res = PyInt_AsLong(res);
|
|
} else {
|
|
if (expect_int_result) {
|
|
ERROR("unknown result from python code\n");
|
|
}
|
|
Py_DECREF(res);
|
|
}
|
|
|
|
return py_res;
|
|
}
|
|
|
|
SCPyPyAction::SCPyPyAction(const string& arg) {
|
|
py_func = Py_CompileString(arg.c_str(), "<mod_py>", Py_file_input);
|
|
if (NULL == py_func) {
|
|
ERROR("compiling python code '%s'\n",
|
|
arg.c_str());
|
|
if(PyErr_Occurred())
|
|
PyErr_Print();
|
|
|
|
throw string("compiling python code '" + arg +"'");
|
|
}
|
|
}
|
|
|
|
EXEC_ACTION_START(SCPyPyAction) {
|
|
py_execute((PyCodeObject*)py_func, sc_sess,
|
|
event, event_params, false);
|
|
|
|
} EXEC_ACTION_END;
|
|
|
|
|
|
PyPyCondition::PyPyCondition(const string& arg) {
|
|
py_func = Py_CompileString(arg.c_str(), "<mod_py>", Py_eval_input);
|
|
if (NULL == py_func) {
|
|
ERROR("compiling python code '%s'\n",
|
|
arg.c_str());
|
|
if(PyErr_Occurred())
|
|
PyErr_Print();
|
|
|
|
throw string("compiling python code '" + arg +"'");
|
|
}
|
|
}
|
|
|
|
MATCH_CONDITION_START(PyPyCondition) {
|
|
return py_execute((PyCodeObject*)py_func, sc_sess,
|
|
event, event_params, false);
|
|
} MATCH_CONDITION_END;
|