mmdb 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.
Files changed (4) hide show
  1. checksums.yaml +7 -0
  2. data/ext/mmdb/extconf.rb +5 -0
  3. data/ext/mmdb/mmdb.c +216 -0
  4. metadata +89 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ad529fdf8ed88f374d68a50945c7d35545e5e951
4
+ data.tar.gz: 1df94fc12ba9eb92b999e2fa0944dbcdeae89072
5
+ SHA512:
6
+ metadata.gz: 3d3bd638e59a2c155bb00cbb320a9bc909f0543441a74504b5d667fec5d96e7bd38da9caed2caac2d356960bcbcf6afe70e2e255150025dd857b15310abff377
7
+ data.tar.gz: e85ff600fb171883011c9ce26821f2c0c68cbf29d9563aee1d92b9d1016fca359e725416f9a7d95bc3a6e5831a328a0fb9cb54b461b69279146e593773c6b92b
@@ -0,0 +1,5 @@
1
+ require 'mkmf'
2
+
3
+ if have_header("maxminddb.h") && have_library("maxminddb")
4
+ create_makefile("mmdb")
5
+ end
@@ -0,0 +1,216 @@
1
+ #include <ruby.h>
2
+
3
+ #include <maxminddb.h>
4
+ #include <netdb.h>
5
+ #include <stdio.h>
6
+ #include <sys/socket.h>
7
+ #include <sys/types.h>
8
+
9
+ static VALUE rb_cMaxMindDB;
10
+
11
+ static VALUE rb_sym_city;
12
+ static VALUE rb_sym_country;
13
+ static VALUE rb_sym_country_code;
14
+ static VALUE rb_sym_continent;
15
+ static VALUE rb_sym_latitude;
16
+ static VALUE rb_sym_longitude;
17
+ static VALUE rb_sym_postcode;
18
+
19
+ const static char *en = "en";
20
+ const static char *names = "names";
21
+ const static char *city = "city";
22
+ const static char *country = "country";
23
+ const static char *country_code = "country_code";
24
+ const static char *continent = "continent";
25
+ const static char *location = "location";
26
+ const static char *latitude = "latitude";
27
+ const static char *longitude = "longitude";
28
+ const static char *postal = "postal";
29
+ const static char *code = "code";
30
+ const static char *iso_code = "iso_code";
31
+ const static char *postcode = "postcode";
32
+
33
+ struct MaxMindDB {
34
+ MMDB_s *mmdb;
35
+ };
36
+
37
+ static size_t
38
+ maxminddb_memsize(const void *p) {
39
+ const struct MaxMindDB *ptr = p;
40
+ size_t size = 0;
41
+
42
+ if (ptr) {
43
+ size += sizeof(ptr);
44
+ if (ptr->mmdb) {
45
+ size += sizeof(MMDB_s);
46
+ }
47
+ }
48
+
49
+ return size;
50
+ }
51
+
52
+ void
53
+ maxminddb_free(void *p) {
54
+ struct MaxMindDB *ptr = p;
55
+ if (ptr) {
56
+ if (ptr->mmdb) {
57
+ MMDB_close(ptr->mmdb);
58
+ }
59
+ xfree(ptr);
60
+ }
61
+ }
62
+
63
+ static const rb_data_type_t mmdb_data_type = {
64
+ "mmdb",
65
+ {0, maxminddb_free, maxminddb_memsize,},
66
+ 0, 0,
67
+ RUBY_TYPED_FREE_IMMEDIATELY,
68
+ };
69
+
70
+ #define check_maxminddb(self) ((struct MaxMindDB*)rb_check_typeddata((self), &mmdb_data_type))
71
+
72
+ static struct MaxMindDB*
73
+ get_maxminddb(VALUE self) {
74
+ struct MaxMindDB *ptr = check_maxminddb(self);
75
+ if (!ptr) {
76
+ rb_raise(rb_eStandardError, "uninitialized");
77
+ }
78
+ return ptr;
79
+ }
80
+
81
+ #define MaxMindDB(self) get_maxminddb(self)
82
+
83
+ static VALUE
84
+ maxminddb_alloc(VALUE klass) {
85
+ return TypedData_Wrap_Struct(klass, &mmdb_data_type, 0);
86
+ }
87
+
88
+ static void
89
+ maxminddb_set_result(VALUE hash, VALUE key, MMDB_entry_data_s *data) {
90
+ if (data->has_data) {
91
+ switch (data->type) {
92
+ case MMDB_DATA_TYPE_UTF8_STRING:
93
+ rb_hash_aset(hash, key, rb_utf8_str_new(data->utf8_string, data->data_size));
94
+ break;
95
+ case MMDB_DATA_TYPE_DOUBLE:
96
+ rb_hash_aset(hash, key, rb_float_new(data->double_value));
97
+ break;
98
+ default:
99
+ rb_hash_aset(hash, key, Qnil);
100
+ }
101
+ } else {
102
+ rb_hash_aset(hash, key, Qnil);
103
+ }
104
+ }
105
+
106
+ VALUE
107
+ maxminddb_initialize(int argc, VALUE* argv, VALUE self) {
108
+ VALUE db_path;
109
+ MMDB_s *mmdb = ALLOC(MMDB_s);
110
+ struct MaxMindDB *ptr;
111
+
112
+ rb_scan_args(argc, argv, "1", &db_path);
113
+
114
+ FilePathValue(db_path);
115
+
116
+ if (MMDB_open(StringValuePtr(db_path), MMDB_MODE_MMAP, mmdb) != MMDB_SUCCESS) {
117
+ rb_sys_fail_str(db_path);
118
+ }
119
+
120
+ ptr = ALLOC(struct MaxMindDB);
121
+ DATA_PTR(self) = ptr;
122
+ ptr->mmdb = mmdb;
123
+
124
+ return self;
125
+ }
126
+
127
+ /**
128
+ *
129
+ * mmdb.lookup("123.45.67.89") -> Hash
130
+ *
131
+ * TODO:
132
+ * To receive `opts` argument that have language code and respond specified language data.
133
+ */
134
+ VALUE
135
+ maxminddb_lookup(VALUE self, VALUE ip) {
136
+ VALUE ret;
137
+ char *target;
138
+ int gai_error, mmdb_error;
139
+ struct MaxMindDB *ptr = MaxMindDB(self);
140
+ MMDB_s *mmdb = ptr->mmdb;
141
+
142
+ if (NIL_P(ip)) {
143
+ return Qnil;
144
+ }
145
+
146
+ target = StringValuePtr(ip);
147
+
148
+ MMDB_lookup_result_s lookuped = MMDB_lookup_string(mmdb, target, &gai_error, &mmdb_error);
149
+ if (gai_error) {
150
+ rb_sys_fail(gai_strerror(gai_error));
151
+ }
152
+ if (mmdb_error) {
153
+ rb_sys_fail(MMDB_strerror(mmdb_error));
154
+ }
155
+
156
+ if (lookuped.found_entry) {
157
+ ret = rb_hash_new();
158
+ MMDB_entry_data_s data;
159
+ MMDB_entry_s *entry = &lookuped.entry;
160
+ MMDB_get_value(entry, &data, city, names, en, NULL);
161
+ maxminddb_set_result(ret, rb_sym_city, &data);
162
+ MMDB_get_value(entry, &data, country, names, en, NULL);
163
+ maxminddb_set_result(ret, rb_sym_country, &data);
164
+ MMDB_get_value(entry, &data, country, iso_code, NULL);
165
+ maxminddb_set_result(ret, rb_sym_country_code, &data);
166
+ MMDB_get_value(entry, &data, continent, names, en, NULL);
167
+ maxminddb_set_result(ret, rb_sym_continent, &data);
168
+ MMDB_get_value(entry, &data, location, latitude, NULL);
169
+ maxminddb_set_result(ret, rb_sym_latitude, &data);
170
+ MMDB_get_value(entry, &data, location, longitude, NULL);
171
+ maxminddb_set_result(ret, rb_sym_longitude, &data);
172
+ MMDB_get_value(entry, &data, postal, code, NULL);
173
+ maxminddb_set_result(ret, rb_sym_postcode, &data);
174
+ } else {
175
+ ret = Qnil;
176
+ }
177
+
178
+ return ret;
179
+ }
180
+
181
+ VALUE
182
+ maxminddb_close(VALUE self) {
183
+ struct MaxMindDB *ptr = MaxMindDB(self);
184
+
185
+ if (ptr) {
186
+ if (ptr->mmdb) {
187
+ MMDB_close(ptr->mmdb);
188
+ }
189
+ }
190
+
191
+ return Qnil;
192
+ }
193
+
194
+ void
195
+ maxminddb_init_rb_variables() {
196
+ rb_sym_city = rb_to_symbol(rb_str_new2(city));
197
+ rb_sym_country = rb_to_symbol(rb_str_new2(country));
198
+ rb_sym_country_code = rb_to_symbol(rb_str_new2(country_code));
199
+ rb_sym_continent = rb_to_symbol(rb_str_new2(continent));
200
+ rb_sym_latitude = rb_to_symbol(rb_str_new2(latitude));
201
+ rb_sym_longitude = rb_to_symbol(rb_str_new2(longitude));
202
+ rb_sym_postcode = rb_to_symbol(rb_str_new2(postcode));
203
+ }
204
+
205
+ void
206
+ Init_mmdb() {
207
+ rb_cMaxMindDB = rb_define_class("MaxMindDB", rb_cObject);
208
+
209
+ rb_define_alloc_func(rb_cMaxMindDB, maxminddb_alloc);
210
+
211
+ rb_define_method(rb_cMaxMindDB, "initialize", maxminddb_initialize, -1);
212
+ rb_define_method(rb_cMaxMindDB, "lookup", maxminddb_lookup, 1);
213
+ rb_define_method(rb_cMaxMindDB, "close", maxminddb_close, 0);
214
+
215
+ maxminddb_init_rb_variables();
216
+ }
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: mmdb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - yoppi
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.12'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.12'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: Fast looking-up IP address from MaxMindDB(GeoIP2 format)
56
+ email:
57
+ - y.hirokazu@gmail.com
58
+ executables: []
59
+ extensions:
60
+ - ext/mmdb/extconf.rb
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ext/mmdb/extconf.rb
64
+ - ext/mmdb/mmdb.c
65
+ homepage: https://github.com/yoppi/mmdb
66
+ licenses:
67
+ - MIT
68
+ metadata: {}
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ required_rubygems_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ requirements: []
84
+ rubyforge_project:
85
+ rubygems_version: 2.5.1
86
+ signing_key:
87
+ specification_version: 4
88
+ summary: MaxMindDB client for Ruby
89
+ test_files: []