mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* lib/resolv.rb: Support LOC resources.
[ruby-core:23361] [Feature #1436] by JB Smith. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@40162 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
5427a5df05
commit
c4d8cc4eae
3 changed files with 315 additions and 1 deletions
|
@ -1,3 +1,8 @@
|
|||
Sat Apr 6 23:40:40 2013 Tanaka Akira <akr@fsij.org>
|
||||
|
||||
* lib/resolv.rb: Support LOC resources.
|
||||
[ruby-core:23361] [Feature #1436] by JB Smith.
|
||||
|
||||
Sat Apr 6 23:38:09 2013 Naohisa Goto <ngotogenome@gmail.com>
|
||||
|
||||
* addr2line.c: quad_t and u_quad_t is not available on Solaris.
|
||||
|
|
1
NEWS
1
NEWS
|
@ -50,6 +50,7 @@ with all sufficient information, see the ChangeLog file.
|
|||
* New methods:
|
||||
* Resolv::DNS.fetch_resource
|
||||
* One-shot multicast DNS support
|
||||
* Support LOC resources
|
||||
|
||||
* Rinda::RingServer, Rinda::RingFinger
|
||||
* Rinda now supports multicast sockets. See Rinda::RingServer and
|
||||
|
|
310
lib/resolv.rb
310
lib/resolv.rb
|
@ -1979,6 +1979,97 @@ class Resolv
|
|||
end
|
||||
end
|
||||
|
||||
##
|
||||
# Location resource
|
||||
|
||||
class LOC < Resource
|
||||
|
||||
TypeValue = 29 # :nodoc:
|
||||
|
||||
def initialize(version, ssize, hprecision, vprecision, latitude, longitude, altitude)
|
||||
@version = version
|
||||
@ssize = Resolv::LOC::Size.create(ssize)
|
||||
@hprecision = Resolv::LOC::Size.create(hprecision)
|
||||
@vprecision = Resolv::LOC::Size.create(vprecision)
|
||||
@latitude = Resolv::LOC::Coord.create(latitude)
|
||||
@longitude = Resolv::LOC::Coord.create(longitude)
|
||||
@altitude = Resolv::LOC::Alt.create(altitude)
|
||||
end
|
||||
|
||||
##
|
||||
# Returns the version value for this LOC record which should always be 00
|
||||
|
||||
attr_reader :version
|
||||
|
||||
##
|
||||
# The spherical size of this LOC
|
||||
# in meters using scientific notation as 2 integers of XeY
|
||||
|
||||
attr_reader :ssize
|
||||
|
||||
##
|
||||
# The horizontal precision using ssize type values
|
||||
# in meters using scientific notation as 2 integers of XeY
|
||||
# for precision use value/2 e.g. 2m = +/-1m
|
||||
|
||||
attr_reader :hprecision
|
||||
|
||||
##
|
||||
# The vertical precision using ssize type values
|
||||
# in meters using scientific notation as 2 integers of XeY
|
||||
# for precision use value/2 e.g. 2m = +/-1m
|
||||
|
||||
attr_reader :vprecision
|
||||
|
||||
##
|
||||
# The latitude for this LOC where 2**31 is the equator
|
||||
# in thousandths of an arc second as an unsigned 32bit integer
|
||||
|
||||
attr_reader :latitude
|
||||
|
||||
##
|
||||
# The longitude for this LOC where 2**31 is the prime meridian
|
||||
# in thousandths of an arc second as an unsigned 32bit integer
|
||||
|
||||
attr_reader :longitude
|
||||
|
||||
##
|
||||
# The altitude of the LOC above a reference sphere whose surface sits 100km below the WGS84 spheroid
|
||||
# in centimeters as an unsigned 32bit integer
|
||||
|
||||
attr_reader :altitude
|
||||
|
||||
|
||||
def encode_rdata(msg) # :nodoc:
|
||||
msg.put_bytes(@version)
|
||||
msg.put_bytes(@ssize.scalar)
|
||||
msg.put_bytes(@hprecision.scalar)
|
||||
msg.put_bytes(@vprecision.scalar)
|
||||
msg.put_bytes(@latitude.coordinates)
|
||||
msg.put_bytes(@longitude.coordinates)
|
||||
msg.put_bytes(@altitude.altitude)
|
||||
end
|
||||
|
||||
def self.decode_rdata(msg) # :nodoc:
|
||||
version = msg.get_bytes(1)
|
||||
ssize = msg.get_bytes(1)
|
||||
hprecision = msg.get_bytes(1)
|
||||
vprecision = msg.get_bytes(1)
|
||||
latitude = msg.get_bytes(4)
|
||||
longitude = msg.get_bytes(4)
|
||||
altitude = msg.get_bytes(4)
|
||||
return self.new(
|
||||
version,
|
||||
Resolv::LOC::Size.new(ssize),
|
||||
Resolv::LOC::Size.new(hprecision),
|
||||
Resolv::LOC::Size.new(vprecision),
|
||||
Resolv::LOC::Coord.new(latitude,"lat"),
|
||||
Resolv::LOC::Coord.new(longitude,"lon"),
|
||||
Resolv::LOC::Alt.new(altitude)
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
##
|
||||
# A Query type requesting any RR.
|
||||
|
||||
|
@ -1987,7 +2078,7 @@ class Resolv
|
|||
end
|
||||
|
||||
ClassInsensitiveTypes = [ # :nodoc:
|
||||
NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, ANY
|
||||
NS, CNAME, SOA, PTR, HINFO, MINFO, MX, TXT, LOC, ANY
|
||||
]
|
||||
|
||||
##
|
||||
|
@ -2489,6 +2580,223 @@ class Resolv
|
|||
|
||||
end
|
||||
|
||||
module LOC
|
||||
|
||||
##
|
||||
# A Resolv::LOC::Size
|
||||
|
||||
class Size
|
||||
|
||||
Regex = /^(\d+\.*\d*)[m]$/
|
||||
|
||||
##
|
||||
# Creates a new LOC::Size from +arg+ which may be:
|
||||
#
|
||||
# LOC::Size:: returns +arg+.
|
||||
# String:: +arg+ must match the LOC::Size::Regex constant
|
||||
|
||||
def self.create(arg)
|
||||
case arg
|
||||
when Size
|
||||
return arg
|
||||
when String
|
||||
scalar = ''
|
||||
if Regex =~ arg
|
||||
scalar = [(($1.to_f*(1e2)).to_i.to_s[0].to_i*(2**4)+(($1.to_f*(1e2)).to_i.to_s.length-1))].pack("C")
|
||||
else
|
||||
raise ArgumentError.new("not a properly formed Size string: " + arg)
|
||||
end
|
||||
return Size.new(scalar)
|
||||
else
|
||||
raise ArgumentError.new("cannot interpret as Size: #{arg.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(scalar)
|
||||
@scalar = scalar
|
||||
end
|
||||
|
||||
##
|
||||
# The raw size
|
||||
|
||||
attr_reader :scalar
|
||||
|
||||
def to_s # :nodoc:
|
||||
s = @scalar.unpack("H2").join.to_s
|
||||
return ((s[0].to_i)*(10**(s[1].to_i-2))).to_s << "m"
|
||||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
return "#<#{self.class} #{self.to_s}>"
|
||||
end
|
||||
|
||||
def ==(other) # :nodoc:
|
||||
return @scalar == other.scalar
|
||||
end
|
||||
|
||||
def eql?(other) # :nodoc:
|
||||
return self == other
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
return @scalar.hash
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# A Resolv::LOC::Coord
|
||||
|
||||
class Coord
|
||||
|
||||
Regex = /^(\d+)\s(\d+)\s(\d+\.\d+)\s([NESW])$/
|
||||
|
||||
##
|
||||
# Creates a new LOC::Coord from +arg+ which may be:
|
||||
#
|
||||
# LOC::Coord:: returns +arg+.
|
||||
# String:: +arg+ must match the LOC::Coord::Regex constant
|
||||
|
||||
def self.create(arg)
|
||||
case arg
|
||||
when Coord
|
||||
return arg
|
||||
when String
|
||||
coordinates = ''
|
||||
if Regex =~ arg && $1<180
|
||||
hemi = ($4[/([NE])/,1]) || ($4[/([SW])/,1]) ? 1 : -1
|
||||
coordinates = [(($1.to_i*(36e5))+($2.to_i*(6e4))+($3.to_f*(1e3)))*hemi+(2**31)].pack("N")
|
||||
(orientation ||= '') << $4[[/NS/],1] ? 'lat' : 'lon'
|
||||
else
|
||||
raise ArgumentError.new("not a properly formed Coord string: " + arg)
|
||||
end
|
||||
return Coord.new(coordinates,orientation)
|
||||
else
|
||||
raise ArgumentError.new("cannot interpret as Coord: #{arg.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(coordinates,orientation)
|
||||
unless coordinates.kind_of?(String)
|
||||
raise ArgumentError.new("Coord must be a 32bit unsigned integer in hex format: #{coordinates.inspect}")
|
||||
end
|
||||
unless orientation.kind_of?(String) && orientation[/^lon$|^lat$/]
|
||||
raise ArgumentError.new('Coord expects orientation to be a String argument of "lat" or "lon"')
|
||||
end
|
||||
@coordinates = coordinates
|
||||
@orientation = orientation
|
||||
end
|
||||
|
||||
##
|
||||
# The raw coordinates
|
||||
|
||||
attr_reader :coordinates
|
||||
|
||||
## The orientation of the hemisphere as 'lat' or 'lon'
|
||||
|
||||
attr_reader :orientation
|
||||
|
||||
def to_s # :nodoc:
|
||||
c = @coordinates.unpack("N").join.to_i
|
||||
val = (c - (2**31)).abs
|
||||
fracsecs = (val % 1e3).to_i.to_s
|
||||
val = val / 1e3
|
||||
secs = (val % 60).to_i.to_s
|
||||
val = val / 60
|
||||
mins = (val % 60).to_i.to_s
|
||||
degs = (val / 60).to_i.to_s
|
||||
posi = (c >= 2**31)
|
||||
case posi
|
||||
when true
|
||||
hemi = @orientation[/^lat$/] ? "N" : "E"
|
||||
else
|
||||
hemi = @orientation[/^lon$/] ? "W" : "S"
|
||||
end
|
||||
return degs << " " << mins << " " << secs << "." << fracsecs << " " << hemi
|
||||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
return "#<#{self.class} #{self.to_s}>"
|
||||
end
|
||||
|
||||
def ==(other) # :nodoc:
|
||||
return @coordinates == other.coordinates
|
||||
end
|
||||
|
||||
def eql?(other) # :nodoc:
|
||||
return self == other
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
return @coordinates.hash
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# A Resolv::LOC::Alt
|
||||
|
||||
class Alt
|
||||
|
||||
Regex = /^([+-]*\d+\.*\d*)[m]$/
|
||||
|
||||
##
|
||||
# Creates a new LOC::Alt from +arg+ which may be:
|
||||
#
|
||||
# LOC::Alt:: returns +arg+.
|
||||
# String:: +arg+ must match the LOC::Alt::Regex constant
|
||||
|
||||
def self.create(arg)
|
||||
case arg
|
||||
when Alt
|
||||
return arg
|
||||
when String
|
||||
altitude = ''
|
||||
if Regex =~ arg
|
||||
altitude = [($1.to_f*(1e2))+(1e7)].pack("N")
|
||||
else
|
||||
raise ArgumentError.new("not a properly formed Alt string: " + arg)
|
||||
end
|
||||
return Alt.new(altitude)
|
||||
else
|
||||
raise ArgumentError.new("cannot interpret as Alt: #{arg.inspect}")
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(altitude)
|
||||
@altitude = altitude
|
||||
end
|
||||
|
||||
##
|
||||
# The raw altitude
|
||||
|
||||
attr_reader :altitude
|
||||
|
||||
def to_s # :nodoc:
|
||||
a = @altitude.unpack("N").join.to_i
|
||||
return ((a.to_f/1e2)-1e5).to_s + "m"
|
||||
end
|
||||
|
||||
def inspect # :nodoc:
|
||||
return "#<#{self.class} #{self.to_s}>"
|
||||
end
|
||||
|
||||
def ==(other) # :nodoc:
|
||||
return @altitude == other.altitude
|
||||
end
|
||||
|
||||
def eql?(other) # :nodoc:
|
||||
return self == other
|
||||
end
|
||||
|
||||
def hash # :nodoc:
|
||||
return @altitude.hash
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
##
|
||||
# Default resolver to use for Resolv class methods.
|
||||
|
||||
|
|
Loading…
Reference in a new issue