]> git.ipfire.org Git - location/libloc.git/blob - src/perl/Location.xs
perl: Add get_country_name() function.
[location/libloc.git] / src / perl / Location.xs
1 #define PERL_NO_GET_CONTEXT
2 #include "EXTERN.h"
3 #include "perl.h"
4 #include "XSUB.h"
5
6 #include <stdio.h>
7 #include <string.h>
8
9 #include <loc/libloc.h>
10 #include <loc/database.h>
11 #include <loc/network.h>
12 #include <loc/country.h>
13
14 MODULE = Location PACKAGE = Location
15
16 struct loc_database *
17 init(file)
18 char* file;
19
20 CODE:
21 struct loc_ctx* ctx = NULL;
22
23 // Initialise location context
24 int err = loc_new(&ctx);
25 if (err < 0)
26 croak("Could not initialize libloc context: %d\n", err);
27
28 // Open the database file for reading
29 FILE* f = fopen(file, "r");
30 if (!f) {
31 loc_unref(ctx);
32
33 croak("Could not open file for reading: %s: %s\n",
34 file, strerror(errno));
35 }
36
37 // Parse the database
38 struct loc_database* db = NULL;
39 err = loc_database_new(ctx, &db, f);
40
41 // We can close the database file straight away
42 // because loc_database_new creates a copy of the file descriptor
43 fclose(f);
44
45 if (err) {
46 loc_unref(ctx);
47
48 croak("Could not read database: %s\n", file);
49 }
50
51 // Cleanup
52 loc_unref(ctx);
53
54 RETVAL = db;
55 OUTPUT:
56 RETVAL
57
58 #
59 # Database functions
60 #
61 bool
62 verify(db, keyfile)
63 struct loc_database* db;
64 char* keyfile;
65
66 CODE:
67 // Try to open the keyfile
68 FILE* f = fopen(keyfile, "r");
69 if (!f) {
70 croak("Could not open keyfile %s: %s\n",
71 keyfile, strerror(errno));
72 }
73
74 // Verify the database
75 int status = loc_database_verify(db, f);
76 if (status) {
77 RETVAL = false;
78 fclose(f);
79
80 croak("Could not verify the database signature\n");
81 }
82
83 // Database was validated successfully
84 RETVAL = true;
85
86 // Close the keyfile
87 fclose(f);
88 OUTPUT:
89 RETVAL
90
91 const char*
92 get_vendor(db)
93 struct loc_database* db;
94
95 CODE:
96 // Get vendor
97 RETVAL = loc_database_get_vendor(db);
98 OUTPUT:
99 RETVAL
100
101 const char*
102 get_description(db)
103 struct loc_database* db;
104
105 CODE:
106 // Get database description
107 RETVAL = loc_database_get_description(db);
108 OUTPUT:
109 RETVAL
110
111 const char*
112 get_license(db)
113 struct loc_database* db;
114
115 CODE:
116 // Get database license
117 RETVAL = loc_database_get_license(db);
118 OUTPUT:
119 RETVAL
120
121 void
122 database_countries(db)
123 struct loc_database* db;
124
125 PPCODE:
126 // Create Database enumerator
127 struct loc_database_enumerator* enumerator;
128 int err = loc_database_enumerator_new(&enumerator, db, LOC_DB_ENUMERATE_COUNTRIES);
129
130 if (err) {
131 croak("Could not create a database enumerator\n");
132 }
133
134 // Init and enumerate first country.
135 struct loc_country* country;
136 err = loc_database_enumerator_next_country(enumerator, &country);
137 if (err) {
138 croak("Could not enumerate next country\n");
139 }
140
141 while (country) {
142 // Extract the country code.
143 const char* ccode = loc_country_get_code(country);
144
145 // Push country code.
146 XPUSHs(sv_2mortal(newSVpv(ccode, 2)));
147
148 // Unref country pointer.
149 loc_country_unref(country);
150
151 // Enumerate next item.
152 err = loc_database_enumerator_next_country(enumerator, &country);
153 if (err) {
154 croak("Could not enumerate next country\n");
155 }
156 }
157
158 loc_database_enumerator_unref(enumerator);
159
160 #
161 # Lookup functions
162 #
163 SV*
164 lookup_country_code(db, address)
165 struct loc_database* db;
166 char* address;
167
168 CODE:
169 RETVAL = &PL_sv_undef;
170
171 // Lookup network
172 struct loc_network *network;
173 int err = loc_database_lookup_from_string(db, address, &network);
174 if (!err) {
175 // Extract the country code
176 const char* country_code = loc_network_get_country_code(network);
177 RETVAL = newSVpv(country_code, strlen(country_code));
178
179 loc_network_unref(network);
180 }
181 OUTPUT:
182 RETVAL
183
184 bool
185 lookup_network_has_flag(db, address, flag)
186 struct loc_database* db;
187 char* address;
188 char* flag;
189
190 CODE:
191 RETVAL = false;
192
193 enum loc_network_flags iv = 0;
194
195 if (strcmp("LOC_NETWORK_FLAG_ANONYMOUS_PROXY", flag) == 0)
196 iv |= LOC_NETWORK_FLAG_ANONYMOUS_PROXY;
197 else if (strcmp("LOC_NETWORK_FLAG_SATELLITE_PROVIDER", flag) == 0)
198 iv |= LOC_NETWORK_FLAG_SATELLITE_PROVIDER;
199 else if (strcmp("LOC_NETWORK_FLAG_ANYCAST", flag) == 0)
200 iv |= LOC_NETWORK_FLAG_ANYCAST;
201 else
202 croak("Invalid flag");
203
204 // Lookup network
205 struct loc_network *network;
206 int err = loc_database_lookup_from_string(db, address, &network);
207
208 if (!err) {
209 // Check if the network has the given flag.
210 if (loc_network_has_flag(network, iv)) {
211 RETVAL = true;
212 }
213
214 loc_network_unref(network);
215 }
216
217 OUTPUT:
218 RETVAL
219
220 SV*
221 lookup_asn(db, address)
222 struct loc_database* db;
223 char* address;
224
225 CODE:
226 RETVAL = &PL_sv_undef;
227
228 // Lookup network
229 struct loc_network *network;
230 int err = loc_database_lookup_from_string(db, address, &network);
231 if (!err) {
232 // Extract the ASN
233 unsigned int as_number = loc_network_get_asn(network);
234 if (as_number > 0) {
235 RETVAL = newSViv(as_number);
236 }
237
238 loc_network_unref(network);
239 }
240 OUTPUT:
241 RETVAL
242
243 #
244 # Get functions
245 #
246 SV*
247 get_country_name(db, ccode)
248 struct loc_database* db;
249 char* ccode;
250
251 CODE:
252 RETVAL = &PL_sv_undef;
253
254 // Lookup country code
255 struct loc_country *country;
256 int err = loc_database_get_country(db, &country, ccode);
257 if(!err) {
258 // Extract the name for the given country code.
259 const char* country_name = loc_country_get_name(country);
260 RETVAL = newSVpv(country_name, strlen(country_name));
261
262 loc_country_unref(country);
263 }
264
265 OUTPUT:
266 RETVAL
267
268 SV*
269 get_continent_code(db, ccode)
270 struct loc_database* db;
271 char* ccode;
272
273 CODE:
274 RETVAL = &PL_sv_undef;
275
276 // Lookup country code
277 struct loc_country *country;
278 int err = loc_database_get_country(db, &country, ccode);
279 if(!err) {
280 //Extract the continent code for the given country code.
281 const char* continent_code = loc_country_get_continent_code(country);
282 RETVAL = newSVpv(continent_code, strlen(continent_code));
283
284 loc_country_unref(country);
285 }
286
287 OUTPUT:
288 RETVAL
289
290 SV*
291 get_as_name(db, as_number)
292 struct loc_database* db;
293 unsigned int as_number;
294
295 CODE:
296 RETVAL = &PL_sv_undef;
297
298 // Lookup AS.
299 struct loc_as *as;
300 int err = loc_database_get_as(db, &as, as_number);
301 if(!err) {
302 // Get the name of the given AS number.
303 const char* as_name = loc_as_get_name(as);
304
305 RETVAL = newSVpv(as_name, strlen(as_name));
306
307 loc_as_unref(as);
308 }
309
310 OUTPUT:
311 RETVAL
312
313 void
314 DESTROY(db)
315 struct loc_database* db;
316
317 CODE:
318 // Close database
319 loc_database_unref(db);