From 5e621e6251308eb1276f175bf99ab92f15df8d2e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marek=20Vavru=C5=A1a?= <marek.vavrusa@nic.cz>
Date: Mon, 15 Jun 2015 22:53:07 +0200
Subject: [PATCH] daemon/bindings: some basic Lua interface to rplan and query

---
 daemon/bindings/kres.c | 104 ++++++++++++++++++++++++++++++++---------
 daemon/bindings/kres.h |   5 ++
 daemon/ffimodule.c     |  38 +++++++++++----
 3 files changed, 115 insertions(+), 32 deletions(-)

diff --git a/daemon/bindings/kres.c b/daemon/bindings/kres.c
index 164a18f18..f9d11c162 100644
--- a/daemon/bindings/kres.c
+++ b/daemon/bindings/kres.c
@@ -17,8 +17,21 @@
 #include "daemon/bindings/kres.h"
 #include "daemon/bindings.h"
 
-/* Metatable list */
-#define META_PKT "kres.meta_pkt"
+/** @internal Register metatable. */
+#define META_REGISTER(L, funcs, name) \
+	luaL_newmetatable((L), (name)); \
+	luaL_setfuncs((L), (funcs), 0); \
+	lua_pushvalue((L), -1); \
+	lua_setfield((L), -2, "__index"); \
+	lua_pop((L), 1);
+
+/** @internal Shortcut for dname conversion. */
+static inline void lua_pushdname(lua_State *L, const knot_dname_t *name)
+{
+	char dname_str[KNOT_DNAME_MAXLEN];
+	knot_dname_to_str(dname_str, name, sizeof(dname_str));
+	lua_pushstring(L, dname_str);
+}
 
 /* 
  * Packet interface
@@ -88,45 +101,89 @@ static int pkt_qclass(lua_State *L)
 static int pkt_qname(lua_State *L)
 {
 	knot_pkt_t *pkt = lua_touserdata(L, 1);
-	const knot_dname_t *dname = knot_pkt_qname(pkt);
-	char dname_str[KNOT_DNAME_MAXLEN];
-	knot_dname_to_str(dname_str, dname, sizeof(dname_str));
-	lua_pushstring(L, dname_str);
+	lua_pushdname(L, knot_pkt_qname(pkt));
 	return 1;	
 }
 
 #warning TODO: record interfaces
 
-static int pkt_meta_set(lua_State *L)
+static int pkt_meta_register(lua_State *L)
 {
-	static const luaL_Reg pkt_wrap[] = {
-		{ "flag",      pkt_flag},
-		{ "rcode",     pkt_rcode},
-		{ "opcode",    pkt_opcode},
-		{ "qtype",     pkt_qtype },
+	static const luaL_Reg wrap[] = {
+		{ "flag",      pkt_flag   },
+		{ "rcode",     pkt_rcode  },
+		{ "opcode",    pkt_opcode },
+		{ "qtype",     pkt_qtype  },
 		{ "qclass",    pkt_qclass },
-		{ "qname",     pkt_qname },
+		{ "qname",     pkt_qname  },
 		{ NULL, NULL }
 	};
-	luaL_newmetatable(L, META_PKT);
-	luaL_setfuncs(L, pkt_wrap, 0);
-	lua_pushvalue(L, -1);
-	lua_setfield(L, -2, "__index");
-	lua_pop(L, 1);
+	META_REGISTER (L, wrap, META_PKT);
 	return 0;
 }
 
-static int pkt_meta_get(lua_State *L)
+/**
+ * Query interface.
+ */
+
+static int query_qtype(lua_State *L)
 {
-	luaL_getmetatable(L, META_PKT);
-	lua_setmetatable(L, -2);
+	struct kr_query *qry = lua_touserdata(L, 1);
+	lua_pushnumber(L, qry->stype);
 	return 1;
 }
 
+static int query_qclass(lua_State *L)
+{
+	struct kr_query *qry = lua_touserdata(L, 1);
+	lua_pushnumber(L, qry->sclass);
+	return 1;	
+}
+
+static int query_qname(lua_State *L)
+{
+	struct kr_query *qry = lua_touserdata(L, 1);
+	lua_pushdname(L, qry->sname);
+	return 1;	
+}
+
+static int query_meta_register(lua_State *L)
+{
+	static const luaL_Reg wrap[] = {
+		{ "qtype",     query_qtype  },
+		{ "qclass",    query_qclass },
+		{ "qname",     query_qname  },
+		{ NULL, NULL }
+	};
+	META_REGISTER (L, wrap, META_QUERY);
+	return 0;
+}
+
 /**
  * Resolution context interface.
  */
 
+static int rplan_query(lua_State *L)
+{
+	struct kr_rplan *rplan = lua_touserdata(L, 1);
+	lua_pushlightuserdata(L, kr_rplan_current(rplan));
+	luaL_getmetatable(L, META_QUERY);
+	lua_setmetatable(L, -2);
+	return 1;
+}
+
+static int rplan_meta_register(lua_State *L)
+{
+	static const luaL_Reg wrap[] = {
+		{ "query",      rplan_query },
+		// { "pending",    rplan_pending },
+		// { "resolved",   rplan_resolved },
+		{ NULL, NULL }
+	};
+	META_REGISTER (L, wrap, META_RPLAN);
+	return 0;
+}
+
 #warning TODO: context interface, rplan
 
 #define WRAP_NUMBER(L, name, val) \
