app_lua: function params can be dynamic strings
authorDaniel-Constantin Mierla <miconda@gmail.com>
Fri, 29 Jan 2010 21:52:45 +0000 (22:52 +0100)
committerDaniel-Constantin Mierla <miconda@gmail.com>
Fri, 29 Jan 2010 21:52:45 +0000 (22:52 +0100)
- 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

modules/app_lua/README
modules/app_lua/app_lua_api.c
modules/app_lua/app_lua_api.h
modules/app_lua/app_lua_mod.c
modules/app_lua/doc/app_lua_admin.xml

index c9422c9..95a730c 100644 (file)
@@ -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
index 37724b1..88ee832 100644 (file)
@@ -289,6 +289,34 @@ int app_lua_dofile(struct sip_msg *msg, char *script)
 /**
  *
  */
+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;
+}
+
+/**
+ *
+ */
 int app_lua_run(struct sip_msg *msg, char *func, char *p1, char *p2,
                char *p3)
 {
@@ -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;
+               }
+       }
+}
index ff6d0d2..fbf12d5 100644 (file)
@@ -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
 
index 3441892..bc7fc2c 100644 (file)
@@ -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);
+}
+
index 4aef690..fe5f546 100644 (file)
@@ -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>