geoipdb 0.1.4 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
- }