hive_geoip2 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/hive_geoip2/extconf.rb +9 -0
- data/ext/hive_geoip2/hive_geoip2.c +392 -0
- data/hive_geoip2.gemspec +17 -0
- data/lib/hive_geoip2/hive_geoip2.rb +1 -0
- metadata +48 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 8db3b40343a6db6c1c0ffc20f8f31fd8a62d82e5
|
4
|
+
data.tar.gz: 7627dbb58b18b2b34410993bebe29127f7ef36e6
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6ba971888c29661ff3fddf3d46d00f67d0d734c82af1ef3fb1967f3eaa0d4b1fb5ae34f47b4e83f79563ae5be1a35c15a730aa42ca019dd0ec11c0327a321f37
|
7
|
+
data.tar.gz: 6c22963486413a1f7448d8a3483b8de9b4d97937b1cf1fd2556a0edc8defcf5eb33507db0e5660ad62d642336cb6449c9931ee1a930c35f638102be40f157107
|
@@ -0,0 +1,392 @@
|
|
1
|
+
#define RSTRING_NOT_MODIFIED
|
2
|
+
|
3
|
+
#include <ruby/ruby.h>
|
4
|
+
#include <ruby/encoding.h>
|
5
|
+
|
6
|
+
#include "maxminddb.h"
|
7
|
+
|
8
|
+
#define WORDS_64 (64 / CHAR_BIT / SIZEOF_LONG)
|
9
|
+
#define WORDS_128 (128/ CHAR_BIT / SIZEOF_LONG)
|
10
|
+
|
11
|
+
VALUE rb_mHive;
|
12
|
+
VALUE rb_cGeoIP2;
|
13
|
+
|
14
|
+
static void guard_parse_data_list(VALUE arg);
|
15
|
+
static MMDB_entry_data_list_s * parse_data_list(
|
16
|
+
MMDB_entry_data_list_s *data_list, VALUE *ret_obj
|
17
|
+
);
|
18
|
+
static void mmdb_try_open(char *db_path, MMDB_s *mmdb);
|
19
|
+
static inline bool mmdb_is_closed(MMDB_s *mmdb);
|
20
|
+
static inline void mmdb_close(MMDB_s *mmdb);
|
21
|
+
static VALUE mmdb_lookup(MMDB_s *mmdb, char *ip_addr, bool cleanup);
|
22
|
+
|
23
|
+
static VALUE rb_hive_geo_lookup(VALUE self, VALUE ip_arg);
|
24
|
+
static VALUE rb_hive_geo_lookup2(VALUE self, VALUE ip_arg, VALUE db_arg);
|
25
|
+
static VALUE rb_hive_geo_is_closed(VALUE self);
|
26
|
+
static VALUE rb_hive_geo_close(VALUE self);
|
27
|
+
static void rb_hive_geo_free(MMDB_s *mmdb);
|
28
|
+
static VALUE rb_hive_geo_alloc(VALUE self);
|
29
|
+
static VALUE rb_hive_geo_init(VALUE self, VALUE db_arg);
|
30
|
+
|
31
|
+
struct args_parse_data_list {
|
32
|
+
MMDB_entry_data_list_s *data_list;
|
33
|
+
VALUE *ret_obj;
|
34
|
+
};
|
35
|
+
|
36
|
+
static void guard_parse_data_list(VALUE arg) {
|
37
|
+
struct args_parse_data_list *args = (struct args_parse_data_list *)arg;
|
38
|
+
|
39
|
+
parse_data_list(args->data_list, args->ret_obj);
|
40
|
+
}
|
41
|
+
|
42
|
+
static MMDB_entry_data_list_s *
|
43
|
+
parse_data_list(MMDB_entry_data_list_s *data_list, VALUE *ret_obj) {
|
44
|
+
switch (data_list->entry_data.type) {
|
45
|
+
case MMDB_DATA_TYPE_MAP:
|
46
|
+
{
|
47
|
+
uint32_t size = data_list->entry_data.data_size;
|
48
|
+
|
49
|
+
VALUE val;
|
50
|
+
|
51
|
+
VALUE hash = rb_hash_new();
|
52
|
+
|
53
|
+
for (data_list = data_list->next; size && data_list; size--) {
|
54
|
+
VALUE key = rb_enc_str_new(
|
55
|
+
data_list->entry_data.utf8_string,
|
56
|
+
data_list->entry_data.data_size,
|
57
|
+
rb_utf8_encoding()
|
58
|
+
);
|
59
|
+
|
60
|
+
data_list = data_list->next;
|
61
|
+
data_list = parse_data_list(data_list, &val);
|
62
|
+
|
63
|
+
rb_hash_aset(hash, key, val);
|
64
|
+
|
65
|
+
}
|
66
|
+
|
67
|
+
*ret_obj = hash;
|
68
|
+
|
69
|
+
break;
|
70
|
+
}
|
71
|
+
|
72
|
+
case MMDB_DATA_TYPE_ARRAY:
|
73
|
+
{
|
74
|
+
uint32_t size = data_list->entry_data.data_size;
|
75
|
+
|
76
|
+
VALUE val;
|
77
|
+
|
78
|
+
VALUE ary = rb_ary_new();
|
79
|
+
|
80
|
+
for (data_list = data_list->next; size && data_list; size--) {
|
81
|
+
data_list = parse_data_list(data_list, &val);
|
82
|
+
rb_ary_push(ary, val);
|
83
|
+
}
|
84
|
+
|
85
|
+
*ret_obj = ary;
|
86
|
+
|
87
|
+
break;
|
88
|
+
}
|
89
|
+
|
90
|
+
case MMDB_DATA_TYPE_UTF8_STRING:
|
91
|
+
{
|
92
|
+
*ret_obj = rb_enc_str_new(
|
93
|
+
data_list->entry_data.utf8_string,
|
94
|
+
data_list->entry_data.data_size,
|
95
|
+
rb_utf8_encoding()
|
96
|
+
);
|
97
|
+
|
98
|
+
data_list = data_list->next;
|
99
|
+
|
100
|
+
break;
|
101
|
+
}
|
102
|
+
|
103
|
+
case MMDB_DATA_TYPE_BYTES:
|
104
|
+
{
|
105
|
+
*ret_obj = rb_enc_str_new(
|
106
|
+
data_list->entry_data.bytes,
|
107
|
+
data_list->entry_data.data_size,
|
108
|
+
rb_ascii8bit_encoding()
|
109
|
+
);
|
110
|
+
|
111
|
+
data_list = data_list->next;
|
112
|
+
|
113
|
+
break;
|
114
|
+
}
|
115
|
+
|
116
|
+
case MMDB_DATA_TYPE_DOUBLE:
|
117
|
+
{
|
118
|
+
*ret_obj = rb_float_new(data_list->entry_data.double_value);
|
119
|
+
|
120
|
+
data_list = data_list->next;
|
121
|
+
|
122
|
+
break;
|
123
|
+
}
|
124
|
+
|
125
|
+
case MMDB_DATA_TYPE_FLOAT:
|
126
|
+
{
|
127
|
+
*ret_obj = rb_float_new(data_list->entry_data.float_value);
|
128
|
+
|
129
|
+
data_list = data_list->next;
|
130
|
+
|
131
|
+
break;
|
132
|
+
}
|
133
|
+
|
134
|
+
case MMDB_DATA_TYPE_UINT16:
|
135
|
+
{
|
136
|
+
*ret_obj = UINT2NUM(data_list->entry_data.uint16);
|
137
|
+
|
138
|
+
data_list = data_list->next;
|
139
|
+
|
140
|
+
break;
|
141
|
+
}
|
142
|
+
|
143
|
+
case MMDB_DATA_TYPE_UINT32:
|
144
|
+
{
|
145
|
+
*ret_obj = UINT2NUM(data_list->entry_data.uint32);
|
146
|
+
|
147
|
+
data_list = data_list->next;
|
148
|
+
|
149
|
+
break;
|
150
|
+
}
|
151
|
+
|
152
|
+
case MMDB_DATA_TYPE_BOOLEAN:
|
153
|
+
{
|
154
|
+
*ret_obj = data_list->entry_data.boolean ? Qtrue : Qfalse;
|
155
|
+
|
156
|
+
data_list = data_list->next;
|
157
|
+
|
158
|
+
break;
|
159
|
+
}
|
160
|
+
|
161
|
+
case MMDB_DATA_TYPE_UINT64:
|
162
|
+
{
|
163
|
+
*ret_obj = rb_big_unpack(&data_list->entry_data.uint64, WORDS_64);
|
164
|
+
|
165
|
+
data_list = data_list->next;
|
166
|
+
|
167
|
+
break;
|
168
|
+
}
|
169
|
+
|
170
|
+
case MMDB_DATA_TYPE_UINT128:
|
171
|
+
{
|
172
|
+
#if MMDB_UINT128_IS_BYTE_ARRAY
|
173
|
+
char buf[16];
|
174
|
+
uint8_t i;
|
175
|
+
uint8_t idx = 15;
|
176
|
+
uint8_t *data = data_list->entry_data.uint128;
|
177
|
+
|
178
|
+
for (i = 0; i < 16; ++i) {
|
179
|
+
buf[i] = data[idx];
|
180
|
+
idx--;
|
181
|
+
}
|
182
|
+
|
183
|
+
*ret_obj = rb_big_unpack(&buf, WORDS_128);
|
184
|
+
#else
|
185
|
+
*ret_obj = rb_big_unpack(&data_list->entry_data.uint128, WORDS_128);
|
186
|
+
#endif
|
187
|
+
|
188
|
+
data_list = data_list->next;
|
189
|
+
|
190
|
+
break;
|
191
|
+
}
|
192
|
+
|
193
|
+
case MMDB_DATA_TYPE_INT32:
|
194
|
+
{
|
195
|
+
*ret_obj = INT2NUM(data_list->entry_data.int32);
|
196
|
+
|
197
|
+
data_list = data_list->next;
|
198
|
+
|
199
|
+
break;
|
200
|
+
}
|
201
|
+
|
202
|
+
default:
|
203
|
+
rb_raise(rb_eRuntimeError,
|
204
|
+
"GeoIP2 - %s", MMDB_strerror(MMDB_INVALID_DATA_ERROR)
|
205
|
+
);
|
206
|
+
}
|
207
|
+
|
208
|
+
return data_list;
|
209
|
+
}
|
210
|
+
|
211
|
+
static void mmdb_try_open(char *db_path, MMDB_s *mmdb) {
|
212
|
+
int status = MMDB_open(db_path, MMDB_MODE_MMAP, mmdb);
|
213
|
+
|
214
|
+
if (status != MMDB_SUCCESS) {
|
215
|
+
rb_raise(rb_eIOError, "GeoIP2 - %s: %s",
|
216
|
+
MMDB_strerror(status), db_path
|
217
|
+
);
|
218
|
+
}
|
219
|
+
}
|
220
|
+
|
221
|
+
static inline bool mmdb_is_closed(MMDB_s *mmdb) {
|
222
|
+
return mmdb->file_content == NULL;
|
223
|
+
}
|
224
|
+
|
225
|
+
static inline void mmdb_close(MMDB_s *mmdb) {
|
226
|
+
MMDB_close(mmdb);
|
227
|
+
mmdb->file_content = NULL;
|
228
|
+
}
|
229
|
+
|
230
|
+
static VALUE mmdb_lookup(MMDB_s *mmdb, char *ip_addr, bool cleanup) {
|
231
|
+
int status, gai_error, mmdb_error;
|
232
|
+
|
233
|
+
MMDB_lookup_result_s result =
|
234
|
+
MMDB_lookup_string(mmdb, ip_addr, &gai_error, &mmdb_error);
|
235
|
+
|
236
|
+
if (mmdb_error != MMDB_SUCCESS) {
|
237
|
+
if (cleanup) {
|
238
|
+
mmdb_close(mmdb);
|
239
|
+
}
|
240
|
+
|
241
|
+
rb_raise(rb_eRuntimeError,
|
242
|
+
"GeoIP2 - lookup failed: %s", MMDB_strerror(mmdb_error)
|
243
|
+
);
|
244
|
+
}
|
245
|
+
|
246
|
+
if (gai_error != 0) {
|
247
|
+
if (cleanup) {
|
248
|
+
mmdb_close(mmdb);
|
249
|
+
}
|
250
|
+
|
251
|
+
rb_raise(rb_eRuntimeError,
|
252
|
+
"GeoIP2 - getaddrinfo failed: %s", gai_strerror(gai_error)
|
253
|
+
);
|
254
|
+
}
|
255
|
+
|
256
|
+
if (result.found_entry) {
|
257
|
+
MMDB_entry_data_list_s *data_list, *first;
|
258
|
+
|
259
|
+
status = MMDB_get_entry_data_list(&result.entry, &data_list);
|
260
|
+
|
261
|
+
if (status != MMDB_SUCCESS) {
|
262
|
+
MMDB_free_entry_data_list(data_list);
|
263
|
+
|
264
|
+
if (cleanup) {
|
265
|
+
mmdb_close(mmdb);
|
266
|
+
}
|
267
|
+
|
268
|
+
rb_raise(rb_eRuntimeError,
|
269
|
+
"GeoIP2 - couldn\'t fetch results: %s", MMDB_strerror(status)
|
270
|
+
);
|
271
|
+
}
|
272
|
+
|
273
|
+
first = data_list;
|
274
|
+
|
275
|
+
int exception = 0;
|
276
|
+
|
277
|
+
VALUE ret_obj;
|
278
|
+
|
279
|
+
struct args_parse_data_list args;
|
280
|
+
args.data_list = data_list;
|
281
|
+
args.ret_obj = &ret_obj;
|
282
|
+
|
283
|
+
rb_protect(guard_parse_data_list, (VALUE)&args, &exception);
|
284
|
+
|
285
|
+
MMDB_free_entry_data_list(first);
|
286
|
+
|
287
|
+
if (cleanup) {
|
288
|
+
mmdb_close(mmdb);
|
289
|
+
}
|
290
|
+
|
291
|
+
if (exception) {
|
292
|
+
rb_jump_tag(exception);
|
293
|
+
}
|
294
|
+
|
295
|
+
return ret_obj;
|
296
|
+
}
|
297
|
+
else {
|
298
|
+
return Qnil;
|
299
|
+
}
|
300
|
+
}
|
301
|
+
|
302
|
+
static VALUE rb_hive_geo_lookup(VALUE self, VALUE ip_arg) {
|
303
|
+
Check_Type(ip_arg, T_STRING);
|
304
|
+
|
305
|
+
char *ip_addr = StringValuePtr(ip_arg);
|
306
|
+
|
307
|
+
MMDB_s *mmdb;
|
308
|
+
|
309
|
+
Data_Get_Struct(self, MMDB_s, mmdb);
|
310
|
+
|
311
|
+
if (mmdb_is_closed(mmdb)) {
|
312
|
+
rb_raise(rb_eIOError, "GeoIP2 - closed database");
|
313
|
+
}
|
314
|
+
|
315
|
+
return mmdb_lookup(mmdb, ip_addr, false);
|
316
|
+
}
|
317
|
+
|
318
|
+
static VALUE rb_hive_geo_lookup2(VALUE self, VALUE ip_arg, VALUE db_arg) {
|
319
|
+
Check_Type(ip_arg, T_STRING);
|
320
|
+
Check_Type(db_arg, T_STRING);
|
321
|
+
|
322
|
+
char *ip_addr = StringValuePtr(ip_arg);
|
323
|
+
char *db_path = StringValuePtr(db_arg);
|
324
|
+
|
325
|
+
MMDB_s mmdb;
|
326
|
+
|
327
|
+
mmdb_try_open(db_path, &mmdb);
|
328
|
+
|
329
|
+
return mmdb_lookup(&mmdb, ip_addr, true);
|
330
|
+
}
|
331
|
+
|
332
|
+
static VALUE rb_hive_geo_is_closed(VALUE self) {
|
333
|
+
MMDB_s *mmdb;
|
334
|
+
|
335
|
+
Data_Get_Struct(self, MMDB_s, mmdb);
|
336
|
+
|
337
|
+
return mmdb_is_closed(mmdb) ? Qtrue : Qfalse;
|
338
|
+
}
|
339
|
+
|
340
|
+
static VALUE rb_hive_geo_close(VALUE self) {
|
341
|
+
MMDB_s *mmdb;
|
342
|
+
|
343
|
+
Data_Get_Struct(self, MMDB_s, mmdb);
|
344
|
+
|
345
|
+
if (!mmdb_is_closed(mmdb)) {
|
346
|
+
mmdb_close(mmdb);
|
347
|
+
}
|
348
|
+
|
349
|
+
return Qnil;
|
350
|
+
}
|
351
|
+
|
352
|
+
static void rb_hive_geo_free(MMDB_s *mmdb) {
|
353
|
+
if (!mmdb_is_closed(mmdb)) {
|
354
|
+
mmdb_close(mmdb);
|
355
|
+
}
|
356
|
+
|
357
|
+
xfree(mmdb);
|
358
|
+
}
|
359
|
+
|
360
|
+
static VALUE rb_hive_geo_alloc(VALUE self) {
|
361
|
+
MMDB_s *mmdb = ALLOC(MMDB_s);
|
362
|
+
|
363
|
+
return Data_Wrap_Struct(self, NULL, rb_hive_geo_free, mmdb);
|
364
|
+
}
|
365
|
+
|
366
|
+
static VALUE rb_hive_geo_init(VALUE self, VALUE db_arg) {
|
367
|
+
Check_Type(db_arg, T_STRING);
|
368
|
+
|
369
|
+
char *db_path = StringValuePtr(db_arg);
|
370
|
+
|
371
|
+
MMDB_s *mmdb;
|
372
|
+
|
373
|
+
Data_Get_Struct(self, MMDB_s, mmdb);
|
374
|
+
|
375
|
+
mmdb_try_open(db_path, mmdb);
|
376
|
+
|
377
|
+
return Qnil;
|
378
|
+
}
|
379
|
+
|
380
|
+
void Init_hive_geoip2() {
|
381
|
+
rb_mHive = rb_define_module("Hive");
|
382
|
+
rb_cGeoIP2 = rb_define_class_under(rb_mHive, "GeoIP2", rb_cObject);
|
383
|
+
|
384
|
+
rb_define_alloc_func(rb_cGeoIP2, rb_hive_geo_alloc);
|
385
|
+
|
386
|
+
rb_define_singleton_method(rb_cGeoIP2, "lookup", rb_hive_geo_lookup2, 2);
|
387
|
+
|
388
|
+
rb_define_method(rb_cGeoIP2, "initialize", rb_hive_geo_init, 1);
|
389
|
+
rb_define_method(rb_cGeoIP2, "close", rb_hive_geo_close, 0);
|
390
|
+
rb_define_method(rb_cGeoIP2, "closed?", rb_hive_geo_is_closed, 0);
|
391
|
+
rb_define_method(rb_cGeoIP2, "lookup", rb_hive_geo_lookup, 1);
|
392
|
+
}
|
data/hive_geoip2.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = 'hive_geoip2'
|
3
|
+
s.version = '0.1.0'
|
4
|
+
s.summary = 'libmaxminddb GeoIP2 Ruby bindings'
|
5
|
+
s.author = 'Maxime Youdine'
|
6
|
+
s.license = 'MIT'
|
7
|
+
s.homepage = 'https://github.com/desuwa/hive_geoip2'
|
8
|
+
s.required_ruby_version = '>= 1.9.2'
|
9
|
+
s.files = %w[
|
10
|
+
hive_geoip2.gemspec
|
11
|
+
lib/hive_geoip2/hive_geoip2.rb
|
12
|
+
ext/hive_geoip2/extconf.rb
|
13
|
+
ext/hive_geoip2/hive_geoip2.c
|
14
|
+
]
|
15
|
+
s.extensions = ['ext/hive_geoip2/extconf.rb']
|
16
|
+
s.require_paths = ['lib']
|
17
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'hive-geoip2.so'
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: hive_geoip2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Maxime Youdine
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-09-22 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
executables: []
|
16
|
+
extensions:
|
17
|
+
- ext/hive_geoip2/extconf.rb
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ext/hive_geoip2/extconf.rb
|
21
|
+
- ext/hive_geoip2/hive_geoip2.c
|
22
|
+
- hive_geoip2.gemspec
|
23
|
+
- lib/hive_geoip2/hive_geoip2.rb
|
24
|
+
homepage: https://github.com/desuwa/hive_geoip2
|
25
|
+
licenses:
|
26
|
+
- MIT
|
27
|
+
metadata: {}
|
28
|
+
post_install_message:
|
29
|
+
rdoc_options: []
|
30
|
+
require_paths:
|
31
|
+
- lib
|
32
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
33
|
+
requirements:
|
34
|
+
- - ">="
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: 1.9.2
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
requirements: []
|
43
|
+
rubyforge_project:
|
44
|
+
rubygems_version: 2.4.1
|
45
|
+
signing_key:
|
46
|
+
specification_version: 4
|
47
|
+
summary: libmaxminddb GeoIP2 Ruby bindings
|
48
|
+
test_files: []
|