From: Michael Tremer Date: Thu, 22 Feb 2024 13:43:34 +0000 (+0000) Subject: lua: Add a Network object X-Git-Tag: 0.9.18~164 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e914e3ca99c7a85b41ca03fa5327a53823e64802;p=location%2Flibloc.git lua: Add a Network object Signed-off-by: Michael Tremer --- diff --git a/Makefile.am b/Makefile.am index 8b986a4..e3ed1fc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -240,7 +240,9 @@ src_lua_location_la_SOURCES = \ src/lua/database.c \ src/lua/database.h \ src/lua/location.c \ - src/lua/location.h + src/lua/location.h \ + src/lua/network.c \ + src/lua/network.h src_lua_location_la_CFLAGS = \ $(AM_CFLAGS) \ @@ -262,7 +264,9 @@ EXTRA_DIST += \ src/lua/database.c \ src/lua/database.h \ src/lua/location.c \ - src/lua/location.h + src/lua/location.h \ + src/lua/network.c \ + src/lua/network.h LUA_TESTS = \ tests/lua/main.lua diff --git a/src/lua/database.c b/src/lua/database.c index 13a81bd..2912f4c 100644 --- a/src/lua/database.c +++ b/src/lua/database.c @@ -109,15 +109,5 @@ static const struct luaL_Reg database_functions[] = { }; int register_database(lua_State* L) { - // Create a new metatable - luaL_newmetatable(L, "location.Database"); - - // Set functions - luaL_setfuncs(L, database_functions, 0); - - // Configure metatable - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - - return 1; + return register_class(L, "location.Database", database_functions); } diff --git a/src/lua/location.c b/src/lua/location.c index ee9bce5..315a790 100644 --- a/src/lua/location.c +++ b/src/lua/location.c @@ -25,6 +25,7 @@ #include "location.h" #include "database.h" +#include "network.h" struct loc_ctx* ctx = NULL; @@ -55,5 +56,10 @@ int luaopen_location(lua_State* L) { lua_setfield(L, -2, "Database"); + // Register Network type + register_network(L); + + lua_setfield(L, -2, "Network"); + return 1; } diff --git a/src/lua/location.h b/src/lua/location.h index 6eef1a6..cc261e6 100644 --- a/src/lua/location.h +++ b/src/lua/location.h @@ -25,4 +25,19 @@ extern struct loc_ctx* ctx; int luaopen_location(lua_State* L); +static inline int register_class(lua_State* L, + const char* name, const struct luaL_Reg* functions) { + // Create a new metatable + luaL_newmetatable(L, name); + + // Set functions + luaL_setfuncs(L, functions, 0); + + // Configure metatable + lua_pushvalue(L, -1); + lua_setfield(L, -2, "__index"); + + return 1; +} + #endif /* LUA_LOCATION_LOCATION_H */ diff --git a/src/lua/network.c b/src/lua/network.c new file mode 100644 index 0000000..0706fe2 --- /dev/null +++ b/src/lua/network.c @@ -0,0 +1,149 @@ +/* + libloc - A library to determine the location of someone on the Internet + + Copyright (C) 2024 IPFire Development Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. +*/ + +#include +#include +#include + +#include +#include + +#include + +#include "location.h" +#include "network.h" + +typedef struct network { + struct loc_network* network; +} Network; + +static Network* luaL_checknetwork(lua_State* L, int i) { + void* userdata = luaL_checkudata(L, i, "location.Network"); + + // Throw an error if the argument doesn't match + luaL_argcheck(L, userdata, i, "Network expected"); + + return (Network*)userdata; +} + +static int create_network(lua_State* L, struct loc_network* network) { + // Allocate a new object + Network* self = (Network*)lua_newuserdata(L, sizeof(*self)); + + // Set metatable + luaL_setmetatable(L, "location.Network"); + + // Store network + self->network = loc_network_ref(network); + + return 1; +} + +static int Network_new(lua_State* L) { + struct loc_network* network = NULL; + const char* n = NULL; + int r; + + // Fetch the network + n = luaL_checkstring(L, 1); + + // Parse the string + r = loc_network_new_from_string(ctx, &network, n); + if (r) + return luaL_error(L, "Could not create network %s: %s\n", n, strerror(errno)); + + // Return the network + r = create_network(L, network); + loc_network_unref(network); + + return r; +} + +static int Network_gc(lua_State* L) { + Network* self = luaL_checknetwork(L, 0); + + if (self->network) + loc_network_unref(self->network); + + free(self); + return 0; +} + +static int Network_tostring(lua_State* L) { + Network* self = luaL_checknetwork(L, 1); + + // Push string representation of the network + lua_pushstring(L, loc_network_str(self->network)); + + return 1; +} + +// ASN + +static int Network_get_asn(lua_State* L) { + Network* self = luaL_checknetwork(L, 0); + + uint32_t asn = loc_network_get_asn(self->network); + + // Push ASN + if (asn) + lua_pushnumber(L, asn); + else + lua_pushnil(L); + + return 1; +} + +// Family + +static int Network_get_family(lua_State* L) { + Network* self = luaL_checknetwork(L, 0); + + // Push family + lua_pushnumber(L, loc_network_address_family(self->network)); + + return 1; +} + +// Country Code + +static int Network_get_country_code(lua_State* L) { + Network* self = luaL_checknetwork(L, 0); + + const char* country_code = loc_network_get_country_code(self->network); + + // Push country code + if (country_code && *country_code) + lua_pushstring(L, country_code); + else + lua_pushnil(L); + + return 1; +} + +static const struct luaL_Reg Network_functions[] = { + { "new", Network_new }, + { "get_asn", Network_get_asn }, + { "get_family", Network_get_family }, + { "get_country_code", Network_get_country_code }, + { "__gc", Network_gc }, + { "__tostring", Network_tostring }, + { NULL, NULL }, +}; + +int register_network(lua_State* L) { + return register_class(L, "location.Network", Network_functions); +} diff --git a/src/lua/network.h b/src/lua/network.h new file mode 100644 index 0000000..54be76d --- /dev/null +++ b/src/lua/network.h @@ -0,0 +1,25 @@ +/* + libloc - A library to determine the location of someone on the Internet + + Copyright (C) 2024 IPFire Development Team + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. +*/ + +#ifndef LUA_LOCATION_NETWORK_H +#define LUA_LOCATION_NETWORK_H + +#include +#include + +int register_network(lua_State* L); + +#endif /* LUA_LOCATION_NETWORK_H */ diff --git a/tests/lua/main.lua b/tests/lua/main.lua index 174bd3b..fada168 100755 --- a/tests/lua/main.lua +++ b/tests/lua/main.lua @@ -46,4 +46,19 @@ function test_lookup() db.lookup("81.3.27.32") end +function test_network() + location = require("location") + + n1 = location.Network.new("10.0.0.0/8") + + -- The ASN should be nul + luaunit.assertNil(n1.get_asn()) + + -- The family should be IPv4 + luaunit.assertEquals(n1.get_family(), 2) + + -- The country code should be empty + luaunit.assertNil(n1.get_country_code()) +end + os.exit(luaunit.LuaUnit.run())