1
0
Fork 0
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:
akr 2013-04-06 14:52:48 +00:00
parent 5427a5df05
commit c4d8cc4eae
3 changed files with 315 additions and 1 deletions

View file

@ -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
View file

@ -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

View file

@ -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.