warden/lib/warden/network.rb
# coding: UTF-8
require "yajl"
module Warden
module Network
class Octets
attr_reader :v
include Comparable
def <=>(other)
v <=> Octets.new(other).v
end
def eql?(other)
v == Octets.new(other).v
end
def hash
v.hash
end
def initialize(v, *args)
if args.empty?
if v.kind_of?(Integer)
@v = v
elsif v.kind_of?(Octets)
@v = v.v
elsif v.kind_of?(String)
if v.match(/[0-9a-f]{8}/)
@v = v.to_i(16)
else
@v = to_integer(v.split("."))
end
else
raise "invalid value"
end
else
@v = to_integer([v] + args)
end
raise "invalid address" if @v != (@v & (2 ** 32 - 1))
end
def to_octets
[(v >> 24) & 255, (v >> 16) & 255, (v >> 8) & 255, (v >> 0) & 255]
end
def to_hex
to_octets.map { |e| "%02x" % e }.join
end
def to_human
to_octets.join(".")
end
def to_json
Yajl::Encoder.encode(to_human)
end
protected
def to_integer(octets)
octets.inject(0) { |a,e| a * 256 + e.to_i }
end
end
class Netmask < Octets
def initialize(*args)
super
raise "invalid netmask" unless valid?
end
def size
(~v & (2 ** 32 - 1)) + 1
end
protected
# Netmask size should be a power of 2
def valid?
((size - 1) & size) == 0
end
end
class Address < Octets
def network(netmask)
Address.new(v & netmask.v)
end
def +(other)
case other
when Fixnum
Address.new(v + other)
when Netmask
Address.new(v + other.size)
else
raise "cannot add #{other.class}"
end
end
end
end
end