2
0
Эх сурвалжийг харах

Merge branch 'master' of ssh://git.sip-router.org/sip-router

* 'master' of ssh://git.sip-router.org/sip-router: (31 commits)
  app_lua: several tm functions added to Lua api
  tm: added export structure for extra API
  app_lua: added several core functions to sr package
  app_lua: helper function to return error code
  app_lua: fixed name of module in modparam examples
  app_lua: added registrar API to Lua
  registrar(k): exported inter-module API
  usrloc(k): db modes defines moved in usrloc.h
  usrloc(k)API function get_udomain()
  usrloc(k): preload parameter exported
  usrloc(k): new parameter 'preload'
  sqlops: added LF to end of debug message
  app_lua: sr.maxfwd mentioned as available submodule
  maxfwd(k): added inter-module API structure
  auth_db(k): added new file api.h
  app_lua: typo in register parameter
  app_lua: added functions from auth_db api
  auth_db(k): close db handle only for second param fixup
  app_lua: note about submodule sr.auth
  app_lua: exported functions from AUTH API to Lua
  ...
Jan Janak 15 жил өмнө
parent
commit
1b209e395c
44 өөрчлөгдсөн 2373 нэмэгдсэн , 226 устгасан
  1. 14 5
      modules/app_lua/README
  2. 18 0
      modules/app_lua/app_lua_api.c
  3. 2 0
      modules/app_lua/app_lua_api.h
  4. 1033 67
      modules/app_lua/app_lua_exp.c
  5. 421 6
      modules/app_lua/app_lua_sr.c
  6. 44 2
      modules/app_lua/doc/app_lua_admin.xml
  7. 3 0
      modules/auth/api.c
  8. 41 3
      modules/auth/api.h
  9. 137 64
      modules/auth/auth_mod.c
  10. 17 6
      modules/tm/tm.c
  11. 19 0
      modules/tm/tm_load.c
  12. 41 0
      modules/tm/tm_load.h
  13. 63 0
      modules_k/auth_db/api.h
  14. 3 1
      modules_k/auth_db/authdb_mod.c
  15. 67 29
      modules_k/auth_db/authorize.c
  16. 6 0
      modules_k/auth_db/authorize.h
  17. 62 0
      modules_k/maxfwd/api.h
  18. 33 3
      modules_k/maxfwd/maxfwd.c
  19. 79 0
      modules_k/registrar/api.c
  20. 72 0
      modules_k/registrar/api.h
  21. 5 5
      modules_k/registrar/lookup.c
  22. 2 1
      modules_k/registrar/lookup.h
  23. 25 4
      modules_k/registrar/reg_mod.c
  24. 2 2
      modules_k/registrar/save.c
  25. 2 1
      modules_k/registrar/save.h
  26. 2 0
      modules_k/rr/api.c
  27. 19 9
      modules_k/rr/api.h
  28. 1 3
      modules_k/rr/loose.c
  29. 1 3
      modules_k/rr/loose.h
  30. 13 2
      modules_k/rr/rr_mod.c
  31. 2 2
      modules_k/sqlops/sql_api.c
  32. 2 2
      modules_k/sqlops/sql_api.h
  33. 1 1
      modules_k/sqlops/sqlops.c
  34. 18 0
      modules_k/usrloc/README
  35. 24 0
      modules_k/usrloc/dlist.c
  36. 9 0
      modules_k/usrloc/dlist.h
  37. 23 0
      modules_k/usrloc/doc/usrloc_admin.xml
  38. 1 0
      modules_k/usrloc/ucontact.c
  39. 1 0
      modules_k/usrloc/udomain.c
  40. 36 0
      modules_k/usrloc/ul_mod.c
  41. 0 5
      modules_k/usrloc/ul_mod.h
  42. 1 0
      modules_k/usrloc/urecord.c
  43. 1 0
      modules_k/usrloc/usrloc.c
  44. 7 0
      modules_k/usrloc/usrloc.h

+ 14 - 5
modules/app_lua/README

@@ -10,7 +10,7 @@ Daniel-Constantin Mierla
 
    <[email protected]>
 
-   Copyright © 2010 Daniel-Constantin Mierla (asipto.com)
+   Copyright © 2010 Daniel-Constantin Mierla (asipto.com)
      __________________________________________________________________
 
    Table of Contents
@@ -116,27 +116,36 @@ Chapter 1. Admin Guide
    use lua_run(function, params) to execute a function from the script at
    runtime.
 
-   Default value is "null".
+   Default value is “null�.
 
    Example 1.1. Set load parameter
 ...
-modparam("lua", "load", "/usr/local/etc/kamailio/lua/myscript.lua")
+modparam("app_lua", "load", "/usr/local/etc/kamailio/lua/myscript.lua")
 ...
 
 3.2. register (string)
 
    Use this function to register optional SIP Router submodules to Lua.
    Available submodules are:
+     * auth - register functions from auth module under 'sr.auth'.
+     * auth_db - register functions from auth_db module under
+       'sr.auth_db'.
+     * maxfwd - register functions from maxfwd module under 'sr.maxfwd'.
+     * registrar - register functions from registrar module under
+       'sr.registrar'.
+     * rr - register functions from rr module under 'sr.rr'.
+     * sqlops - register functions from sqlops module under 'sr.sqlops'.
      * sl - register functions from sl module under 'sr.sl'.
+     * tm - register functions from tm module under 'sr.tm'.
 
    Note that 'sr', 'sr.hdr' and 'sr.pv' modules are always registered to
    Lua.
 
-   Default value is "null".
+   Default value is “null�.
 
    Example 1.2. Set register parameter
 ...
-modparam("lua", "register", "sr")
+modparam("app_lua", "register", "sl")
 ...
 
 4. Exported Functions

+ 18 - 0
modules/app_lua/app_lua_api.c

@@ -271,6 +271,24 @@ int lua_sr_initialized(void)
 	return 1;
 }
 
+/**
+ *
+ */
+int app_lua_return_int(lua_State *L, int v)
+{
+	lua_pushinteger(L, v);
+	return 1;
+}
+
+/**
+ *
+ */
+int app_lua_return_error(lua_State *L)
+{
+	lua_pushinteger(L, -1);
+	return 1;
+}
+
 /**
  *
  */

+ 2 - 0
modules/app_lua/app_lua_api.h

@@ -60,6 +60,8 @@ int app_lua_run(struct sip_msg *msg, char *func, char *p1, char *p2,
 int app_lua_return_boolean(lua_State *L, int b);
 int app_lua_return_false(lua_State *L);
 int app_lua_return_true(lua_State *L);
+int app_lua_return_int(lua_State *L, int v);
+int app_lua_return_error(lua_State *L);
 
 void app_lua_dump_stack(lua_State *L);
 

+ 1033 - 67
modules/app_lua/app_lua_exp.c

@@ -28,15 +28,28 @@
 
 #include "../../sr_module.h"
 #include "../../dprint.h"
+#include "../../route.h"
 #include "../../ut.h"
 
 #include "../../modules/sl/sl.h"
 #include "../../modules/tm/tm_load.h"
+#include "../../modules_k/sqlops/sql_api.h"
+#include "../../modules_k/rr/api.h"
+#include "../../modules/auth/api.h"
+#include "../../modules_k/auth_db/api.h"
+#include "../../modules_k/maxfwd/api.h"
+#include "../../modules_k/registrar/api.h"
 
 #include "app_lua_api.h"
 
-#define SR_LUA_EXP_MOD_SL	(1<<0)
-#define SR_LUA_EXP_MOD_TM	(1<<1)
+#define SR_LUA_EXP_MOD_SL         (1<<0)
+#define SR_LUA_EXP_MOD_TM         (1<<1)
+#define SR_LUA_EXP_MOD_SQLOPS     (1<<2)
+#define SR_LUA_EXP_MOD_RR         (1<<3)
+#define SR_LUA_EXP_MOD_AUTH       (1<<4)
+#define SR_LUA_EXP_MOD_AUTH_DB    (1<<5)
+#define SR_LUA_EXP_MOD_MAXFWD     (1<<6)
+#define SR_LUA_EXP_MOD_REGISTRAR  (1<<7)
 
 /**
  *
@@ -44,14 +57,45 @@
 static unsigned int _sr_lua_exp_reg_mods = 0;
 
 /**
- *
+ * auth
+ */
+static auth_api_s_t _lua_authb;
+
+/**
+ * auth_db
+ */
+static auth_db_api_t _lua_auth_dbb;
+
+/**
+ * maxfwd
+ */
+static maxfwd_api_t _lua_maxfwdb;
+
+/**
+ * registrar
+ */
+static registrar_api_t _lua_registrarb;
+
+/**
+ * rr
+ */
+static rr_api_t _lua_rrb;
+
+/**
+ * sqlops
+ */
+static sqlops_api_t _lua_sqlopsb;
+
+/**
+ * sl
  */
 static sl_api_t _lua_slb;
 
 /**
  * tm
  */
-static tm_api_t _lua_tmb;
+static tm_api_t  _lua_tmb;
+static tm_xapi_t _lua_xtmb;
 
 /**
  *
@@ -68,27 +112,26 @@ static int lua_sr_sl_send_reply (lua_State *L)
 	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SL))
 	{
 		LM_WARN("weird: sl function executed but module not registered\n");
-		return app_lua_return_false(L);
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
 	}
 
 	code = lua_tointeger(L, -2);
 
 	if(code<100 || code>=800)
-		return app_lua_return_false(L);
+		return app_lua_return_error(L);
 	
 	txt.s = (char*)lua_tostring(L, -1);
-	if(txt.s!=NULL && env_L->msg!=NULL)
-	{
-		txt.len = strlen(txt.s);
-		ret = _lua_slb.freply(env_L->msg, code, &txt);
-		if(ret<0)
-		{
-			LM_WARN("sl send_reply returned false\n");
-			return app_lua_return_false(L);
-		}
-		return app_lua_return_true(L);
-	}
-	return app_lua_return_false(L);
+	if(txt.s==NULL || env_L->msg==NULL)
+		return app_lua_return_error(L);
+
+	txt.len = strlen(txt.s);
+	ret = _lua_slb.freply(env_L->msg, code, &txt);
+	return app_lua_return_int(L, ret);
 }
 
 /**
@@ -107,6 +150,11 @@ static int lua_sr_sl_get_reply_totag (lua_State *L)
 		LM_WARN("weird: sl function executed but module not registered\n");
 		return app_lua_return_false(L);
 	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
 	ret = _lua_slb.get_reply_totag(env_L->msg, &txt);
 	if(ret<0)
 	{
@@ -141,27 +189,26 @@ static int lua_sr_tm_t_reply(lua_State *L)
 	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
 	{
 		LM_WARN("weird: tm function executed but module not registered\n");
-		return app_lua_return_false(L);
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
 	}
 
 	code = lua_tointeger(L, -2);
 
 	if(code<100 || code>=800)
-		return app_lua_return_false(L);
+		return app_lua_return_error(L);
 
 	txt = (char*)lua_tostring(L, -1);
 	if(txt!=NULL && env_L->msg!=NULL)
 	{
 		ret = _lua_tmb.t_reply(env_L->msg, code, txt);
-		if(ret<0)
-		{
-			LM_WARN("tm t_reply returned false\n");
-			/* shall push FALSE to Lua ?!? */
-			return app_lua_return_false(L);
-		}
-		return app_lua_return_true(L);
+		return app_lua_return_int(L, ret);
 	}
