Manifest:
- loption.h loption.cc: the C++ OptionPtr encapsulated into a lua full
- userdata with a few methods ported.
+ userdata with some methods ported.
- ppkt4.h ppkt4.cc: the C++ Pkt4Ptr encapsulated into a lua full userdata
- with a few methods ported.
+ with some methods ported.
one can complete these lua types or/and new lua type.
namespace { // anonymous namespace
+// __gc
+int option__gc(lua_State* L) {
+ // This is a critical code to avoid memory leaks
+ cout << "option__gc called\n";
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ self->object.reset();
+ return (0);
+}
+
+// __tostring
+int option__tostring(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ lua_pushstring(L, self->object->toText(0).c_str());
+ return (1);
+}
+
+// Method table
+const luaL_Reg option_method[] = {
+ { "__gc", option__gc },
+ { "__tostring", option__tostring },
+ { NULL, NULL }
+};
+
// factory(universe, type, data)
int factory(lua_State* L) {
- // Require 3 arguments
- if (lua_gettop(L) - 1 != 3) {
+ // Requires 3 arguments
+ if (lua_gettop(L) != 3) {
return (luaL_error(L, "option.factory takes 3 arguments"));
}
- if (lua_type(L, -3) != LUA_TNUMBER) {
- return (luaL_error(L, "universe must be a number"));
+ if (!lua_isinteger(L, 1)) {
+ return (luaL_error(L, "universe must be an integer"));
}
- if (lua_type(L, -2) != LUA_TNUMBER) {
- return (luaL_error(L, "type must be a number"));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "type must be an integer"));
}
- if (lua_type(L, -1) != LUA_TSTRING) {
+ if (!lua_isstring(L, 3)) {
return (luaL_error(L, "data must be a string"));
}
- unsigned char u = static_cast<unsigned char>(lua_tonumber(L, -3));
- unsigned short t = static_cast<unsigned short>(lua_tonumber(L, -2));
+ uint8_t u = static_cast<uint8_t>(lua_tointeger(L, 1));
+ uint16_t t = static_cast<uint16_t>(lua_tointeger(L, 2));
Option::Universe universe;
switch (u) {
case 4:
}
size_t len = 0;
- const char* d = lua_tolstring(L, -1, &len);
+ const char* d = lua_tolstring(L, 3, &len);
OptionBuffer data;
data.resize(len);
if (len) {
return (1);
}
-// __gc
-int option__gc(lua_State* L) {
- // This is a critical code to avoid memory leaks
- cout << "option__gc called\n";
- l_option* const self =
- static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
- self->object.reset();
- return (0);
-}
-
-// __tostring
-int option__tostring(lua_State* L) {
- l_option* const self =
- static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
- lua_pushstring(L, self->object->toText(0).c_str());
- return (1);
-}
-
// getUniverse() method
int getUniverse(lua_State* L) {
l_option* const self =
}
}
-// Method table
-const luaL_Reg option_method[] = {
- { "__gc", option__gc },
- { "__tostring", option__tostring },
- { "getUniverse", getUniverse },
- { NULL, NULL }
-};
+// toBinary(bool include_header = false) method
+int toBinary(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ vector<uint8_t> bin = self->object->toBinary(true);
+ lua_pushlstring(L, reinterpret_cast<char*>(&bin[0]), bin.size());
+ return (1);
+}
+
+// getType() method
+int getType(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->getType()));
+ return (1);
+}
+
+// len() method
+int len(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->len()));
+ return (1);
+}
+
+// getHeaderLen() method
+int getHeaderLen(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->getHeaderLen()));
+ return (1);
+}
+
+// getData() method
+int getData(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ const OptionBuffer& data = self->object->getData();
+ lua_pushlstring(L, reinterpret_cast<const char*>(&data[0]), data.size());
+ return (1);
+}
+
+// addOption(OptionPtr opt) method
+int addOption(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "option.addOption takes 2 arguments"));
+ }
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ l_option* const sub =
+ static_cast<l_option*>(luaL_checkudata(L, 2, LUA_KEAOPTION));
+ self->object->addOption(sub->object);
+ return (0);
+}
+
+// getOption(uint16_t type) method
+int getOption(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "option.getOption takes 2 arguments"));
+ }
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "type must be an integer"));
+ }
+ uint16_t t = static_cast<uint16_t>(lua_tointeger(L, 2));
+ OptionPtr sub = self->object->getOption(t);
+ if (sub) {
+ void* ret =
+ static_cast<l_option*>(lua_newuserdata(L, sizeof(l_option)));
+ memset(ret, 0, sizeof(l_option));
+ (static_cast<l_option*>(ret))->object = sub;
+ } else {
+ lua_pushnil(L);
+ }
+ return (1);
+}
+
+// TODO: getOptions() method
+
+// delOption(uint16_t type) method
+int delOption(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "option.delOption takes 2 arguments"));
+ }
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "type must be an integer"));
+ }
+ uint16_t t = static_cast<uint16_t>(lua_tointeger(L, 2));
+ bool ret = self->object->delOption(t);
+ lua_pushboolean(L, ret ? 1 : 0);
+ return (1);
+}
+
+// setData(<byte>) method
+int setData(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "option.setData takes 2 arguments"));
+ }
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ if (!lua_isstring(L, 2)) {
+ return (luaL_error(L, "data must be a string"));
+ }
+ size_t len = 0;
+ const char* d = lua_tolstring(L, 2, &len);
+ OptionBuffer data;
+ data.resize(len);
+ if (len) {
+ memmove(&data[0], d, len);
+ }
+ self->object->setData(data.begin(), data.end());
+ return (0);
+}
+
+// setEncapsulatedSpace(const string& encapsulated_space) method
+int setEncapsulatedSpace(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L,
+ "option.setEncapsulatedSpace takes 2 arguments"));
+ }
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ if (!lua_isstring(L, 2)) {
+ return (luaL_error(L, "encapsulated_state must be a string"));
+ }
+ string state(lua_tostring(L, 2));
+ self->object->setEncapsulatedSpace(state);
+ return (0);
+}
+
+// getEncapsulatedSpace() method
+int getEncapsulatedSpace(lua_State* L) {
+ l_option* const self =
+ static_cast<l_option*>(luaL_checkudata(L, 1, LUA_KEAOPTION));
+ lua_pushstring(L, self->object->getEncapsulatedSpace().c_str());
+ return (1);
+}
// Function table
const luaL_Reg option_function[] = {
+ { "factory", factory },
+ { "getUniverse", getUniverse },
+ { "toBinary", toBinary },
+ { "getType", getType },
+ { "len", len },
+ { "getHeaderLen", getHeaderLen },
+ { "getData", getData },
+ { "addOption", addOption },
+ { "getOption", getOption },
+ { "delOption", delOption },
+ { "setData", setData },
+ { "setEncapsulatedSpace", setEncapsulatedSpace },
+ { "getEncapsulatedSpace", getEncapsulatedSpace },
{ NULL, NULL }
};
return (1);
}
+// Method table
+const luaL_Reg pkt4_method[] = {
+ { "__gc", pkt4__gc },
+ { "__tostring", pkt4__tostring },
+ { NULL, NULL }
+};
+
// addOption(const OptionPtr opt) method
int addOption(lua_State* L) {
l_pkt4* const self =
return (0);
}
-// Method table
-const luaL_Reg pkt4_method[] = {
- { "__gc", pkt4__gc },
- { "__tostring", pkt4__tostring },
- { "addOption", addOption },
- { NULL, NULL }
-};
+// delOption(uint16_t type) method
+int delOption(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.delOption takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "type must be an integer"));
+ }
+ uint16_t t = static_cast<uint16_t>(lua_tointeger(L, 2));
+ bool ret = self->object->delOption(t);
+ lua_pushboolean(L, ret ? 1 : 0);
+ return (1);
+}
+
+// len() method
+int len(lua_State* L) {
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->len()));
+ return (1);
+}
+
+// getType() method
+int getType(lua_State* L) {
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->getType()));
+ return (1);
+}
+
+// setType(uint8_t type) method
+int setType(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.setType takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "type must be an integer"));
+ }
+ uint16_t t = static_cast<uint16_t>(lua_tointeger(L, 2));
+ self->object->setType(t);
+ return (1);
+}
+
+// setTransid(uint32_t transid) method
+int setTransid(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.setTransid takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "transid must be an integer"));
+ }
+ uint32_t t = static_cast<uint32_t>(lua_tointeger(L, 2));
+ self->object->setTransid(t);
+ return (1);
+}
+
+// getTransid() method
+int getTransid(lua_State* L) {
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->getTransid()));
+ return (1);
+}
+
+// inClass(const isc::dhcp::ClientClass& client_class) method
+int inClass(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.inClass takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isstring(L, 2)) {
+ return (luaL_error(L, "client_class must be a string"));
+ }
+ const ClientClass& cclass(lua_tostring(L, 2));
+ bool ret = self->object->inClass(cclass);
+ lua_pushboolean(L, ret ? 1 : 0);
+ return (1);
+}
+
+// addClass(const isc::dhcp::ClientClass& client_class) method
+int addClass(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.addClass takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isstring(L, 2)) {
+ return (luaL_error(L, "client_class must be a string"));
+ }
+ const ClientClass& cclass(lua_tostring(L, 2));
+ self->object->addClass(cclass);
+ return (0);
+}
+
+// TODO: getClasses() method
+
+// getOption(uint16_t type) method
+int getOption(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.getOption takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "type must be an integer"));
+ }
+ uint16_t t = static_cast<uint16_t>(lua_tointeger(L, 2));
+ OptionPtr sub = self->object->getOption(t);
+ if (sub) {
+ void* ret =
+ static_cast<l_option*>(lua_newuserdata(L, sizeof(l_option)));
+ memset(ret, 0, sizeof(l_option));
+ (static_cast<l_option*>(ret))->object = sub;
+ } else {
+ lua_pushnil(L);
+ }
+ return (1);
+}
+
+// TODO: getTimestamp() method
+
+// TODO: set/getLocal/RemoteAddr/Port methods
+
+// setIndex(uint32_t ifindex) method
+int setIndex(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.setIndex takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isinteger(L, 2)) {
+ return (luaL_error(L, "ifindex must be an integer"));
+ }
+ uint32_t t = static_cast<uint32_t>(lua_tointeger(L, 2));
+ self->object->setIndex(t);
+ return (1);
+}
+
+// getIndex() method
+int getIndex(lua_State* L) {
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ lua_pushinteger(L, static_cast<lua_Integer>(self->object->getIndex()));
+ return (1);
+}
+
+// getIface() method
+int getIface(lua_State* L) {
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ lua_pushstring(L, self->object->getIface().c_str());
+ return (1);
+}
+
+// setIface(const std::string& iface) method
+int setIface(lua_State* L) {
+ // Requires 2 arguments
+ if (lua_gettop(L) != 2) {
+ return (luaL_error(L, "pkt4.setIface takes 2 arguments"));
+ }
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ if (!lua_isstring(L, 2)) {
+ return (luaL_error(L, "iface must be a string"));
+ }
+ const ClientClass& cclass(lua_tostring(L, 2));
+ self->object->setIface(cclass);
+ return (0);
+}
+
+// TODO many methods
+
+// getHWAddr() method
+int getHWAddr(lua_State* L) {
+ l_pkt4* const self =
+ static_cast<l_pkt4*>(luaL_checkudata(L, 1, LUA_KEAPKT4));
+ HWAddrPtr hwaddr = self->object->getHWAddr();
+ vector<uint8_t> bin;
+ if (hwaddr) {
+ bin = hwaddr->hwaddr_;
+ }
+ lua_pushlstring(L, reinterpret_cast<char*>(&bin[0]), bin.size());
+ return (1);
+}
// Function table
const luaL_Reg pkt4_function[] = {
+ { "addOption", addOption },
+ { "delOption", delOption },
+ { "len", len },
+ { "getType", getType },
+ { "setType", setType },
+ { "setTransid", setTransid },
+ { "getTransid", getTransid },
+ { "inClass", inClass },
+ { "addClass", addClass },
+ { "getOption", getOption },
+ { "setIndex", setIndex },
+ { "getIndex", getIndex },
+ { "getIface", getIface },
+ { "setIface", setIface },
+ { "getHWAddr", getHWAddr },
{ NULL, NULL }
};
external getIface : pkt4 -> string = "pkt4_getIface"
external setIface : pkt4 -> string -> unit = "pkt4_setIface"
+
+ external getHWAddr : pkt4 -> bytes = "pkt4_getHWAddr"
end
let _ = print_leave "pkt4"
external getIface : pkt4 -> string = "pkt4_getIface"
external setIface : pkt4 -> string -> unit = "pkt4_setIface"
+
+ (* TODO many *)
+
+ external getHWAddr : pkt4 -> bytes = "pkt4_getHWAddr"
end
val next_step_continue : int
CAMLparam1(opt);
CAMLlocal1(result);
oc_opt* const self = static_cast<oc_opt*>(Data_custom_val(opt));
- vector<uint8_t> bin = self->object->toBinary(0);
+ vector<uint8_t> bin = self->object->toBinary(true);
result = caml_alloc_string(static_cast<mlsize_t>(bin.size()));
memmove(String_val(result), &bin[0], bin.size());
CAMLreturn (result);
CAMLreturn (Val_unit);
}
+// TODO many
+
+extern "C" CAMLprim value pkt4_getHWAddr(value pkt) {
+ CAMLparam1(pkt);
+ CAMLlocal1(result);
+ oc_pkt4* const self = static_cast<oc_pkt4*>(Data_custom_val(pkt));
+ HWAddrPtr hwaddr = self->object->getHWAddr();
+ vector<uint8_t> bin;
+ if (hwaddr) {
+ bin = hwaddr->hwaddr_;
+ }
+ result = caml_alloc_string(static_cast<mlsize_t>(bin.size()));
+ if (!bin.empty()) {
+ memmove(String_val(result), &bin[0], bin.size());
+ }
+ CAMLreturn (result);
+}
+
} // end of namespace ocaml
} // end of namespace isc
extern "C" CAMLprim value pkt4_getIndex(value pkt);
extern "C" CAMLprim value pkt4_getIface(value pkt);
extern "C" CAMLprim value pkt4_setIface(value pkt, value ifn);
+extern "C" CAMLprim value pkt4_getHWAddr(value pkt);
CAMLextern struct custom_operations* pkt4_ops;
OptionBuffer data;
data.resize(PyBytes_GET_SIZE(d));
- memmove(&data[0], PyBytes_AS_STRING(d), data.size());
+ if (!data.empty()) {
+ memmove(&data[0], PyBytes_AS_STRING(d), data.size());
+ }
py_option* const self = static_cast<py_option*>(obj);
self->object.reset(new Option(universe, t, data));
}
vector<uint8_t> data;
data.resize(PyBytes_GET_SIZE(d));
- memmove(&data[0], PyBytes_AS_STRING(d), data.size());
+ if (!data.empty()) {
+ memmove(&data[0], PyBytes_AS_STRING(d), data.size());
+ }
py_option* const self = static_cast<py_option*>(obj);
self->object->setData(data.begin(), data.end());
Py_RETURN_NONE;
}
+// TODO many methods
+
+// getHWAddr() method
+PyObject*
+getHWAddr(PyObject* obj) {
+ py_pkt4* const self = static_cast<py_pkt4*>(obj);
+ HWAddrPtr hwaddr = self->object->getHWAddr();
+ vector<uint8_t> bin;
+ if (hwaddr) {
+ bin = hwaddr->hwaddr_;
+ }
+ return (PyBytes_FromStringAndSize(reinterpret_cast<char*>(&bin[0]),
+ static_cast<Py_ssize_t>(bin.size())));
+}
+
// Method table
PyMethodDef pkt4_method[] = {
{ "addOption", addOption, METH_VARARGS,
"return interface name" },
{ "setIface", setIface, METH_VARARGS,
"sets interface name" },
+ { "getHWAddr", (PyCFunction)getHWAddr, METH_NOARGS,
+ "returns hardware address information" },
{ NULL, NULL, 0, NULL }
};