Last active
August 29, 2015 14:26
-
-
Save vavrusa/7c4b02ac2e4714358273 to your computer and use it in GitHub Desktop.
Lua/C DHCP example #1
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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