summaryrefslogtreecommitdiff
path: root/lib/frrscript.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/frrscript.c')
-rw-r--r--lib/frrscript.c174
1 files changed, 102 insertions, 72 deletions
diff --git a/lib/frrscript.c b/lib/frrscript.c
index 081ecd026f..c8ea946334 100644
--- a/lib/frrscript.c
+++ b/lib/frrscript.c
@@ -27,133 +27,171 @@
#include "frrlua.h"
-/* Type encoders */
-
-struct encoder {
- char *typename;
- encoder_func encoder;
-};
-
-struct hash *encoder_hash;
-
-static unsigned int encoder_hash_key(const void *data)
+/* Codecs */
+
+struct frrscript_codec frrscript_codecs_lib[] = {
+ {.typename = "integer",
+ .encoder = (encoder_func)lua_pushintegerp,
+ .decoder = lua_tointegerp},
+ {.typename = "string",
+ .encoder = (encoder_func)lua_pushstring,
+ .decoder = lua_tostringp},
+ {.typename = "prefix",
+ .encoder = (encoder_func)lua_pushprefix,
+ .decoder = lua_toprefix},
+ {.typename = "interface",
+ .encoder = (encoder_func)lua_pushinterface,
+ .decoder = lua_tointerface},
+ {.typename = "in_addr",
+ .encoder = (encoder_func)lua_pushinaddr,
+ .decoder = lua_toinaddr},
+ {.typename = "in6_addr",
+ .encoder = (encoder_func)lua_pushin6addr,
+ .decoder = lua_toin6addr},
+ {.typename = "sockunion",
+ .encoder = (encoder_func)lua_pushsockunion,
+ .decoder = lua_tosockunion},
+ {.typename = "time_t",
+ .encoder = (encoder_func)lua_pushtimet,
+ .decoder = lua_totimet},
+ {}};
+
+/* Type codecs */
+
+struct hash *codec_hash;
+
+static unsigned int codec_hash_key(const void *data)
{
- const struct encoder *e = data;
+ const struct frrscript_codec *c = data;
- return string_hash_make(e->typename);
+ return string_hash_make(c->typename);
}
-static bool encoder_hash_cmp(const void *d1, const void *d2)
+static bool codec_hash_cmp(const void *d1, const void *d2)
{
- const struct encoder *e1 = d1;
- const struct encoder *e2 = d2;
+ const struct frrscript_codec *e1 = d1;
+ const struct frrscript_codec *e2 = d2;
return strmatch(e1->typename, e2->typename);
}
-static void *encoder_alloc(void *arg)
+static void *codec_alloc(void *arg)
{
- struct encoder *tmp = arg;
+ struct frrscript_codec *tmp = arg;
- struct encoder *e = XCALLOC(MTYPE_TMP, sizeof(struct encoder));
+ struct frrscript_codec *e =
+ XCALLOC(MTYPE_TMP, sizeof(struct frrscript_codec));
e->typename = XSTRDUP(MTYPE_TMP, tmp->typename);
e->encoder = tmp->encoder;
+ e->decoder = tmp->decoder;
return e;
}
#if 0
-static void encoder_free(struct encoder *e)
+static void codec_free(struct codec *c)
{
- XFREE(MTYPE_TMP, e->typename);
- XFREE(MTYPE_TMP, e);
+ XFREE(MTYPE_TMP, c->typename);
+ XFREE(MTYPE_TMP, c);
}
#endif
/* Generic script APIs */
-int frrscript_lua_call(struct frrscript *fs, ...)
+int frrscript_call(struct frrscript *fs, struct frrscript_env *env)
{
- va_list vl;
- va_start(vl, fs);
-
- int nargs = va_arg(vl, int);
- assert(nargs % 3 == 0);
-
- zlog_debug("%s: Script '%s' called with # args: %d", __func__, fs->name,
- nargs);
-
- struct encoder e = {};
- void *arg;
+ struct frrscript_codec c = {};
+ const void *arg;
const char *bindname;
/* Encode script arguments */
- for (int i = 0; i < nargs; i += 3) {
- bindname = va_arg(vl, const char *);
- e.typename = va_arg(vl, char *);
- arg = va_arg(vl, void *);
+ for (int i = 0; env && env[i].val != NULL; i++) {
+ bindname = env[i].name;
+ c.typename = env[i].typename;
+ arg = env[i].val;
zlog_debug("Script argument | Bind name: %s | Type: %s",
- bindname, e.typename);
+ bindname, c.typename);
- struct encoder *enc = hash_lookup(encoder_hash, &e);
- assert(enc
+ struct frrscript_codec *codec = hash_lookup(codec_hash, &c);
+ assert(codec
&& "No encoder for type; rerun with debug logs to see more");
- enc->encoder(fs->L, arg);
+ codec->encoder(fs->L, arg);
lua_setglobal(fs->L, bindname);
}
- int nresults = va_arg(vl, int);
- zlog_debug("Expected script results: %d", nresults);
-
- int ret = lua_pcall(fs->L, 0, nresults, 0);
+ int ret = lua_pcall(fs->L, 0, 0, 0);
switch (ret) {
case LUA_OK:
break;
case LUA_ERRRUN:
- zlog_err("Script '%s' runtime error: %s", fs->name, lua_tostring(fs->L, -1));
+ zlog_err("Script '%s' runtime error: %s", fs->name,
+ lua_tostring(fs->L, -1));
break;
case LUA_ERRMEM:
- zlog_err("Script '%s' memory error: %s", fs->name, lua_tostring(fs->L, -1));
+ zlog_err("Script '%s' memory error: %s", fs->name,
+ lua_tostring(fs->L, -1));
break;
case LUA_ERRERR:
- zlog_err("Script '%s' error handler error: %s", fs->name, lua_tostring(fs->L, -1));
+ zlog_err("Script '%s' error handler error: %s", fs->name,
+ lua_tostring(fs->L, -1));
break;
case LUA_ERRGCMM:
- zlog_err("Script '%s' garbage collector error: %s", fs->name, lua_tostring(fs->L, -1));
+ zlog_err("Script '%s' garbage collector error: %s", fs->name,
+ lua_tostring(fs->L, -1));
break;
default:
- zlog_err("Script '%s' unknown error: %s", fs->name, lua_tostring(fs->L, -1));
+ zlog_err("Script '%s' unknown error: %s", fs->name,
+ lua_tostring(fs->L, -1));
break;
}
- if (ret != LUA_OK)
+ if (ret != LUA_OK) {
lua_pop(fs->L, 1);
-
- /* After script returns, decode results */
- for (int i = 0; i < nresults; i++) {
- const char *resultname = va_arg(vl, const char *);
- fprintf(stderr, "result: %s\n", resultname);
+ goto done;
}
+done:
/* LUA_OK is 0, so we can just return lua_pcall's result directly */
return ret;
}
-void frrscript_register_type_encoder(const char *typename, encoder_func encoder)
+void *frrscript_get_result(struct frrscript *fs,
+ const struct frrscript_env *result)
{
- struct encoder e = {.typename = (char *)typename, .encoder = encoder};
+ void *r;
+ struct frrscript_codec c = {.typename = result->typename};
+
+ struct frrscript_codec *codec = hash_lookup(codec_hash, &c);
+
+ lua_getglobal(fs->L, result->name);
+ r = codec->decoder(fs->L, -1);
+ lua_pop(fs->L, 1);
+
+ return r;
+}
- if (hash_lookup(encoder_hash, &e)) {
+void frrscript_register_type_codec(struct frrscript_codec *codec)
+{
+ struct frrscript_codec c = *codec;
+
+ zlog_debug("Registering codec for '%s'", codec->typename);
+
+ if (hash_lookup(codec_hash, &c)) {
zlog_backtrace(LOG_ERR);
- assert(!"Type encoder double-registered.");
+ assert(!"Type codec double-registered.");
}
- assert(hash_get(encoder_hash, &e, encoder_alloc));
+ assert(hash_get(codec_hash, &c, codec_alloc));
}
+void frrscript_register_type_codecs(struct frrscript_codec *codecs)
+{
+ for (int i = 0; codecs[i].typename != NULL; i++)
+ frrscript_register_type_codec(&codecs[i]);
+}
struct frrscript *frrscript_load(const char *name,
int (*load_cb)(struct frrscript *))
@@ -216,17 +254,9 @@ void frrscript_unload(struct frrscript *fs)
void frrscript_init()
{
- encoder_hash = hash_create(encoder_hash_key, encoder_hash_cmp,
- "Lua type encoders");
+ codec_hash = hash_create(codec_hash_key, codec_hash_cmp,
+ "Lua type encoders");
/* Register core library types */
- frrscript_register_type_encoder("integer", (encoder_func) lua_pushintegerp);
- frrscript_register_type_encoder("string", (encoder_func) lua_pushstring);
- frrscript_register_type_encoder("prefix", (encoder_func)lua_pushprefix);
- frrscript_register_type_encoder("interface",
- (encoder_func)lua_pushinterface);
- frrscript_register_type_encoder("sockunion", (encoder_func) lua_pushsockunion);
- frrscript_register_type_encoder("in_addr", (encoder_func) lua_pushinaddr);
- frrscript_register_type_encoder("in6_addr", (encoder_func) lua_pushin6addr);
- frrscript_register_type_encoder("time_t", (encoder_func) lua_pushtimet);
+ frrscript_register_type_codecs(frrscript_codecs_lib);
}