Forráskód Böngészése

app_lua: function params can be dynamic strings

- all functions accept parameters with PVs that are evaluated at runtime
- new function lua_runstring() to run lua script in the context of
  loaded lua files at startup
- helper functions to return boolean to lua and print lua stack in c
  side
Daniel-Constantin Mierla 15 éve
szülő
commit
71e1256177

+ 30 - 10
modules/app_lua/README

@@ -33,6 +33,7 @@ Daniel-Constantin Mierla
               4.1. lua_dofile(path)
               4.2. lua_dostring(script)
               4.3. lua_run(function, params)
+              4.4. lua_runstring(script)
 
         5. Example of usage
 
@@ -41,8 +42,9 @@ Daniel-Constantin Mierla
    1.1. Set load parameter
    1.2. Set register parameter
    1.3. lua_dofile usage
-   1.4. lua_doscript usage
-   1.5. lua_doscript usage
+   1.4. lua_dostring usage
+   1.5. lua_run usage
+   1.6. lua_runstring usage
 
 Chapter 1. Admin Guide
 
@@ -64,6 +66,7 @@ Chapter 1. Admin Guide
         4.1. lua_dofile(path)
         4.2. lua_dostring(script)
         4.3. lua_run(function, params)
+        4.4. lua_runstring(script)
 
    5. Example of usage
 
@@ -141,10 +144,12 @@ modparam("lua", "register", "sr")
    4.1. lua_dofile(path)
    4.2. lua_dostring(script)
    4.3. lua_run(function, params)
+   4.4. lua_runstring(script)
 
 4.1.  lua_dofile(path)
 
-   Execute the Lua script stored in 'path'.
+   Execute the Lua script stored in 'path'. The parameter can be a string
+   with pseudo-variables evaluated at runtime.
 
    Example 1.3. lua_dofile usage
 ...
@@ -153,11 +158,12 @@ lua_dofile("/usr/local/etc/kamailio/lua/myscript.lua");
 
 4.2.  lua_dostring(script)
 
-   Execute the Lua script stored in parameter.
+   i Execute the Lua script stored in parameter. The parameter can be a
+   string with pseudo-variables.
 
-   Example 1.4. lua_doscript usage
+   Example 1.4. lua_dostring usage
 ...
-if(!lua_dostring("sr.log([[err]], [[----------- Hello World\n]])"))
+if(!lua_dostring("sr.log([[err]], [[----------- Hello World from $fU\n]])"))
 {
     xdbg("SCRIPT: failed to execute lua script!\n");
 }
@@ -167,17 +173,31 @@ if(!lua_dostring("sr.log([[err]], [[----------- Hello World\n]])"))
 
    Execute the Lua function 'func' giving params as parameters. There can
    be up to 3 string parameters. The function must exist in the script
-   loaded at startup via parameter 'load'. So far the parameters are
-   considered static strings (allowing pv is in the roadmap).
+   loaded at startup via parameter 'load'. Parameters can be strings with
+   pseudo-variables that are evaluated at runtime.
 
-   Example 1.5. lua_doscript usage
+   Example 1.5. lua_run usage
 ...
 if(!lua_run("sr_append_fu_to_reply"))
 {
     xdbg("SCRIPT: failed to execute lua function!\n");
 }
 ...
-lua_run("lua_funcx", "1", "2");
+lua_run("lua_funcx", "$rU", "2");
+...
+
+4.4.  lua_runstring(script)
+
+   i Execute the Lua script stored in parameter. The parameter can be a
+   string with pseudo-variables. The script is executed in Lua context
+   specific to loaded Lua files at startup.
+
+   Example 1.6. lua_runstring usage
+...
+if(!lua_runstring("sr.log([[err]], [[----------- Hello World from $fU\n]])"))
+{
+    xdbg("SCRIPT: failed to execute lua script!\n");
+}
 ...
 
 5. Example of usage

+ 57 - 0
modules/app_lua/app_lua_api.c

@@ -286,6 +286,34 @@ int app_lua_dofile(struct sip_msg *msg, char *script)
 	return (ret==0)?1:-1;
 }
 
+/**
+ *
+ */
+int app_lua_runstring(struct sip_msg *msg, char *script)
+{
+	int ret;
+	char *txt;
+
+	if(_sr_L_env.LL==NULL)
+	{
+		LM_ERR("lua loading state not initialized (call: %s)\n", script);
+		return -1;
+	}
+
+	LM_DBG("running Lua string: [[%s]]\n", script);
+	LM_DBG("lua top index is: %d\n", lua_gettop(_sr_L_env.LL));
+	_sr_L_env.msg = msg;
+	ret = luaL_dostring(_sr_L_env.LL, script);
+	if(ret!=0)
+	{
+		txt = (char*)lua_tostring(_sr_L_env.LL, -1);
+		LM_ERR("error from Lua: %s\n", (txt)?txt:"unknown");
+		lua_pop (_sr_L_env.LL, 1);
+	}
+	_sr_L_env.msg = 0;
+	return (ret==0)?1:-1;
+}
+
 /**
  *
  */