@@ -146,7 +203,6 @@ static int pkt_meta_get(lua_State *L)
 int lib_kres(lua_State *L)
 {
 	static const luaL_Reg lib[] = {
-		{ "packet", pkt_meta_get },
 		{ NULL, NULL }
 	};
 	/* Create module and register functions */
@@ -162,6 +218,8 @@ int lib_kres(lua_State *L)
 	WRAP_LUT(L, "opcode", knot_opcode_names);
 	WRAP_LUT(L, "wire",   wire_flag_names);
 	/* Register metatables */
-	pkt_meta_set(L);
+	pkt_meta_register(L);
+	query_meta_register(L);
+	rplan_meta_register(L);
 	return 1;	
 }
\ No newline at end of file
diff --git a/daemon/bindings/kres.h b/daemon/bindings/kres.h
index 39209e03a..d9881e36e 100644
--- a/daemon/bindings/kres.h
+++ b/daemon/bindings/kres.h
@@ -22,6 +22,11 @@
 
 #include "daemon/bindings.h"
 
+/* Metatable list */
+#define META_PKT   "kres.meta_pkt"
+#define META_QUERY "kres.meta_query"
+#define META_RPLAN "kres.meta_rplan"
+
 /**
  * Load libkres library.
  * @param  L scriptable
diff --git a/daemon/ffimodule.c b/daemon/ffimodule.c
index d1482b184..26eed9674 100644
--- a/daemon/ffimodule.c
+++ b/daemon/ffimodule.c
@@ -17,8 +17,9 @@
 #include <uv.h>
 
 #include "daemon/engine.h"
-#include "daemon/bindings.h"
 #include "daemon/ffimodule.h"
+#include "daemon/bindings.h"
+#include "daemon/bindings/kres.h"
 #include "lib/module.h"
 #include "lib/layer.h"
 
@@ -28,6 +29,13 @@
 #define l_resume(L, argc) lua_resume((L), (argc))
 #endif
 
+/** @internal Set metatable on the object on stack. */
+static void set_metatable(lua_State *L, const char *tname)
+{
+	luaL_getmetatable(L, tname);
+	lua_setmetatable(L, -2);
+}
+
 /** @internal Helper for retrieving the right function entrypoint. */
 static inline lua_State *l_ffi_preface(struct kr_module *module, const char *call) {
 	lua_State *L = module->lib;
@@ -131,51 +139,61 @@ static int l_ffi_deinit(struct kr_module *module)
 		lua_pop(L, 1); \
 		return ctx->state; \
 	} \
-	lua_pushnumber(L, ctx->state);
+	lua_pushnumber(L, ctx->state)
+
+/** @internal Push rplan and metatable. */
+#define LAYER_PUSH_RPLAN(ctx) do { \
+	struct kr_request *req = (ctx)->data; \
+	lua_pushlightuserdata(L, &req->rplan); \
+	set_metatable(L, META_RPLAN); \
+} while (0)
 
 static int l_ffi_layer_begin(knot_layer_t *ctx, void *module_param)
 {
+	ctx->data = module_param;
 	LAYER_FFI_CALL(ctx, "begin");
 	lua_pushlightuserdata(L, module_param);
-	ctx->data = module_param;
 	return l_ffi_call(L, 2);
 }
 
 static int l_ffi_layer_reset(knot_layer_t *ctx)
 {
 	LAYER_FFI_CALL(ctx, "reset");
-	lua_pushlightuserdata(L, ctx->data);
+	LAYER_PUSH_RPLAN(ctx);
 	return l_ffi_call(L, 2);
 }
 
 static int l_ffi_layer_finish(knot_layer_t *ctx)
 {
 	LAYER_FFI_CALL(ctx, "finish");
-	lua_pushlightuserdata(L, ctx->data);
+	LAYER_PUSH_RPLAN(ctx);
 	return l_ffi_call(L, 2);
 }
 
 static int l_ffi_layer_consume(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	LAYER_FFI_CALL(ctx, "consume");
-	lua_pushlightuserdata(L, ctx->data);
+	LAYER_PUSH_RPLAN(ctx);
 	lua_pushlightuserdata(L, pkt);
+	set_metatable(L, META_PKT);
 	return l_ffi_call(L, 3);
 }
 
 static int l_ffi_layer_produce(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	LAYER_FFI_CALL(ctx, "produce");
-	lua_pushlightuserdata(L, ctx->data);
+	LAYER_PUSH_RPLAN(ctx);
 	lua_pushlightuserdata(L, pkt);
+	set_metatable(L, META_PKT);
 	return l_ffi_call(L, 3);
 }
 
 static int l_ffi_layer_fail(knot_layer_t *ctx, knot_pkt_t *pkt)
 {
 	LAYER_FFI_CALL(ctx, "fail");
-	lua_pushlightuserdata(L, ctx->data);
+	LAYER_PUSH_RPLAN(ctx);
 	lua_pushlightuserdata(L, pkt);
+	set_metatable(L, META_PKT);
 	return l_ffi_call(L, 3);
 }
 
@@ -200,7 +218,8 @@ static const knot_layer_api_t* l_ffi_layer(struct kr_module *module)
 		api = malloc(sizeof(*api));
 		if (api) {
 			memset(api, 0, sizeof(*api));
-			LAYER_REGISTER(L, api, begin);
+			/* Begin is always set, as it initializes layer baton. */
+			api->begin = l_ffi_layer_begin;
 			LAYER_REGISTER(L, api, finish);
 			LAYER_REGISTER(L, api, consume);
 			LAYER_REGISTER(L, api, produce);
@@ -218,6 +237,7 @@ static const knot_layer_api_t* l_ffi_layer(struct kr_module *module)
 
 #undef LAYER_REGISTER
 #undef LAYER_FFI_CALL
+#undef LAYER_PUSH_RPLAN
 
 /** @internal Helper macro for function presence check. */
 #define REGISTER_FFI_CALL(L, attr, name, cb) do { \
-- 
GitLab