geoipdb 0.1.4 → 0.3.1

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.
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Eugen Martin
1
+ Copyright (c) 2010 madvertise GmbH
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
@@ -2,17 +2,17 @@
2
2
 
3
3
  Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.
4
4
 
5
- * Returns a GeoLocation to a given IP.
5
+ * Returns a GeoLocation and additional information for a given IP.
6
6
  * Reads Data from CSV-Files and uses internal binary caching.
7
7
 
8
8
  ## Usage
9
9
 
10
- db = GeoIpDb.init "city_codes.csv", "ip_city.txt", "ip_city.cache"
11
- location_hash = db.city_by_ip("178.0.0.1")
12
- # => {"name"=>"eschborn", "country"=>"deu", "lng"=>8.55, "lat"=>50.133333}
10
+ db = IpDb.init "city_codes.csv", "ip_city.txt", "ip_city.cache"
11
+ ip_info = db.information_for_ip("178.0.0.1")
12
+ ip_info.inspect
13
+ => #<IpInformation:0x101385c78 @city_name="eschborn", @city_code="ax5", @lng=8.55, @country_iso_code="de", @lat=50.133333, @is_mobile=true>
13
14
 
14
15
  == Copyright
15
16
 
16
- Copyright (c) 2010 Eugen Martin. See LICENSE.txt for
17
- further details.
18
-
17
+ Copyright (c) 2010 madvertise GmbH. See LICENSE.txt for
18
+ further details.
data/Rakefile CHANGED
@@ -13,14 +13,15 @@ require 'jeweler'
13
13
  Jeweler::Tasks.new do |gem|
14
14
  # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
15
  gem.name = "geoipdb"
16
- gem.homepage = "http://github.com/olgen/geoipdb"
16
+ gem.homepage = "http://github.com/madvertise/geoipdb"
17
17
  gem.license = "MIT"
18
18
  gem.summary = %Q{Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.}
19
- gem.description = %Q{Returns a GeoLocation to a given IP. Reads Data from CSV-Files and uses internal binary caching.}
19
+ gem.description = %Q{Returns a GeoLocation and additional information for given IP. Reads Data from CSV-Files and uses internal binary caching.}
20
20
  gem.email = "eugeniusmartinus@googlemail.com"
21
- gem.authors = ["Eugen Martin"]
22
- gem.extensions = ['ext/extconf.rb']
23
- gem.require_path = "ext"
21
+ gem.authors = ["Eugen Martin", "Martin Karlsch"]
22
+ gem.extensions = ['ext/geoipdb/extconf.rb']
23
+ gem.require_paths = ["lib","ext"]
24
+
24
25
  end
25
26
  Jeweler::RubygemsDotOrgTasks.new
26
27
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.4
1
+ 0.3.1
@@ -0,0 +1,187 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ #### Start of system configuration section. ####
5
+
6
+ srcdir = .
7
+ topdir = /Users/eugen/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1
8
+ hdrdir = /Users/eugen/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1
9
+ arch_hdrdir = /Users/eugen/.rvm/rubies/ruby-1.9.2-p180/include/ruby-1.9.1/$(arch)
10
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
11
+ prefix = $(DESTDIR)/Users/eugen/.rvm/rubies/ruby-1.9.2-p180
12
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
13
+ exec_prefix = $(prefix)
14
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
15
+ sitehdrdir = $(rubyhdrdir)/site_ruby
16
+ rubyhdrdir = $(includedir)/$(RUBY_BASE_NAME)-$(ruby_version)
17
+ vendordir = $(rubylibprefix)/vendor_ruby
18
+ sitedir = $(rubylibprefix)/site_ruby
19
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
20
+ mandir = $(datarootdir)/man
21
+ localedir = $(datarootdir)/locale
22
+ libdir = $(exec_prefix)/lib
23
+ psdir = $(docdir)
24
+ pdfdir = $(docdir)
25
+ dvidir = $(docdir)
26
+ htmldir = $(docdir)
27
+ infodir = $(datarootdir)/info
28
+ docdir = $(datarootdir)/doc/$(PACKAGE)
29
+ oldincludedir = $(DESTDIR)/usr/include
30
+ includedir = $(prefix)/include
31
+ localstatedir = $(prefix)/var
32
+ sharedstatedir = $(prefix)/com
33
+ sysconfdir = $(prefix)/etc
34
+ datadir = $(datarootdir)
35
+ datarootdir = $(prefix)/share
36
+ libexecdir = $(exec_prefix)/libexec
37
+ sbindir = $(exec_prefix)/sbin
38
+ bindir = $(exec_prefix)/bin
39
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
40
+ archdir = $(rubylibdir)/$(arch)
41
+ sitelibdir = $(sitedir)/$(ruby_version)
42
+ sitearchdir = $(sitelibdir)/$(sitearch)
43
+ vendorlibdir = $(vendordir)/$(ruby_version)
44
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
45
+
46
+ CC = gcc
47
+ CXX = g++
48
+ LIBRUBY = $(LIBRUBY_SO)
49
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
50
+ LIBRUBYARG_SHARED = -l$(RUBY_SO_NAME)
51
+ LIBRUBYARG_STATIC = -l$(RUBY_SO_NAME)-static
52
+ OUTFLAG = -o
53
+ COUTFLAG = -o
54
+
55
+ RUBY_EXTCONF_H =
56
+ cflags = $(optflags) $(debugflags) $(warnflags)
57
+ optflags = -O3
58
+ debugflags = -ggdb
59
+ warnflags = -Wextra -Wno-unused-parameter -Wno-parentheses -Wpointer-arith -Wwrite-strings -Wno-missing-field-initializers -Wshorten-64-to-32 -Wno-long-long
60
+ CFLAGS = -fno-common $(cflags) -fno-common -pipe
61
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
62
+ DEFS =
63
+ CPPFLAGS = -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE $(DEFS) $(cppflags)
64
+ CXXFLAGS = $(CFLAGS) $(cxxflags)
65
+ ldflags = -L. -L/usr/local/lib
66
+ dldflags = -Wl,-undefined,dynamic_lookup -Wl,-multiply_defined,suppress -Wl,-flat_namespace
67
+ ARCH_FLAG =
68
+ DLDFLAGS = $(ldflags) $(dldflags)
69
+ LDSHARED = $(CC) -dynamic -bundle
70
+ LDSHAREDXX = $(CXX) -dynamic -bundle
71
+ AR = ar
72
+ EXEEXT =
73
+
74
+ RUBY_BASE_NAME = ruby
75
+ RUBY_INSTALL_NAME = ruby
76
+ RUBY_SO_NAME = ruby.1.9.1
77
+ arch = x86_64-darwin10.7.0
78
+ sitearch = $(arch)
79
+ ruby_version = 1.9.1
80
+ ruby = /Users/eugen/.rvm/rubies/ruby-1.9.2-p180/bin/ruby
81
+ RUBY = $(ruby)
82
+ RM = rm -f
83
+ RM_RF = $(RUBY) -run -e rm -- -rf
84
+ RMDIRS = $(RUBY) -run -e rmdir -- -p
85
+ MAKEDIRS = mkdir -p
86
+ INSTALL = /usr/bin/install -c
87
+ INSTALL_PROG = $(INSTALL) -m 0755
88
+ INSTALL_DATA = $(INSTALL) -m 644
89
+ COPY = cp
90
+
91
+ #### End of system configuration section. ####
92
+
93
+ preload =
94
+
95
+ libpath = . $(libdir)
96
+ LIBPATH = -L. -L$(libdir)
97
+ DEFFILE =
98
+
99
+ CLEANFILES = mkmf.log
100
+ DISTCLEANFILES =
101
+ DISTCLEANDIRS =
102
+
103
+ extout =
104
+ extout_prefix =
105
+ target_prefix = /geoipdb
106
+ LOCAL_LIBS =
107
+ LIBS = $(LIBRUBYARG_SHARED) -lpthread -ldl -lobjc
108
+ SRCS = geoipdb.c ipdb.c
109
+ OBJS = geoipdb.o ipdb.o
110
+ TARGET = geoipdb
111
+ DLLIB = $(TARGET).bundle
112
+ EXTSTATIC =
113
+ STATIC_LIB =
114
+
115
+ BINDIR = $(bindir)
116
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
117
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
118
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
119
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
120
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
121
+
122
+ TARGET_SO = $(DLLIB)
123
+ CLEANLIBS = $(TARGET).bundle
124
+ CLEANOBJS = *.o *.bak
125
+
126
+ all: $(DLLIB)
127
+ static: $(STATIC_LIB)
128
+ .PHONY: all install static install-so install-rb
129
+ .PHONY: clean clean-so clean-rb
130
+
131
+ clean-rb-default::
132
+ clean-rb::
133
+ clean-so::
134
+ clean: clean-so clean-rb-default clean-rb
135
+ @-$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES)
136
+
137
+ distclean-rb-default::
138
+ distclean-rb::
139
+ distclean-so::
140
+ distclean: clean distclean-so distclean-rb-default distclean-rb
141
+ @-$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
142
+ @-$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
143
+ @-$(RMDIRS) $(DISTCLEANDIRS)
144
+
145
+ realclean: distclean
146
+ install: install-so install-rb
147
+
148
+ install-so: $(RUBYARCHDIR)
149
+ install-so: $(RUBYARCHDIR)/$(DLLIB)
150
+ $(RUBYARCHDIR)/$(DLLIB): $(DLLIB)
151
+ @-$(MAKEDIRS) $(@D)
152
+ $(INSTALL_PROG) $(DLLIB) $(@D)
153
+ install-rb: pre-install-rb install-rb-default
154
+ install-rb-default: pre-install-rb-default
155
+ pre-install-rb: Makefile
156
+ pre-install-rb-default: Makefile
157
+ $(RUBYARCHDIR):
158
+ $(MAKEDIRS) $@
159
+
160
+ site-install: site-install-so site-install-rb
161
+ site-install-so: install-so
162
+ site-install-rb: install-rb
163
+
164
+ .SUFFIXES: .c .m .cc .cxx .cpp .C .o
165
+
166
+ .cc.o:
167
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
168
+
169
+ .cxx.o:
170
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
171
+
172
+ .cpp.o:
173
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
174
+
175
+ .C.o:
176
+ $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $<
177
+
178
+ .c.o:
179
+ $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $<
180
+
181
+ $(DLLIB): $(OBJS) Makefile
182
+ @-$(RM) $(@)
183
+ $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
184
+
185
+
186
+
187
+ $(OBJS): $(hdrdir)/ruby.h $(hdrdir)/ruby/defines.h $(arch_hdrdir)/ruby/config.h
File without changes
@@ -0,0 +1,5 @@
1
+ require "mkmf"
2
+
3
+ #extension_name = "geoipdb"
4
+ #dir_config(extension_name)
5
+ create_makefile("geoipdb/geoipdb")
@@ -0,0 +1,112 @@
1
+ #include "ipdb.h"
2
+
3
+ #include "ruby.h"
4
+ /**
5
+ Ruby Wrapper
6
+ */
7
+
8
+ typedef struct geipdb {
9
+ IPDB *db;
10
+ } geoipdb;
11
+
12
+ static VALUE cIpDb;
13
+
14
+ // free the memory used by the db, called by the Ruby-GC
15
+ void geoipdb_free(geoipdb *gi) {
16
+ printf("Freeing memory for the GeoIpDb.. \n");
17
+ if(gi == NULL)
18
+ return;
19
+ if (gi->db != NULL){
20
+ if(gi->db->cities != NULL ){
21
+ printf("..freeing cities \n");
22
+ free(gi->db->cities);
23
+ gi->db->cities = NULL;
24
+ }
25
+ if(gi->db->ranges != NULL ){
26
+ printf("..freeing ranges \n");
27
+ free(gi->db->ranges);
28
+ gi->db->ranges = NULL;
29
+ }
30
+ if(gi->db != NULL){
31
+ printf("..freeing ipdb \n");
32
+ free(gi->db);
33
+ }
34
+ }
35
+ }
36
+
37
+
38
+ VALUE ipdb_init(VALUE self, VALUE cities_file_name, VALUE ranges_file_name, VALUE cache_file_name) {
39
+ geoipdb *gi;
40
+
41
+ Check_Type(cities_file_name, T_STRING);
42
+ Check_Type(ranges_file_name, T_STRING);
43
+ Check_Type(cache_file_name, T_STRING);
44
+
45
+ char *cities_csv_file = RSTRING_PTR(cities_file_name);
46
+ char *ranges_csv_file = RSTRING_PTR(ranges_file_name);
47
+ char *cache_file = RSTRING_PTR(cache_file_name);
48
+
49
+ gi = ALLOC(geoipdb);
50
+
51
+ gi->db= init_db(cities_csv_file, ranges_csv_file, cache_file);
52
+
53
+
54
+ if(gi->db == NULL)
55
+ {
56
+ if(DEBUG)
57
+ printf("Could not init DB!\n");
58
+ /*
59
+ TODO: Add geoipdb_free in this case.. though not important for production...
60
+ */
61
+ return Qnil;
62
+ }else{
63
+ if(DEBUG)
64
+ printf("\nDB Init completed!\n");
65
+ return(Data_Wrap_Struct(cIpDb, 0, geoipdb_free, gi));
66
+ }
67
+ }
68
+
69
+
70
+ VALUE build_ip_information_object(IpRange *range, City *city, char* isp) {
71
+ VALUE CIpInformation;
72
+
73
+ CIpInformation = rb_const_get(rb_cObject, rb_intern("IpInformation"));
74
+
75
+ VALUE ip_information = rb_funcall(CIpInformation, rb_intern("new"), 0);
76
+ rb_ivar_set(ip_information, rb_intern("@country_iso_code"), rb_str_new2(city->country_iso2) );
77
+ rb_ivar_set(ip_information, rb_intern("@city_name"), rb_str_new2(city->name) );
78
+ rb_ivar_set(ip_information, rb_intern("@city_code"), INT2FIX(city->city_code) );
79
+ rb_ivar_set(ip_information, rb_intern("@lng"), rb_float_new(city->lng) );
80
+ rb_ivar_set(ip_information, rb_intern("@lat"), rb_float_new(city->lat) );
81
+ rb_ivar_set(ip_information, rb_intern("@is_mobile"), range->is_mobile == 1 ? Qtrue : Qfalse );
82
+ rb_ivar_set(ip_information, rb_intern("@isp_name"), isp == NULL ? Qnil : ID2SYM( rb_intern(isp) ) );
83
+
84
+ return ip_information;
85
+ }
86
+
87
+ VALUE ipdb_information_for_ip(VALUE self, VALUE ip_string){
88
+ char *ip = RSTRING_PTR(ip_string);
89
+ geoipdb *gi;
90
+
91
+ Data_Get_Struct(self, geoipdb, gi);
92
+
93
+ IpRange* ip_range = find_range_for_ip(gi->db, ip);
94
+
95
+ if(!ip_range)
96
+ return Qnil;
97
+
98
+ City * city = find_city_for_ip_range(gi->db, ip_range);
99
+ if(!city)
100
+ return Qnil;
101
+
102
+ char* isp = find_isp_for_ip_range(gi->db, ip_range);
103
+
104
+ return build_ip_information_object(ip_range, city, isp);
105
+ }
106
+
107
+ void Init_geoipdb(void)
108
+ {
109
+ cIpDb = rb_define_class( "GeoIpDb", rb_cObject);
110
+ rb_define_singleton_method( cIpDb, "init", ipdb_init, 3);
111
+ rb_define_method( cIpDb, "information_for_ip", ipdb_information_for_ip, 1);
112
+ }
@@ -6,9 +6,6 @@
6
6
  #include <stdlib.h>
