Browse Source

app_python: implementation of kemi interpreter for python

Daniel-Constantin Mierla 9 years ago
parent
commit
89726e2bc7
2 changed files with 319 additions and 30 deletions
  1. 309 23
      modules/app_python/apy_kemi.c
  2. 10 7
      modules/app_python/python_exec.c

+ 309 - 23
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; i<SR_KEMI_PARAMS_MAX; i++) {
 		if(ket->ptypes[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<emods_size; k++) {
+			n++;
+			_sr_crt_KSRMethods += n;
+			snprintf(mname, 128, "KSR.%s", emods[k].kexp[0].mname.s);
+			for(i=0; emods[k].kexp[i].func!=NULL; i++) {
+				LM_DBG("exporting %s.%s(...)\n", mname,
+						emods[k].kexp[i].fname.s);
+				_sr_crt_KSRMethods[i].ml_name = emods[k].kexp[i].fname.s;
+				_sr_crt_KSRMethods[i].ml_meth =
+					sr_apy_kemi_export_associate(&emods[k].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++;
+			}
+			LM_DBG("initializing kemi sub-module: %s (%s)\n", mname,
+					emods[k].kexp[0].mname.s);
+			_sr_apy_ksr_modules_list[m] = Py_InitModule(mname, _sr_crt_KSRMethods);
+			PyDict_SetItemString(_sr_apy_ksr_module_dict,
+					emods[k].kexp[0].mname.s, _sr_apy_ksr_modules_list[m]);
+			Py_INCREF(_sr_apy_ksr_modules_list[m]);
+			m++;
+		}
+	}
 	LM_DBG("module 'KSR' has been initialized\n");
 	return 0;
 }
@@ -226,7 +512,7 @@ void sr_apy_destroy_ksr(void)
 		_sr_apy_ksr_module_dict = NULL;
 	}
 	if(_sr_KSRMethods!=NULL) {
-		pkg_free(_sr_KSRMethods);
+		free(_sr_KSRMethods);
 		_sr_KSRMethods = NULL;
 	}
 

+ 10 - 7
modules/app_python/python_exec.c

@@ -53,8 +53,11 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 	PyObject *pFunc, *pArgs, *pValue, *pResult;
 	PyObject *pmsg;
 	int rval;
+	sip_msg_t *bmsg;
 
+	bmsg = _sr_apy_env.msg;
 	_sr_apy_env.msg = _msg;
+
 	PyEval_AcquireLock();
 	PyThreadState_Swap(myThreadState);
 
@@ -68,7 +71,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 		Py_XDECREF(pFunc);
 		PyThreadState_Swap(NULL);
 		PyEval_ReleaseLock();
-		_sr_apy_env.msg = NULL;
+		_sr_apy_env.msg = bmsg;
 		if(emode==1) {
 			return -1;
 		} else {
@@ -82,7 +85,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 		Py_DECREF(pFunc);
 		PyThreadState_Swap(NULL);
 		PyEval_ReleaseLock();
-		_sr_apy_env.msg = NULL;
+		_sr_apy_env.msg = bmsg;
 		return -1;
 	}
 
@@ -94,7 +97,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 		Py_DECREF(pFunc);
 		PyThreadState_Swap(NULL);
 		PyEval_ReleaseLock();
-		_sr_apy_env.msg = NULL;
+		_sr_apy_env.msg = bmsg;
 		return -1;
 	}
 	PyTuple_SetItem(pArgs, 0, pmsg);
@@ -109,7 +112,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 			Py_DECREF(pFunc);
 			PyThreadState_Swap(NULL);
 			PyEval_ReleaseLock();
-			_sr_apy_env.msg = NULL;
+			_sr_apy_env.msg = bmsg;
 			return -1;
 		}
 		PyTuple_SetItem(pArgs, 1, pValue);
@@ -125,7 +128,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 		python_handle_exception("python_exec2");
 		PyThreadState_Swap(NULL);
 		PyEval_ReleaseLock();
-		_sr_apy_env.msg = NULL;
+		_sr_apy_env.msg = bmsg;
 		return -1;
 	}
 
@@ -133,7 +136,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 		LM_ERR("PyObject_CallObject() returned NULL\n");
 		PyThreadState_Swap(NULL);
 		PyEval_ReleaseLock();
-		_sr_apy_env.msg = NULL;
+		_sr_apy_env.msg = bmsg;
 		return -1;
 	}
 
@@ -141,7 +144,7 @@ int apy_exec(sip_msg_t *_msg, char *fname, char *fparam, int emode)
 	Py_DECREF(pResult);
 	PyThreadState_Swap(NULL);
 	PyEval_ReleaseLock();
-	_sr_apy_env.msg = NULL;
+	_sr_apy_env.msg = bmsg;
 	return rval;
 }