diff options
Diffstat (limited to 'lua/common.c')
-rw-r--r-- | lua/common.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/lua/common.c b/lua/common.c index d9467967..fad2f857 100644 --- a/lua/common.c +++ b/lua/common.c @@ -64,6 +64,12 @@ static int luaB_trace(lua_State *L) { #define lua_settablecfunction(L, idx, val) lua_sett(L, idx, val, cfunction) #define lua_settableinteger(L, idx, val) lua_sett(L, idx, val, integer) #define lua_settableip4(L, idx, val) lua_sett(L, idx, val, ip4) +#define lua_settablelightuserdata(L, idx, val) lua_sett(L, idx, val, lightuserdata) + +#define lua_setglobalcfunction(L, n, val) do { \ + lua_pushcfunction(L, val); \ + lua_setglobal(L, n); \ +} while (0) static int luaB_generic_concat(lua_State *L) { int n = lua_gettop(L); @@ -125,7 +131,34 @@ static void lua_puship4(lua_State *L, ip4_addr a) { lua_setmetatable(L, -2); } -void luaB_push_bird(lua_State *L) { +static lua_bird_state *luaB_getinternalstate(lua_State *L) { + lua_getglobal(L, "bird"); + lua_pushstring(L, "_internal_state"); + lua_gettable(L, -2); + if (!lua_isuserdata(L, -1)) + luaL_error(L, "fatal: bird internal state not found, type %d", lua_type(L, -1)); + + lua_bird_state *lbs = lua_touserdata(L, -1); + lua_pop(L, 2); /* Pop the user data and then the table. The string is consumed by gettable(). */ + return lbs; +} + +static int luaB_global_exception(lua_State *L, int value) { + int n = lua_gettop(L); + if (n > 1) + log(L_WARN "Called exception with too many arguments."); + + lua_bird_state *lbs = luaB_getinternalstate(L); + lbs->exception = value; + + lua_error(L); + return 0; +} + +static inline int luaB_accept(lua_State *L) { return luaB_global_exception(L, F_ACCEPT); } +static inline int luaB_reject(lua_State *L) { return luaB_global_exception(L, F_REJECT); } + +lua_bird_state *luaB_init(lua_State *L, struct linpool *lp) { lua_newtable(L); lua_settablecfunction(L, "err", luaB_err); @@ -133,9 +166,21 @@ void luaB_push_bird(lua_State *L) { lua_settablecfunction(L, "info", luaB_info); lua_settablecfunction(L, "trace", luaB_trace); + lua_bird_state *lbs = lp_allocz(lp, sizeof(lua_bird_state)); + + lua_settablelightuserdata(L, "_internal_state", lbs); + lua_settableip4(L, "router_id", config->router_id); lua_setglobal(L, "bird"); + + lua_pushcfunction(L, luaB_accept); + lua_setglobal(L, "accept"); + + lua_pushcfunction(L, luaB_reject); + lua_setglobal(L, "reject"); + + return lbs; } void luaB_push_route(lua_State *L, struct rte *e) { |