@@ -346,3 +374,32 @@ int app_lua_run(struct sip_msg *msg, char *func, char *p1, char *p2,
 	return 1;
 }
 
+void app_lua_dump_stack(lua_State *L)
+{
+	int i;
+	int t;
+	int top;
+
+	top = lua_gettop(L);
+
+	for (i = 1; i <= top; i++)
+	{
+		t = lua_type(L, i);
+		switch (t)
+		{
+			case LUA_TSTRING:  /* strings */
+				LM_DBG("[%i:s> %s\n", i, lua_tostring(L, i));
+			break;
+			case LUA_TBOOLEAN:  /* booleans */
+				LM_DBG("[%i:b> %s\n", i,
+					lua_toboolean(L, i) ? "true" : "false");
+			break;
+			case LUA_TNUMBER:  /* numbers */
+				LM_DBG("[%i:n> %g\n", i, lua_tonumber(L, i));
+			break;
+			default:  /* other values */
+				LM_DBG("[%i:t> %s\n", i, lua_typename(L, t));
+			break;
+		}
+	}
+}

+ 3 - 0
modules/app_lua/app_lua_api.h

@@ -50,10 +50,13 @@ int sr_lua_register_module(char *mname);
 
 int app_lua_dostring(struct sip_msg *msg, char *script);
 int app_lua_dofile(struct sip_msg *msg, char *script);
+int app_lua_runstring(struct sip_msg *msg, char *script);
 int app_lua_run(struct sip_msg *msg, char *func, char *p1, char *p2,
 		char *p3);
 
 int app_lua_return_boolean(lua_State *L, int b);
 
+void app_lua_dump_stack(lua_State *L);
+
 #endif
 

+ 172 - 9
modules/app_lua/app_lua_mod.c

@@ -43,8 +43,19 @@ static int  child_init(int rank);
 
 static int w_app_lua_dostring(struct sip_msg *msg, char *script, char *extra);
 static int w_app_lua_dofile(struct sip_msg *msg, char *script, char *extra);
+static int w_app_lua_runstring(struct sip_msg *msg, char *script, char *extra);
 static int w_app_lua_run(struct sip_msg *msg, char *func, char *p1, char *p2,
 		char *p3);
+static int w_app_lua_run0(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3);
+static int w_app_lua_run1(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3);
+static int w_app_lua_run2(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3);
+static int w_app_lua_run3(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3);
+
+static int fixup_lua_run(void** param, int param_no);
 
 int app_lua_load_param(modparam_t type, void *val);
 int app_lua_register_param(modparam_t type, void *val);
