From 89726e2bc7092d674f12867a5693a09765d150f2 Mon Sep 17 00:00:00 2001 From: Daniel-Constantin Mierla Date: Tue, 19 Apr 2016 13:10:34 +0200 Subject: [PATCH] app_python: implementation of kemi interpreter for python --- modules/app_python/apy_kemi.c | 332 ++++++++++++++++++++++++++++--- modules/app_python/python_exec.c | 17 +- 2 files changed, 319 insertions(+), 30 deletions(-) diff --git a/modules/app_python/apy_kemi.c b/modules/app_python/apy_kemi.c index 5f3c7dfcc90..d2815d8b79d 100644 --- a/modules/app_python/apy_kemi.c +++ b/modules/app_python/apy_kemi.c @@ -26,6 +26,7 @@ #include "../../dprint.h" #include "../../route.h" +#include "../../fmsg.h" #include "../../kemi.h" #include "../../mem/pkg.h" @@ -88,6 +89,33 @@ int sr_kemi_config_engine_python(sip_msg_t *msg, int rtype, str *rname) return 1; } +/** + * + */ +PyObject *sr_apy_kemi_return_true(void) +{ + Py_INCREF(Py_True); + return Py_True; +} + +/** + * + */ +PyObject *sr_apy_kemi_return_false(void) +{ + Py_INCREF(Py_False); + return Py_False; +} + + +/** + * + */ +PyObject *sr_apy_kemi_return_int(sr_kemi_t *ket, int rval) +{ + return PyInt_FromLong((long)rval); +} + /** * */ @@ -95,22 +123,27 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx) { str fname; int i; + int ret; sr_kemi_t *ket = NULL; sr_kemi_val_t vps[SR_KEMI_PARAMS_MAX]; sr_apy_env_t *env_P; + sip_msg_t *lmsg = NULL; env_P = sr_apy_env_get(); - if(env_P==NULL || env_P->msg==NULL) { + if(env_P==NULL) { LM_ERR("invalid Python environment attributes\n"); - Py_INCREF(Py_None); - return Py_None; + return sr_apy_kemi_return_false(); + } + if(env_P->msg==NULL) { + lmsg = faked_msg_next(); + } else { + lmsg = env_P->msg; } ket = sr_apy_kemi_export_get(idx); if(ket==NULL) { - Py_INCREF(Py_None); - return Py_None; + return sr_apy_kemi_return_false(); } if(ket->mname.len>0) { LM_DBG("execution of method: %.*s\n", ket->fname.len, ket->fname.s); @@ -121,6 +154,11 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx) } fname = ket->fname; + if(ket->ptypes[0]==SR_KEMIP_NONE) { + ret = ((sr_kemi_fm_f)(ket->func))(lmsg); + return sr_apy_kemi_return_int(ket, ret); + } + memset(vps, 0, SR_KEMI_PARAMS_MAX*sizeof(sr_kemi_val_t)); for(i=0; iptypes[i]==SR_KEMIP_NONE) { @@ -128,8 +166,7 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx) } else if(ket->ptypes[i]==SR_KEMIP_STR) { if(!PyArg_ParseTuple(args, "s:kemi-param", &vps[i].s.s)) { LM_ERR("unable to retrieve str param %d\n", i); - Py_INCREF(Py_None); - return Py_None; + return sr_apy_kemi_return_false(); } vps[i].s.len = strlen(vps[i].s.s); LM_DBG("param[%d] for: %.*s is str: %.*s\n", i, @@ -137,20 +174,190 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx) } else if(ket->ptypes[i]==SR_KEMIP_INT) { if(!PyArg_ParseTuple(args, "i:kemi-param", &vps[i].n)) { LM_ERR("unable to retrieve int param %d\n", i); - Py_INCREF(Py_None); - return Py_None; + return sr_apy_kemi_return_false(); } LM_DBG("param[%d] for: %.*s is int: %d\n", i, fname.len, fname.s, vps[i].n); } else { LM_ERR("unknown parameter type %d (%d)\n", ket->ptypes[i], i); - Py_INCREF(Py_None); - return Py_None; + return sr_apy_kemi_return_false(); } } - Py_INCREF(Py_None); - return Py_None; + switch(i) { + case 1: + if(ket->ptypes[0]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmn_f)(ket->func))(lmsg, vps[0].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[0]==SR_KEMIP_STR) { + ret = ((sr_kemi_fms_f)(ket->func))(lmsg, &vps[0].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + break; + case 2: + if(ket->ptypes[0]==SR_KEMIP_INT) { + if(ket->ptypes[1]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmnn_f)(ket->func))(lmsg, vps[0].n, vps[1].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[1]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmns_f)(ket->func))(lmsg, vps[0].n, &vps[1].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else if(ket->ptypes[0]==SR_KEMIP_STR) { + if(ket->ptypes[1]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmsn_f)(ket->func))(lmsg, &vps[0].s, vps[1].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[1]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmss_f)(ket->func))(lmsg, &vps[0].s, &vps[1].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + break; + case 3: + if(ket->ptypes[0]==SR_KEMIP_INT) { + if(ket->ptypes[1]==SR_KEMIP_INT) { + if(ket->ptypes[2]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmnnn_f)(ket->func))(lmsg, + vps[0].n, vps[1].n, vps[2].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[2]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmnns_f)(ket->func))(lmsg, + vps[0].n, vps[1].n, &vps[2].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else if(ket->ptypes[1]==SR_KEMIP_STR) { + if(ket->ptypes[2]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmnsn_f)(ket->func))(lmsg, + vps[0].n, &vps[1].s, vps[2].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[2]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmnss_f)(ket->func))(lmsg, + vps[0].n, &vps[1].s, &vps[2].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else if(ket->ptypes[0]==SR_KEMIP_STR) { + if(ket->ptypes[1]==SR_KEMIP_INT) { + if(ket->ptypes[2]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmsnn_f)(ket->func))(lmsg, + &vps[0].s, vps[1].n, vps[2].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[2]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmsns_f)(ket->func))(lmsg, + &vps[0].s, vps[1].n, &vps[2].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else if(ket->ptypes[1]==SR_KEMIP_STR) { + if(ket->ptypes[2]==SR_KEMIP_INT) { + ret = ((sr_kemi_fmssn_f)(ket->func))(lmsg, + &vps[0].s, &vps[1].s, vps[2].n); + return sr_apy_kemi_return_int(ket, ret); + } else if(ket->ptypes[2]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmsss_f)(ket->func))(lmsg, + &vps[0].s, &vps[1].s, &vps[2].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + break; + case 4: + if(ket->ptypes[0]==SR_KEMIP_STR + || ket->ptypes[1]==SR_KEMIP_STR + || ket->ptypes[2]==SR_KEMIP_STR + || ket->ptypes[3]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmssss_f)(ket->func))(lmsg, + &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + break; + case 5: + if(ket->ptypes[0]==SR_KEMIP_STR + || ket->ptypes[1]==SR_KEMIP_STR + || ket->ptypes[2]==SR_KEMIP_STR + || ket->ptypes[3]==SR_KEMIP_STR + || ket->ptypes[4]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmsssss_f)(ket->func))(lmsg, + &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s, + &vps[4].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + break; + case 6: + if(ket->ptypes[0]==SR_KEMIP_STR + || ket->ptypes[1]==SR_KEMIP_STR + || ket->ptypes[2]==SR_KEMIP_STR + || ket->ptypes[3]==SR_KEMIP_STR + || ket->ptypes[4]==SR_KEMIP_STR + || ket->ptypes[5]==SR_KEMIP_STR) { + ret = ((sr_kemi_fmssssss_f)(ket->func))(lmsg, + &vps[0].s, &vps[1].s, &vps[2].s, &vps[3].s, + &vps[4].s, &vps[5].s); + return sr_apy_kemi_return_int(ket, ret); + } else { + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + break; + default: + LM_ERR("invalid parameters for: %.*s\n", + fname.len, fname.s); + return sr_apy_kemi_return_false(); + } + + return sr_apy_kemi_return_false(); } /** @@ -158,9 +365,11 @@ PyObject *sr_apy_kemi_exec_func(PyObject *self, PyObject *args, int idx) */ PyObject *_sr_apy_ksr_module = NULL; PyObject *_sr_apy_ksr_module_dict = NULL; +PyObject **_sr_apy_ksr_modules_list = NULL; PyMethodDef *_sr_KSRMethods = NULL; -#define SR_APY_KSR_METHOS_SIZE 256 +#define SR_APY_KSR_MODULES_SIZE 256 +#define SR_APY_KSR_METHODS_SIZE (SR_APY_KEMI_EXPORT_SIZE + SR_APY_KSR_MODULES_SIZE) /** * @@ -176,7 +385,7 @@ static int sr_apy_kemi_f_dbg(sip_msg_t *msg, str *txt) * */ static sr_kemi_t _sr_apy_kemi_test[] = { - { str_init("test"), str_init("dbg"), + { str_init(""), str_init("ktest"), SR_KEMIP_NONE, sr_apy_kemi_f_dbg, { SR_KEMIP_STR, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE, SR_KEMIP_NONE } @@ -191,23 +400,100 @@ static sr_kemi_t _sr_apy_kemi_test[] = { */ int sr_apy_init_ksr(void) { - _sr_KSRMethods = pkg_malloc(SR_APY_KSR_METHOS_SIZE * sizeof(PyMethodDef)); + PyMethodDef *_sr_crt_KSRMethods = NULL; + sr_kemi_module_t *emods = NULL; + int emods_size = 0; + int i; + int k; + int m; + int n; + char mname[128]; + + /* init faked sip msg */ + if(faked_msg_init()<0) + { + LM_ERR("failed to init local faked sip msg\n"); + return -1; + } + + _sr_KSRMethods = malloc(SR_APY_KSR_METHODS_SIZE * sizeof(PyMethodDef)); if(_sr_KSRMethods==NULL) { LM_ERR("no more pkg memory\n"); return -1; } - memset(_sr_KSRMethods, 0, SR_APY_KSR_METHOS_SIZE * sizeof(PyMethodDef)); + _sr_apy_ksr_modules_list = malloc(SR_APY_KSR_MODULES_SIZE * sizeof(PyObject*)); + if(_sr_apy_ksr_modules_list==NULL) { + LM_ERR("no more pkg memory\n"); + return -1; + } + memset(_sr_KSRMethods, 0, SR_APY_KSR_METHODS_SIZE * sizeof(PyMethodDef)); + memset(_sr_apy_ksr_modules_list, 0, SR_APY_KSR_MODULES_SIZE * sizeof(PyObject*)); + + emods_size = sr_kemi_modules_size_get(); + emods = sr_kemi_modules_get(); - _sr_KSRMethods[0].ml_name = _sr_apy_kemi_test[0].fname.s; - _sr_KSRMethods[0].ml_meth = sr_apy_kemi_export_associate(&_sr_apy_kemi_test[0]); - _sr_KSRMethods[0].ml_flags = METH_VARARGS; - _sr_KSRMethods[0].ml_doc = "Kamailio function"; + n = 0; + _sr_crt_KSRMethods = _sr_KSRMethods; + if(emods_size==0 || emods[0].kexp==NULL) { + LM_DBG("exporting KSR.%s(...)\n", _sr_apy_kemi_test[0].fname.s); + _sr_crt_KSRMethods[0].ml_name = _sr_apy_kemi_test[0].fname.s; + _sr_crt_KSRMethods[0].ml_meth = sr_apy_kemi_export_associate(&_sr_apy_kemi_test[0]); + _sr_crt_KSRMethods[0].ml_flags = METH_VARARGS; + _sr_crt_KSRMethods[0].ml_doc = NAME " exported function"; + } else { + for(i=0; emods[0].kexp[i].func!=NULL; i++) { + LM_DBG("exporting KSR.%s(...)\n", emods[0].kexp[i].fname.s); + _sr_crt_KSRMethods[i].ml_name = emods[0].kexp[i].fname.s; + _sr_crt_KSRMethods[i].ml_meth = + sr_apy_kemi_export_associate(&emods[0].kexp[i]); + if(_sr_crt_KSRMethods[i].ml_meth == NULL) { + LM_ERR("failed to associate kemi function with python export\n"); + free(_sr_KSRMethods); + _sr_KSRMethods = NULL; + return -1; + } + _sr_crt_KSRMethods[i].ml_flags = METH_VARARGS; + _sr_crt_KSRMethods[i].ml_doc = NAME " exported function"; + n++; + } + } - _sr_apy_ksr_module = Py_InitModule("KSR", _sr_KSRMethods); + _sr_apy_ksr_module = Py_InitModule("KSR", _sr_crt_KSRMethods); _sr_apy_ksr_module_dict = PyModule_GetDict(_sr_apy_ksr_module); Py_INCREF(_sr_apy_ksr_module); + m = 0; + if(emods_size>1) { + for(k=1; k