-	return app_lua_return_false(L);
+	return app_lua_return_error(L);
 }
 
 /**
@@ -177,15 +224,188 @@ static int lua_sr_tm_t_relay(lua_State *L)
 	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
 	{
 		LM_WARN("weird: tm function executed but module not registered\n");
-		return app_lua_return_false(L);
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
 	}
 	ret = _lua_tmb.t_relay(env_L->msg, NULL, NULL);
-	if(ret<0)
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_on_failure(lua_State *L)
+{
+	char *name;
+	int i;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
 	{
-		LM_WARN("tm t_relay returned false\n");
-		return app_lua_return_false(L);
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
 	}
-	return app_lua_return_true(L);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	name = (char*)lua_tostring(L, -1);
+	if(name==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+
+	i = route_get(&failure_rt, name);
+	if(failure_rt.rlist[i]==0)
+	{
+		LM_WARN("no actions in failure_route[%s]\n", name);
+		return app_lua_return_error(L);
+	}
+
+	_lua_xtmb.t_on_failure((unsigned int)i);
+	return app_lua_return_int(L, 1);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_on_branch(lua_State *L)
+{
+	char *name;
+	int i;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	name = (char*)lua_tostring(L, -1);
+	if(name==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+
+	i = route_get(&branch_rt, name);
+	if(branch_rt.rlist[i]==0)
+	{
+		LM_WARN("no actions in branch_route[%s]\n", name);
+		return app_lua_return_error(L);
+	}
+
+	_lua_xtmb.t_on_branch((unsigned int)i);
+	return app_lua_return_int(L, 1);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_on_reply(lua_State *L)
+{
+	char *name;
+	int i;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	name = (char*)lua_tostring(L, -1);
+	if(name==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+
+	i = route_get(&onreply_rt, name);
+	if(onreply_rt.rlist[i]==0)
+	{
+		LM_WARN("no actions in onreply_route[%s]\n", name);
+		return app_lua_return_error(L);
+	}
+
+	_lua_xtmb.t_on_reply((unsigned int)i);
+	return app_lua_return_int(L, 1);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_check_trans(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	ret = _lua_xtmb.t_check_trans(env_L->msg);
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_tm_t_is_canceled(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM))
+	{
+		LM_WARN("weird: tm function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+
+	ret = _lua_xtmb.t_is_canceled(env_L->msg);
+	return app_lua_return_int(L, ret);
 }
 
 
@@ -193,8 +413,13 @@ static int lua_sr_tm_t_relay(lua_State *L)
  *
  */
 static const luaL_reg _sr_tm_Map [] = {
-	{"t_reply", lua_sr_tm_t_reply},
-	{"t_relay", lua_sr_tm_t_relay},
+	{"t_reply",        lua_sr_tm_t_reply},
+	{"t_relay",        lua_sr_tm_t_relay},
+	{"t_on_failure",   lua_sr_tm_t_on_failure},
+	{"t_on_branch",    lua_sr_tm_t_on_branch},
+	{"t_on_reply",     lua_sr_tm_t_on_reply},
+	{"t_check_trans",  lua_sr_tm_t_check_trans},
+	{"t_is_canceled",  lua_sr_tm_t_is_canceled},
 	{NULL, NULL}
 };
 
@@ -202,60 +427,801 @@ static const luaL_reg _sr_tm_Map [] = {
 /**
  *
  */
-int lua_sr_exp_init_mod(void)
+static int lua_sr_sqlops_query(lua_State *L)
 {
-	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SL)
+	str scon;
+	str squery;
+	str sres;
+	int ret;
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
 	{
-		/* bind the SL API */
-		if (sl_load_api(&_lua_slb)!=0) {
-			LM_ERR("cannot bind to SL API\n");
-			return -1;
-		}
-		LM_DBG("loaded sl api\n");
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_error(L);
 	}
-	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM)
+
+	scon.s = (char*)lua_tostring(L, -3);
+	squery.s = (char*)lua_tostring(L, -2);
+	sres.s = (char*)lua_tostring(L, -1);
+	if(scon.s == NULL || squery.s == NULL || sres.s == NULL)
 	{
-		/* bind the TM API */
-		if (tm_load_api(&_lua_tmb) == -1)
-		{
-			LM_ERR("cannot bind to TM API\n");
-			return -1;
-		}
-		LM_DBG("loaded tm api\n");
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
 	}
-	return 0;
+	scon.len = strlen(scon.s);
+	squery.len = strlen(squery.s);
+	sres.len = strlen(sres.s);
+
+	ret = _lua_sqlopsb.query(&scon, &squery, &sres);
+	return app_lua_return_int(L, ret);
 }
 
 /**
  *
  */