@@ -56,17 +67,19 @@ static param_export_t params[]={
 };
 
 static cmd_export_t cmds[]={
-	{"lua_dostring", (cmd_function)w_app_lua_dostring, 1, 0,
+	{"lua_dostring", (cmd_function)w_app_lua_dostring, 1, fixup_spve_null,
+		0, ANY_ROUTE},
+	{"lua_dofile", (cmd_function)w_app_lua_dofile, 1, fixup_spve_null,
 		0, ANY_ROUTE},
-	{"lua_dofile", (cmd_function)w_app_lua_dofile, 1, 0,
+	{"lua_runstring", (cmd_function)w_app_lua_runstring, 1, fixup_spve_null,
 		0, ANY_ROUTE},
-	{"lua_run", (cmd_function)w_app_lua_run, 1, 0,
+	{"lua_run", (cmd_function)w_app_lua_run0, 1, fixup_lua_run,
 		0, ANY_ROUTE},
-	{"lua_run", (cmd_function)w_app_lua_run, 2, 0,
+	{"lua_run", (cmd_function)w_app_lua_run1, 2, fixup_lua_run,
 		0, ANY_ROUTE},
-	{"lua_run", (cmd_function)w_app_lua_run, 3, 0,
+	{"lua_run", (cmd_function)w_app_lua_run2, 3, fixup_lua_run,
 		0, ANY_ROUTE},
-	{"lua_run", (cmd_function)w_app_lua_run, 4, 0,
+	{"lua_run", (cmd_function)w_app_lua_run3, 4, fixup_lua_run,
 		0, ANY_ROUTE},
 	{0, 0, 0, 0, 0, 0}
 };
@@ -113,35 +126,180 @@ static void mod_destroy(void)
 	lua_sr_destroy();
 }
 
+static char _lua_buf_stack[4][512];
+
 static int w_app_lua_dostring(struct sip_msg *msg, char *script, char *extra)
 {
+	str s;
 	if(!lua_sr_initialized())
 	{
 		LM_ERR("Lua env not intitialized");
 		return -1;
 	}
-	return app_lua_dostring(msg, script);
+	if(fixup_get_svalue(msg, (gparam_p)script, &s)<0)
+	{
+		LM_ERR("cannot get the script\n");
+		return -1;
+	}
+	if(s.len>=511)
+	{
+		LM_ERR("script too long %d\n", s.len);
+		return -1;
+	}
+	memcpy(_lua_buf_stack[0], s.s, s.len);
+	_lua_buf_stack[0][s.len] = '\0';
+	return app_lua_dostring(msg, _lua_buf_stack[0]);
 }
 
 static int w_app_lua_dofile(struct sip_msg *msg, char *script, char *extra)
 {
+	str s;
+	if(!lua_sr_initialized())
+	{
+		LM_ERR("Lua env not intitialized");
+		return -1;
+	}
+	if(fixup_get_svalue(msg, (gparam_p)script, &s)<0)
+	{
+		LM_ERR("cannot get the script\n");
+		return -1;
+	}
+	if(s.len>=511)
+	{
+		LM_ERR("script too long %d\n", s.len);
+		return -1;
+	}
+	memcpy(_lua_buf_stack[0], s.s, s.len);
+	_lua_buf_stack[0][s.len] = '\0';
+	return app_lua_dofile(msg, _lua_buf_stack[0]);
+}
+
+static int w_app_lua_runstring(struct sip_msg *msg, char *script, char *extra)
+{
+	str s;
 	if(!lua_sr_initialized())
 	{
 		LM_ERR("Lua env not intitialized");
 		return -1;
 	}
-	return app_lua_dofile(msg, script);
+	if(fixup_get_svalue(msg, (gparam_p)script, &s)<0)
+	{
+		LM_ERR("cannot get the script\n");
+		return -1;
+	}
+	if(s.len>=511)
+	{
+		LM_ERR("script too long %d\n", s.len);
+		return -1;
+	}
+	memcpy(_lua_buf_stack[0], s.s, s.len);
+	_lua_buf_stack[0][s.len] = '\0';
+	return app_lua_runstring(msg, _lua_buf_stack[0]);
 }
 
 static int w_app_lua_run(struct sip_msg *msg, char *func, char *p1, char *p2,
 		char *p3)
 {
+	str s;
 	if(!lua_sr_initialized())
 	{
 		LM_ERR("Lua env not intitialized");
 		return -1;
 	}
-	return app_lua_run(msg, func, p1, p2, p3);
+	if(fixup_get_svalue(msg, (gparam_p)func, &s)<0)
+	{
+		LM_ERR("cannot get the function\n");
+		return -1;
+	}
+	if(s.len>=511)
+	{
+		LM_ERR("function too long %d\n", s.len);
+		return -1;
+	}
+	memcpy(_lua_buf_stack[0], s.s, s.len);
+	_lua_buf_stack[0][s.len] = '\0';
+
+	if(p1!=NULL)
+	{
+		if(fixup_get_svalue(msg, (gparam_p)p1, &s)<0)
+		{
+			LM_ERR("cannot get p1\n");
+			return -1;
+		}
+		if(s.len>=511)
+		{
+			LM_ERR("p1 too long %d\n", s.len);
+			return -1;
+		}
+		memcpy(_lua_buf_stack[1], s.s, s.len);
+		_lua_buf_stack[1][s.len] = '\0';
+
+		if(p2!=NULL)
+		{
+			if(fixup_get_svalue(msg, (gparam_p)p2, &s)<0)
+			{
+				LM_ERR("cannot get p2\n");
+				return -1;
+			}
+			if(s.len>=511)
+			{
+				LM_ERR("p2 too long %d\n", s.len);
+				return -1;
+			}
+			memcpy(_lua_buf_stack[2], s.s, s.len);
+			_lua_buf_stack[2][s.len] = '\0';
+
+			if(p3!=NULL)
+			{
+				if(fixup_get_svalue(msg, (gparam_p)p3, &s)<0)
+				{
+					LM_ERR("cannot get p3\n");
+					return -1;
+				}
+				if(s.len>=511)
+				{
+					LM_ERR("p3 too long %d\n", s.len);
+					return -1;
+				}
+				memcpy(_lua_buf_stack[3], s.s, s.len);
+				_lua_buf_stack[3][s.len] = '\0';
+			}
+		} else {
+			p3 = NULL;
+		}
+	} else {
+		p2 = NULL;
+		p3 = NULL;
+	}
+
+	return app_lua_run(msg, _lua_buf_stack[0],
+			(p1!=NULL)?_lua_buf_stack[1]:NULL,
+			(p2!=NULL)?_lua_buf_stack[2]:NULL,
+			(p3!=NULL)?_lua_buf_stack[3]:NULL);
+}
+
+static int w_app_lua_run0(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3)
+{
+	return w_app_lua_run(msg, func, NULL, NULL, NULL);
+}
+
+static int w_app_lua_run1(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3)
+{
+	return w_app_lua_run(msg, func, p1, NULL, NULL);
+}
+
+static int w_app_lua_run2(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3)
+{
+	return w_app_lua_run(msg, func, p1, p2, NULL);
+}
+
+static int w_app_lua_run3(struct sip_msg *msg, char *func, char *p1, char *p2,
+		char *p3)
+{
+	return w_app_lua_run(msg, func, p1, p2, p3);
 }
 
 int app_lua_load_param(modparam_t type, void *val)
@@ -158,3 +316,8 @@ int app_lua_register_param(modparam_t type, void *val)
 	return sr_lua_register_module((char*)val);
 }
 
+static int fixup_lua_run(void** param, int param_no)
+{
+	return fixup_spve_null(param, 1);
+}
+

+ 34 - 10
modules/app_lua/doc/app_lua_admin.xml

@@ -144,7 +144,8 @@ modparam("lua", "register", "sr")
 		<function moreinfo="none">lua_dofile(path)</function>
 	    </title>
 	    <para>
-		Execute the Lua script stored in 'path'.
+		Execute the Lua script stored in 'path'. The parameter can be
+		a string with pseudo-variables evaluated at runtime.
 	    </para>
 		<example>
 		<title><function>lua_dofile</function> usage</title>
@@ -160,14 +161,15 @@ lua_dofile("/usr/local/etc/kamailio/lua/myscript.lua");
 	    <title>
 		<function moreinfo="none">lua_dostring(script)</function>
 	    </title>
-	    <para>
-		Execute the Lua script stored in parameter.
+	    <para>i
+		Execute the Lua script stored in parameter. The parameter can be
+		a string with pseudo-variables.
 	    </para>
 		<example>
-		<title><function>lua_doscript</function> usage</title>
+		<title><function>lua_dostring</function> usage</title>
 		<programlisting format="linespecific">
 ...
-if(!lua_dostring("sr.log([[err]], [[----------- Hello World\n]])"))
+if(!lua_dostring("sr.log([[err]], [[----------- Hello World from $fU\n]])"))
 {
     xdbg("SCRIPT: failed to execute lua script!\n");
 }
@@ -175,7 +177,7 @@ if(!lua_dostring("sr.log([[err]], [[----------- Hello World\n]])"))
 </programlisting>
 	    </example>
 	</section>
-	
+
 	<section>
 	    <title>
 		<function moreinfo="none">lua_run(function, params)</function>
@@ -183,11 +185,11 @@ if(!lua_dostring("sr.log([[err]], [[----------- Hello World\n]])"))
 	    <para>
 		Execute the Lua function 'func' giving params as parameters. There
 		can be up to 3 string parameters. The function must exist in the
-		script loaded at startup via parameter 'load'. So far the parameters
-		are considered static strings (allowing pv is in the roadmap).
+		script loaded at startup via parameter 'load'. Parameters can be
+		strings with pseudo-variables that are evaluated at runtime.
 	    </para>
 		<example>
-		<title><function>lua_doscript</function> usage</title>
+		<title><function>lua_run</function> usage</title>
 		<programlisting format="linespecific">
 ...
 if(!lua_run("sr_append_fu_to_reply"))
@@ -195,7 +197,29 @@ if(!lua_run("sr_append_fu_to_reply"))
     xdbg("SCRIPT: failed to execute lua function!\n");
 }
 ...
-lua_run("lua_funcx", "1", "2");
+lua_run("lua_funcx", "$rU", "2");
+...
+</programlisting>
+	    </example>
+	</section>
+
+	<section>
+	    <title>
+		<function moreinfo="none">lua_runstring(script)</function>
+	    </title>
+	    <para>i
+		Execute the Lua script stored in parameter. The parameter can be
+		a string with pseudo-variables. The script is executed in Lua context
+		specific to loaded Lua files at startup.
+	    </para>
+		<example>
+		<title><function>lua_runstring</function> usage</title>
+		<programlisting format="linespecific">
+...
+if(!lua_runstring("sr.log([[err]], [[----------- Hello World from $fU\n]])"))
+{
+    xdbg("SCRIPT: failed to execute lua script!\n");
+}
 ...
 </programlisting>
 	    </example>