]> git.ipfire.org Git - people/ms/libloc.git/blob - src/lua/database.c
lua: database: Implementing fetching AS objects
[people/ms/libloc.git] / src / lua / database.c
1 /*
2 libloc - A library to determine the location of someone on the Internet
3
4 Copyright (C) 2024 IPFire Development Team <info@ipfire.org>
5
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.
10
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.
15 */
16
17 #include <errno.h>
18 #include <string.h>
19
20 #include <lua.h>
21 #include <lauxlib.h>
22
23 #include <libloc/database.h>
24
25 #include "location.h"
26 #include "as.h"
27 #include "database.h"
28 #include "network.h"
29
30 typedef struct database {
31 struct loc_database* db;
32 } Database;
33
34 static Database* luaL_checkdatabase(lua_State* L, int i) {
35 void* userdata = luaL_checkudata(L, i, "location.Database");
36
37 // Throw an error if the argument doesn't match
38 luaL_argcheck(L, userdata, i, "Database expected");
39
40 return (Database*)userdata;
41 }
42
43 static int Database_open(lua_State* L) {
44 const char* path = NULL;
45 FILE* f = NULL;
46 int r;
47
48 // Fetch the path
49 path = luaL_checkstring(L, 1);
50
51 // Allocate a new object
52 Database* self = (Database*)lua_newuserdata(L, sizeof(*self));
53
54 // Set metatable
55 luaL_setmetatable(L, "location.Database");
56
57 // Open the database file
58 f = fopen(path, "r");
59 if (!f)
60 return luaL_error(L, "Could not open %s: %s\n", path, strerror(errno));
61
62 // Open the database
63 r = loc_database_new(ctx, &self->db, f);
64
65 // Close the file descriptor
66 fclose(f);
67
68 // Check for errors
69 if (r)
70 return luaL_error(L, "Could not open database %s: %s\n", path, strerror(errno));
71
72 return 1;
73 }
74
75 static int Database_gc(lua_State* L) {
76 Database* self = luaL_checkdatabase(L, 1);
77
78 // Free database
79 if (self->db) {
80 loc_database_unref(self->db);
81 self->db = NULL;
82 }
83
84 return 0;
85 }
86
87 static int Database_get_as(lua_State* L) {
88 struct loc_as* as = NULL;
89 int r;
90
91 Database* self = luaL_checkdatabase(L, 1);
92
93 // Fetch number
94 uint32_t asn = luaL_checknumber(L, 2);
95
96 // Fetch the AS
97 r = loc_database_get_as(self->db, &as, asn);
98 if (r) {
99 lua_pushnil(L);
100 return 1;
101 }
102
103 // Create a new AS object
104 r = create_as(L, as);
105 loc_as_unref(as);
106
107 return r;
108 }
109
110 static int Database_lookup(lua_State* L) {
111 struct loc_network* network = NULL;
112 int r;
113
114 Database* self = luaL_checkdatabase(L, 1);
115
116 // Require a string
117 const char* address = luaL_checkstring(L, 2);
118
119 // Perform lookup
120 r = loc_database_lookup_from_string(self->db, address, &network);
121 if (r)
122 return luaL_error(L, "Could not lookup address %s: %s\n", address, strerror(errno));
123
124 // Create a network object
125 r = create_network(L, network);
126 loc_network_unref(network);
127
128 return r;
129 }
130
131 static const struct luaL_Reg database_functions[] = {
132 { "get_as", Database_get_as },
133 { "open", Database_open },
134 { "lookup", Database_lookup },
135 { "__gc", Database_gc },
136 { NULL, NULL },
137 };
138
139 int register_database(lua_State* L) {
140 return register_class(L, "location.Database", database_functions);
141 }