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 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,9 @@
1
+ require 'mkmf'
2
+
3
+ dir_config('maxminddb')
4
+
5
+ unless have_header('maxminddb.h') && have_library('maxminddb')
6
+ abort 'Missing libmaxminddb'
7
+ end
8
+
9
+ create_makefile('hive_geoip2')
@@ -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
+ }
@@ -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: []