7
7
  #include <sys/time.h>
8
8
 
9
-
10
-
11
-
12
9
  const char country_iso2_codes[253][3] = { "--","ap","eu","ad","ae","af","ag","ai","al","am","an",
13
10
  "ao","aq","ar","as","at","au","aw","az","ba","bb",
14
11
  "bd","be","bf","bg","bh","bi","bj","bm","bn","bo",
@@ -144,7 +141,26 @@ ip_to_int(const char *addr){
144
141
  ipnum <<= 8;
145
142
  return ipnum + octet;
146
143
  }
147
-
144
+
145
+
146
+ unsigned char con_type_to_int(char* con_type) {
147
+ // possible values
148
+ // ?
149
+ // dialup
150
+ // broadband
151
+ // cable
152
+ // xdsl
153
+ // mobile
154
+ // t1
155
+ // t3
156
+ // oc3
157
+ // oc12
158
+ // satellite
159
+ // wireless
160
+ if(strlen(con_type) > 0 && (con_type[0] == 'm'))
161
+ return 1;
162
+ return 0;
163
+ }
148
164
 
149
165
  // Function to compare
150
166
  // - either two ip-ranges: i.e.: a(from...to) <=> b(from...to)
@@ -250,13 +266,10 @@ city_index_by_code(IPDB * db, uint16 city_code){
250
266
  }
251
267
 
252
268
 
253
- City *
254
- city_by_ip(IPDB *db, char *ip){
255
- IpRange * search, *result;
269
+ IpRange* find_range_for_ip(IPDB *db, char *ip) {
270
+ IpRange* search;
271
+ IpRange* result;
256
272
  search = (IpRange *)malloc(sizeof(IpRange));
257
- void * res;
258
-
259
- // print_stats(db);
260
273
 
261
274
  if(db == NULL)
262
275
  {
@@ -275,24 +288,29 @@ city_by_ip(IPDB *db, char *ip){
275
288
  search->city_index = 0;
276
289
  if(DEBUG)
277
290
  printf("Searching for: ip=%s, ipnum=%lu \n", ip, search->from);
278
- // result = (IpRange*) bsearch(search, db->ranges, db->ranges_count-2, sizeof(IpRange), compare_ranges);
279
- res = bsearch(search, db->ranges, db->ranges_count, sizeof(IpRange), compare_ranges);
291
+ result = (IpRange*)bsearch(search, db->ranges, db->ranges_count, sizeof(IpRange), compare_ranges);
280
292
  if(search != NULL)
281
293
  free(search);
282
294
 
283
- if(res == NULL)
295
+ if(result == NULL)
284
296
  {
285
297
  if(DEBUG)
286
- printf("ERROR: Could not find the IP: %s! THIS SHOULD NOT HAPPEN!\n", ip);
298
+ printf("ERROR: Could not find the IP: %s! THIS SHOULD NOT HAPPEN!\n", ip);
287
299
  return NULL;
288
- }else{
289
- result = (IpRange*) res;
290
- if(DEBUG){
300
+ } else {
301
+ if(DEBUG) {
291
302
  printf("Found Range: \t");
292
303
  print_range(result);
293
- }
304
+ }
305
+ return (IpRange*)result;
294
306
  }
295
-
307
+ }
308
+
309
+ City * find_city_for_ip_range(IPDB * db, IpRange* range)
310
+ {
311
+ if(!db || !range)
312
+ return NULL;
313
+
296
314
  if(db->cities_count == 0)
297
315
  {
298
316
  if(DEBUG)
@@ -300,21 +318,55 @@ city_by_ip(IPDB *db, char *ip){
300
318
  return NULL;
301
319
  }
302
320
 
303
-
304
- if(result->city_index >0 && result->city_index < db->cities_count)
321
+ if( range->city_index <= 0 || range->city_index >= db->cities_count )
305
322
  {
306
- // address the city directly via the array-idx
307
- return &(db->cities[result->city_index]);
308
- } else {
309
323
  if(DEBUG)
310
- printf("ERROR: Could not find city with index: %i - THIS SHOULD NOT HAPPEN!\n", result->city_index);
311
- return NULL;
324
+ printf("ERROR: Could not find city with index: %i - THIS SHOULD NOT HAPPEN!\n", range->city_index);
325
+ }
326
+
327
+ return &(db->cities[range->city_index]);
328
+ }
329
+
330
+ char* find_isp_for_ip_range(IPDB * db, IpRange* range)
331
+ {
332
+ if( range == NULL || range->isp_index < 0 || range->isp_index > MAX_ISPS_COUNT){
333
+ printf("Could not find isp for isp_index=%i", range->isp_index);
334
+ return NULL;
335
+ }
336
+ return db->isps[range->isp_index];
337
+ }
338
+
339
+ int16
340
+ isp_index_by_name(IPDB * db, char* isp_name){
341
+ if(isp_name == NULL || isp_name == "")
342
+ return -1;
343
+ if( db->isps_count > 0){
344
+ int16 i = 0;
345
+ for( i = 0; i < db->isps_count; i++)
346
+ {
347
+ if( strcmp(db->isps[i], isp_name)==0)
348
+ {
349
+ return i;
350
+ }
351
+ }
352
+ }
353
+ // TODO: malloc more space if needed
354
+ // add new isp
355
+ if(db->isps_count < MAX_ISPS_COUNT){
356
+ int16 new_index = db->isps_count;
357
+ strncpy(db->isps[new_index], isp_name, MAX_ISP_NAME_LENGTH);
358
+ db->isps_count++;
359
+ return new_index;
360
+ }else{
361
+ printf("ERROR: MAX_ISPS_COUNT = %i limit reached - this should not happen!", MAX_ISPS_COUNT);
362
+ return -1;
312
363
  }
313
364
  }
314
365
 
315
366
 
367
+
316
368
  // read ip-ranges from csv file, of format:
317
- // from_ip|to_ip|city_code
369
+ // from_ip|to_ip|contype|city_code
318
370
  void
319
371
  read_ranges_csv(IPDB * db){
320
372
  struct timeval tim;
@@ -332,39 +384,56 @@ read_ranges_csv(IPDB * db){
332
384
  return;
333
385
  }
334
386
  char line[256];
335
- char* from = NULL;
336
- char* to = NULL;
337
- char* city_code = NULL;
338
- int invalid_cities_count = 0;
387
+ char* from;
388
+ char* to;
389
+ char* city_code;
339
390
  int city_index;
391
+
392
+ char* con_type;
393
+ char* isp_name;
394
+ uint16 isp_index;
395
+
396
+ int invalid_cities_count = 0;
340
397
 
341
398
  IpRange* entry;
342
399
  db->ranges_count = 0;
343
- while (fgets(line,sizeof(line),f) && db->ranges_count < db->max_ranges_count){
400
+ while (fgets(line, sizeof(line) ,f) && db->ranges_count < db->max_ranges_count){
401
+ from = NULL;
402
+ to = NULL;
403
+ city_code = NULL;
404
+ city_index = 0;
405
+
406
+ con_type = NULL;
407
+ isp_name = NULL;
408
+ int16 isp_index = -1;
409
+
344
410
  if(DEBUG && db->ranges_count % 1000000 == 0)
345
411
  printf("Worked lines: %i\n", db->ranges_count);
346
412
 
347
413
  from = strtok(line, RANGES_DELIM);
348
414
  to = strtok(NULL, RANGES_DELIM);
415
+ con_type = strtok(NULL, RANGES_DELIM);
349
416
  city_code = strtok(NULL, RANGES_DELIM);
417
+ isp_name = strtok(NULL, RANGES_DELIM);
418
+
350
419
  city_index = city_index_by_code(db, atoi(city_code));
420
+ isp_index = isp_index_by_name(db, isp_name);
421
+
351
422
  if(city_index < 0)
352
- {
423
+ {
353
424
  if(DEBUG)
354
425
  printf("Could not find city for code: %i", atoi(city_code));
355
426
  invalid_cities_count ++;
356
427
  continue;
357
428
  }else{
358
429
  entry = &(db->ranges[db->ranges_count]);
359
-
360
430
  entry->from = ip_to_int(from);
361
- entry->to = ip_to_int(to);
362
- // entry->city_code = atoi(city_code);
363
-
431
+ entry->to = ip_to_int(to);
432
+ entry->is_mobile = con_type_to_int(con_type);
364
433
  entry->city_index = city_index;
365
- // printf("Line: %s", line);
366
- // printf("from: %u,to: %u, city_code:%i \n",entry->from,entry->to,entry->city_code);
367
- // db->ranges[i] = *entry;
434
+ entry->isp_index = isp_index;
435
+
436
+ // printf("from: %u,to: %u, city_code:%s, city_index: %i\n",entry->from,entry->to,city_code, entry->city_index);
368
437
  // printf("working record nr: %li\n", db->ranges_count);
369
438
  db->ranges_count++;
370
439
  }
@@ -488,13 +557,20 @@ write_cache_file(IPDB * db){
488
557
  printf("FieldLength: %li\n",sizeof(db->ranges[0].from));
489
558
  }
490
559
  //write the header: i.e.: numbers of records
491
- fwrite(&(db->cities_count), sizeof(db->cities_count),1,f);
560
+ fwrite(&(db->cities_count), sizeof(db->cities_count),1,f);
561
+ fwrite(&(db->isps_count), sizeof(db->isps_count),1,f);
492
562
  fwrite(&(db->ranges_count), sizeof(db->ranges_count),1,f);
493
563
 
494
564
  if(DEBUG)
495
565
  printf("Writing Contents with %i cities, a %li bytes each, should = %li \n", db->cities_count, sizeof(City), db->cities_count * sizeof(City));
496
566
  //write the actual data: all the ranges-array-buffer:
497
567
  objects_written = fwrite(db->cities, sizeof(City), db->cities_count, f);
568
+
569
+ if(DEBUG)
570
+ printf("Writing Contents with %i isps, a %li bytes each, should = %li \n", db->isps_count, MAX_ISP_NAME_LENGTH, db->isps_count * MAX_ISP_NAME_LENGTH);
571
+ //write the actual data: all the ranges-array-buffer:
572
+ objects_written += fwrite(db->isps, MAX_ISP_NAME_LENGTH, db->isps_count, f);
573
+
498
574
  if(DEBUG)
499
575
  printf("Writing Contents with %i ranges, a %li bytes each, should = %li \n", db->ranges_count, sizeof(IpRange), db->ranges_count * sizeof(IpRange));
500
576
  //write the actual data: all the ranges-array-buffer:
@@ -518,22 +594,28 @@ read_cache_file(IPDB * db){
518
594
  return 0;
519
595
  }
520
596
  int cities_header_read = fread(&(db->cities_count), sizeof(db->cities_count),1,f);
597
+ int isps_header_read = fread(&(db->isps_count), sizeof(db->isps_count),1,f);
521
598
  int ranges_header_read = fread(&(db->ranges_count), sizeof(db->ranges_count),1,f);
522
599
 
523
600
 
524
- if(cities_header_read == 0 || ranges_header_read == 0 || db->cities_count == 0 || db->ranges_count ==0 )
601
+ if(cities_header_read == 0 || isps_header_read == 0 || ranges_header_read == 0 || db->cities_count == 0 || db->isps_count ==0 || db->ranges_count ==0)
525
602
  {
526
603
  printf("Could not read Cities-Header from Cache-File: %s", db->cache_file_name);
527
604
  return 0;
528
605
  }
529
606
  if(DEBUG)
530
- printf("Reading DB-Header from Cache-File: %s, with %i cities and %i ranges\n",db->cache_file_name, db->cities_count, db->ranges_count);
607
+ printf("Reading DB-Header from Cache-File: %s, with %i cities, %iisps and %i ranges\n",db->cache_file_name, db->cities_count, db->isps_count, db->ranges_count);
531
608
 
532
609
  int objects_read = 0;
533
610
  if(DEBUG)
534
611
  printf("Allocating: %lu for cities-array \n", sizeof(City)*(db->cities_count));
535
612
  db->cities = malloc(sizeof(City) * db->cities_count);
536
613
  objects_read += fread(db->cities, sizeof(City),db->cities_count,f);
614
+
615
+ if(DEBUG)
616
+ printf("Reading in the isps into preallocated buffer of size: ", sizeof(db->isps));
617
+ objects_read += fread(db->isps, MAX_ISP_NAME_LENGTH, db->isps_count,f);
618
+
537
619
  if(DEBUG)
538
620
  printf("Allocating: %lu for ranges-array \n", sizeof(IpRange)*(db->ranges_count));
539
621
  db->ranges = malloc(sizeof(IpRange) * db->ranges_count);
@@ -554,8 +636,9 @@ benchmark_search(IPDB * db,int count){
554
636
  int i;
555
637
  City * city;
556
638
 
557
- for(i=0;i<count; i++){
558
- city = city_by_ip(db, "278.50.47.0");
639
+ for(i=0;i<count; i++){
640
+ IpRange* range = find_range_for_ip(db,"278.50.47.0");
641
+ City* city = find_city_for_ip_range(db,range);
559
642
  }
560
643
  double delta = get_time(&tim)-t1;
561
644
 
@@ -563,6 +646,8 @@ benchmark_search(IPDB * db,int count){
563
646
  }
564
647
 
565
648
  IPDB * init_db(char * cities_csv_file, char * ranges_csv_file, char * cache_file_name){
649
+ if(DEBUG)
650
+ printf("Initializing db");
566
651
  IPDB *db;
567
652
  db = (IPDB*)malloc(sizeof(IPDB));
568
653
  if (db == NULL) //no memory left
@@ -575,6 +660,10 @@ IPDB * init_db(char * cities_csv_file, char * ranges_csv_file, char * cache_file
575
660
  db->max_cities_count = MAX_CITIES_COUNT;
576
661
  db->ranges_csv_file = ranges_csv_file;
577
662
  db->max_ranges_count = MAX_RANGES_COUNT;
663
+
664
+ // db->isps = NULL;
665
+ // db->isps = malloc(MAX_ISP_NAME_LENGTH * MAX_ISPS_COUNT);
666
+ db->isps_count = 0;
578
667
 
579
668
 
580
669
  if(USE_CACHE && read_cache_file(db) > 0){
@@ -11,21 +11,31 @@ typedef unsigned short uint16;
11
11
  typedef int int32;
12
12
  #endif
13
13
 
14
+ #ifdef RSTRING_PTR
15
+ #else
16
+ # define RSTRING_LEN(x) (RSTRING(x)->len)
17
+ # define RSTRING_PTR(x) (RSTRING(x)->ptr)
18
+ #endif
19
+
20
+
21
+ #define RANGES_DELIM ",\n"
22
+ #define CITIES_DELIM ",\n"
14
23
 
15
- #define RANGES_DELIM "|"
16
- #define CITIES_DELIM ","
17
24
  #define MAX_CITIES_COUNT 100000 //Usually we have about 50 000 Cities
18
- #define MAX_RANGES_COUNT 10000000 //Usually we have about 6 Mio IP-Ranges
25
+ #define MAX_RANGES_COUNT 10000000 //Usually we have about 6 Mio IP-Ranges
19
26
 
27
+ #define MAX_ISPS_COUNT 100000
28
+ #define MAX_ISP_NAME_LENGTH 100
20
29
 
21
30
  #define USE_CACHE 1
22
31
  #define DEBUG 0
23
32
 
24
33
  typedef struct{
25
34
  unsigned long from;
26
- unsigned long to;
27
- // uint16 city_code; //city codes are not larger than 2**16 = 65536
35
+ unsigned long to;
36
+ unsigned char is_mobile;
28
37
  uint16 city_index; //index of the city in the cities-array
38
+ int16 isp_index; //index of the isp in the isps-array
29
39
  } IpRange;
30
40
 
31
41
  typedef struct{
@@ -47,11 +57,14 @@ typedef struct{
47
57
  unsigned int cities_count;
48
58
  unsigned int max_cities_count;
49
59
 
50
-
51
60
  char *cache_file_name; // a binary file to store the whole db.....
52
61
  IpRange * ranges;
53
62
  City * cities;
54
63
 
64
+ char isps[MAX_ISPS_COUNT][MAX_ISP_NAME_LENGTH]; // a fixed size array of strings should be enough here...do not expect the isps to grow dramatically..
65
+ uint16 isps_count;
66
+
67
+
55
68
  } IPDB;
56
69
 
57
70
 
@@ -59,11 +72,18 @@ typedef struct{
59
72
  IPDB *
60
73
  init_db(char * cities_csv_file, char * ranges_csv_file, char * cache_file_name);
61
74
 
62
- City *
63
- city_by_ip(IPDB *db, char *ip);
64
75
 
65
76
  void
66
77
  print_city(const City * e);
67
78
 
68
79
  void
69
- benchmark_search(IPDB * db,int count);
80
+ benchmark_search(IPDB * db,int count);
81
+
82
+ IpRange*
83
+ find_range_for_ip(IPDB *db, char *ip);
84
+
85
+ City*
86
+ find_city_for_ip_range(IPDB * db, IpRange* range);
87
+
88
+ char*
89
+ find_isp_for_ip_range(IPDB * db, IpRange* range);
@@ -5,14 +5,14 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{geoipdb}
8
- s.version = "0.1.4"
8
+ s.version = "0.3.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Eugen Martin"]
12
- s.date = %q{2011-01-13}
13
- s.description = %q{Returns a GeoLocation to a given IP. Reads Data from CSV-Files and uses internal binary caching.}
11
+ s.authors = ["Eugen Martin", "Martin Karlsch"]
12
+ s.date = %q{2011-06-14}
13
+ s.description = %q{Returns a GeoLocation and additional information for given IP. Reads Data from CSV-Files and uses internal binary caching.}
14
14
  s.email = %q{eugeniusmartinus@googlemail.com}
15
- s.extensions = ["ext/extconf.rb"]
15
+ s.extensions = ["ext/geoipdb/extconf.rb"]
16
16
  s.extra_rdoc_files = [
17
17
  "LICENSE.txt",
18
18
  "README.markdown"
@@ -25,21 +25,26 @@ Gem::Specification.new do |s|
25
25
  "README.markdown",
26
26
  "Rakefile",
27
27
  "VERSION",
28
- "ext/build.sh",
29
- "ext/extconf.rb",
30
- "ext/geoipdb.c",
31
- "ext/ipdb.c",
32
- "ext/ipdb.h",
33
- "ext/test.c",
28
+ "ext/geoipdb/Makefile",
29
+ "ext/geoipdb/build.sh",
30
+ "ext/geoipdb/extconf.rb",
31
+ "ext/geoipdb/geoipdb.c",
32
+ "ext/geoipdb/ipdb.c",
33
+ "ext/geoipdb/ipdb.h",
34
34
  "geoipdb.gemspec",
35
35
  "lib/geoipdb.rb",
36
+ "sample_data/cities.csv",
37
+ "sample_data/citiess_corrupt.csv",
38
+ "sample_data/ip_ranges.csv",
39
+ "sample_data/ip_ranges_corrupt.csv",
36
40
  "spec/geoipdb_spec.rb",
37
- "spec/spec_helper.rb"
41
+ "spec/spec_helper.rb",
42
+ "test.rb"
38
43
  ]
39
- s.homepage = %q{http://github.com/olgen/geoipdb}
44
+ s.homepage = %q{http://github.com/madvertise/geoipdb}
40
45
  s.licenses = ["MIT"]
41
- s.require_paths = ["ext"]
42
- s.rubygems_version = %q{1.3.7}
46
+ s.require_paths = ["lib", "ext"]
47
+ s.rubygems_version = %q{1.5.3}
43
48
  s.summary = %q{Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.}
44
49
  s.test_files = [
45
50
  "spec/geoipdb_spec.rb",
@@ -47,7 +52,6 @@ Gem::Specification.new do |s|
47
52
  ]
48
53
 
49
54
  if s.respond_to? :specification_version then
50
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
51
55
  s.specification_version = 3
52
56
 
53
57
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
@@ -0,0 +1,17 @@
1
+ require 'rbconfig'
2
+
3
+ require 'geoipdb/geoipdb'
4
+
5
+ class IpInformation
6
+ attr_accessor :country_iso_code
7
+ attr_accessor :city_code
8
+ attr_accessor :city_name
9
+ attr_accessor :lat
10
+ attr_accessor :lng
11
+ attr_accessor :is_mobile
12
+ attr_accessor :isp_name
13
+
14
+ def mobile?
15
+ @is_mobile
16
+ end
17
+ end
@@ -1,11 +1,11 @@
1
- start_ip|end_ip|field 13|
2
- 0.0.0.0|0.0.0.255|0|
3
- 0.0.1.0|0.255.255.255|1|
4
- 1.0.0.0|1.0.0.255|2|
5
- 1.0.1.0|1.1.0.255|3|
6
- 1.1.1.0|1.1.1.255|4|
7
- 1.1.2.0|1.2.2.255|5|
8
- 1.2.3.0|1.2.3.255|5|
9
- 1.2.4.0|1.3.255.255|2|
10
- 1.4.0.0|1.4.0.255|5|
11
- 1.4.1.0|1.8.255.255|3|
1
+ start_ip,end_ip,field 4,field 13,
2
+ 0.0.0.0,0.0.0.255,mobile,0
3
+ 0.0.1.0,0.255.255.255,mobile,1,asdf,
4
+ 1.0.0.0,1.0.0.255,xdsl,2,vodafone
5
+ 1.0.1.0,1.1.0.255,wireless,3,
6
+ 1.1.1.0,1.1.1.255,mobile,4,1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone
7
+ 1.1.2.0,1.2.2.255,mobile,5,
8
+ 1.2.3.0,1.2.3.255,mobile,5,
9
+ 1.2.4.0,1.3.255.255,mobile,2,
10
+ 1.4.0.0,1.4.0.255,mobile,5,
11
+ 1.4.1.0,1.8.255.255,mobile,3,
@@ -1,20 +1,20 @@
1
1
 
2
2
 
3
3
 
4
- start_ip|end_ip|field 13|
5
- 0.0.0.0|0.0.0.255|0|
4
+ start_ip,end_ip,field 13,
5
+ 0.0.0.0,0.0.0.255,0,
6
6
 
7
- 0.0.1.0|0.255.255.255|1|
7
+ 0.0.1.0,0.255.255.255,1,
8
8
 
9
- 1.0.0.0|1.0.0.255|2|
9
+ 1.0.0.0,1.0.0.255,2,
10
10
 
11
- 1.0.1.0|1.1.0.255|3|
11
+ 1.0.1.0,1.1.0.255,3,
12
12
 
13
13
  asfdasdf asdf asfasdfasdf§$%&/
14
14
 
15
- 1, | ||.1.1.0|1.1.1.255|4|
16
- 1.1.2.0|1.2.2.255|5|
17
- 1.2.3.0|1.2.3.255|5|
18
- 1.2.4.0|1.3.255.255|2|
19
- 1.4.0.0|1.4.0.255|5|
20
- 1.4.1.0|1.8.255.255|3|
15
+ 1, , ,,.1.1.0,1.1.1.255,4,
16
+ 1.1.2.0,1.2.2.255,5,
17
+ 1.2.3.0,1.2.3.255,5,
18
+ 1.2.4.0,1.3.255.255,2,
19
+ 1.4.0.0,1.4.0.255,5,
20
+ 1.4.1.0,1.8.255.255,3,
@@ -1,37 +1,57 @@
1
1
  require File.expand_path(File.dirname(__FILE__)+'/spec_helper')
2
2
 
3
3
 
4
- describe "Geoipdb" do
4
+ describe GeoIpDb do
5
+
6
+ CACHE_FILE = 'sample_data/ipdb.cache'
7
+
5
8
  def init_db
6
- @db = GeoIpDb.init './sample_data/cities.csv', './sample_data/ip_ranges.csv', @cache_file
7
- end
9
+ @db = GeoIpDb.init './sample_data/cities.csv', './sample_data/ip_ranges.csv', CACHE_FILE
10
+ end
8
11
 
9
- before :each do
10
- @cache_file = 'sample_data/ipdb.cache'
12
+ it "should not throw an exception fault if data is corrupt" do
13
+ @db = GeoIpDb.init './sample_data/cities_corrupt.csv', './sample_data/ip_ranges_corrupt.csv', CACHE_FILE
14
+ end
15
+
16
+ it "should not init a db object if data files are missing" do
17
+ GeoIpDb.init( './sample_data/bla.csv', './sample_data/blubb.csv', CACHE_FILE ).should be_nil
11
18
  end
12
19
 
13
20
  it "should init correctly with sample data and create the cache-file" do
14
21
  init_db
15
22
  @db.should_not be_nil
16
- File.exist?(@cache_file).should be_true
23
+ File.exist?(CACHE_FILE).should be_true
17
24
  end
18
25
 
19
26
  it "sould find the sample cities correcty" do
20
27
  init_db
21
28
  #afg,no region,kabul,-1,3,34.5167,69.1833
22
- @db.city_by_ip("1.1.0.254").should == {'city_code'=>3, 'name'=>'kabul', 'country'=>'af', 'lat'=>34.5167, 'lng'=>69.1833}
29
+ info = @db.information_for_ip "1.1.0.254"
30
+ info.city_code.should == 3
31
+ info.city_name.should == 'kabul'
32
+ info.country_iso_code.should == 'af'
33
+ info.lat.should == 34.5167
34
+ info.lng.should == 69.1833
35
+ info.should_not be_mobile
23
36
  end
24
37
 
25
- it "should not throw an exception fault if data is corrupt" do
26
- @db = GeoIpDb.init './sample_data/cities_corrupt.csv', './sample_data/ip_ranges_corrupt.csv', @cache_file
27
- end
28
-
29
- it "should not init a db object if data files are missing" do
30
- GeoIpDb.init( './sample_data/bla.csv', './sample_data/blubb.csv', @cache_file ).should be_nil
38
+ it 'should return correct is_mobile information' do
39
+ init_db
40
+ @db.information_for_ip("1.0.0.1").should_not be_mobile
41
+ @db.information_for_ip("1.1.1.1").should be_mobile
42
+ end
43
+
44
+ it 'should return correct isp_name in ip_information' do
45
+ init_db
46
+ @db.information_for_ip("1.0.0.1").isp_name.should == :vodafone
47
+ @db.information_for_ip("1.1.1.1").isp_name.should == "1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone1vodafone2vodafone3vodafone4vodafone5vodafone"[0..99].to_sym
48
+ @db.information_for_ip("1.2.1.1").isp_name.should == nil
31
49
  end
32
50
 
51
+ it "should write and read the cachefile correctly"
33
52
 
34
53
  after :each do
35
- File.unlink @cache_file if File.exist? @cache_file
54
+ File.unlink CACHE_FILE if File.exist? CACHE_FILE
36
55
  end
56
+
37
57
  end
@@ -1,7 +1,8 @@
1
1
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'ext'))
2
2
  $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
3
4
  require 'rspec'
4
- require 'geoipdb'
5
+ require 'lib/geoipdb'
5
6
 
6
7
  # Requires supporting files with custom matchers and macros, etc,
7
8
  # in ./support/ and its subdirectories.
data/test.rb ADDED
@@ -0,0 +1,9 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'ext'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ require 'lib/geoipdb'
5
+
6
+
7
+ db = GeoIpDb.init 'ext/data/cities.csv', 'ext/data/ip_ranges.csv', 'ext/data/ipdb.cache'
8
+
9
+ puts db.information_for_ip("165.193.245.54").inspect
metadata CHANGED
@@ -1,25 +1,26 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geoipdb
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 17
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
+ - 3
8
9
  - 1
9
- - 4
10
- version: 0.1.4
10
+ version: 0.3.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Eugen Martin
14
+ - Martin Karlsch
14
15
  autorequire:
15
16
  bindir: bin
16
17
  cert_chain: []
17
18
 
18
- date: 2011-01-14 00:00:00 +01:00
19
+ date: 2011-06-14 00:00:00 +02:00
19
20
  default_executable:
20
21
  dependencies:
21
22
  - !ruby/object:Gem::Dependency
22
- type: :development
23
+ name: rspec
23
24
  version_requirements: &id001 !ruby/object:Gem::Requirement
24
25
  none: false
25
26
  requirements:
@@ -31,11 +32,11 @@ dependencies:
31
32
  - 1
32
33
  - 0
33
34
  version: 2.1.0
34
- requirement: *id001
35
35
  prerelease: false
36
- name: rspec
37
- - !ruby/object:Gem::Dependency
38
36
  type: :development
37
+ requirement: *id001
38
+ - !ruby/object:Gem::Dependency
39
+ name: bundler
39
40
  version_requirements: &id002 !ruby/object:Gem::Requirement
40
41
  none: false
41
42
  requirements:
@@ -47,11 +48,11 @@ dependencies:
47
48
  - 0
48
49
  - 0
49
50
  version: 1.0.0
50
- requirement: *id002
51
51
  prerelease: false
52
- name: bundler
53
- - !ruby/object:Gem::Dependency
54
52
  type: :development
53
+ requirement: *id002
54
+ - !ruby/object:Gem::Dependency
55
+ name: jeweler
55
56
  version_requirements: &id003 !ruby/object:Gem::Requirement
56
57
  none: false
57
58
  requirements:
@@ -63,11 +64,11 @@ dependencies:
63
64
  - 5
64
65
  - 1
65
66
  version: 1.5.1
66
- requirement: *id003
67
67
  prerelease: false
68
- name: jeweler
69
- - !ruby/object:Gem::Dependency
70
68
  type: :development
69
+ requirement: *id003
70
+ - !ruby/object:Gem::Dependency
71
+ name: rcov
71
72
  version_requirements: &id004 !ruby/object:Gem::Requirement
72
73
  none: false
73
74
  requirements:
@@ -77,15 +78,15 @@ dependencies:
77
78
  segments:
78
79
  - 0
79
80
  version: "0"
80
- requirement: *id004
81
81
  prerelease: false
82
- name: rcov
83
- description: Returns a GeoLocation to a given IP. Reads Data from CSV-Files and uses internal binary caching.
82
+ type: :development
83
+ requirement: *id004
84
+ description: Returns a GeoLocation and additional information for given IP. Reads Data from CSV-Files and uses internal binary caching.
84
85
  email: eugeniusmartinus@googlemail.com
85
86
  executables: []
86
87
 
87
88
  extensions:
88
- - ext/extconf.rb
89
+ - ext/geoipdb/extconf.rb
89
90
  extra_rdoc_files:
90
91
  - LICENSE.txt
91
92
  - README.markdown
@@ -97,12 +98,12 @@ files:
97
98
  - README.markdown
98
99
  - Rakefile
99
100
  - VERSION
100
- - ext/build.sh
101
- - ext/extconf.rb
102
- - ext/geoipdb.c
103
- - ext/ipdb.c
104
- - ext/ipdb.h
105
- - ext/test.c
101
+ - ext/geoipdb/Makefile
102
+ - ext/geoipdb/build.sh
103
+ - ext/geoipdb/extconf.rb
104
+ - ext/geoipdb/geoipdb.c
105
+ - ext/geoipdb/ipdb.c
106
+ - ext/geoipdb/ipdb.h
106
107
  - geoipdb.gemspec
107
108
  - lib/geoipdb.rb
108
109
  - sample_data/cities.csv
@@ -111,14 +112,16 @@ files:
111
112
  - sample_data/ip_ranges_corrupt.csv
112
113
  - spec/geoipdb_spec.rb
113
114
  - spec/spec_helper.rb
115
+ - test.rb
114
116
  has_rdoc: true
115
- homepage: http://github.com/olgen/geoipdb
117
+ homepage: http://github.com/madvertise/geoipdb
116
118
  licenses:
117
119
  - MIT
118
120
  post_install_message:
119
121
  rdoc_options: []
120
122
 
121
123
  require_paths:
124
+ - lib
122
125
  - ext
123
126
  required_ruby_version: !ruby/object:Gem::Requirement
124
127
  none: false
@@ -141,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
144
  requirements: []
142
145
 
143
146
  rubyforge_project:
144
- rubygems_version: 1.4.2
147
+ rubygems_version: 1.5.3
145
148
  signing_key:
146
149
  specification_version: 3
147
150
  summary: Fast (>3 Mio queries/sec!!!) GeoIpDb implementation for Ruby using C-Extensions.
@@ -1,5 +0,0 @@
1
- require "mkmf"
2
-
3
- extension_name = "geoipdb"
4
- dir_config(extension_name)
5
- create_makefile(extension_name)
@@ -1,109 +0,0 @@
1
- #include "ipdb.h"
2
-
3
- #include "ruby.h"
4
-
5
- /**
6
- Ruby Wrapper
7
- */
8
-
9
- typedef struct geipdb {
10
- IPDB *db;
11
- } geoipdb;
12
-
13
- static VALUE cGeoIpDb;
14
-
15
- VALUE method_hello_world(VALUE self);
16
-
17
- // free the memory used by the db, called by the Ruby-GC
18
- void geoipdb_free(geoipdb *gi) {
19
- printf("Freeing memory for the GeoIpDb.. \n");
20
- if(gi == NULL)
21
- return;
22
- if (gi->db != NULL){
23
- if(gi->db->cities != NULL ){
24
- printf("..freeing cities \n");
25
- free(gi->db->cities);
26
- gi->db->cities = NULL;
27
- }
28
- if(gi->db->ranges != NULL ){
29
- printf("..freeing ranges \n");
30
- free(gi->db->ranges);
31
- gi->db->ranges = NULL;
32
- }
33
- if(gi->db != NULL){
34
- printf("..freeing ipdb \n");
35
- free(gi->db);
36
- }
37
- }
38
- }
39
-
40
-
41
- VALUE ipdb_init(VALUE self, VALUE cities_file_name, VALUE ranges_file_name, VALUE cache_file_name) {
42
- geoipdb *gi;
43
-
44
- Check_Type(cities_file_name, T_STRING);
45
- Check_Type(ranges_file_name, T_STRING);
46
- Check_Type(cache_file_name, T_STRING);
47
-
48
- char *cities_csv_file = RSTRING(cities_file_name)->ptr;
49
- char *ranges_csv_file = RSTRING(ranges_file_name)->ptr;
50
- char *cache_file = RSTRING(cache_file_name)->ptr;
51
-
52
- gi = malloc(sizeof(geoipdb));
53
-
54
- gi->db= init_db(cities_csv_file, ranges_csv_file, cache_file);
55
-
56
- if(gi->db == NULL)
57
- {
58
- if(DEBUG)
59
- printf("Could not init DB!\n");
60
- /*
61
- TODO: Add geoipdb_free in this case.. though not important for production...
62
- */
63
- return Qnil;
64
- }else{
65
- if(DEBUG)
66
- printf("\nDB Init completed!\n");
67
- return(Data_Wrap_Struct(cGeoIpDb, 0, geoipdb_free, gi));
68
- }
69
- }
70
-
71
-
72
- VALUE city_to_hash(City * city){
73
- VALUE hash = rb_hash_new();
74
- // return a ruby-hash with the needed data
75
- rb_hash_aset(hash, rb_str_new2("name"), rb_str_new2(city->name));
76
- rb_hash_aset(hash, rb_str_new2("country"), rb_str_new2(city->country_iso2));
77
- rb_hash_aset(hash, rb_str_new2("lat"), rb_float_new(city->lat));
78
- rb_hash_aset(hash, rb_str_new2("lng"), rb_float_new(city->lng));
79
- rb_hash_aset(hash, rb_str_new2("city_code"), INT2FIX(city->city_code));
80
- return hash;
81
- }
82
-
83
- VALUE ipdb_city_by_ip(VALUE self, VALUE ip_string){
84
- char *ip = RSTRING(ip_string)->ptr;
85
- geoipdb *gi;
86
-
87
- Data_Get_Struct(self, geoipdb, gi);
88
- City * city = city_by_ip(gi->db, ip);
89
- if(city == NULL)
90
- {
91
- // printf("Could not find city for ip: %s\n", ip);
92
- return Qnil;
93
- }else{
94
- // printf("Found city for ip: %s\n", ip);
95
- // print_city(city);
96
- return city_to_hash(city);
97
- // create a hash to return to ruby:
98
- }
99
- }
100
-
101
-
102
-
103
- void Init_geoipdb(void)
104
- {
105
- //Erstelle die Klasse cGeoIpDb als Subklasse von Object
106
- cGeoIpDb = rb_define_class( "GeoIpDb", rb_cObject);
107
- rb_define_singleton_method( cGeoIpDb, "init", ipdb_init, 3);
108
- rb_define_method( cGeoIpDb, "city_by_ip", ipdb_city_by_ip, 1);
109
- }
data/ext/test.c DELETED
@@ -1,42 +0,0 @@
1
- #include "ipdb.h"
2
-
3
- #include <search.h>
4
- #include <stdio.h>
5
- #include <string.h>
6
- #include <stdlib.h>
7
- #include <sys/time.h>
8
-
9
-
10
-
11
- int main() {
12
- IPDB * db = init_db("data/cities.csv", "data/ip_ranges.csv", "data/ipdb.cache");
13
- // IPDB * db = init_db(NULL, NULL, NULL);
14
-
15
-
16
- // City * city;
17
- //
18
- // // city = city_by_ip(db, "1.16.0.0");
19
- // int i;
20
- int count = 10000000;
21
-
22
- benchmark_search(db, count);
23
-
24
- // for(i = 0; i < count; ++i)
25
- // {
26
- // if(i % 100000 == 0)
27
- // printf("Working: i= %i \n", i);
28
- //
29
- // city = city_by_ip(db, "91.44.93.35");
30
- // }
31
-
32
-
33
-
34
-
35
-
36
- //
37
- int * response;
38
- scanf("%i",response);
39
-
40
- return 0;
41
-
42
- }