2 libloc - A library to determine the location of someone on the Internet
4 Copyright (C) 2024 IPFire Development Team <info@ipfire.org>
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Lesser General Public
8 License as published by the Free Software Foundation; either
9 version 2.1 of the License, or (at your option) any later version.
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
23 #include <libloc/database.h>
32 typedef struct database
{
33 struct loc_database
* db
;
36 static Database
* luaL_checkdatabase(lua_State
* L
, int i
) {
37 void* userdata
= luaL_checkudata(L
, i
, "location.Database");
39 // Throw an error if the argument doesn't match
40 luaL_argcheck(L
, userdata
, i
, "Database expected");
42 return (Database
*)userdata
;
45 static int Database_open(lua_State
* L
) {
46 const char* path
= NULL
;
51 path
= luaL_checkstring(L
, 1);
53 // Allocate a new object
54 Database
* self
= (Database
*)lua_newuserdata(L
, sizeof(*self
));
57 luaL_setmetatable(L
, "location.Database");
59 // Open the database file
62 return luaL_error(L
, "Could not open %s: %s\n", path
, strerror(errno
));
65 r
= loc_database_new(ctx
, &self
->db
, f
);
67 // Close the file descriptor
72 return luaL_error(L
, "Could not open database %s: %s\n", path
, strerror(errno
));
77 static int Database_gc(lua_State
* L
) {
78 Database
* self
= luaL_checkdatabase(L
, 1);
82 loc_database_unref(self
->db
);
91 static int Database_created_at(lua_State
* L
) {
92 Database
* self
= luaL_checkdatabase(L
, 1);
95 time_t created_at
= loc_database_created_at(self
->db
);
97 // Push the time onto the stack
98 lua_pushnumber(L
, created_at
);
105 static int Database_get_description(lua_State
* L
) {
106 Database
* self
= luaL_checkdatabase(L
, 1);
108 // Push the description
109 lua_pushstring(L
, loc_database_get_description(self
->db
));
116 static int Database_get_license(lua_State
* L
) {
117 Database
* self
= luaL_checkdatabase(L
, 1);
120 lua_pushstring(L
, loc_database_get_license(self
->db
));
125 static int Database_get_vendor(lua_State
* L
) {
126 Database
* self
= luaL_checkdatabase(L
, 1);
129 lua_pushstring(L
, loc_database_get_vendor(self
->db
));
134 static int Database_get_as(lua_State
* L
) {
135 struct loc_as
* as
= NULL
;
138 Database
* self
= luaL_checkdatabase(L
, 1);
141 uint32_t asn
= luaL_checknumber(L
, 2);
144 r
= loc_database_get_as(self
->db
, &as
, asn
);
150 // Create a new AS object
151 r
= create_as(L
, as
);
157 static int Database_get_country(lua_State
* L
) {
158 struct loc_country
* country
= NULL
;
161 Database
* self
= luaL_checkdatabase(L
, 1);
164 const char* code
= luaL_checkstring(L
, 2);
167 r
= loc_database_get_country(self
->db
, &country
, code
);
173 // Create a new country object
174 r
= create_country(L
, country
);
175 loc_country_unref(country
);
180 static int Database_lookup(lua_State
* L
) {
181 struct loc_network
* network
= NULL
;
184 Database
* self
= luaL_checkdatabase(L
, 1);
187 const char* address
= luaL_checkstring(L
, 2);
190 r
= loc_database_lookup_from_string(self
->db
, address
, &network
);
193 // Return nil if the network was not found
199 return luaL_error(L
, "Could not lookup address %s: %s\n", address
, strerror(errno
));
203 // Create a network object
204 r
= create_network(L
, network
);
205 loc_network_unref(network
);
210 static int Database_verify(lua_State
* L
) {
214 Database
* self
= luaL_checkdatabase(L
, 1);
217 const char* key
= luaL_checkstring(L
, 2);
222 return luaL_error(L
, "Could not open key %s: %s\n", key
, strerror(errno
));
225 r
= loc_database_verify(self
->db
, f
);
228 // Push result onto the stack
229 lua_pushboolean(L
, (r
== 0));
234 typedef struct enumerator
{
235 struct loc_database_enumerator
* e
;
236 } DatabaseEnumerator
;
238 static DatabaseEnumerator
* luaL_checkdatabaseenumerator(lua_State
* L
, int i
) {
239 void* userdata
= luaL_checkudata(L
, i
, "location.DatabaseEnumerator");
241 // Throw an error if the argument doesn't match
242 luaL_argcheck(L
, userdata
, i
, "DatabaseEnumerator expected");
244 return (DatabaseEnumerator
*)userdata
;
247 static int DatabaseEnumerator_gc(lua_State
* L
) {
248 DatabaseEnumerator
* self
= luaL_checkdatabaseenumerator(L
, 1);
251 loc_database_enumerator_unref(self
->e
);
258 static int DatabaseEnumerator_next_network(lua_State
* L
) {
259 struct loc_network
* network
= NULL
;
262 DatabaseEnumerator
* self
= luaL_checkdatabaseenumerator(L
, lua_upvalueindex(1));
264 // Fetch the next network
265 r
= loc_database_enumerator_next_network(self
->e
, &network
);
267 return luaL_error(L
, "Could not fetch network: %s\n", strerror(errno
));
269 // If we have received no network, we have reached the end
275 // Create a network object
276 r
= create_network(L
, network
);
277 loc_network_unref(network
);
282 static int Database_list_networks(lua_State
* L
) {
283 DatabaseEnumerator
* e
= NULL
;
286 Database
* self
= luaL_checkdatabase(L
, 1);
288 // Allocate a new enumerator
289 e
= lua_newuserdata(L
, sizeof(*e
));
290 luaL_setmetatable(L
, "location.DatabaseEnumerator");
292 // Create a new enumerator
293 r
= loc_database_enumerator_new(&e
->e
, self
->db
, LOC_DB_ENUMERATE_NETWORKS
, 0);
295 return luaL_error(L
, "Could not create enumerator: %s\n", strerror(errno
));
297 // Push the closure onto the stack
298 lua_pushcclosure(L
, DatabaseEnumerator_next_network
, 1);
303 static const struct luaL_Reg database_functions
[] = {
304 { "created_at", Database_created_at
},
305 { "get_as", Database_get_as
},
306 { "get_description", Database_get_description
},
307 { "get_country", Database_get_country
},
308 { "get_license", Database_get_license
},
309 { "get_vendor", Database_get_vendor
},
310 { "open", Database_open
},
311 { "lookup", Database_lookup
},
312 { "list_networks", Database_list_networks
},
313 { "verify", Database_verify
},
314 { "__gc", Database_gc
},
318 int register_database(lua_State
* L
) {
319 return register_class(L
, "location.Database", database_functions
);
322 static const struct luaL_Reg database_enumerator_functions
[] = {
323 { "__gc", DatabaseEnumerator_gc
},
327 int register_database_enumerator(lua_State
* L
) {
328 return register_class(L
, "location.DatabaseEnumerator", database_enumerator_functions
);