geoip 0.8.5 → 0.8.6
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.
- 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
|