geoip 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/geoip.rb +32 -21
- metadata +3 -3
data/lib/geoip.rb
CHANGED
@@ -43,9 +43,14 @@ $:.unshift File.dirname(__FILE__)
|
|
43
43
|
#=end
|
44
44
|
require 'thread' # Needed for Mutex
|
45
45
|
require 'socket'
|
46
|
+
begin
|
47
|
+
require 'io/extra' # for IO.pread
|
48
|
+
rescue LoadError
|
49
|
+
# oh well, hope they're not forking after initializing
|
50
|
+
end
|
46
51
|
|
47
52
|
class GeoIP
|
48
|
-
VERSION = "0.8.
|
53
|
+
VERSION = "0.8.6"
|
49
54
|
private
|
50
55
|
CountryCode = [
|
51
56
|
"--","AP","EU","AD","AE","AF","AG","AI","AL","AM","AN",
|
@@ -429,7 +434,7 @@ class GeoIP
|
|
429
434
|
# +filename+ is a String holding the path to the GeoIP.dat file
|
430
435
|
# +options+ is an integer holding caching flags (unimplemented)
|
431
436
|
def initialize(filename, flags = 0)
|
432
|
-
@mutex = Mutex.new
|
437
|
+
@mutex = IO.respond_to?(:pread) ? false : Mutex.new
|
433
438
|
@flags = flags
|
434
439
|
@databaseType = GEOIP_COUNTRY_EDITION
|
435
440
|
@record_length = STANDARD_RECORD_LENGTH
|
@@ -530,11 +535,9 @@ class GeoIP
|
|
530
535
|
private
|
531
536
|
|
532
537
|
def read_city(pos, hostname = '', ip = '')
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
return nil unless record = @file.read(FULL_RECORD_LENGTH)
|
537
|
-
}
|
538
|
+
off = pos + (2*@record_length-1) * @databaseSegments[0]
|
539
|
+
record = atomic_read(FULL_RECORD_LENGTH, off)
|
540
|
+
return nil unless record && record.size == FULL_RECORD_LENGTH
|
538
541
|
|
539
542
|
# The country code is the first byte:
|
540
543
|
code = record[0]
|
@@ -656,11 +659,8 @@ class GeoIP
|
|
656
659
|
throw "Invalid GeoIP database type, can't look up Organization/ISP by IP"
|
657
660
|
end
|
658
661
|
pos = seek_record(ipnum);
|
659
|
-
|
660
|
-
|
661
|
-
@file.seek(pos + (2*@record_length-1) * @databaseSegments[0])
|
662
|
-
record = @file.read(MAX_ORG_RECORD_LENGTH)
|
663
|
-
}
|
662
|
+
off = pos + (2*@record_length-1) * @databaseSegments[0]
|
663
|
+
record = atomic_read(MAX_ORG_RECORD_LENGTH, off)
|
664
664
|
record = record.sub(/\000.*/n, '')
|
665
665
|
record
|
666
666
|
end
|
@@ -687,11 +687,8 @@ class GeoIP
|
|
687
687
|
throw "Invalid GeoIP database type, can't look up ASN by IP"
|
688
688
|
end
|
689
689
|
pos = seek_record(ipnum);
|
690
|
-
|
691
|
-
|
692
|
-
@file.seek(pos + (2*@record_length-1) * @databaseSegments[0])
|
693
|
-
record = @file.read(MAX_ASN_RECORD_LENGTH)
|
694
|
-
}
|
690
|
+
off = pos + (2*@record_length-1) * @databaseSegments[0]
|
691
|
+
record = atomic_read(MAX_ASN_RECORD_LENGTH, off)
|
695
692
|
record = record.sub(/\000.*/n, '')
|
696
693
|
|
697
694
|
if record =~ /^(AS\d+)\s(.*)$/
|
@@ -740,10 +737,8 @@ class GeoIP
|
|
740
737
|
offset = 0
|
741
738
|
mask = 0x80000000
|
742
739
|
31.downto(0) { |depth|
|
743
|
-
|
744
|
-
|
745
|
-
@file.read(@record_length * 2);
|
746
|
-
}
|
740
|
+
off = @record_length * 2 * offset
|
741
|
+
buf = atomic_read(@record_length * 2, off)
|
747
742
|
buf.slice!(0...@record_length) if ((ipnum & mask) != 0)
|
748
743
|
offset = le_to_ui(buf[0...@record_length].unpack("C*"))
|
749
744
|
return offset if (offset >= @databaseSegments[0])
|
@@ -762,6 +757,22 @@ class GeoIP
|
|
762
757
|
def le_to_ui(s)
|
763
758
|
be_to_ui(s.reverse)
|
764
759
|
end
|
760
|
+
|
761
|
+
# reads +length+ bytes from +offset+ as atomically as possible
|
762
|
+
# if IO.pread is available, it'll use that (making it both multithread
|
763
|
+
# and multiprocess-safe). Otherwise we'll use a mutex to synchronize
|
764
|
+
# access (only providing protection against multiple threads, but not
|
765
|
+
# file descriptors shared across multiple processes).
|
766
|
+
def atomic_read(length, offset)
|
767
|
+
if @mutex
|
768
|
+
@mutex.synchronize {
|
769
|
+
@file.seek(offset)
|
770
|
+
@file.read(length)
|
771
|
+
}
|
772
|
+
else
|
773
|
+
IO.pread(@file.fileno, length, offset)
|
774
|
+
end
|
775
|
+
end
|
765
776
|
end
|
766
777
|
|
767
778
|
if $0 == __FILE__
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: geoip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Clifford Heath
|
@@ -10,7 +10,7 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2009-11-
|
13
|
+
date: 2009-11-12 00:00:00 +00:00
|
14
14
|
default_executable:
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
@@ -21,7 +21,7 @@ dependencies:
|
|
21
21
|
requirements:
|
22
22
|
- - ">="
|
23
23
|
- !ruby/object:Gem::Version
|
24
|
-
version: 2.3.
|
24
|
+
version: 2.3.3
|
25
25
|
version:
|
26
26
|
description: |-
|
27
27
|
GeoIP searches a GeoIP database for a given host or IP address, and
|