-int lua_sr_exp_register_mod(char *mname)
+static int lua_sr_sqlops_value(lua_State *L)
 {
-	int len;
+	str sres;
+	int col;
+	int row;
+	sql_val_t *val;
 
-	len = strlen(mname);
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
+	{
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_false(L);
+	}
+	sres.s = (char*)lua_tostring(L, -3);
+	row = lua_tointeger(L, -2);
+	col = lua_tointeger(L, -1);
+	if(row<0 || col<0 || sres.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+	sres.len = strlen(sres.s);
+	if(_lua_sqlopsb.value(&sres, row, col, &val)<0)
+		return app_lua_return_false(L);
+	if(val->flags&PV_VAL_NULL)
+	{
+		lua_pushinteger(L, 0);
+		return 1;
+	}
 
-	if(len==2 && strcmp(mname, "sl")==0)
+	if(val->flags&PV_VAL_INT)
 	{
-		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_SL;
-		return 0;
-	} else 	if(len==2 && strcmp(mname, "tm")==0) {
-		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_TM;
-		return 0;
+		lua_pushinteger(L, val->value.n);
+		return 1;
 	}
+	lua_pushlstring(L, val->value.s.s, val->value.s.len);
+	return 1;
+}
 
-	return -1;
+/**
+ *
+ */
+static int lua_sr_sqlops_is_null(lua_State *L)
+{
+	str sres;
+	int col;
+	int row;
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
+	{
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_false(L);
+	}
+	sres.s = (char*)lua_tostring(L, -3);
+	row = lua_tointeger(L, -2);
+	col = lua_tointeger(L, -1);
+	if(row<0 || col<0 || sres.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+	sres.len = strlen(sres.s);
+	if(_lua_sqlopsb.is_null(&sres, row, col)==1)
+		return app_lua_return_true(L);
+	return app_lua_return_false(L);
 }
 
 /**
  *
  */
-void lua_sr_exp_openlibs(lua_State *L)
+static int lua_sr_sqlops_column(lua_State *L)
 {
-	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SL)
-		luaL_openlib(L, "sr.sl",   _sr_sl_Map,   0);
-	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM)
-		luaL_openlib(L, "sr.tm",   _sr_tm_Map,   0);
+	str sres;
+	int col;
+	str name = {0, 0};
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
+	{
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_false(L);
+	}
+	sres.s = (char*)lua_tostring(L, -2);
+	col = lua_tointeger(L, -1);
+	if(col<0 || sres.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+	sres.len = strlen(sres.s);
+	if(_lua_sqlopsb.column(&sres, col, &name)<0)
+		return app_lua_return_false(L);
+	lua_pushlstring(L, name.s, name.len);
+	return 1;
+}
+
+/**
+ *
+ */
+static int lua_sr_sqlops_nrows(lua_State *L)
+{
+	str sres;
+	int rows;
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
+	{
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_false(L);
+	}
+	sres.s = (char*)lua_tostring(L, -1);
+	if(sres.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+	sres.len = strlen(sres.s);
+	rows = _lua_sqlopsb.nrows(&sres);
+	if(rows<0)
+		return app_lua_return_false(L);
+	lua_pushinteger(L, rows);
+	return 1;
+}
+
+/**
+ *
+ */
+static int lua_sr_sqlops_ncols(lua_State *L)
+{
+	str sres;
+	int cols;
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
+	{
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_false(L);
+	}
+	sres.s = (char*)lua_tostring(L, -1);
+	if(sres.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+	sres.len = strlen(sres.s);
+	cols = _lua_sqlopsb.ncols(&sres);
+	if(cols<0)
+		return app_lua_return_false(L);
+	lua_pushinteger(L, cols);
+	return 1;
 }
 
+/**
+ *
+ */
+static int lua_sr_sqlops_reset(lua_State *L)
+{
+	str sres;
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS))
+	{
+		LM_WARN("weird: sqlops function executed but module not registered\n");
+		return app_lua_return_false(L);
+	}
+	sres.s = (char*)lua_tostring(L, -1);
+	if(sres.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+	sres.len = strlen(sres.s);
+	_lua_sqlopsb.reset(&sres);
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static const luaL_reg _sr_sqlops_Map [] = {
+	{"query",   lua_sr_sqlops_query},
+	{"value",   lua_sr_sqlops_value},
+	{"is_null", lua_sr_sqlops_is_null},
+	{"column",  lua_sr_sqlops_column},
+	{"nrows",   lua_sr_sqlops_nrows},
+	{"ncols",   lua_sr_sqlops_ncols},
+	{"reset",   lua_sr_sqlops_reset},
+	{NULL, NULL}
+};
+
+
+/**
+ *
+ */
+static int lua_sr_rr_record_route(lua_State *L)
+{
+	int ret;
+	str sv = {0, 0};
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_RR))
+	{
+		LM_WARN("weird: rr function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)==1)
+	{
+		sv.s = (char*)lua_tostring(L, -1);
+		if(sv.s!=NULL)
+			sv.len = strlen(sv.s);
+	}
+	ret = _lua_rrb.record_route(env_L->msg, (sv.len>0)?&sv:NULL);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_rr_loose_route(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_RR))
+	{
+		LM_WARN("weird: rr function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	ret = _lua_rrb.loose_route(env_L->msg);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static const luaL_reg _sr_rr_Map [] = {
+	{"record_route",    lua_sr_rr_record_route},
+	{"loose_route",     lua_sr_rr_loose_route},
+	{NULL, NULL}
+};
+
+
+static int lua_sr_auth_challenge(lua_State *L, int hftype)
+{
+	int ret;
+	str realm = {0, 0};
+	int flags;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH))
+	{
+		LM_WARN("weird: auth function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=2)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	realm.s = (char*)lua_tostring(L, -2);
+	flags   = lua_tointeger(L, -1);
+	if(flags<0 || realm.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	realm.len = strlen(realm.s);
+	ret = _lua_authb.auth_challenge(env_L->msg, &realm, flags, hftype);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_www_challenge(lua_State *L)
+{
+	return lua_sr_auth_challenge(L, HDR_AUTHORIZATION_T);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_proxy_challenge(lua_State *L)
+{
+	return lua_sr_auth_challenge(L, HDR_PROXYAUTH_T);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_pv_authenticate(lua_State *L, int hftype)
+{
+	int ret;
+	str realm  = {0, 0};
+	str passwd = {0, 0};
+	int flags;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH))
+	{
+		LM_WARN("weird: auth function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=3)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	realm.s  = (char*)lua_tostring(L, -3);
+	passwd.s = (char*)lua_tostring(L, -2);
+	flags    = lua_tointeger(L, -1);
+	if(flags<0 || realm.s==NULL || passwd.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	realm.len = strlen(realm.s);
+	passwd.len = strlen(passwd.s);
+	ret = _lua_authb.pv_authenticate(env_L->msg, &realm, &passwd, flags,
+			hftype);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_pv_www_authenticate(lua_State *L)
+{
+	return lua_sr_auth_pv_authenticate(L, HDR_AUTHORIZATION_T);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_pv_proxy_authenticate(lua_State *L)
+{
+	return lua_sr_auth_pv_authenticate(L, HDR_PROXYAUTH_T);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_consume_credentials(lua_State *L)
+{
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH))
+	{
+		LM_WARN("weird: auth function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	ret = _lua_authb.consume_credentials(env_L->msg);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static const luaL_reg _sr_auth_Map [] = {
+	{"www_challenge",            lua_sr_auth_www_challenge},
+	{"proxy_challenge",          lua_sr_auth_proxy_challenge},
+	{"pv_www_authenticate",      lua_sr_auth_pv_www_authenticate},
+	{"pv_proxy_authenticate",    lua_sr_auth_pv_proxy_authenticate},
+	{"consume_credentials",      lua_sr_auth_consume_credentials},
+	{NULL, NULL}
+};
+
+
+/**
+ *
+ */
+static int lua_sr_auth_db_authenticate(lua_State *L, hdr_types_t hftype)
+{
+	int ret;
+	str realm = {0, 0};
+	str table = {0, 0};
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH_DB))
+	{
+		LM_WARN("weird: auth function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=2)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	realm.s  = (char*)lua_tostring(L, -2);
+	table.s  = (char*)lua_tostring(L, -1);
+	if(realm.s==NULL || table.s==NULL)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	realm.len = strlen(realm.s);
+	table.len = strlen(table.s);
+	ret = _lua_auth_dbb.digest_authenticate(env_L->msg, &realm, &table,
+			hftype);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_db_www_authenticate(lua_State *L)
+{
+	return lua_sr_auth_db_authenticate(L, HDR_AUTHORIZATION_T);
+}
+
+/**
+ *
+ */
+static int lua_sr_auth_db_proxy_authenticate(lua_State *L)
+{
+	return lua_sr_auth_db_authenticate(L, HDR_PROXYAUTH_T);
+}
+
+/**
+ *
+ */
+static const luaL_reg _sr_auth_db_Map [] = {
+	{"www_authenticate",      lua_sr_auth_db_www_authenticate},
+	{"proxy_authenticate",    lua_sr_auth_db_proxy_authenticate},
+	{NULL, NULL}
+};
+
+
+/**
+ *
+ */
+static int lua_sr_maxfwd_process_maxfwd(lua_State *L)
+{
+	int ret;
+	int limit;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_MAXFWD))
+	{
+		LM_WARN("weird: maxfwd function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=1)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	limit = lua_tointeger(L, -1);
+	if(limit<0)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	ret = _lua_maxfwdb.process_maxfwd(env_L->msg, limit);
+
+	return app_lua_return_int(L, ret);
+}
+
+
+/**
+ *
+ */
+static const luaL_reg _sr_maxfwd_Map [] = {
+	{"process_maxfwd",      lua_sr_maxfwd_process_maxfwd},
+	{NULL, NULL}
+};
+
+
+/**
+ *
+ */
+static int lua_sr_registrar_save(lua_State *L)
+{
+	int ret;
+	int flags;
+	char *table;
+	sr_lua_env_t *env_L;
+
+	flags = 0;
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_MAXFWD))
+	{
+		LM_WARN("weird: maxfwd function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)==1)
+	{
+		table  = (char*)lua_tostring(L, -1);
+	} else if(lua_gettop(L)==2) {
+		table  = (char*)lua_tostring(L, -2);
+		flags = lua_tointeger(L, -1);
+	} else {
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	if(table==NULL || strlen(table)==0)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	ret = _lua_registrarb.save(env_L->msg, table, flags);
+
+	return app_lua_return_int(L, ret);
+}
+
+/**
+ *
+ */
+static int lua_sr_registrar_lookup(lua_State *L)
+{
+	int ret;
+	char *table;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+
+	if(!(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_MAXFWD))
+	{
+		LM_WARN("weird: maxfwd function executed but module not registered\n");
+		return app_lua_return_error(L);
+	}
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_error(L);
+	}
+	if(lua_gettop(L)!=1)
+	{
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	table  = (char*)lua_tostring(L, -1);
+	if(table==NULL || strlen(table)==0)
+	{
+		LM_WARN("invalid parameters from Lua\n");
+		return app_lua_return_error(L);
+	}
+	ret = _lua_registrarb.lookup(env_L->msg, table);
+
+	return app_lua_return_int(L, ret);
+}
+
+
+/**
+ *
+ */
+static const luaL_reg _sr_registrar_Map [] = {
+	{"save",      lua_sr_registrar_save},
+	{"lookup",    lua_sr_registrar_lookup},
+	{NULL, NULL}
+};
+
+
+/**
+ *
+ */
+int lua_sr_exp_init_mod(void)
+{
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SL)
+	{
+		/* bind the SL API */
+		if (sl_load_api(&_lua_slb) < 0) {
+			LM_ERR("cannot bind to SL API\n");
+			return -1;
+		}
+		LM_DBG("loaded sl api\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM)
+	{
+		/* bind the TM API */
+		if (tm_load_api(&_lua_tmb) < 0)
+		{
+			LM_ERR("cannot bind to TM API\n");
+			return -1;
+		}
+		LM_DBG("loaded tm api\n");
+		/* bind the TM XAPI */
+		if (tm_load_xapi(&_lua_xtmb) < 0)
+		{
+			LM_ERR("cannot bind to TM XAPI\n");
+			return -1;
+		}
+		LM_DBG("loaded tm xapi\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS)
+	{
+		/* bind the SQLOPS API */
+		if (sqlops_load_api(&_lua_sqlopsb) < 0)
+		{
+			LM_ERR("cannot bind to SQLOPS API\n");
+			return -1;
+		}
+		LM_DBG("loaded sqlops api\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_RR)
+	{
+		/* bind the RR API */
+		if (rr_load_api(&_lua_rrb) < 0)
+		{
+			LM_ERR("cannot bind to RR API\n");
+			return -1;
+		}
+		LM_DBG("loaded rr api\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH)
+	{
+		/* bind the AUTH API */
+		if (auth_load_api(&_lua_authb) < 0)
+		{
+			LM_ERR("cannot bind to AUTH API\n");
+			return -1;
+		}
+		LM_DBG("loaded auth api\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH_DB)
+	{
+		/* bind the AUTH_DB API */
+		if (auth_db_load_api(&_lua_auth_dbb) < 0)
+		{
+			LM_ERR("cannot bind to AUTH_DB API\n");
+			return -1;
+		}
+		LM_DBG("loaded auth_db api\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_MAXFWD)
+	{
+		/* bind the MAXFWD API */
+		if (maxfwd_load_api(&_lua_maxfwdb) < 0)
+		{
+			LM_ERR("cannot bind to MAXFWD API\n");
+			return -1;
+		}
+		LM_DBG("loaded maxfwd api\n");
+	}
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_REGISTRAR)
+	{
+		/* bind the REGISTRAR API */
+		if (registrar_load_api(&_lua_registrarb) < 0)
+		{
+			LM_ERR("cannot bind to REGISTRAR API\n");
+			return -1;
+		}
+		LM_DBG("loaded registrar api\n");
+	}
+	return 0;
+}
+
+/**
+ *
+ */
+int lua_sr_exp_register_mod(char *mname)
+{
+	int len;
+
+	len = strlen(mname);
+
+	if(len==2 && strcmp(mname, "sl")==0)
+	{
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_SL;
+		return 0;
+	} else 	if(len==2 && strcmp(mname, "tm")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_TM;
+		return 0;
+	} else 	if(len==6 && strcmp(mname, "sqlops")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_SQLOPS;
+		return 0;
+	} else 	if(len==2 && strcmp(mname, "rr")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_RR;
+		return 0;
+	} else 	if(len==4 && strcmp(mname, "auth")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_AUTH;
+		return 0;
+	} else 	if(len==7 && strcmp(mname, "auth_db")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_AUTH_DB;
+		return 0;
+	} else 	if(len==6 && strcmp(mname, "maxfwd")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_MAXFWD;
+		return 0;
+	} else 	if(len==9 && strcmp(mname, "registrar")==0) {
+		_sr_lua_exp_reg_mods |= SR_LUA_EXP_MOD_REGISTRAR;
+		return 0;
+	}
+
+	return -1;
+}
+
+/**
+ *
+ */
+void lua_sr_exp_openlibs(lua_State *L)
+{
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SL)
+		luaL_openlib(L, "sr.sl",         _sr_sl_Map,          0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_TM)
+		luaL_openlib(L, "sr.tm",         _sr_tm_Map,          0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_SQLOPS)
+		luaL_openlib(L, "sr.sqlops",     _sr_sqlops_Map,      0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_RR)
+		luaL_openlib(L, "sr.rr",         _sr_rr_Map,          0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH)
+		luaL_openlib(L, "sr.auth",       _sr_auth_Map,        0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_AUTH_DB)
+		luaL_openlib(L, "sr.auth_db",    _sr_auth_db_Map,     0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_MAXFWD)
+		luaL_openlib(L, "sr.maxfwd",     _sr_maxfwd_Map,      0);
+	if(_sr_lua_exp_reg_mods&SR_LUA_EXP_MOD_REGISTRAR)
+		luaL_openlib(L, "sr.registrar",  _sr_registrar_Map,   0);
+}
 

+ 421 - 6
modules/app_lua/app_lua_sr.c

@@ -34,6 +34,10 @@
 #include "../../mem/mem.h"
 #include "../../data_lump.h"
 #include "../../data_lump_rpl.h"
+#include "../../forward.h"
+#include "../../flags.h"
+#include "../../dset.h"
+#include "../../parser/parse_uri.h"
 #include "../../lib/kcore/cmpapi.h"
 
 #include "app_lua_api.h"
@@ -271,15 +275,426 @@ error:
 	return 1;
 }
 
+/**
+ *
+ */
+static int lua_sr_is_myself (lua_State *L)
+{
+	str uri;
+	struct sip_uri puri;
+	int ret;
+
+	uri.s = (char*)lua_tostring(L, -1);
+	if(uri.s==NULL)
+	{
+		LM_ERR("invalid uri parameter\n");
+		return app_lua_return_false(L);
+	}
+	uri.len = strlen(uri.s);
+	if(uri.len>4 && (strncmp(uri.s, "sip:", 4)==0
+				|| strncmp(uri.s, "sips:", 5)==0))
+	{
+		if(parse_uri(uri.s, uri.len, &puri)!=0)
+		{
+			LM_ERR("failed to parse uri [%s]\n", uri.s);
+			return app_lua_return_false(L);
+		}
+		ret = check_self(&puri.host, (puri.port.s)?puri.port_no:0,
+				(puri.transport_val.s)?puri.proto:0);
+	} else {
+		ret = check_self(&uri, 0, 0);
+	}
+	if(ret==1)
+		return app_lua_return_true(L);
+	return app_lua_return_false(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_setflag (lua_State *L)
+{
+	int flag;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	flag = lua_tointeger(L, -1);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (!flag_in_range(flag))
+	{
+		LM_ERR("invalid flag parameter %d\n", flag);
+		return app_lua_return_false(L);
+	}
+
+	setflag(env_L->msg, flag);
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_resetflag (lua_State *L)
+{
+	int flag;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	flag = lua_tointeger(L, -1);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (!flag_in_range(flag))
+	{
+		LM_ERR("invalid flag parameter %d\n", flag);
+		return app_lua_return_false(L);
+	}
+
+	resetflag(env_L->msg, flag);
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_isflagset (lua_State *L)
+{
+	int flag;
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	flag = lua_tointeger(L, -1);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (!flag_in_range(flag))
+	{
+		LM_ERR("invalid flag parameter %d\n", flag);
+		return app_lua_return_false(L);
+	}
+
+	ret = isflagset(env_L->msg, flag);
+	if(ret>0)
+		return app_lua_return_true(L);
+	return app_lua_return_false(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_setbflag (lua_State *L)
+{
+	int flag;
+	int branch;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	if(lua_gettop(L)==1)
+	{
+		flag = lua_tointeger(L, -1);
+		branch = 0;
+	} else if(lua_gettop(L)==2) {
+		flag = lua_tointeger(L, -2);
+		branch = lua_tointeger(L, -1);
+	} else {
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (!flag_in_range(flag))
+	{
+		LM_ERR("invalid flag parameter %d\n", flag);
+		return app_lua_return_false(L);
+	}
+
+	setbflag(branch, flag);
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_resetbflag (lua_State *L)
+{
+	int flag;
+	int branch;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	if(lua_gettop(L)==1)
+	{
+		flag = lua_tointeger(L, -1);
+		branch = 0;
+	} else if(lua_gettop(L)==2) {
+		flag = lua_tointeger(L, -2);
+		branch = lua_tointeger(L, -1);
+	} else {
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (!flag_in_range(flag))
+	{
+		LM_ERR("invalid flag parameter %d\n", flag);
+		return app_lua_return_false(L);
+	}
+
+	resetbflag(branch, flag);
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_isbflagset (lua_State *L)
+{
+	int flag;
+	int branch;
+	int ret;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	if(lua_gettop(L)==1)
+	{
+		flag = lua_tointeger(L, -1);
+		branch = 0;
+	} else if(lua_gettop(L)==2) {
+		flag = lua_tointeger(L, -2);
+		branch = lua_tointeger(L, -1);
+	} else {
+		LM_WARN("invalid number of parameters from Lua\n");
+		return app_lua_return_false(L);
+	}
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (!flag_in_range(flag))
+	{
+		LM_ERR("invalid flag parameter %d\n", flag);
+		return app_lua_return_false(L);
+	}
+
+	ret = isbflagset(branch, flag);
+	if(ret>0)
+		return app_lua_return_true(L);
+	return app_lua_return_false(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_seturi (lua_State *L)
+{
+	struct action  act;
+	struct run_act_ctx h;
+	str uri;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	uri.s = (char*)lua_tostring(L, -1);
+	if(uri.s==NULL)
+	{
+		LM_ERR("invalid uri parameter\n");
+		return app_lua_return_false(L);
+	}
+	uri.len = strlen(uri.s);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	memset(&act, 0, sizeof(act));
+	act.val[0].type = STRING_ST;
+	act.val[0].u.string = uri.s;
+	act.type = SET_URI_T;
+	init_run_actions_ctx(&h);
+	if (do_action(&h, &act, env_L->msg)<0)
+	{
+		LM_ERR("do action failed\n");
+		return app_lua_return_false(L);
+	}
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_setuser (lua_State *L)
+{
+	struct action  act;
+	struct run_act_ctx h;
+	str uri;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	uri.s = (char*)lua_tostring(L, -1);
+	if(uri.s==NULL)
+	{
+		LM_ERR("invalid uri parameter\n");
+		return app_lua_return_false(L);
+	}
+	uri.len = strlen(uri.s);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	memset(&act, 0, sizeof(act));
+	act.val[0].type = STRING_ST;
+	act.val[0].u.string = uri.s;
+	act.type = SET_USER_T;
+	init_run_actions_ctx(&h);
+	if (do_action(&h, &act, env_L->msg)<0)
+	{
+		LM_ERR("do action failed\n");
+		return app_lua_return_false(L);
+	}
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_sethost (lua_State *L)
+{
+	struct action  act;
+	struct run_act_ctx h;
+	str uri;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	uri.s = (char*)lua_tostring(L, -1);
+	if(uri.s==NULL)
+	{
+		LM_ERR("invalid uri parameter\n");
+		return app_lua_return_false(L);
+	}
+	uri.len = strlen(uri.s);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	memset(&act, 0, sizeof(act));
+	act.val[0].type = STRING_ST;
+	act.val[0].u.string = uri.s;
+	act.type = SET_HOST_T;
+	init_run_actions_ctx(&h);
+	if (do_action(&h, &act, env_L->msg)<0)
+	{
+		LM_ERR("do action failed\n");
+		return app_lua_return_false(L);
+	}
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_setdsturi (lua_State *L)
+{
+	str uri;
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	uri.s = (char*)lua_tostring(L, -1);
+	if(uri.s==NULL)
+	{
+		LM_ERR("invalid uri parameter\n");
+		return app_lua_return_false(L);
+	}
+	uri.len = strlen(uri.s);
+
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	if (set_dst_uri(env_L->msg, &uri)<0)
+	{
+		LM_ERR("setting dst uri failed\n");
+		return app_lua_return_false(L);
+	}
+	return app_lua_return_true(L);
+}
+
+/**
+ *
+ */
+static int lua_sr_resetdsturi (lua_State *L)
+{
+	sr_lua_env_t *env_L;
+
+	env_L = sr_lua_env_get();
+	if(env_L->msg==NULL)
+	{
+		LM_WARN("invalid parameters from Lua env\n");
+		return app_lua_return_false(L);
+	}
+
+	reset_dst_uri(env_L->msg);
+	return app_lua_return_true(L);
+}
+
+
 /**
  *
  */
 static const luaL_reg _sr_core_Map [] = {
-	{"probe", lua_sr_probe},
-	{"dbg",   lua_sr_dbg},
-	{"err",   lua_sr_err},
-	{"log",   lua_sr_log},
-	{"modf",  lua_sr_modf},
+	{"probe",        lua_sr_probe},
+	{"dbg",          lua_sr_dbg},
+	{"err",          lua_sr_err},
+	{"log",          lua_sr_log},
+	{"modf",         lua_sr_modf},
+	{"is_myself",    lua_sr_is_myself},
+	{"setflag",      lua_sr_setflag},
+	{"resetflag",    lua_sr_resetflag},
+	{"isflagset",    lua_sr_isflagset},
+	{"setbflag",     lua_sr_setbflag},
+	{"resetbflag",   lua_sr_resetbflag},
+	{"isbflagset",   lua_sr_isbflagset},
+	{"seturi",       lua_sr_seturi},
+	{"setuser",      lua_sr_setuser},
+	{"sethost",      lua_sr_sethost},
+	{"setdsturi",    lua_sr_setdsturi},
+	{"resetdsturi",  lua_sr_resetdsturi},
 	{NULL, NULL}
 };
 
@@ -629,7 +1044,7 @@ static int lua_sr_pv_is_null (lua_State *L)
 		return 0;
 
 	pvn.len = strlen(pvn.s);
-	LM_DBG("pv is null: %s\n", pvn.s);
+	LM_DBG("pv is null test: %s\n", pvn.s);
 	if(pv_parse_spec(&pvn, &pvs)<0)
 	{
 		LM_ERR("unable to parse pv [%s]\n", pvn.s);

+ 44 - 2
modules/app_lua/doc/app_lua_admin.xml

@@ -96,7 +96,7 @@
 		<title>Set <varname>load</varname> parameter</title>
 		<programlisting format="linespecific">
 ...
-modparam("lua", "load", "/usr/local/etc/kamailio/lua/myscript.lua")
+modparam("app_lua", "load", "/usr/local/etc/kamailio/lua/myscript.lua")
 ...
 </programlisting>
 	    </example>
@@ -109,12 +109,54 @@ modparam("lua", "load", "/usr/local/etc/kamailio/lua/myscript.lua")
 			to Lua. Available submodules are:
 	    </para>
 	    	<itemizedlist>
+		    <listitem>
+			<para>
+				<emphasis>auth</emphasis> - register functions from auth module
+				under 'sr.auth'.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+				<emphasis>auth_db</emphasis> - register functions from auth_db
+				module under 'sr.auth_db'.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+				<emphasis>maxfwd</emphasis> - register functions from maxfwd
+				module under 'sr.maxfwd'.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+				<emphasis>registrar</emphasis> - register functions from
+				registrar module under 'sr.registrar'.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+				<emphasis>rr</emphasis> - register functions from rr module
+				under 'sr.rr'.
+			</para>
+		    </listitem>
+		    <listitem>
+			<para>
+				<emphasis>sqlops</emphasis> - register functions from sqlops
+				module under 'sr.sqlops'.
+			</para>
+		    </listitem>
 		    <listitem>
 			<para>
 				<emphasis>sl</emphasis> - register functions from sl module
 				under 'sr.sl'.
 			</para>
 		    </listitem>
+		    <listitem>
+			<para>
+				<emphasis>tm</emphasis> - register functions from tm module
+				under 'sr.tm'.
+			</para>
+		    </listitem>
 	    	</itemizedlist>
 	    <para>
 			Note that 'sr', 'sr.hdr' and 'sr.pv' modules are always registered
@@ -129,7 +171,7 @@ modparam("lua", "load", "/usr/local/etc/kamailio/lua/myscript.lua")
 		<title>Set <varname>register</varname> parameter</title>
 		<programlisting format="linespecific">
 ...
-modparam("lua", "register", "sr")
+modparam("app_lua", "register", "sl")
 ...
 </programlisting>
 	    </example>

+ 3 - 0
modules/auth/api.c

@@ -232,5 +232,8 @@ int bind_auth_s(auth_api_s_t* api)
 	api->calc_HA1 = calc_HA1;
 	api->calc_response = calc_response;
 	api->check_response = auth_check_response;
+	api->auth_challenge = auth_challenge;
+	api->pv_authenticate = pv_authenticate;
+	api->consume_credentials = consume_credentials;
 	return 0;
 }

+ 41 - 3
modules/auth/api.h

@@ -33,6 +33,7 @@
 
 #include "../../parser/msg_parser.h"
 #include "../../parser/digest/digest.h"
+#include "../../sr_module.h"
 #include "../../usr_avp.h"
 #include "../../parser/hf.h"
 #include "../../str.h"
@@ -96,6 +97,19 @@ auth_result_t post_auth(struct sip_msg* msg, struct hdr_field* hdr);
 typedef int (*check_response_t)(dig_cred_t* cred, str* method, char* ha1);
 int auth_check_response(dig_cred_t* cred, str* method, char* ha1);
 
+typedef int (*auth_challenge_f)(struct sip_msg *msg, str *realm, int flags,
+		int hftype);
+int auth_challenge(struct sip_msg *msg, str *realm, int flags,
+		int hftype);
+
+typedef int (*pv_authenticate_f)(struct sip_msg *msg, str *realm, str *passwd,
+		int flags, int hftype);
+int pv_authenticate(struct sip_msg *msg, str *realm, str *passwd,
+		int flags, int hftype);
+
+typedef int (*consume_credentials_f)(struct sip_msg* msg);
+int consume_credentials(struct sip_msg* msg);
+
 /*
  * Auth module API
  */
@@ -104,13 +118,37 @@ typedef struct auth_api_s {
     post_auth_t post_auth;                /* The function to be called after authentication */
     build_challenge_hf_t build_challenge; /* Function to build digest challenge header */
     struct qp* qop;                       /* qop module parameter */
-	calc_HA1_t      calc_HA1;
-	calc_response_t calc_response;
-	check_response_t check_response;
+	calc_HA1_t         calc_HA1;
+	calc_response_t    calc_response;
+	check_response_t   check_response;
+	auth_challenge_f   auth_challenge;
+	pv_authenticate_f  pv_authenticate;
+	consume_credentials_f consume_credentials;
 } auth_api_s_t;
 
 typedef int (*bind_auth_s_t)(auth_api_s_t* api);
 int bind_auth_s(auth_api_s_t* api);
 
+/**
+ * load AUTH module API
+ */
+static inline int auth_load_api(auth_api_s_t* api)
+{
+	bind_auth_s_t bind_auth;
+
+	/* bind to auth module and import the API */
+	bind_auth = (bind_auth_s_t)find_export("bind_auth_s", 0, 0);
+	if (!bind_auth) {
+		LM_ERR("unable to find bind_auth function. Check if you load"
+				" the auth module.\n");
+		return -1;
+	}
+
+	if (bind_auth(api) < 0) {
+		LM_ERR("unable to bind auth module\n");
+		return -1;
+	}
+	return 0;
+}
 
 #endif /* API_H */

+ 137 - 64
modules/auth/auth_mod.c

@@ -77,7 +77,7 @@ static int mod_init(void);
 /*
  * Remove used credentials from a SIP message header
  */
-int consume_credentials(struct sip_msg* msg, char* s1, char* s2);
+int w_consume_credentials(struct sip_msg* msg, char* s1, char* s2);
 
 static int pv_proxy_authenticate(struct sip_msg* msg, char* realm,
 		char *passwd, char *flags);
@@ -132,7 +132,7 @@ sl_api_t slb;
  * Exported functions
  */
 static cmd_export_t cmds[] = {
-    {"consume_credentials",    consume_credentials,                  0,
+    {"consume_credentials",    w_consume_credentials,                0,
 			0, REQUEST_ROUTE},
     {"www_challenge",          (cmd_function)www_challenge,          2,
 			fixup_auth_challenge, REQUEST_ROUTE},
@@ -355,7 +355,7 @@ static void destroy(void)
 /*
  * Remove used credentials from a SIP message header
  */
-int consume_credentials(struct sip_msg* msg, char* s1, char* s2)
+int consume_credentials(struct sip_msg* msg)
 {
     struct hdr_field* h;
     int len;
@@ -383,15 +383,20 @@ int consume_credentials(struct sip_msg* msg, char* s1, char* s2)
     return 1;
 }
 
+/**
+ *
+ */
+int w_consume_credentials(struct sip_msg* msg, char* s1, char* s2)
+{
+	return consume_credentials(msg);
+}
+
 /**
  * @brief do WWW-Digest authentication with password taken from cfg var
  */
-static int pv_authenticate(struct sip_msg *msg, char *p1, char *p2,
-		char *p3, int hftype)
+int pv_authenticate(struct sip_msg *msg, str *realm, str *passwd,
+		int flags, int hftype)
 {
-    int flags = 0;
-    str realm  = {0, 0};
-    str passwd = {0, 0};
 	struct hdr_field* h;
 	auth_body_t* cred;
 	int ret;
@@ -403,32 +408,7 @@ static int pv_authenticate(struct sip_msg *msg, char *p1, char *p2,
 	cred = 0;
 	ret = AUTH_ERROR;
 
-	if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) {
-		LM_ERR("failed to get realm value\n");
-		goto error;
-	}
-
-	if(realm.len==0) {
-		LM_ERR("invalid realm value - empty content\n");
-		goto error;
-	}
-
-	if (get_str_fparam(&passwd, msg, (fparam_t*)p2) < 0) {
-		LM_ERR("failed to get passwd value\n");
-		goto error;
-	}
-
-	if(passwd.len==0) {
-		LM_ERR("invalid password value - empty content\n");
-		goto error;
-	}
-
-	if (get_int_fparam(&flags, msg, (fparam_t*)p3) < 0) {
-		LM_ERR("invalid flags value\n");
-		goto error;
-	}
-
-	switch(pre_auth(msg, &realm, hftype, &h, NULL)) {
+	switch(pre_auth(msg, realm, hftype, &h, NULL)) {
 		case ERROR:
 		case BAD_CREDENTIALS:
 			LM_DBG("error or bad credentials\n");
@@ -458,12 +438,12 @@ static int pv_authenticate(struct sip_msg *msg, char *p1, char *p2,
 	/* compute HA1 if needed */
 	if ((flags&1)==0) {
 		/* Plaintext password is stored in PV, calculate HA1 */
-		calc_HA1(HA_MD5, &cred->digest.username.whole, &realm,
-				&passwd, 0, 0, ha1);
+		calc_HA1(HA_MD5, &cred->digest.username.whole, realm,
+				passwd, 0, 0, ha1);
 		LM_DBG("HA1 string calculated: %s\n", ha1);
 	} else {
-		memcpy(ha1, passwd.s, passwd.len);
-		ha1[passwd.len] = '\0';
+		memcpy(ha1, passwd->s, passwd->len);
+		ha1[passwd->len] = '\0';
 	}
 
 	/* Recalculate response, it must be same to authorize successfully */
@@ -496,7 +476,7 @@ end:
 			qop = &auth_qauth;
 		}
 		if (get_challenge_hf(msg, (cred ? cred->stale : 0),
-				&realm, NULL, NULL, qop, hftype, &hf) < 0) {
+				realm, NULL, NULL, qop, hftype, &hf) < 0) {
 			ERR("Error while creating challenge\n");
 			ret = AUTH_ERROR;
 		} else {
@@ -510,9 +490,7 @@ end:
 		}
 	}
 
-error:
 	return ret;
-
 }
 
 /**
@@ -521,7 +499,38 @@ error:
 static int pv_proxy_authenticate(struct sip_msg *msg, char* realm,
 		char *passwd, char *flags)
 {
-	return pv_authenticate(msg, realm, passwd, flags, HDR_PROXYAUTH_T);
+    int vflags = 0;
+    str srealm  = {0, 0};
+    str spasswd = {0, 0};
+
+	if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
+		LM_ERR("failed to get realm value\n");
+		goto error;
+	}
+
+	if(srealm.len==0) {
+		LM_ERR("invalid realm value - empty content\n");
+		goto error;
+	}
+
+	if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) {
+		LM_ERR("failed to get passwd value\n");
+		goto error;
+	}
+
+	if(spasswd.len==0) {
+		LM_ERR("invalid password value - empty content\n");
+		goto error;
+	}
+
+	if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) {
+		LM_ERR("invalid flags value\n");
+		goto error;
+	}
+	return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_PROXYAUTH_T);
+
+error:
+	return AUTH_ERROR;
 }
 
 /**
@@ -530,7 +539,38 @@ static int pv_proxy_authenticate(struct sip_msg *msg, char* realm,
 static int pv_www_authenticate(struct sip_msg *msg, char* realm,
 		char *passwd, char *flags)
 {
-	return pv_authenticate(msg, realm, passwd, flags, HDR_AUTHORIZATION_T);
+    int vflags = 0;
+    str srealm  = {0, 0};
+    str spasswd = {0, 0};
+
+	if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
+		LM_ERR("failed to get realm value\n");
+		goto error;
+	}
+
+	if(srealm.len==0) {
+		LM_ERR("invalid realm value - empty content\n");
+		goto error;
+	}
+
+	if (get_str_fparam(&spasswd, msg, (fparam_t*)passwd) < 0) {
+		LM_ERR("failed to get passwd value\n");
+		goto error;
+	}
+
+	if(spasswd.len==0) {
+		LM_ERR("invalid password value - empty content\n");
+		goto error;
+	}
+
+	if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) {
+		LM_ERR("invalid flags value\n");
+		goto error;
+	}
+	return pv_authenticate(msg, &srealm, &spasswd, vflags, HDR_AUTHORIZATION_T);
+
+error:
+	return AUTH_ERROR;
 }
 
 /**
@@ -581,37 +621,20 @@ static int auth_send_reply(struct sip_msg *msg, int code, char *reason,
 /**
  *
  */
-static int auth_challenge(struct sip_msg *msg, char *p1, char *p2, int hftype)
+int auth_challenge(struct sip_msg *msg, str *realm, int flags, int hftype)
 {
-    int flags = 0;
-    str realm  = {0, 0};
 	int ret;
     str hf = {0, 0};
 	struct qp *qop = NULL;
 
 	ret = -1;
 
-	if (get_str_fparam(&realm, msg, (fparam_t*)p1) < 0) {
-		LM_ERR("failed to get realm value\n");
-		goto error;
-	}
-
-	if(realm.len==0) {
-		LM_ERR("invalid realm value - empty content\n");
-		goto error;
-	}
-
-	if (get_int_fparam(&flags, msg, (fparam_t*)p2) < 0) {
-		LM_ERR("invalid flags value\n");
-		goto error;
-	}
-	
 	if(flags&2) {
 		qop = &auth_qauthint;
 	} else if(flags&1) {
 		qop = &auth_qauth;
 	}
-	if (get_challenge_hf(msg, 0, &realm, NULL, NULL, qop, hftype, &hf) < 0) {
+	if (get_challenge_hf(msg, 0, realm, NULL, NULL, qop, hftype, &hf) < 0) {
 		ERR("Error while creating challenge\n");
 		ret = -2;
 		goto error;
@@ -647,7 +670,32 @@ error:
  */
 static int proxy_challenge(struct sip_msg *msg, char* realm, char *flags)
 {
-	return auth_challenge(msg, realm, flags, HDR_PROXYAUTH_T);
+	int vflags = 0;
+	str srealm  = {0, 0};
+
+	if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
+		LM_ERR("failed to get realm value\n");
+		goto error;
+	}
+
+	if(srealm.len==0) {
+		LM_ERR("invalid realm value - empty content\n");
+		goto error;
+	}
+
+	if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) {
+		LM_ERR("invalid flags value\n");
+		goto error;
+	}
+
+	return auth_challenge(msg, &srealm, vflags, HDR_PROXYAUTH_T);
+
+error:
+	if(!(vflags&4)) {
+		if(auth_send_reply(msg, 500, "Internal Server Error", 0, 0) <0 )
+			return -4;
+	}
+	return -1;
 }
 
 /**
@@ -655,7 +703,32 @@ static int proxy_challenge(struct sip_msg *msg, char* realm, char *flags)
  */
 static int www_challenge(struct sip_msg *msg, char* realm, char *flags)
 {
-	return auth_challenge(msg, realm, flags, HDR_AUTHORIZATION_T);
+	int vflags = 0;
+	str srealm  = {0, 0};
+
+	if (get_str_fparam(&srealm, msg, (fparam_t*)realm) < 0) {
+		LM_ERR("failed to get realm value\n");
+		goto error;
+	}
+
+	if(srealm.len==0) {
+		LM_ERR("invalid realm value - empty content\n");
+		goto error;
+	}
+
+	if (get_int_fparam(&vflags, msg, (fparam_t*)flags) < 0) {
+		LM_ERR("invalid flags value\n");
+		goto error;
+	}
+
+	return auth_challenge(msg, &srealm, vflags, HDR_AUTHORIZATION_T);
+
+error:
+	if(!(vflags&4)) {
+		if(auth_send_reply(msg, 500, "Internal Server Error", 0, 0) <0 )
+			return -4;
+	}
+	return -1;
 }
 
 /**

+ 17 - 6
modules/tm/tm.c

@@ -292,12 +292,12 @@ static int t_branch_timeout(struct sip_msg* msg, char*, char*);
 static int t_branch_replied(struct sip_msg* msg, char*, char*);
 static int t_any_timeout(struct sip_msg* msg, char*, char*);
 static int t_any_replied(struct sip_msg* msg, char*, char*);
-static int t_is_canceled(struct sip_msg* msg, char*, char*);
+static int w_t_is_canceled(struct sip_msg* msg, char*, char*);
 static int t_is_expired(struct sip_msg* msg, char*, char*);
 static int t_grep_status(struct sip_msg* msg, char*, char*);
 static int w_t_drop_replies(struct sip_msg* msg, char* foo, char* bar);
 static int w_t_save_lumps(struct sip_msg* msg, char* foo, char* bar);
-static int t_check_trans(struct sip_msg* msg, char* foo, char* bar);
+static int w_t_check_trans(struct sip_msg* msg, char* foo, char* bar);
 
 
 /* by default the fr timers avps are not set, so that the avps won't be
@@ -448,7 +448,7 @@ static cmd_export_t cmds[]={
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 	{"t_any_replied",     t_any_replied,            0, 0, 
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
-	{"t_is_canceled",     t_is_canceled,            0, 0,
+	{"t_is_canceled",     w_t_is_canceled,          0, 0,
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
 	{"t_is_expired",      t_is_expired,             0, 0,
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE },
@@ -460,7 +460,7 @@ static cmd_export_t cmds[]={
 			FAILURE_ROUTE},
 	{"t_save_lumps",      w_t_save_lumps,           0, 0,
 			REQUEST_ROUTE},
-	{"t_check_trans",	t_check_trans,				0, 0,
+	{"t_check_trans",	  w_t_check_trans,			0, 0,
 			REQUEST_ROUTE|TM_ONREPLY_ROUTE|BRANCH_ROUTE },
 
 	{"t_load_contacts", t_load_contacts,            0, 0,
@@ -470,6 +470,7 @@ static cmd_export_t cmds[]={
 
 	/* not applicable from the script */
 	{"load_tm",            (cmd_function)load_tm,           NO_SCRIPT,   0, 0},
+	{"load_xtm",           (cmd_function)load_xtm,          NO_SCRIPT,   0, 0},
 	{0,0,0,0,0}
 };
 
@@ -1755,7 +1756,7 @@ int t_branch_replied(struct sip_msg* msg, char* foo, char* bar)
 
 
 /* script function, returns: 1 if the transaction was canceled, -1 if not */
-int t_is_canceled(struct sip_msg* msg, char* foo, char* bar)
+int t_is_canceled(struct sip_msg* msg)
 {
 	struct cell *t;
 	int ret;
@@ -1773,6 +1774,11 @@ int t_is_canceled(struct sip_msg* msg, char* foo, char* bar)
 	return ret;
 }
 
+static int w_t_is_canceled(struct sip_msg* msg, char* foo, char* bar)
+{
+	return t_is_canceled(msg);
+}
+
 /* script function, returns: 1 if the transaction lifetime interval has already elapsed, -1 if not */
 int t_is_expired(struct sip_msg* msg, char* foo, char* bar)
 {
@@ -1937,7 +1943,7 @@ int w_t_reply_wrp(struct sip_msg *m, unsigned int code, char *txt)
  *       reliable: if the ACK  is delayed the proxied transaction might
  *       be already deleted when it reaches the proxy (wait_timeout))
  */
-static int t_check_trans(struct sip_msg* msg, char* foo, char* bar)
+int t_check_trans(struct sip_msg* msg)
 {
 	struct cell* t;
 	
@@ -1976,6 +1982,11 @@ static int t_check_trans(struct sip_msg* msg, char* foo, char* bar)
 	return -1;
 }
 
+static int w_t_check_trans(struct sip_msg* msg, char* foo, char* bar)
+{
+	return t_check_trans(msg);
+}
+
 static int hexatoi(str *s, unsigned int* result)
 {
 	int i, xv, fact;

+ 19 - 0
modules/tm/tm_load.c

@@ -145,3 +145,22 @@ int load_tm( struct tm_binds *tmb)
 #endif
 	return 1;
 }
+
+int load_xtm(tm_xapi_t *xapi)
+{
+	if(xapi==NULL)
+	{
+		LM_ERR("invalid parameter\n");
+		return -1;
+	}
+
+	memset(xapi, 0, sizeof(tm_xapi_t));
+
+	xapi->t_on_failure    = t_on_negative;
+	xapi->t_on_branch     = t_on_branch;
+	xapi->t_on_reply      = t_on_reply;
+	xapi->t_check_trans   = t_check_trans;
+	xapi->t_is_canceled   = t_is_canceled;
+
+	return 0;
+}

+ 41 - 0
modules/tm/tm_load.h

@@ -163,4 +163,45 @@ static inline int tm_load_api(tm_api_t *tmb)
 	return load_tm_api(tmb);
 }
 
+/**
+ * eXtra API - not common used in other modules
+ */
+
+typedef void (*t_on_route_f)(unsigned int);
+typedef int (*t_no_param_f)(struct sip_msg *);
+
+int t_check_trans(struct sip_msg* msg);
+int t_is_canceled(struct sip_msg* msg);
+
+typedef struct tm_xbinds {
+	t_on_route_f t_on_failure;
+	t_on_route_f t_on_branch;
+	t_on_route_f t_on_reply;
+	t_no_param_f t_check_trans;
+	t_no_param_f t_is_canceled;
+} tm_xapi_t;
+
+typedef int(*load_xtm_f)( tm_xapi_t *xtmb );
+int load_xtm(tm_xapi_t *xtmb);
+
+static inline int tm_load_xapi(tm_xapi_t *xtmb)
+{
+	load_xtm_f load_xtm;
+
+	/* import the TM auto-loading function */
+	load_xtm = (load_xtm_f)find_export("load_xtm", NO_SCRIPT, 0);
+
+	if (load_tm == NULL) {
+		LOG(L_WARN, "Cannot import load_xtm function from tm module\n");
+		return -1;
+	}
+
+	/* let the auto-loading function load all extra TM stuff */
+	if (load_xtm(xtmb) < 0) {
+		LOG(L_WARN, "Cannot bind xapi from tm module\n");
+		return -1;
+	}
+	return 0;
+}
+
 #endif

+ 63 - 0
modules_k/auth_db/api.h

@@ -0,0 +1,63 @@
+/*
+ * $Id$
+ *
+ * Digest Authentication - Database support
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio 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
+ *
+ * Kamailio 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
+ */
+
+
+#ifndef _AUTH_DB_API_H_
+#define _AUTH_DB_API_H_
+
+#include "../../sr_module.h"
+#include "../../parser/msg_parser.h"
+
+typedef int (*digest_authenticate_f)(struct sip_msg* msg, str *realm,
+				str *table, hdr_types_t hftype);
+/**
+ * @brief AUTH_DB API structure
+ */
+typedef struct auth_db_api {
+	digest_authenticate_f digest_authenticate;
+} auth_db_api_t;
+
+typedef int (*bind_auth_db_f)(auth_db_api_t* api);
+
+/**
+ * @brief Load the SL API
+ */
+static inline int auth_db_load_api(auth_db_api_t *api)
+{
+	bind_auth_db_f bindauthdb;
+
+	bindauthdb = (bind_auth_db_f)find_export("bind_auth_db", 0, 0);
+	if(bindauthdb == 0) {
+		LM_ERR("cannot find bind_auth_db\n");
+		return -1;
+	}
+	if (bindauthdb(api)==-1)
+	{
+		LM_ERR("cannot bind authdb api\n");
+		return -1;
+	}
+	return 0;
+}
+
+#endif /* _AUTH_DB_API_H_ */

+ 3 - 1
modules_k/auth_db/authdb_mod.c

@@ -117,6 +117,8 @@ static cmd_export_t cmds[] = {
 		REQUEST_ROUTE},
 	{"proxy_authenticate", (cmd_function)proxy_authenticate, 2, auth_fixup, 0,
 		REQUEST_ROUTE},
+	{"bind_auth_db",       (cmd_function)bind_auth_db,       0, 0, 0,
+		0},
 	{0, 0, 0, 0, 0, 0}
 };
 
@@ -253,7 +255,7 @@ static int auth_fixup(void** param, int param_no)
 			auth_dbf.close(dbh);
 			return -1;
 		}
+		auth_dbf.close(dbh);
 	}
-	auth_dbf.close(dbh);
 	return 0;
 }

+ 67 - 29
modules_k/auth_db/authorize.c

@@ -45,6 +45,7 @@
 #include "../../mod_fix.h"
 #include "../../mem/mem.h"
 #include "aaa_avps.h"
+#include "api.h"
 #include "authdb_mod.h"
 
 
@@ -204,41 +205,20 @@ static int generate_avps(db1_res_t* result)
 /*
  * Authorize digest credentials
  */
-static inline int digest_authenticate(struct sip_msg* msg, fparam_t* realm,
-									char* tname, hdr_types_t hftype)
+static int digest_authenticate(struct sip_msg* msg, str *realm,
+				str *table, hdr_types_t hftype)
 {
 	char ha1[256];
 	int res;
 	struct hdr_field* h;
 	auth_body_t* cred;
-	str domain, table;
 	db1_res_t* result = NULL;
 	int ret;
 
 	cred = 0;
 	ret = AUTH_ERROR;
 
-	if(!tname) {
-		LM_ERR("invalid table parameter\n");
-		return AUTH_ERROR;
-	}
-
-	table.s = tname;
-	table.len = strlen(tname);
-
-	if (get_str_fparam(&domain, msg, realm) < 0) {
-		LM_ERR("failed to get realm value\n");
-		goto end;
-	}
-
-	if (domain.len==0)
-	{
-		LM_ERR("invalid realm parameter - empty value\n");
-		goto end;
-	}
-	LM_DBG("realm value [%.*s]\n", domain.len, domain.s);
-
-	ret = auth_api.pre_auth(msg, &domain, hftype, &h, NULL);
+	ret = auth_api.pre_auth(msg, realm, hftype, &h, NULL);
 	switch(ret) {
 		case ERROR:
 		case BAD_CREDENTIALS:
@@ -266,7 +246,7 @@ static inline int digest_authenticate(struct sip_msg* msg, fparam_t* realm,
 
 	cred = (auth_body_t*)h->parsed;
 
-	res = get_ha1(&cred->digest.username, &domain, &table, ha1, &result);
+	res = get_ha1(&cred->digest.username, realm, table, ha1, &result);
 	if (res < 0) {
 		/* Error while accessing the database */
 		ret = AUTH_ERROR;
@@ -310,8 +290,30 @@ end:
  */
 int proxy_authenticate(struct sip_msg* _m, char* _realm, char* _table)
 {
-	return digest_authenticate(_m, (fparam_t*)_realm, _table,
-			HDR_PROXYAUTH_T);
+	str srealm;
+	str stable;
+
+	if(_table==NULL) {
+		LM_ERR("invalid table parameter\n");
+		return AUTH_ERROR;
+	}
+
+	stable.s   = _table;
+	stable.len = strlen(stable.s);
+
+	if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0) {
+		LM_ERR("failed to get realm value\n");
+		return AUTH_ERROR;
+	}
+
+	if (srealm.len==0)
+	{
+		LM_ERR("invalid realm parameter - empty value\n");
+		return AUTH_ERROR;
+	}
+	LM_DBG("realm value [%.*s]\n", srealm.len, srealm.s);
+
+	return digest_authenticate(_m, &srealm, &stable, HDR_PROXYAUTH_T);
 }
 
 
@@ -320,6 +322,42 @@ int proxy_authenticate(struct sip_msg* _m, char* _realm, char* _table)
  */
 int www_authenticate(struct sip_msg* _m, char* _realm, char* _table)
 {
-	return digest_authenticate(_m, (fparam_t*)_realm, _table,
-			HDR_AUTHORIZATION_T);
+	str srealm;
+	str stable;
+
+	if(_table==NULL) {
+		LM_ERR("invalid table parameter\n");
+		return AUTH_ERROR;
+	}
+
+	stable.s   = _table;
+	stable.len = strlen(stable.s);
+
+	if (get_str_fparam(&srealm, _m, (fparam_t*)_realm) < 0) {
+		LM_ERR("failed to get realm value\n");
+		return AUTH_ERROR;
+	}
+
+	if (srealm.len==0)
+	{
+		LM_ERR("invalid realm parameter - empty value\n");
+		return AUTH_ERROR;
+	}
+	LM_DBG("realm value [%.*s]\n", srealm.len, srealm.s);
+
+	return digest_authenticate(_m, &srealm, &stable, HDR_AUTHORIZATION_T);
+}
+
+/**
+ * @brief bind functions to AUTH_DB API structure
+ */
+int bind_auth_db(auth_db_api_t *api)
+{
+	if (!api) {
+		ERR("Invalid parameter value\n");
+		return -1;
+	}
+	api->digest_authenticate = digest_authenticate;
+
+	return 0;
 }

+ 6 - 0
modules_k/auth_db/authorize.h

@@ -28,6 +28,7 @@
 
 
 #include "../../parser/msg_parser.h"
+#include "api.h"
 
 int auth_db_init(const str* db_url);
 int auth_db_bind(const str* db_url);
@@ -45,4 +46,9 @@ int proxy_authenticate(struct sip_msg* _msg, char* _realm, char* _table);
 int www_authenticate(struct sip_msg* _msg, char* _realm, char* _table);
 
 
+/*
+ * Bind to AUTH_DB API
+ */
+int bind_auth_db(auth_db_api_t* api);
+
 #endif /* AUTHORIZE_H */

+ 62 - 0
modules_k/maxfwd/api.h

@@ -0,0 +1,62 @@
+/*
+ * $Id$
+ *
+ * Copyright (C) 2001-2003 FhG Fokus
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio 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
+ *
+ * Kamailio 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
+ */
+
+
+#ifndef _MAXFWD_API_H_
+#define _MAXFWD_API_H_
+
+#include "../../sr_module.h"
+#include "../../parser/msg_parser.h"
+
+typedef int (*process_maxfwd_f)(struct sip_msg *msg, int limit);
+
+/**
+ * @brief MAXFWD API structure
+ */
+typedef struct maxfwd_api {
+	process_maxfwd_f process_maxfwd;
+} maxfwd_api_t;
+
+typedef int (*bind_maxfwd_f)(maxfwd_api_t* api);
+
+/**
+ * @brief Load the MAXFWD API
+ */
+static inline int maxfwd_load_api(maxfwd_api_t *api)
+{
+	bind_maxfwd_f bindmaxfwd;
+
+	bindmaxfwd = (bind_maxfwd_f)find_export("bind_maxfwd", 0, 0);
+	if(bindmaxfwd == 0) {
+		LM_ERR("cannot find bind_maxfwd\n");
+		return -1;
+	}
+	if (bindmaxfwd(api)==-1)
+	{
+		LM_ERR("cannot bind maxfwd api\n");
+		return -1;
+	}
+	return 0;
+}
+
+#endif
+

+ 33 - 3
modules_k/maxfwd/maxfwd.c

@@ -45,6 +45,7 @@
 #include "../../ut.h"
 #include "../../mem/mem.h"
 #include "mf_funcs.h"
+#include "api.h"
 
 MODULE_VERSION
 
@@ -57,11 +58,15 @@ static int w_process_maxfwd_header(struct sip_msg* msg,char* str,char* str2);
 static int is_maxfwd_lt(struct sip_msg *msg, char *slimit, char *foo);
 static int mod_init(void);
 
+int bind_maxfwd(maxfwd_api_t *api);
+
 static cmd_export_t cmds[]={
 	{"mf_process_maxfwd_header", (cmd_function)w_process_maxfwd_header, 1,
 		fixup_maxfwd_header, 0, REQUEST_ROUTE},
 	{"is_maxfwd_lt", (cmd_function)is_maxfwd_lt, 1,
 		fixup_maxfwd_header, 0, REQUEST_ROUTE|FAILURE_ROUTE|BRANCH_ROUTE},
+	{"bind_maxfwd",  (cmd_function)bind_maxfwd,  0,
+		0, 0, 0},
 	{0,0,0,0,0,0}
 };
 
@@ -131,8 +136,10 @@ static int fixup_maxfwd_header(void** param, int param_no)
 }
 
 
-
-static int w_process_maxfwd_header(struct sip_msg* msg, char* str1,char* str2)
+/**
+ * process max forward header
+ */
+int process_maxfwd_header(struct sip_msg *msg, int limit)
 {
 	int val;
 	str mf_value;
@@ -141,7 +148,7 @@ static int w_process_maxfwd_header(struct sip_msg* msg, char* str1,char* str2)
 	switch (val) {
 		/* header not found */
 		case -1:
-			if (add_maxfwd_header( msg, (unsigned int)(unsigned long)str1)!=0)
+			if (add_maxfwd_header(msg, (unsigned int)limit)!=0)
 				goto error;
 			return 2;
 		/* error */
@@ -166,8 +173,18 @@ error:
 	return -2;
 }
 
+/**
+ *
+ */
+static int w_process_maxfwd_header(struct sip_msg* msg, char* str1, char* str2)
+{
+	return process_maxfwd_header(msg, (int)(unsigned long)str1);
+}
 
 
+/**
+ *
+ */
 static int is_maxfwd_lt(struct sip_msg *msg, char *slimit, char *foo)
 {
 	str mf_value;
@@ -189,3 +206,16 @@ static int is_maxfwd_lt(struct sip_msg *msg, char *slimit, char *foo)
 	return 1;
 }
 
+/**
+ * @brief bind functions to MAXFWD API structure
+ */
+int bind_maxfwd(maxfwd_api_t *api)
+{
+	if (!api) {
+		ERR("Invalid parameter value\n");
+		return -1;
+	}
+	api->process_maxfwd = process_maxfwd_header;
+
+	return 0;
+}

+ 79 - 0
modules_k/registrar/api.c

@@ -0,0 +1,79 @@
+/*
+ * $Id$
+ *
+ * Functions that process REGISTER message 
+ * and store data in usrloc
+ *
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio 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
+ *
+ * Kamailio 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 <stdio.h>
+
+#include "../../dprint.h"
+
+#include "reg_mod.h"
+#include "lookup.h"
+#include "save.h"
+#include "api.h"
+
+/**
+ *
+ */
+int regapi_save(struct sip_msg *msg, char *table, int flags)
+{
+	udomain_t* d;
+
+	if(ul.get_udomain(table, &d)<0)
+	{
+		LM_ERR("usrloc domain [%s] not found\n", table);
+		return -1;
+	}
+	return save(msg, d, flags);
+}
+
+/**
+ *
+ */
+int regapi_lookup(struct sip_msg *msg, char *table)
+{
+	udomain_t* d;
+
+	if(ul.get_udomain(table, &d)<0)
+	{
+		LM_ERR("usrloc domain [%s] not found\n", table);
+		return -1;
+	}
+	return lookup(msg, d);
+}
+
+/**
+ *
+ */
+int bind_registrar(registrar_api_t* api)
+{
+	if (!api) {
+		ERR("Invalid parameter value\n");
+		return -1;
+	}
+	api->save   = regapi_save;
+	api->lookup = regapi_lookup;
+
+	return 0;
+}

+ 72 - 0
modules_k/registrar/api.h

@@ -0,0 +1,72 @@
+/*
+ * $Id$
+ *
+ * Functions that process REGISTER message 
+ * and store data in usrloc
+ *
+ * Copyright (C) 2010 Daniel-Constantin Mierla (asipto.com)
+ *
+ * This file is part of Kamailio, a free SIP server.
+ *
+ * Kamailio 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
+ *
+ * Kamailio 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
+ *
+ */
+
+
+#ifndef _REGISTRAR_API_H_
+#define _REGISTRAR_API_H_
+
+#include "../../sr_module.h"
+#include "../../parser/msg_parser.h"
+
+typedef int (*regapi_save_f)(struct sip_msg *msg, char *table, int flags);
+int regapi_save(struct sip_msg *msg, char *table, int flags);
+
+typedef int (*regapi_lookup_f)(struct sip_msg *msg, char *table);
+int regapi_lookup(struct sip_msg *msg, char *table);
+
+/**
+ * @brief REGISTRAR API structure
+ */
+typedef struct registrar_api {
+	regapi_save_f    save;
+	regapi_lookup_f  lookup;
+} registrar_api_t;
+
+typedef int (*bind_registrar_f)(registrar_api_t* api);
+int bind_registrar(registrar_api_t* api);
+
+/**
+ * @brief Load the REGISTRAR API
+ */
+static inline int registrar_load_api(registrar_api_t *api)
+{
+	bind_registrar_f bindregistrar;
+
+	bindregistrar = (bind_registrar_f)find_export("bind_registrar", 0, 0);
+	if(bindregistrar == 0) {
+		LM_ERR("cannot find bind_registrar\n");
+		return -1;
+	}
+	if (bindregistrar(api) < 0)
+	{
+		LM_ERR("cannot bind registrar api\n");
+		return -1;
+	}
+	return 0;
+}
+
+
+#endif

+ 5 - 5
modules_k/registrar/lookup.c

@@ -57,7 +57,7 @@
  *          -2 : found but method not allowed
  *          -3 : error
  */
-int lookup(struct sip_msg* _m, char* _t, char* _s)
+int lookup(struct sip_msg* _m, udomain_t* _d)
 {
 	urecord_t* r;
 	str aor, uri;
@@ -78,11 +78,11 @@ int lookup(struct sip_msg* _m, char* _t, char* _s)
 	
 	get_act_time();
 
-	ul.lock_udomain((udomain_t*)_t, &aor);
-	res = ul.get_urecord((udomain_t*)_t, &aor, &r);
+	ul.lock_udomain(_d, &aor);
+	res = ul.get_urecord(_d, &aor, &r);
 	if (res > 0) {
 		LM_DBG("'%.*s' Not found in usrloc\n", aor.len, ZSW(aor.s));
-		ul.unlock_udomain((udomain_t*)_t, &aor);
+		ul.unlock_udomain(_d, &aor);
 		return -1;
 	}
 
@@ -171,7 +171,7 @@ int lookup(struct sip_msg* _m, char* _t, char* _s)
 
 done:
 	ul.release_urecord(r);
-	ul.unlock_udomain((udomain_t*)_t, &aor);
+	ul.unlock_udomain(_d, &aor);
 	return ret;
 }
 

+ 2 - 1
modules_k/registrar/lookup.h

@@ -33,12 +33,13 @@
 #define LOOKUP_H
 
 #include "../../parser/msg_parser.h"
+#include "../../modules_k/usrloc/usrloc.h"
 
 
 /*! \brief
  * Lookup a contact in usrloc and rewrite R-URI if found
  */
-int lookup(struct sip_msg* _m, char* _t, char* _s);
+int lookup(struct sip_msg* _m, udomain_t* _d);
 
 
 /*! \brief

+ 25 - 4
modules_k/registrar/reg_mod.c

@@ -67,11 +67,12 @@
 #include "../../socket_info.h"
 #include "../../pvar.h"
 #include "../../lib/kcore/km_ut.h"
-#include "../usrloc/ul_mod.h"
+#include "../../modules_k/usrloc/usrloc.h"
 #include "../../modules/sl/sl.h"
 #include "../../mod_fix.h"
 
 #include "save.h"
+#include "api.h"
 #include "lookup.h"
 #include "regpv.h"
 #include "reply.h"
@@ -86,6 +87,9 @@ usrloc_api_t ul;/*!< Structure containing pointers to usrloc functions*/
 static int  mod_init(void);
 static int  child_init(int);
 static void mod_destroy(void);
+static int w_save(struct sip_msg* _m, char* _d, char* _cflags);
+static int w_lookup(struct sip_msg* _m, char* _d, char* _p2);
+
 /*! \brief Fixup functions */
 static int domain_fixup(void** param, int param_no);
 static int save_fixup(void** param, int param_no);
@@ -150,11 +154,11 @@ static pv_export_t mod_pvs[] = {
  * Exported functions
  */
 static cmd_export_t cmds[] = {
-	{"save",         (cmd_function)save,         1,    save_fixup, 0,
+	{"save",         (cmd_function)w_save,       1,    save_fixup, 0,
 			REQUEST_ROUTE | ONREPLY_ROUTE },
-	{"save",         (cmd_function)save,         2,    save_fixup, 0,
+	{"save",         (cmd_function)w_save,       2,    save_fixup, 0,
 			REQUEST_ROUTE | ONREPLY_ROUTE },
-	{"lookup",       (cmd_function)lookup,       1,  domain_fixup, 0,
+	{"lookup",       (cmd_function)w_lookup,     1,  domain_fixup, 0,
 			REQUEST_ROUTE | FAILURE_ROUTE },
 	{"registered",   (cmd_function)registered,   1,  domain_fixup, 0,
 			REQUEST_ROUTE | FAILURE_ROUTE },
@@ -168,6 +172,8 @@ static cmd_export_t cmds[] = {
 	{"reg_free_contacts", (cmd_function)pv_free_contacts,   1,
 			fixup_str_null, 0,
 			REQUEST_ROUTE| FAILURE_ROUTE },
+	{"bind_registrar",  (cmd_function)bind_registrar,  0,
+		0, 0, 0},
 	{0, 0, 0, 0, 0, 0}
 };
 
@@ -383,6 +389,21 @@ static int child_init(int rank)
 	return 0;
 }
 
+/*! \brief
+ * Wrapper to save(location)
+ */
+static int w_save(struct sip_msg* _m, char* _d, char* _cflags)
+{
+	return save(_m, (udomain_t*)_d, ((int)(unsigned long)_cflags));
+}
+
+/*! \brief
+ * Wrapper to lookup(location)
+ */
+static int w_lookup(struct sip_msg* _m, char* _d, char* _p2)
+{
+	return lookup(_m, (udomain_t*)_d);
+}
 
 /*! \brief
  * Convert char* parameter to udomain_t* pointer

+ 2 - 2
modules_k/registrar/save.c

@@ -741,8 +741,8 @@ static inline int add_contacts(struct sip_msg* _m, contact_t* _c,
 /*!\brief
  * Process REGISTER request and save it's contacts
  */
-#define is_cflag_set(_name) (((unsigned int)(unsigned long)_cflags)&(_name))
-int save(struct sip_msg* _m, char* _d, char* _cflags)
+#define is_cflag_set(_name) (((unsigned int)_cflags)&(_name))
+int save(struct sip_msg* _m, udomain_t* _d, int _cflags)
 {
 	contact_t* c;
 	int st, mode;

+ 2 - 1
modules_k/registrar/save.h

@@ -40,12 +40,13 @@
 
 
 #include "../../parser/msg_parser.h"
+#include "../../modules_k/usrloc/usrloc.h"
 
 
 /*! \brief
  * Process REGISTER request and save it's contacts
  */
-int save(struct sip_msg* _m, char* _d, char* _cflags);
+int save(struct sip_msg* _m, udomain_t* _d, int _cflags);
 int unregister(struct sip_msg* _m, char* _d, char* _uri);
 
 

+ 2 - 0
modules_k/rr/api.c

@@ -56,6 +56,8 @@ extern int append_fromtag;
  */
 int load_rr( struct rr_binds *rrb )
 {
+	rrb->record_route      = record_route;
+	rrb->loose_route       = loose_route;
 	rrb->add_rr_param      = add_rr_param;
 	rrb->check_route_param = check_route_param;
 	rrb->is_direction      = is_direction;

+ 19 - 9
modules_k/rr/api.h

@@ -50,17 +50,20 @@ typedef  int (*add_rr_param_t)(struct sip_msg*, str*);
 typedef  int (*check_route_param_t)(struct sip_msg*, regex_t*);
 typedef  int (*is_direction_t)(struct sip_msg*, int);
 typedef  int (*get_route_param_t)(struct sip_msg*, str*, str*);
-
+typedef  int (*record_route_f)(struct sip_msg*, str*);
+typedef  int (*loose_route_f)(struct sip_msg*);
 
 /*! record-route API export binding */
-struct rr_binds {
-	add_rr_param_t		add_rr_param;
-	check_route_param_t	check_route_param;
-	is_direction_t			is_direction;
-	get_route_param_t		get_route_param;
-	register_rrcb_t			register_rrcb;
-	int					append_fromtag;
-};
+typedef struct rr_binds {
+	record_route_f       record_route;
+	loose_route_f        loose_route;
+	add_rr_param_t       add_rr_param;
+	check_route_param_t  check_route_param;
+	is_direction_t       is_direction;
+	get_route_param_t    get_route_param;
+	register_rrcb_t      register_rrcb;
+	int                  append_fromtag;
+} rr_api_t;
 
 typedef  int (*load_rr_f)( struct rr_binds* );
 
@@ -92,5 +95,12 @@ inline static int load_rr_api( struct rr_binds *rrb )
 	return 0;
 }
 
+/**
+ *
+ */
+inline static int rr_load_api( rr_api_t *rrb )
+{
+	return load_rr_api(rrb);
+}
 
 #endif

+ 1 - 3
modules_k/rr/loose.c

@@ -900,11 +900,9 @@ done:
 /*!
  * \brief Do loose routing as per RFC3261
  * \param _m SIP message
- * \param _s1 unused
- * \param _s2 unused
  * \return -1 on failure, 1 on success
  */
-int loose_route(struct sip_msg* _m, char* _s1, char* _s2)
+int loose_route(struct sip_msg* _m)
 {
 	int ret;
 

+ 1 - 3
modules_k/rr/loose.h

@@ -42,11 +42,9 @@
 /*!
  * \brief Do loose routing as per RFC3261
  * \param _m SIP message
- * \param _s1 unused
- * \param _s2 unused
  * \return -1 on failure, 1 on success
  */
-int loose_route(struct sip_msg* _m, char* _s1, char* _s2);
+int loose_route(struct sip_msg* _m);
 
 
 /*!

+ 13 - 2
modules_k/rr/rr_mod.c

@@ -65,7 +65,8 @@ static int  mod_init(void);static void mod_destroy(void);
 static int direction_fixup(void** param, int param_no);
 static int it_list_fixup(void** param, int param_no);
 /* wrapper functions */
-static int w_record_route(struct sip_msg *,char *, char *);
+static int w_loose_route(struct sip_msg *, char *, char *);
+static int w_record_route(struct sip_msg *, char *, char *);
 static int w_record_route_preset(struct sip_msg *,char *, char *);
 static int w_add_rr_param(struct sip_msg *,char *, char *);
 static int w_check_route_param(struct sip_msg *,char *, char *);
@@ -75,7 +76,7 @@ static int w_is_direction(struct sip_msg *,char *, char *);
  * \brief Exported functions
  */
 static cmd_export_t cmds[] = {
-	{"loose_route",          (cmd_function)loose_route,			0, 0, 0,
+	{"loose_route",          (cmd_function)w_loose_route,		0, 0, 0,
 			REQUEST_ROUTE},
 	{"record_route",         (cmd_function)w_record_route,		0, 0, 0,
 			REQUEST_ROUTE|BRANCH_ROUTE|FAILURE_ROUTE},
@@ -199,7 +200,17 @@ static int direction_fixup(void** param, int param_no)
 	return 0;
 }
 
+/**
+ * wrapper for loose_route(msg)
+ */
+static int w_loose_route(struct sip_msg *msg, char *p1, char *p2)
+{
+	return loose_route(msg);
+}
 
+/**
+ * wrapper for record_route(msg, params)
+ */
 static int w_record_route(struct sip_msg *msg, char *key, char *bar)
 {
 	str s;

+ 2 - 2
modules_k/sqlops/sql_api.c

@@ -440,7 +440,7 @@ error:
 /**
  *
  */
-int sqlops_get_value(str *sres, int i, int j, sql_val_t *val)
+int sqlops_get_value(str *sres, int i, int j, sql_val_t **val)
 {
 	sql_result_t *res = NULL;
 
@@ -460,7 +460,7 @@ int sqlops_get_value(str *sres, int i, int j, sql_val_t *val)
 		LM_ERR("column index out of bounds [%d/%d]\n", j, res->ncols);
 		goto error;
 	}
-	val = &res->vals[i][j];
+	*val = &res->vals[i][j];
 
 	return 0;
 error:

+ 2 - 2
modules_k/sqlops/sql_api.h

@@ -81,8 +81,8 @@ void sql_reset_result(sql_result_t *res);
 typedef int (*sqlops_do_query_f)(str *scon, str *squery, str *sres);
 int sqlops_do_query(str *scon, str *squery, str *sres);
 
-typedef int (*sqlops_get_value_f)(str *sres, int i, int j, sql_val_t *val);
-int sqlops_get_value(str *sres, int i, int j, sql_val_t *val);
+typedef int (*sqlops_get_value_f)(str *sres, int i, int j, sql_val_t **val);
+int sqlops_get_value(str *sres, int i, int j, sql_val_t **val);
 
 typedef int (*sqlops_is_null_f)(str *sres, int i, int j);
 int sqlops_is_null(str *res, int i, int j);

+ 1 - 1
modules_k/sqlops/sqlops.c

@@ -149,7 +149,7 @@ int sql_res_param(modparam_t type, void *val)
 
 	if(val==NULL)
 	{
-		LM_ERR("invalid parameter");
+		LM_ERR("invalid parameter\n");
 		goto error;
 	}
 

+ 18 - 0
modules_k/usrloc/README

@@ -62,6 +62,7 @@ Bogdan-Andrei Iancu
               3.22. cseq_delay (integer)
               3.23. fetch_rows (integer)
               3.24. hash_size (integer)
+              3.25. preload (string)
 
         4. Exported Functions
         5. Exported MI Functions
@@ -130,6 +131,7 @@ Bogdan-Andrei Iancu
    1.22. Set cseq_delay parameter
    1.23. Set fetch_rows parameter
    1.24. Set hash_size parameter
+   1.25. Set preload parameter
 
 Chapter 1. Admin Guide
 
@@ -170,6 +172,7 @@ Chapter 1. Admin Guide
         3.22. cseq_delay (integer)
         3.23. fetch_rows (integer)
         3.24. hash_size (integer)
+        3.25. preload (string)
 
    4. Exported Functions
    5. Exported MI Functions
@@ -270,6 +273,7 @@ Chapter 1. Admin Guide
    3.22. cseq_delay (integer)
    3.23. fetch_rows (integer)
    3.24. hash_size (integer)
+   3.25. preload (string)
 
 3.1. nat_bflag (integer)
 
@@ -600,6 +604,20 @@ modparam("usrloc", "fetch_rows", 3000)
 modparam("usrloc", "hash_size", 10)
 ...
 
+3.25. preload (string)
+
+   Preload location table given as value. A location table is loaded based
+   on fixup of registrar functions, therefore you need to use this
+   parameter only to load tables that are not used by registrar module
+   directly in configuration file.
+
+   Default value is “NULL”.
+
+   Example 1.25. Set preload parameter
+...
+modparam("usrloc", "preload", "location")
+...
+
 4. Exported Functions
 
    There are no exported functions that could be used in scripts.

+ 24 - 0
modules_k/usrloc/dlist.c

@@ -46,6 +46,7 @@
 #include "../../ip_addr.h"
 #include "../../socket_info.h"
 #include "udomain.h"           /* new_udomain, free_udomain */
+#include "usrloc.h"
 #include "utime.h"
 #include "ul_mod.h"
 
@@ -447,6 +448,29 @@ static inline int new_dlist(str* _n, dlist_t** _d)
 	return 0;
 }
 
+/*!
+ * \brief Registers a new domain with usrloc
+ *
+ * Find and return a usrloc domain (location table)
+ * \param _n domain name
+ * \param _d usrloc domain
+ * \return 0 on success, -1 on failure
+ */
+int get_udomain(const char* _n, udomain_t** _d)
+{
+	dlist_t* d;
+	str s;
+
+	s.s = (char*)_n;
+	s.len = strlen(_n);
+
+	if (find_dlist(&s, &d) == 0) {
+		*_d = d->d;
+		return 0;
+	}
+	*_d = NULL;
+	return -1;
+}
 
 /*!
  * \brief Registers a new domain with usrloc

+ 9 - 0
modules_k/usrloc/dlist.h

@@ -66,6 +66,15 @@ extern dlist_t* root;
 typedef int (*register_udomain_t)(const char* _n, udomain_t** _d);
 int register_udomain(const char* _n, udomain_t** _d);
 
+/*!
+ * \brief Find and return usrloc domain
+ *
+ * \param _n domain name
+ * \param _d usrloc domain (location table)
+ * \return 0 on success, -1 on failure
+ */
+typedef int (*get_udomain_t)(const char* _n, udomain_t** _d);
+int get_udomain(const char* _n, udomain_t** _d);
 
 /*!
  * \brief Free all allocated memory for domains

+ 23 - 0
modules_k/usrloc/doc/usrloc_admin.xml

@@ -690,6 +690,29 @@ modparam("usrloc", "hash_size", 10)
 		</example>
 	</section>
 
+	<section id="preload">
+		<title><varname>preload</varname> (string)</title>
+		<para>
+		Preload location table given as value. A location table is loaded
+		based on fixup of registrar functions, therefore you need to use this
+		parameter only to load tables that are not used by registrar module
+		directly in configuration file.
+		</para>
+		<para>
+		<emphasis>
+			Default value is <quote>NULL</quote>.
+		</emphasis>
+		</para>
+		<example>
+		<title>Set <varname>preload</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+modparam("usrloc", "preload", "location")
+...
+</programlisting>
+		</example>
+	</section>
+
 	</section>
 
 	<section>

+ 1 - 0
modules_k/usrloc/ucontact.c

@@ -43,6 +43,7 @@
 #include "../../lib/srdb1/db.h"
 #include "ul_mod.h"
 #include "ul_callback.h"
+#include "usrloc.h"
 #include "urecord.h"
 #include "ucontact.h"
 

+ 1 - 0
modules_k/usrloc/udomain.c

@@ -45,6 +45,7 @@
 #include "../../ut.h"
 #include "../../lib/kcore/hash_func.h"
 #include "ul_mod.h"            /* usrloc module parameters */
+#include "usrloc.h"
 #include "utime.h"
 
 

+ 36 - 0
modules_k/usrloc/ul_mod.c

@@ -92,6 +92,11 @@ static void timer(unsigned int ticks, void* param); /*!< Timer handler */
 static int child_init(int rank);                    /*!< Per-child init function */
 static int mi_child_init(void);
 
+#define UL_PRELOAD_SIZE	8
+static char* ul_preload_list[UL_PRELOAD_SIZE];
+static int ul_preload_index = 0;
+static int ul_preload_param(modparam_t type, void* val);
+
 extern int bind_usrloc(usrloc_api_t* api);
 extern int ul_locks_no;
 /*
@@ -168,6 +173,7 @@ static param_export_t params[] = {
 	{"fetch_rows",        INT_PARAM, &ul_fetch_rows   },
 	{"hash_size",         INT_PARAM, &ul_hash_size    },
 	{"nat_bflag",         INT_PARAM, &nat_bflag       },
+	{"preload",           STR_PARAM|USE_FUNC_PARAM, (void*)ul_preload_param},
 	{0, 0, 0}
 };
 
@@ -216,6 +222,9 @@ struct module_exports exports = {
  */
 static int mod_init(void)
 {
+	int i;
+	udomain_t* d;
+
 #ifdef STATISTICS
 	/* register statistics */
 	if (register_module_stats( exports.name, mod_stats)!=0 ) {
@@ -311,6 +320,12 @@ static int mod_init(void)
 		nat_bflag = 1<<nat_bflag;
 	}
 
+	for(i=0; i<ul_preload_index; i++) {
+		if(register_udomain((const char*)ul_preload_list[i], &d)<0) {
+			LM_ERR("cannot register preloaded table %s\n", ul_preload_list[i]);
+			return -1;
+		}
+	}
 	init_flag = 1;
 
 	return 0;
@@ -419,3 +434,24 @@ static void timer(unsigned int ticks, void* param)
 	}
 }
 
+/*! \brief
+ * preload module parameter handler
+ */
+static int ul_preload_param(modparam_t type, void* val)
+{
+	if(val==NULL)
+	{
+		LM_ERR("invalid parameter\n");
+		goto error;
+	}
+	if(ul_preload_index>=UL_PRELOAD_SIZE)
+	{
+		LM_ERR("too many preloaded tables\n");
+		goto error;
+	}
+	ul_preload_list[ul_preload_index] = (char*)val;
+	ul_preload_index++;
+	return 0;
+error:
+	return -1;
+}

+ 0 - 5
modules_k/usrloc/ul_mod.h

@@ -43,11 +43,6 @@
  */
 
 
-#define NO_DB         0
-#define WRITE_THROUGH 1
-#define WRITE_BACK    2
-#define DB_ONLY       3
-
 #define UL_TABLE_VERSION 1004
 
 extern str user_col;

+ 1 - 0
modules_k/usrloc/urecord.c

@@ -41,6 +41,7 @@
 #include "../../ut.h"
 #include "../../lib/kcore/hash_func.h"
 #include "ul_mod.h"
+#include "usrloc.h"
 #include "utime.h"
 #include "ul_callback.h"
 

+ 1 - 0
modules_k/usrloc/usrloc.c

@@ -61,6 +61,7 @@ int bind_usrloc(usrloc_api_t* api)
 	}
 
 	api->register_udomain   = register_udomain;
+	api->get_udomain        = get_udomain;
 	api->get_all_ucontacts  = get_all_ucontacts;
 	api->insert_urecord     = insert_urecord;
 	api->delete_urecord     = delete_urecord;

+ 7 - 0
modules_k/usrloc/usrloc.h

@@ -35,6 +35,12 @@
 #include "ucontact.h"
 #include "ul_callback.h"
 
+/* storage modes */
+#define NO_DB         0
+#define WRITE_THROUGH 1
+#define WRITE_BACK    2
+#define DB_ONLY       3
+
 
 /*! usrloc API export structure */
 typedef struct usrloc_api {
@@ -43,6 +49,7 @@ typedef struct usrloc_api {
 	unsigned int  nat_flag;   /*! nat_flag module parameter */
 
 	register_udomain_t   register_udomain;
+	get_udomain_t        get_udomain;
 	get_all_ucontacts_t  get_all_ucontacts;
 
 	insert_urecord_t     insert_urecord;