Skip to content

Instantly share code, notes, and snippets.

@vavrusa
Last active Aug 29, 2015
Embed
What would you like to do?
Lua/C DHCP example #1
#include <stdio.h>
#include <string.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
#include <arpa/inet.h>
/* Get/set opcode */
static int msg_op(lua_State *L)
{
char *msg = lua_touserdata(L, 1);
if (lua_isnumber(L, 2)) {
msg[0] = lua_tointeger(L, 2) & 0xFF;
}
lua_pushnumber(L, msg[0]);
return 1;
}
/* Get/set "your address" */
static int msg_yiaddr(lua_State *L)
{
char *msg = lua_touserdata(L, 1);
if (lua_isstring(L, 2)) {
inet_pton(AF_INET, lua_tostring(L, 2), msg + 16);
return 0;
}
char strbuf[INET_ADDRSTRLEN] = {'\0'};
inet_ntop(AF_INET, msg + 16, strbuf, sizeof(strbuf));
lua_pushstring(L, strbuf); /* Make a copy */
return 1;
}
/* Get "client hardware address" */
static int msg_chaddr(lua_State *L)
{
char *msg = lua_touserdata(L, 1);
lua_pushlstring(L, msg + 28, 16);
return 1;
}
/* Register 'msg' meta table */
static int msg_register(lua_State *L)
{
static const luaL_Reg wrap[] = {
{ "op", &msg_op },
{ "yiaddr", &msg_yiaddr },
{ "chaddr", &msg_chaddr },
{ NULL, NULL }
};
luaL_newmetatable(L, "msg");
lua_pushvalue(L, -1);
lua_setfield(L, -2, "__index");
luaL_openlib(L, NULL, wrap, 0);
lua_pop(L, 1);
return 0;
}
static int on_recv(lua_State *L, int cb_ref, char *buf, size_t len)
{
lua_rawgeti(L, LUA_REGISTRYINDEX, cb_ref);
lua_pushlightuserdata(L, buf);
luaL_getmetatable(L, "msg");
lua_setmetatable(L, -2);
lua_pushinteger(L, len);
return lua_pcall(L, 2, 1, 0);
}
/* Convenience stuff */
static void close_state(lua_State **L) { lua_close(*L); }
#define cleanup(x) __attribute__((cleanup(x)))
#define auto_lclose cleanup(close_state)
int main(int argc, char *argv[])
{
/* Create VM state */
auto_lclose lua_State *L = luaL_newstate();
if (!L)
return 1;
luaL_openlibs(L);
/* Load config file */
if (argc > 1) {
luaL_loadfile(L, argv[1]); /* (1) */
int ret = lua_pcall(L, 0, 0, 0);
if (ret != 0) {
fprintf(stderr, "%s\n", lua_tostring(L, -1));
return 1;
}
}
/* Read out config */
lua_getglobal(L, "address"); /* (2) */
lua_getglobal(L, "port");
printf("address: %s, port: %ld\n", /* (3) */
lua_tostring(L, -2), lua_tointeger(L, -1));
lua_settop(L, 0); /* (4) */
/* Register bindings */
msg_register(L);
lua_getglobal(L, "callback");
int cb_ref = luaL_ref(L, LUA_REGISTRYINDEX);
/* Prepare mock datagram. */
char dhcp_req[512] = {
0x01, 0x01, 0x06, 0x00
};
char dgram[sizeof(dhcp_req)];
/* Call a few times, no I/O yet. */
const size_t nr_calls = 1000000;
for (unsigned i = 0; i < nr_calls; ++i) {
dgram[0] = 0x01; /* reset to DHCPDISCOVER */
int ret = on_recv(L, cb_ref, dgram, sizeof(dgram));
if (ret != 0) {
printf("%s\n", lua_tostring(L, -1));
return 1;
}
lua_pop(L, 1);
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment