From c552869166e4c7d96bb97eb23c7d038aba06fa0a Mon Sep 17 00:00:00 2001 From: kazuya Date: Wed, 27 Mar 2013 10:12:48 +0900 Subject: [PATCH 1/4] Add IPv4Address and IPv6Address classes. --- ruby/trema/ipv4address.rb | 166 +++++++++++++++++++++++++++++++++ ruby/trema/ipv6address.rb | 162 ++++++++++++++++++++++++++++++++ spec/trema/ipv4address_spec.rb | 109 ++++++++++++++++++++++ spec/trema/ipv6address_spec.rb | 144 ++++++++++++++++++++++++++++ 4 files changed, 581 insertions(+) create mode 100644 ruby/trema/ipv4address.rb create mode 100644 ruby/trema/ipv6address.rb create mode 100644 spec/trema/ipv4address_spec.rb create mode 100644 spec/trema/ipv6address_spec.rb diff --git a/ruby/trema/ipv4address.rb b/ruby/trema/ipv4address.rb new file mode 100644 index 00000000..e01a3d83 --- /dev/null +++ b/ruby/trema/ipv4address.rb @@ -0,0 +1,166 @@ +# +# Copyright (C) 2008-2013 NEC Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + + +module Trema + # + # IPv4 Address + # + class IPv4Address + require "ipaddr" + + + # + # @return [IPAddr] value object instance of proxied IPAddr. + # + attr_reader :value + + + # + # Creates a {IP} instance object as a proxy to IPAddr class. + # + # @overload initialize(addr) + # + # @param [String] addr + # an IPv4 address specified either as a String or Number. + # + # @raise [ArgumentError] invalid address if supplied argument is invalid + # IPv4 address. + # + # @return [IP] self + # a proxy to IPAddr. + # + def initialize addr + if !addr.kind_of? String + @value = IPAddr.new( addr, Socket::AF_INET ) + else + @value = IPAddr.new( addr ) + end + end + + + # + # @return [String] the IPv4 address in its text representation. + # + def to_s + @value.to_s + end + + + # + # @return [Number] the IPv4 address in its numeric representation. + # + def to_i + @value.to_i + end + + + # + # @return [Array] + # an array of decimal numbers converted from IPv4 address. + # + def to_a + to_s.split( "." ).collect do | each | + each.to_i + end + end + alias :to_array :to_a + + + # + # @return [IPv4Address] + # Returns the IPv4 address masked with masklen. + # + def mask! masklen + @value = @value.mask( masklen ) + return self + end + alias :prefix! :mask! + + + # + # @return [IPv4Address] + # Returns the IPv4 address masked with masklen. + # + def mask masklen + self.clone.mask!( masklen ) + end + alias :prefix :mask + + + # + # @return [bool] + # Returns true if the address belongs to class A. + # + def class_a? + mask( 1 ).to_s == "0.0.0.0" + end + + + # + # @return [bool] + # Returns true if the address belongs to class B. + # + def class_b? + mask( 2 ).to_s == "128.0.0.0" + end + + + # + # @return [bool] + # Returns true if the address belongs to class C. + # + def class_c? + mask( 3 ).to_s == "192.0.0.0" + end + + + # + # @return [bool] + # Returns true if the address belongs to class D. + # + def class_d? + mask( 4 ).to_s == "224.0.0.0" + end + alias :multicast? :class_d? + + + # + # @return [bool] + # Returns true if the address belongs to class E. + # + def class_e? + mask( 4 ).to_s == "240.0.0.0" + end + + + # + # @return [bool] + # Returns true if the address is unicast address. + # + def unicast? + class_a? or class_b? or class_c? + end + end +end + + +### Local variables: +### mode: Ruby +### coding: utf-8-unix +### indent-tabs-mode: nil +### End: diff --git a/ruby/trema/ipv6address.rb b/ruby/trema/ipv6address.rb new file mode 100644 index 00000000..06c148bc --- /dev/null +++ b/ruby/trema/ipv6address.rb @@ -0,0 +1,162 @@ +# +# Copyright (C) 2008-2013 NEC Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + + +module Trema + # + # IPv6 Address + # + class IPv6Address + require "ipaddr" + + + # + # @return [IPAddr] value object instance of proxied IPAddr. + # + attr_reader :value + + + # + # Creates a {IPv6Address} instance object as a proxy to IPAddr class. + # + # @overload initialize(addr) + # + # @param [String] addr + # an IPv6 address specified either as a String or Number. + # + # @raise [ArgumentError] invalid address if supplied argument is invalid + # IPv6 address. + # + # @return [IP] self + # a proxy to IPAddr. + # + def initialize addr + if !addr.kind_of? String + @value = IPAddr.new( addr, Socket::AF_INET6 ) + else + @value = IPAddr.new( addr ) + end + end + + + # + # @return [String] the IPv6 address in its text representation. + # + def to_s + @value.to_s + end + + + # + # @return [Number] the IPv6 address in its numeric representation. + # + def to_i + @value.to_i + end + + + # + # @return [Array] + # an array of decimal numbers converted from IPv6 address. + # + def to_a + @value.hton.unpack( "C*" ) + end + alias :to_array :to_a + + + # + # @return [IPv6Address] + # Returns the IPv6 address masked with masklen. + # + def mask! masklen + @value = @value.mask( masklen ) + return self + end + alias :prefix! :mask! + + + # + # @return [IPv6Address] + # Returns the IPv6 address masked with masklen. + # + def mask masklen + self.clone.mask!( masklen ) + end + alias :prefix :mask + + # + # @return [bool] + # Returns true if the address is unspecified address (See rfc4291). + # + def unspecified? + to_s == "::" + end + + + # + # @return [bool] + # Returns true if the address is loopback address (See rfc 4291). + # + def loopback? + to_s == "::1" + end + + + # + # @return [bool] + # Returns true if the address is multicast address (See rfc4291). + # + def multicast? + mask( 8 ).to_s == "ff00::" + end + + + # + # @return [bool] + # Returns true if the address is link-local unicast address (See rfc4291). + # + def link_local_unicast? + mask( 10 ).to_s == "fe80::" + end + + + # + # @return [bool] + # Returns true if the address is global unicast address (See rfc4291). + # + def global_unicast? + not ( unspecified? or loopback? or multicast? or link_local_unicast? ) + end + + + # + # @return [bool] + # Returns true if the address is unicast address. + # + def unicast? + link_local_unicast? or global_unicast? + end + end +end + + +### Local variables: +### mode: Ruby +### coding: utf-8-unix +### indent-tabs-mode: nil +### End: diff --git a/spec/trema/ipv4address_spec.rb b/spec/trema/ipv4address_spec.rb new file mode 100644 index 00000000..ae66b4fb --- /dev/null +++ b/spec/trema/ipv4address_spec.rb @@ -0,0 +1,109 @@ +# +# Copyright (C) 2008-2013 NEC Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + + +require File.join( File.dirname( __FILE__ ), "..", "spec_helper" ) +require "trema/ipv4address" + + +module Trema + describe IPv4Address do + context "creates" do + subject { IPv4Address.new( ip_address ) } + + context %{when "192.168.1.1"} do + let( :ip_address ) { "192.168.1.1" } + + its( :to_s ) { should == "192.168.1.1" } + its( :to_i ) { should == 3232235777 } + its( :to_array ) { should == [ 0xc0, 0xa8, 0x01, 0x01 ] } + its( :class_a? ) { should == false } + its( :class_b? ) { should == false } + its( :class_c? ) { should == true } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } + end + + + context %{when "172.20.1.1"} do + let( :ip_address ) { "172.20.1.1" } + + its( :to_s ) { should == "172.20.1.1" } + its( :to_i ) { should == ( ( 172 * 256 + 20 ) * 256 + 1 ) * 256 + 1 } + its( :to_array ) { should == [ 0xac, 0x14, 0x01, 0x01 ] } + its( :class_a? ) { should == false } + its( :class_b? ) { should == true } + its( :class_c? ) { should == false } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } + end + end + + + context "masks" do + subject { IPv4Address.new( ip_address ).mask!( masklen ) } + + context %{when "10.1.1.1"} do + let( :ip_address ) { "10.1.1.1" } + let( :masklen ) { 8 } + + its( :to_s ) { should == "10.0.0.0" } + its( :to_i ) { should == 10 * 256 * 256 * 256 } + its( :to_array ) { should == [ 0x0a, 0x00, 0x00, 0x00 ] } + its( :class_a? ) { should == true } + its( :class_b? ) { should == false } + its( :class_c? ) { should == false } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } + end + end + + + context "is multicast address" do + subject { IPv4Address.new( ip_address ) } + + context %{when "234.1.1.1"} do + let( :ip_address ) { "234.1.1.1" } + + its( :to_s ) { should == "234.1.1.1" } + its( :to_i ) { should == ( ( 234 * 256 + 1 ) * 256 + 1 ) * 256 + 1 } + its( :to_array ) { should == [ 0xea, 0x01, 0x01, 0x01 ] } + its( :class_a? ) { should == false } + its( :class_b? ) { should == false } + its( :class_c? ) { should == false } + its( :class_d? ) { should == true } + its( :class_e? ) { should == false } + its( :unicast? ) { should == false } + its( :multicast? ) { should == true } + end + end + + end +end + + +### Local variables: +### mode: Ruby +### coding: utf-8-unix +### indent-tabs-mode: nil +### End: diff --git a/spec/trema/ipv6address_spec.rb b/spec/trema/ipv6address_spec.rb new file mode 100644 index 00000000..68456049 --- /dev/null +++ b/spec/trema/ipv6address_spec.rb @@ -0,0 +1,144 @@ +# +# Copyright (C) 2008-2013 NEC Corporation +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License, version 2, as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# + + +require File.join( File.dirname( __FILE__ ), "..", "spec_helper" ) +require "trema/ipv6address" + + +module Trema + describe IPv6Address do + context "creates" do + subject { IPv6Address.new( ipv6_address ) } + + context %{when "2001:db8::1"} do + let( :ipv6_address ) { "2001:db8::1" } + + its( :to_s ) { should == "2001:db8::1" } + its( :to_i ) { should == 42540766411282592856903984951653826561 } + its( :to_array ) { should == [ 0x20, 0x01, 0x0d, 0xb8, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == false } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == true } + its( :unicast? ) { should == true } + end + end + + + context "masks" do + subject { IPv6Address.new( ipv6_address ).prefix( prefixlen ) } + + context %{when "2001:db8:dead:beef::1"} do + let( :ipv6_address ) { "2001:db8:dead:beef::1" } + let( :prefixlen ) { 32 } + + its( :to_s ) { should == "2001:db8::" } + its( :to_i ) { should == 42540766411282592856903984951653826560 } + its( :to_array ) { should == [ 0x20, 0x01, 0x0d, 0xb8, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 ] } + end + end + + + context "addressing" do + subject { IPv6Address.new( ipv6_address ) } + + context %{when unspecified address} do + let( :ipv6_address ) { "::" } + + its( :to_s ) { should == "::" } + its( :to_i ) { should == 0 } + its( :to_array ) { should == [ 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 ] } + its( :unspecified? ) { should == true } + its( :loopback? ) { should == false } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == false } + end + + + context %{when loopback address} do + let( :ipv6_address ) { "::1" } + + its( :to_s ) { should == "::1" } + its( :to_i ) { should == 1 } + its( :to_array ) { should == [ 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == true } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == false } + end + + + context %{when multicast address} do + let( :ipv6_address ) { "ff02::1" } + + its( :to_s ) { should == "ff02::1" } + its( :to_array ) { should == [ 0xff, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == false } + its( :multicast? ) { should == true } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == false } + end + + + context %{when link-local address} do + let( :ipv6_address ) { "fe80::1:1" } + + its( :to_s ) { should == "fe80::1:1" } + its( :to_array ) { should == [ 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == false } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == true } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == true } + end + end + end +end + + +### Local variables: +### mode: Ruby +### coding: utf-8-unix +### indent-tabs-mode: nil +### End: From 81d703f1c121149f28885cf59d2746ba53d98e79 Mon Sep 17 00:00:00 2001 From: Kazuya Suzuki Date: Fri, 9 Aug 2013 10:59:06 +0900 Subject: [PATCH 2/4] Refactor ipv4address_spec.rb --- spec/trema/ipv4address_spec.rb | 162 +++++++++++++++++---------------- 1 file changed, 84 insertions(+), 78 deletions(-) diff --git a/spec/trema/ipv4address_spec.rb b/spec/trema/ipv4address_spec.rb index ae66b4fb..b8bfc361 100644 --- a/spec/trema/ipv4address_spec.rb +++ b/spec/trema/ipv4address_spec.rb @@ -20,85 +20,91 @@ require "trema/ipv4address" -module Trema - describe IPv4Address do - context "creates" do - subject { IPv4Address.new( ip_address ) } - - context %{when "192.168.1.1"} do - let( :ip_address ) { "192.168.1.1" } - - its( :to_s ) { should == "192.168.1.1" } - its( :to_i ) { should == 3232235777 } - its( :to_array ) { should == [ 0xc0, 0xa8, 0x01, 0x01 ] } - its( :class_a? ) { should == false } - its( :class_b? ) { should == false } - its( :class_c? ) { should == true } - its( :class_d? ) { should == false } - its( :class_e? ) { should == false } - its( :unicast? ) { should == true } - its( :multicast? ) { should == false } - end - - - context %{when "172.20.1.1"} do - let( :ip_address ) { "172.20.1.1" } - - its( :to_s ) { should == "172.20.1.1" } - its( :to_i ) { should == ( ( 172 * 256 + 20 ) * 256 + 1 ) * 256 + 1 } - its( :to_array ) { should == [ 0xac, 0x14, 0x01, 0x01 ] } - its( :class_a? ) { should == false } - its( :class_b? ) { should == true } - its( :class_c? ) { should == false } - its( :class_d? ) { should == false } - its( :class_e? ) { should == false } - its( :unicast? ) { should == true } - its( :multicast? ) { should == false } - end - end - - - context "masks" do - subject { IPv4Address.new( ip_address ).mask!( masklen ) } - - context %{when "10.1.1.1"} do - let( :ip_address ) { "10.1.1.1" } - let( :masklen ) { 8 } - - its( :to_s ) { should == "10.0.0.0" } - its( :to_i ) { should == 10 * 256 * 256 * 256 } - its( :to_array ) { should == [ 0x0a, 0x00, 0x00, 0x00 ] } - its( :class_a? ) { should == true } - its( :class_b? ) { should == false } - its( :class_c? ) { should == false } - its( :class_d? ) { should == false } - its( :class_e? ) { should == false } - its( :unicast? ) { should == true } - its( :multicast? ) { should == false } - end - end - - - context "is multicast address" do - subject { IPv4Address.new( ip_address ) } - - context %{when "234.1.1.1"} do - let( :ip_address ) { "234.1.1.1" } - - its( :to_s ) { should == "234.1.1.1" } - its( :to_i ) { should == ( ( 234 * 256 + 1 ) * 256 + 1 ) * 256 + 1 } - its( :to_array ) { should == [ 0xea, 0x01, 0x01, 0x01 ] } - its( :class_a? ) { should == false } - its( :class_b? ) { should == false } - its( :class_c? ) { should == false } - its( :class_d? ) { should == true } - its( :class_e? ) { should == false } - its( :unicast? ) { should == false } - its( :multicast? ) { should == true } - end - end - +describe IPv4Address, ".new( ip_address )" do + subject { IPv4Address.new( ip_address ) } + + + context "when 10.1.1.1" do + let( :ip_address ) { "10.1.1.1" } + + its( :to_s ) { should == "10.1.1.1" } + its( :to_i ) { should == ( ( 10 * 256 + 1 ) * 256 + 1 ) * 256 + 1 } + its( :to_array ) { should == [ 0x0a, 0x01, 0x01, 0x01 ] } + its( :class_a? ) { should == true } + its( :class_b? ) { should == false } + its( :class_c? ) { should == false } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } end + + + context "when 172.20.1.1" do + let( :ip_address ) { "172.20.1.1" } + + its( :to_s ) { should == "172.20.1.1" } + its( :to_i ) { should == ( ( 172 * 256 + 20 ) * 256 + 1 ) * 256 + 1 } + its( :to_array ) { should == [ 0xac, 0x14, 0x01, 0x01 ] } + its( :class_a? ) { should == false } + its( :class_b? ) { should == true } + its( :class_c? ) { should == false } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } + end + + + context "when 192.168.1.1" do + let( :ip_address ) { "192.168.1.1" } + + its( :to_s ) { should == "192.168.1.1" } + its( :to_i ) { should == 3232235777 } + its( :to_array ) { should == [ 0xc0, 0xa8, 0x01, 0x01 ] } + its( :class_a? ) { should == false } + its( :class_b? ) { should == false } + its( :class_c? ) { should == true } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } + end + + + context "when 234.1.1.1" do + let( :ip_address ) { "234.1.1.1" } + + its( :to_s ) { should == "234.1.1.1" } + its( :to_i ) { should == ( ( 234 * 256 + 1 ) * 256 + 1 ) * 256 + 1 } + its( :to_array ) { should == [ 0xea, 0x01, 0x01, 0x01 ] } + its( :class_a? ) { should == false } + its( :class_b? ) { should == false } + its( :class_c? ) { should == false } + its( :class_d? ) { should == true } + its( :class_e? ) { should == false } + its( :unicast? ) { should == false } + its( :multicast? ) { should == true } + end +end + + +describe IPv4Address, ".mask!( mask )" do + subject { IPv4Address.new( ip_address ).mask!( mask ) } + + let( :ip_address ) { "10.1.1.1" } + let( :mask ) { 8 } + + its( :to_s ) { should == "10.0.0.0" } + its( :to_i ) { should == 10 * 256 * 256 * 256 } + its( :to_array ) { should == [ 0x0a, 0x00, 0x00, 0x00 ] } + its( :class_a? ) { should == true } + its( :class_b? ) { should == false } + its( :class_c? ) { should == false } + its( :class_d? ) { should == false } + its( :class_e? ) { should == false } + its( :unicast? ) { should == true } + its( :multicast? ) { should == false } end From 56aa8981d4e4ffe8a44117f2994cbf8d767d03e6 Mon Sep 17 00:00:00 2001 From: Kazuya Suzuki Date: Fri, 9 Aug 2013 11:15:34 +0900 Subject: [PATCH 3/4] Refactor ipv6address_spec.rb --- spec/trema/ipv6address_spec.rb | 217 ++++++++++++++++----------------- 1 file changed, 104 insertions(+), 113 deletions(-) diff --git a/spec/trema/ipv6address_spec.rb b/spec/trema/ipv6address_spec.rb index 68456049..770ff8a3 100644 --- a/spec/trema/ipv6address_spec.rb +++ b/spec/trema/ipv6address_spec.rb @@ -20,120 +20,111 @@ require "trema/ipv6address" -module Trema - describe IPv6Address do - context "creates" do - subject { IPv6Address.new( ipv6_address ) } - - context %{when "2001:db8::1"} do - let( :ipv6_address ) { "2001:db8::1" } - - its( :to_s ) { should == "2001:db8::1" } - its( :to_i ) { should == 42540766411282592856903984951653826561 } - its( :to_array ) { should == [ 0x20, 0x01, 0x0d, 0xb8, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 ] } - its( :unspecified? ) { should == false } - its( :loopback? ) { should == false } - its( :multicast? ) { should == false } - its( :link_local_unicast? ) { should == false } - its( :global_unicast? ) { should == true } - its( :unicast? ) { should == true } - end - end - - - context "masks" do - subject { IPv6Address.new( ipv6_address ).prefix( prefixlen ) } - - context %{when "2001:db8:dead:beef::1"} do - let( :ipv6_address ) { "2001:db8:dead:beef::1" } - let( :prefixlen ) { 32 } - - its( :to_s ) { should == "2001:db8::" } - its( :to_i ) { should == 42540766411282592856903984951653826560 } - its( :to_array ) { should == [ 0x20, 0x01, 0x0d, 0xb8, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 ] } - end - end - - - context "addressing" do - subject { IPv6Address.new( ipv6_address ) } - - context %{when unspecified address} do - let( :ipv6_address ) { "::" } - - its( :to_s ) { should == "::" } - its( :to_i ) { should == 0 } - its( :to_array ) { should == [ 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 ] } - its( :unspecified? ) { should == true } - its( :loopback? ) { should == false } - its( :multicast? ) { should == false } - its( :link_local_unicast? ) { should == false } - its( :global_unicast? ) { should == false } - its( :unicast? ) { should == false } - end - - - context %{when loopback address} do - let( :ipv6_address ) { "::1" } - - its( :to_s ) { should == "::1" } - its( :to_i ) { should == 1 } - its( :to_array ) { should == [ 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 ] } - its( :unspecified? ) { should == false } - its( :loopback? ) { should == true } - its( :multicast? ) { should == false } - its( :link_local_unicast? ) { should == false } - its( :global_unicast? ) { should == false } - its( :unicast? ) { should == false } - end - - - context %{when multicast address} do - let( :ipv6_address ) { "ff02::1" } - - its( :to_s ) { should == "ff02::1" } - its( :to_array ) { should == [ 0xff, 0x02, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x01 ] } - its( :unspecified? ) { should == false } - its( :loopback? ) { should == false } - its( :multicast? ) { should == true } - its( :link_local_unicast? ) { should == false } - its( :global_unicast? ) { should == false } - its( :unicast? ) { should == false } - end - - - context %{when link-local address} do - let( :ipv6_address ) { "fe80::1:1" } - - its( :to_s ) { should == "fe80::1:1" } - its( :to_array ) { should == [ 0xfe, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x00, 0x01 ] } - its( :unspecified? ) { should == false } - its( :loopback? ) { should == false } - its( :multicast? ) { should == false } - its( :link_local_unicast? ) { should == true } - its( :global_unicast? ) { should == false } - its( :unicast? ) { should == true } - end - end +describe IPv6Address, ".new( ipv6_address )" do + subject { IPv6Address.new( ipv6_address ) } + + + context "when unspecified" do + let( :ipv6_address ) { "::" } + + its( :to_s ) { should == "::" } + its( :to_i ) { should == 0 } + its( :to_array ) { should == [ 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 ] } + its( :unspecified? ) { should == true } + its( :loopback? ) { should == false } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == false } end + + + context "when loopback" do + let( :ipv6_address ) { "::1" } + + its( :to_s ) { should == "::1" } + its( :to_i ) { should == 1 } + its( :to_array ) { should == [ 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == true } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == false } + end + + + context "when multicast" do + let( :ipv6_address ) { "ff02::1" } + + its( :to_s ) { should == "ff02::1" } + its( :to_array ) { should == [ 0xff, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == false } + its( :multicast? ) { should == true } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == false } + end + + + context "when link-local" do + let( :ipv6_address ) { "fe80::1:1" } + + its( :to_s ) { should == "fe80::1:1" } + its( :to_array ) { should == [ 0xfe, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == false } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == true } + its( :global_unicast? ) { should == false } + its( :unicast? ) { should == true } + end + + + context "when global unicast" do + let( :ipv6_address ) { "2001:db8::1" } + + its( :to_s ) { should == "2001:db8::1" } + its( :to_i ) { should == 42540766411282592856903984951653826561 } + its( :to_array ) { should == [ 0x20, 0x01, 0x0d, 0xb8, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x01 ] } + its( :unspecified? ) { should == false } + its( :loopback? ) { should == false } + its( :multicast? ) { should == false } + its( :link_local_unicast? ) { should == false } + its( :global_unicast? ) { should == true } + its( :unicast? ) { should == true } + end +end + + +describe IPv6Address, ".prefix( prefixlen )" do + subject { IPv6Address.new( ipv6_address ).prefix( prefixlen ) } + + let( :ipv6_address ) { "2001:db8:dead:beef::1" } + let( :prefixlen ) { 32 } + + its( :to_s ) { should == "2001:db8::" } + its( :to_i ) { should == 42540766411282592856903984951653826560 } + its( :to_array ) { should == [ 0x20, 0x01, 0x0d, 0xb8, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00 ] } end From 25b8d55e373546236aa4144ea2da2e730b404bfb Mon Sep 17 00:00:00 2001 From: Kazuya Suzuki Date: Fri, 9 Aug 2013 11:43:59 +0900 Subject: [PATCH 4/4] Refactor IPv4Address and IPv6Address classes --- ruby/trema/ipv4address.rb | 54 +++++++++++++++++++-------------------- ruby/trema/ipv6address.rb | 37 +++++++++++++-------------- 2 files changed, 44 insertions(+), 47 deletions(-) diff --git a/ruby/trema/ipv4address.rb b/ruby/trema/ipv4address.rb index e01a3d83..4049c573 100644 --- a/ruby/trema/ipv4address.rb +++ b/ruby/trema/ipv4address.rb @@ -22,20 +22,22 @@ module Trema # class IPv4Address require "ipaddr" + require "forwardable" + extend Forwardable + - # # @return [IPAddr] value object instance of proxied IPAddr. # attr_reader :value - - + + # # Creates a {IP} instance object as a proxy to IPAddr class. # - # @overload initialize(addr) + # @overload initialize(ipv4address) # - # @param [String] addr + # @param [String] ipv4address # an IPv4 address specified either as a String or Number. # # @raise [ArgumentError] invalid address if supplied argument is invalid @@ -44,30 +46,26 @@ class IPv4Address # @return [IP] self # a proxy to IPAddr. # - def initialize addr - if !addr.kind_of? String - @value = IPAddr.new( addr, Socket::AF_INET ) + def initialize ipv4address + if !ipv4address.kind_of? String + @value = IPAddr.new( ipv4address, Socket::AF_INET ) else - @value = IPAddr.new( addr ) + @value = IPAddr.new( ipv4address ) end end - - + + # # @return [String] the IPv4 address in its text representation. # - def to_s - @value.to_s - end - + def_delegator :value, :to_s + # # @return [Number] the IPv4 address in its numeric representation. # - def to_i - @value.to_i - end - + def_delegator :value, :to_i + # # @return [Array] @@ -79,12 +77,12 @@ def to_a end end alias :to_array :to_a - + # # @return [IPv4Address] # Returns the IPv4 address masked with masklen. - # + # def mask! masklen @value = @value.mask( masklen ) return self @@ -95,7 +93,7 @@ def mask! masklen # # @return [IPv4Address] # Returns the IPv4 address masked with masklen. - # + # def mask masklen self.clone.mask!( masklen ) end @@ -103,7 +101,7 @@ def mask masklen # - # @return [bool] + # @return [bool] # Returns true if the address belongs to class A. # def class_a? @@ -112,7 +110,7 @@ def class_a? # - # @return [bool] + # @return [bool] # Returns true if the address belongs to class B. # def class_b? @@ -121,7 +119,7 @@ def class_b? # - # @return [bool] + # @return [bool] # Returns true if the address belongs to class C. # def class_c? @@ -130,7 +128,7 @@ def class_c? # - # @return [bool] + # @return [bool] # Returns true if the address belongs to class D. # def class_d? @@ -140,7 +138,7 @@ def class_d? # - # @return [bool] + # @return [bool] # Returns true if the address belongs to class E. # def class_e? @@ -149,7 +147,7 @@ def class_e? # - # @return [bool] + # @return [bool] # Returns true if the address is unicast address. # def unicast? diff --git a/ruby/trema/ipv6address.rb b/ruby/trema/ipv6address.rb index 06c148bc..f5f3fab8 100644 --- a/ruby/trema/ipv6address.rb +++ b/ruby/trema/ipv6address.rb @@ -22,6 +22,8 @@ module Trema # class IPv6Address require "ipaddr" + require "forwardable" + extend Forwardable # @@ -33,9 +35,9 @@ class IPv6Address # # Creates a {IPv6Address} instance object as a proxy to IPAddr class. # - # @overload initialize(addr) + # @overload initialize(ipv6address) # - # @param [String] addr + # @param [String] ipv6address # an IPv6 address specified either as a String or Number. # # @raise [ArgumentError] invalid address if supplied argument is invalid @@ -44,11 +46,11 @@ class IPv6Address # @return [IP] self # a proxy to IPAddr. # - def initialize addr - if !addr.kind_of? String - @value = IPAddr.new( addr, Socket::AF_INET6 ) + def initialize ipv6address + if !ipv6address.kind_of? String + @value = IPAddr.new( ipv6address, Socket::AF_INET6 ) else - @value = IPAddr.new( addr ) + @value = IPAddr.new( ipv6address ) end end @@ -56,17 +58,13 @@ def initialize addr # # @return [String] the IPv6 address in its text representation. # - def to_s - @value.to_s - end + def_delegator :value, :to_s # # @return [Number] the IPv6 address in its numeric representation. # - def to_i - @value.to_i - end + def_delegator :value, :to_i # @@ -85,11 +83,11 @@ def to_a # def mask! masklen @value = @value.mask( masklen ) - return self + self end alias :prefix! :mask! - + # # @return [IPv6Address] # Returns the IPv6 address masked with masklen. @@ -99,6 +97,7 @@ def mask masklen end alias :prefix :mask + # # @return [bool] # Returns true if the address is unspecified address (See rfc4291). @@ -116,7 +115,7 @@ def loopback? to_s == "::1" end - + # # @return [bool] # Returns true if the address is multicast address (See rfc4291). @@ -124,7 +123,7 @@ def loopback? def multicast? mask( 8 ).to_s == "ff00::" end - + # # @return [bool] @@ -134,16 +133,16 @@ def link_local_unicast? mask( 10 ).to_s == "fe80::" end - + # # @return [bool] # Returns true if the address is global unicast address (See rfc4291). - # + # def global_unicast? not ( unspecified? or loopback? or multicast? or link_local_unicast? ) end - + # # @return [bool] # Returns true if the address is unicast address.