along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <uv.h>
+
#include "lib/cache.h"
#include "daemon/bindings.h"
/** Unload module. */
static int mod_unload(lua_State *L)
{
- lua_pushstring(L, "not implemented");
- lua_error(L);
+ /* Check parameters */
+ int n = lua_gettop(L);
+ if (n != 1 || !lua_isstring(L, 1)) {
+ lua_pushstring(L, "expected module name");
+ lua_error(L);
+ }
+ /* Unload engine module */
+ struct engine *engine = engine_luaget(L);
+ int ret = engine_unregister(engine, lua_tostring(L, 1));
+ if (ret != 0) {
+ lua_pushstring(L, kr_strerror(ret));
+ lua_error(L);
+ }
return 0;
}
return 1;
}
-int lib_config(lua_State *L)
+/** List active endpoints. */
+static int net_list(lua_State *L)
+{
+ lua_pushstring(L, "not implemented");
+ lua_error(L);
+ return 0;
+}
+
+/** Listen on endpoint. */
+static int net_listen(lua_State *L)
+{
+ lua_pushstring(L, "not implemented");
+ lua_error(L);
+ return 0;
+}
+
+/** Close endpoint. */
+static int net_close(lua_State *L)
{
+ lua_pushstring(L, "not implemented");
+ lua_error(L);
return 0;
}
+/** List available interfaces.
+ * @TODO: Implement as a map {name: { addr: [], mac: "" }}
+ */
+static int net_interfaces(lua_State *L)
+{
+ /* Retrieve interface list */
+ int count = 0;
+ char buf[INET6_ADDRSTRLEN]; /* http://tools.ietf.org/html/rfc4291 */
+ uv_interface_address_t *info = NULL;
+ uv_interface_addresses(&info, &count);
+
+ /* Fill table. */
+ lua_newtable(L);
+ for (int i = count; i--; ) {
+ uv_interface_address_t iface = info[i];
+ lua_newtable(L);
+ lua_pushstring(L, iface.name);
+ lua_setfield(L, -2, "id");
+
+ /* Address */
+ buf[0] = '\0';
+ switch(iface.address.address4.sin_family) {
+ case AF_INET:
+ uv_ip4_name(&iface.address.address4, buf, sizeof(buf));
+ break;
+ case AF_INET6:
+ uv_ip6_name(&iface.address.address6, buf, sizeof(buf));
+ break;
+ }
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "addr");
+
+ /* Hardware address. */
+ char *p = buf;
+ memset(buf, 0, sizeof(buf));
+ for (unsigned k = 0; k < sizeof(iface.phys_addr); ++k) {
+ sprintf(p, "%0x", iface.phys_addr[k] & 0xff);
+ p += 2;
+ }
+ lua_pushstring(L, buf);
+ lua_setfield(L, -2, "mac");
+
+ /* Push table */
+ lua_rawseti(L, -2, i);
+ }
+ uv_free_interface_addresses(info, count);
+
+ return 1;
+}
+
+int lib_net(lua_State *L)
+{
+ static const luaL_Reg lib[] = {
+ { "list", net_list },
+ { "listen", net_listen },
+ { "close", net_close },
+ { "interfaces", net_interfaces },
+ { NULL, NULL }
+ };
+ register_lib(L, "net", lib);
+ return 1;
+}
+
/** Open cache */
static int cache_open(lua_State *L)
{
int lib_modules(lua_State *L);
/**
- * Load 'config' package.
+ * Load 'net' package.
* @param L scriptable
* @return number of packages to load
*/
-int lib_config(lua_State *L);
+int lib_net(lua_State *L);
/**
* Load 'cache' package.
* Global bindings.
*/
+/** Register module callback into Lua world. */
+#define REGISTER_MODULE_CALL(L, module, cb, name) \
+ lua_pushlightuserdata((L), (module)); \
+ lua_pushlightuserdata((L), (cb)); \
+ lua_pushcclosure((L), l_trampoline, 2); \
+ lua_setfield((L), -2, (name))
+
/** Print help and available commands. */
static int l_help(lua_State *L)
{
/** Trampoline function for module properties. */
static int l_trampoline(lua_State *L)
{
- const char *name = lua_tostring(L, lua_upvalueindex(1));
- const char *property = lua_tostring(L, lua_upvalueindex(2));
+ struct kr_module *module = lua_touserdata(L, lua_upvalueindex(1));
+ void* callback = lua_touserdata(L, lua_upvalueindex(2));
struct engine *engine = engine_luaget(L);
- /* Find module. */
- for (unsigned i = 0; i < engine->modules.len; ++i) {
- struct kr_module *module = &engine->modules.at[i];
- if (strcmp(module->name, name) != 0) {
- continue;
- }
- /* Find property. */
- for (struct kr_prop *p = module->props; p && p->name; ++p) {
- if (strcmp(p->name, property) == 0) {
- auto_free char *ret = p->cb(engine, module, NULL);
- lua_pushstring(L, ret);
- return 1;
- }
- }
- break;
+ /* Now we only have property callback or config,
+ * if we expand the callables, we might need a callback_type.
+ */
+ if (callback == module->config) {
+ const char *param = lua_tostring(L, 1);
+ module->config(module, param);
+ } else {
+ kr_prop_cb *prop = (kr_prop_cb *)callback;
+ auto_free char *ret = prop(engine, module, lua_tostring(L, 1));
+ lua_pushstring(L, ret);
+ return 1;
}
+
/* No results */
return 0;
}
static int engine_loadconf(struct engine *engine)
{
+ /* Init environment */
+ static const char l_init[] = {
+ #include "daemon/lua/init.inc"
+ };
+ if (luaL_dostring(engine->L, l_init) != 0) {
+ return kr_error(ENOEXEC);
+ }
+
/* Load config file */
int ret = 0;
if(access("config", F_OK ) != -1 ) {
} else {
/* Load defaults */
static const char config_init[] = {
- #include "daemon/lua/init.inc"
+ #include "daemon/lua/config.inc"
};
ret = luaL_dostring(engine->L, config_init);
}
/* Register properties */
if (module->props) {
lua_newtable(engine->L);
+ if (module->config != NULL) {
+ REGISTER_MODULE_CALL(engine->L, module, module->config, "config");
+ }
for (struct kr_prop *p = module->props; p->name; ++p) {
- lua_pushstring(engine->L, module->name);
- lua_pushstring(engine->L, p->name);
- lua_pushcclosure(engine->L, l_trampoline, 2);
- lua_setfield(engine->L, -2, p->name);
+ if (p->cb != NULL && p->name != NULL) {
+ REGISTER_MODULE_CALL(engine->L, module, p->cb, p->name);
+ }
}
lua_setglobal(engine->L, module->name);
}
* @internal These are forward decls to allow building modules with engine but without Lua.
*/
struct lua_State;
-typedef int (*lua_CFunction) (struct lua_State *L);
#include "lib/resolve.h"
#include "lib/generic/array.h"
int engine_register(struct engine *engine, const char *module);
int engine_unregister(struct engine *engine, const char *module);
/** Return engine light userdata. */
-void engine_lualib(struct engine *engine, const char *name, lua_CFunction lib_cb);
+void engine_lualib(struct engine *engine, const char *name, int (*lib_cb) (struct lua_State *));
struct engine *engine_luaget(struct lua_State *L);
\ No newline at end of file
/* Load bindings */
engine_lualib(&engine, "modules", lib_modules);
- engine_lualib(&engine, "config", lib_config);
- engine_lualib(&engine, "cache", lib_cache);
+ engine_lualib(&engine, "net", lib_net);
+ engine_lualib(&engine, "cache", lib_cache);
/* Create main worker. */
struct worker_ctx worker = {