packetfu 1.0.0 → 1.0.2.pre
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/LICENSE +1 -1
- data/README +3 -0
- data/examples/packetfu-shell.rb +5 -3
- data/lib/packetfu.rb +48 -63
- data/lib/packetfu/packet.rb +144 -206
- data/lib/packetfu/pcap.rb +5 -5
- data/lib/packetfu/{arp.rb → protos/arp.rb} +17 -2
- data/lib/packetfu/{eth.rb → protos/eth.rb} +15 -4
- data/lib/packetfu/protos/hsrp.rb +200 -0
- data/lib/packetfu/{icmp.rb → protos/icmp.rb} +20 -1
- data/lib/packetfu/{invalid.rb → protos/invalid.rb} +14 -0
- data/lib/packetfu/{ip.rb → protos/ip.rb} +29 -0
- data/lib/packetfu/{ipv6.rb → protos/ipv6.rb} +16 -1
- data/lib/packetfu/{tcp.rb → protos/tcp.rb} +26 -2
- data/lib/packetfu/{udp.rb → protos/udp.rb} +25 -1
- data/lib/packetfu/structfu.rb +10 -3
- data/lib/packetfu/version.rb +50 -0
- data/test/all_tests.rb +33 -30
- data/test/arp_test.pcap +0 -0
- data/test/eth_test.pcap +0 -0
- data/test/icmp_test.pcap +0 -0
- data/test/ip_test.pcap +0 -0
- data/test/packetfu_spec.rb +70 -0
- data/test/sample-ipv6.pcap +0 -0
- data/test/sample_hsrp_pcapr.cap +0 -0
- data/test/structfu_spec.rb +338 -0
- data/test/tcp_test.pcap +0 -0
- data/test/test_arp.rb +0 -0
- data/test/test_eth.rb +2 -1
- data/test/test_hsrp.rb +71 -0
- data/test/test_icmp.rb +0 -0
- data/test/test_ip6.rb +0 -0
- data/test/test_octets.rb +0 -0
- data/test/test_packet.rb +137 -3
- data/test/test_structfu.rb +0 -0
- data/test/test_tcp.rb +0 -0
- data/test/test_udp.rb +0 -0
- data/test/udp_test.pcap +0 -0
- metadata +52 -20
- data/TODO +0 -25
@@ -127,7 +127,31 @@ module PacketFu
|
|
127
127
|
class UDPPacket < Packet
|
128
128
|
|
129
129
|
attr_accessor :eth_header, :ip_header, :udp_header
|
130
|
-
|
130
|
+
|
131
|
+
def self.can_parse?(str)
|
132
|
+
return false unless str.size >= 54
|
133
|
+
return false unless EthPacket.can_parse? str
|
134
|
+
return false unless IPPacket.can_parse? str
|
135
|
+
return false unless str[23,1] == "\x11"
|
136
|
+
return true
|
137
|
+
end
|
138
|
+
|
139
|
+
def read(str=nil, args={})
|
140
|
+
raise "Cannot parse `#{str}'" unless self.class.can_parse?(str)
|
141
|
+
@eth_header.read(str)
|
142
|
+
@ip_header.read(str[14,str.size])
|
143
|
+
@eth_header.body = @ip_header
|
144
|
+
if args[:strip]
|
145
|
+
udp_len = str[16,2].unpack("n")[0] - 20
|
146
|
+
@udp_header.read(str[14+(@ip_header.ip_hlen),udp_len])
|
147
|
+
else
|
148
|
+
@udp_header.read(str[14+(@ip_header.ip_hlen),str.size])
|
149
|
+
end
|
150
|
+
@ip_header.body = @udp_header
|
151
|
+
super(args)
|
152
|
+
self
|
153
|
+
end
|
154
|
+
|
131
155
|
def initialize(args={})
|
132
156
|
@eth_header = EthHeader.new(args).read(args[:eth])
|
133
157
|
@ip_header = IPHeader.new(args).read(args[:ip])
|
data/lib/packetfu/structfu.rb
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
# to create meaningful binary data.
|
3
3
|
|
4
4
|
module StructFu
|
5
|
+
|
5
6
|
# Normally, self.size and self.length will refer to the Struct
|
6
7
|
# size as an array. It's a hassle to redefine, so this introduces some
|
7
8
|
# shorthand to get at the size of the resultant string.
|
@@ -106,6 +107,7 @@ module StructFu
|
|
106
107
|
|
107
108
|
# Returns a two byte value as a packed string.
|
108
109
|
def to_s
|
110
|
+
@packstr = (self.e == :big) ? "n" : "v"
|
109
111
|
[(self.v || self.d)].pack(@packstr)
|
110
112
|
end
|
111
113
|
|
@@ -113,10 +115,12 @@ module StructFu
|
|
113
115
|
|
114
116
|
# Int16be is a two byte value in big-endian format.
|
115
117
|
class Int16be < Int16
|
118
|
+
undef :endian=
|
116
119
|
end
|
117
120
|
|
118
121
|
# Int16le is a two byte value in little-endian format.
|
119
122
|
class Int16le < Int16
|
123
|
+
undef :endian=
|
120
124
|
def initialize(v=nil, e=:little)
|
121
125
|
super(v,e)
|
122
126
|
@packstr = (self.e == :big) ? "n" : "v"
|
@@ -132,6 +136,7 @@ module StructFu
|
|
132
136
|
|
133
137
|
# Returns a four byte value as a packed string.
|
134
138
|
def to_s
|
139
|
+
@packstr = (self.e == :big) ? "N" : "V"
|
135
140
|
[(self.v || self.d)].pack(@packstr)
|
136
141
|
end
|
137
142
|
|
@@ -139,10 +144,12 @@ module StructFu
|
|
139
144
|
|
140
145
|
# Int32be is a four byte value in big-endian format.
|
141
146
|
class Int32be < Int32
|
147
|
+
undef :endian=
|
142
148
|
end
|
143
149
|
|
144
150
|
# Int32le is a four byte value in little-endian format.
|
145
151
|
class Int32le < Int32
|
152
|
+
undef :endian=
|
146
153
|
def initialize(v=nil, e=:little)
|
147
154
|
super(v,e)
|
148
155
|
end
|
@@ -166,11 +173,11 @@ module StructFu
|
|
166
173
|
class IntString < Struct.new(:int, :string, :mode)
|
167
174
|
|
168
175
|
def initialize(string='',int=Int8,mode=nil)
|
169
|
-
|
170
|
-
raise StandardError, "Invalid length (#{int.inspect}) associated with this String."
|
171
|
-
else
|
176
|
+
if int < Int
|
172
177
|
super(int.new,string,mode)
|
173
178
|
calc
|
179
|
+
else
|
180
|
+
raise "IntStrings need a StructFu::Int for a length."
|
174
181
|
end
|
175
182
|
end
|
176
183
|
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module PacketFu
|
2
|
+
|
3
|
+
# Version 1.0.0 was released July 31, 2010
|
4
|
+
# Version 1.0.1 is unreleased.
|
5
|
+
VERSION = "1.0.2"
|
6
|
+
|
7
|
+
def self.version
|
8
|
+
VERSION
|
9
|
+
end
|
10
|
+
|
11
|
+
# Returns the version in a binary format for easy comparisons.
|
12
|
+
def self.binarize_version(str)
|
13
|
+
if(str.respond_to?(:split) && str =~ /^[0-9]+(\.([0-9]+)(\.[0-9]+)?)?\..+$/)
|
14
|
+
bin_major,bin_minor,bin_teeny = str.split(/\x2e/).map {|x| x.to_i}
|
15
|
+
bin_version = (bin_major.to_i << 16) + (bin_minor.to_i << 8) + bin_teeny.to_i
|
16
|
+
else
|
17
|
+
raise ArgumentError, "Compare version malformed. Should be \x22x.y.z\x22"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Returns true if the version is equal to or greater than the compare version.
|
22
|
+
# If the current version of PacketFu is "0.3.1" for example:
|
23
|
+
#
|
24
|
+
# PacketFu.at_least? "0" # => true
|
25
|
+
# PacketFu.at_least? "0.2.9" # => true
|
26
|
+
# PacketFu.at_least? "0.3" # => true
|
27
|
+
# PacketFu.at_least? "1" # => true after 1.0's release
|
28
|
+
# PacketFu.at_least? "1.12" # => false
|
29
|
+
# PacketFu.at_least? "2" # => false
|
30
|
+
def self.at_least?(str)
|
31
|
+
this_version = binarize_version(self.version)
|
32
|
+
ask_version = binarize_version(str)
|
33
|
+
this_version >= ask_version
|
34
|
+
end
|
35
|
+
|
36
|
+
# Returns true if the current version is older than the compare version.
|
37
|
+
def self.older_than?(str)
|
38
|
+
return false if str == self.version
|
39
|
+
this_version = binarize_version(self.version)
|
40
|
+
ask_version = binarize_version(str)
|
41
|
+
this_version < ask_version
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns true if the current version is newer than the compare version.
|
45
|
+
def self.newer_than?(str)
|
46
|
+
return false if str == self.version
|
47
|
+
!self.older_than?(str)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/test/all_tests.rb
CHANGED
@@ -1,37 +1,40 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
#
|
3
|
-
#
|
4
|
-
#
|
5
|
-
# ruby-1.
|
6
|
-
# ruby-1.
|
7
|
-
# ruby-1.
|
8
|
-
#
|
9
|
-
# ruby-1.9.2-
|
10
|
-
|
11
|
-
require 'test/unit'
|
12
|
-
$: << File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
13
|
-
require 'packetfu'
|
3
|
+
# Tested on:
|
4
|
+
#
|
5
|
+
# ruby-1.9.3-head [ x86_64 ]
|
6
|
+
# ruby-1.9.1-p378 [ x86_64 ]
|
7
|
+
# ruby-1.8.6-p399 [ x86_64 ]
|
8
|
+
# ruby-1.8.7-p334 [ x86_64 ]
|
9
|
+
# ruby-1.9.2-p180 [ x86_64 ]
|
14
10
|
|
15
|
-
#
|
16
|
-
#
|
11
|
+
# Okay so the regular test/unit stuff screws up some of my
|
12
|
+
# meta magic. I need to move these over to spec and see
|
13
|
+
# if they're any better. In the meantime, behold my
|
14
|
+
# ghetto test exec()'er. It all passes with this,
|
15
|
+
# so I'm just going to go ahead and assume the testing
|
16
|
+
# methodolgy is flawed. TODO: rewrite all this for spec
|
17
|
+
# and incidentally get the gem to test like it's supposed
|
18
|
+
# to.
|
17
19
|
|
18
|
-
|
19
|
-
require '
|
20
|
-
|
21
|
-
require 'test_eth' # Creates eth_test.pcap
|
22
|
-
require 'test_octets'
|
23
|
-
require 'test_packet'
|
24
|
-
require 'test_arp' # Creates arp_test.pcap
|
25
|
-
require 'test_ip' # Creates ip_test.pcap
|
26
|
-
require 'test_icmp' # Creates icmp_test.pcap
|
27
|
-
require 'test_udp' # Creates udp_test.pcap
|
28
|
-
require 'test_tcp'
|
29
|
-
require 'test_ip6'
|
20
|
+
$:.unshift File.expand_path(File.dirname(__FILE__) + "/../lib/")
|
21
|
+
require 'packetfu'
|
22
|
+
dir = Dir.new(File.dirname(__FILE__))
|
30
23
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
24
|
+
dir.each { |file|
|
25
|
+
next unless File.file? file
|
26
|
+
next unless file[/^test_.*rb$/]
|
27
|
+
next if file == $0
|
28
|
+
puts "Running #{file}..."
|
29
|
+
cmd = %x{ruby #{file}}
|
30
|
+
if cmd[/ 0 failures/] && cmd[/ 0 errors/]
|
31
|
+
puts "#{file}: All passed"
|
32
|
+
else
|
33
|
+
puts "File: #{file} had failures or errors:"
|
34
|
+
puts "-" * 80
|
35
|
+
puts cmd
|
36
|
+
puts "-" * 80
|
37
|
+
end
|
38
|
+
}
|
36
39
|
|
37
40
|
# vim: nowrap sw=2 sts=0 ts=2 ff=unix ft=ruby
|
data/test/arp_test.pcap
ADDED
Binary file
|
data/test/eth_test.pcap
ADDED
Binary file
|
data/test/icmp_test.pcap
ADDED
Binary file
|
data/test/ip_test.pcap
ADDED
Binary file
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require File.join("..","lib","packetfu")
|
2
|
+
|
3
|
+
describe PacketFu, "version information" do
|
4
|
+
it "reports a version number" do
|
5
|
+
PacketFu::VERSION.should == "1.0.2"
|
6
|
+
end
|
7
|
+
its(:version) {should eq PacketFu::VERSION}
|
8
|
+
|
9
|
+
it "can compare version strings" do
|
10
|
+
PacketFu.binarize_version("1.2.3").should == 0x010203
|
11
|
+
PacketFu.binarize_version("3.0").should == 0x030000
|
12
|
+
PacketFu.at_least?("1.0").should be_true
|
13
|
+
PacketFu.at_least?("4.0").should be_false
|
14
|
+
PacketFu.older_than?("4.0").should be_true
|
15
|
+
PacketFu.newer_than?("1.0").should be_true
|
16
|
+
end
|
17
|
+
|
18
|
+
it "can handle .pre versions" do
|
19
|
+
PacketFu.binarize_version("1.7.6.pre").should == 0x010706
|
20
|
+
PacketFu.at_least?("0.9.0.pre").should be_true
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe PacketFu, "instance variables" do
|
25
|
+
it "should have a bunch of instance variables" do
|
26
|
+
PacketFu.instance_variable_get(:@byte_order).should == :little
|
27
|
+
PacketFu.instance_variable_get(:@pcaprub_loaded).should_not be_nil
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe PacketFu, "pcaprub deps" do
|
32
|
+
it "should check for pcaprub" do
|
33
|
+
begin
|
34
|
+
has_pcap = false
|
35
|
+
require 'pcaprub'
|
36
|
+
has_pcap = true
|
37
|
+
rescue LoadError
|
38
|
+
end
|
39
|
+
if has_pcap
|
40
|
+
PacketFu.instance_variable_get(:@pcaprub_loaded).should be_true
|
41
|
+
else
|
42
|
+
PacketFu.instance_variable_get(:@pcaprub_loaded).should be_false
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe PacketFu, "protocol requires" do
|
48
|
+
it "should have some protocols defined" do
|
49
|
+
PacketFu::EthPacket.should_not be_nil
|
50
|
+
PacketFu::IPPacket.should_not be_nil
|
51
|
+
PacketFu::TCPPacket.should_not be_nil
|
52
|
+
expect { PacketFu::FakePacket }.to raise_error
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe PacketFu, "packet class list management" do
|
57
|
+
class FooPacket; end
|
58
|
+
class BarPacket; end
|
59
|
+
PacketFu.add_packet_class(FooPacket)
|
60
|
+
PacketFu.add_packet_class(BarPacket)
|
61
|
+
its(:packet_classes) {should include(FooPacket) and include(BarPacket)}
|
62
|
+
it "should disallow non-classes as packet classes" do
|
63
|
+
expect { PacketFu.add_packet_class("A String") }.to raise_error
|
64
|
+
end
|
65
|
+
its(:packet_prefixes) {should include("foo") and include("bar")}
|
66
|
+
it "should disallow nonstandard packet class names" do
|
67
|
+
class PacketBaz; end
|
68
|
+
expect { PacketFu.add_packet_class(PacketBaz) }.to raise_error
|
69
|
+
end
|
70
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,338 @@
|
|
1
|
+
require File.join("..","lib","packetfu")
|
2
|
+
|
3
|
+
describe StructFu, "mixin methods" do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
class StructClass
|
7
|
+
include StructFu
|
8
|
+
end
|
9
|
+
@sc = StructClass.new
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should provide the basic StructFu methods" do
|
13
|
+
@sc.respond_to?(:sz).should be_true
|
14
|
+
@sc.respond_to?(:len).should be_true
|
15
|
+
@sc.respond_to?(:typecast).should be_true
|
16
|
+
@sc.respond_to?(:body=).should be_true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe StructFu::Int, "basic Int class" do
|
21
|
+
|
22
|
+
before :each do
|
23
|
+
@int = StructFu::Int.new(8)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should have an initial state" do
|
27
|
+
new_int = StructFu::Int.new
|
28
|
+
new_int.value.should be_nil
|
29
|
+
new_int.endian.should be_nil
|
30
|
+
new_int.width.should be_nil
|
31
|
+
new_int.default.should == 0
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should raise when to_s'ed directly" do
|
35
|
+
expect { @int.to_s}.to raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should have a value of 8" do
|
39
|
+
@int.value.should == 8
|
40
|
+
@int.to_i.should == 8
|
41
|
+
@int.to_f.to_s.should == "8.0"
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should read an integer" do
|
45
|
+
@int.read(7)
|
46
|
+
@int.to_i.should == 7
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
describe StructFu::Int8, "one byte value" do
|
52
|
+
|
53
|
+
before :each do
|
54
|
+
@int = StructFu::Int8.new(11)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should have an initial state" do
|
58
|
+
new_int = StructFu::Int8.new
|
59
|
+
new_int.value.should be_nil
|
60
|
+
new_int.endian.should be_nil
|
61
|
+
new_int.width.should == 1
|
62
|
+
new_int.default.should == 0
|
63
|
+
end
|
64
|
+
|
65
|
+
it "should print a one character packed string" do
|
66
|
+
@int.to_s.should == "\x0b"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should have a value of 11" do
|
70
|
+
@int.value.should == 11
|
71
|
+
@int.to_i.should == 11
|
72
|
+
@int.to_f.to_s.should == "11.0"
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should reset with a new integer" do
|
76
|
+
@int.read(2)
|
77
|
+
@int.to_i.should == 2
|
78
|
+
@int.to_s.should == "\x02"
|
79
|
+
@int.read(254)
|
80
|
+
@int.to_i.should == 254
|
81
|
+
@int.to_s.should == "\xfe"
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
|
86
|
+
describe StructFu::Int16, "two byte value" do
|
87
|
+
|
88
|
+
before :each do
|
89
|
+
@int = StructFu::Int16.new(11)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should have an initial state" do
|
93
|
+
new_int = StructFu::Int16.new
|
94
|
+
new_int.value.should be_nil
|
95
|
+
new_int.endian.should == :big
|
96
|
+
new_int.width.should == 2
|
97
|
+
new_int.default.should == 0
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should print a two character packed string" do
|
101
|
+
@int.to_s.should == "\x00\x0b"
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should have a value of 11" do
|
105
|
+
@int.value.should == 11
|
106
|
+
@int.to_i.should == 11
|
107
|
+
@int.to_f.to_s.should == "11.0"
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should reset with a new integer" do
|
111
|
+
@int.read(2)
|
112
|
+
@int.to_i.should == 2
|
113
|
+
@int.to_s.should == "\x00\x02"
|
114
|
+
@int.read(254)
|
115
|
+
@int.to_i.should == 254
|
116
|
+
@int.to_s.should == "\x00\xfe"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "should be able to set endianness" do
|
120
|
+
int_be = StructFu::Int16.new(11,:big)
|
121
|
+
int_be.to_s.should == "\x00\x0b"
|
122
|
+
int_le = StructFu::Int16.new(11,:little)
|
123
|
+
int_le.to_s.should == "\x0b\x00"
|
124
|
+
end
|
125
|
+
|
126
|
+
it "should be able to switch endianness" do
|
127
|
+
@int.endian.should == :big
|
128
|
+
@int.to_s.should == "\x00\x0b"
|
129
|
+
@int.endian = :little
|
130
|
+
@int.endian.should == :little
|
131
|
+
@int.read(11)
|
132
|
+
@int.to_s.should == "\x0b\x00"
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
|
137
|
+
describe StructFu::Int16le, "2 byte little-endian value" do
|
138
|
+
|
139
|
+
before :each do
|
140
|
+
@int = StructFu::Int16le.new(11)
|
141
|
+
end
|
142
|
+
|
143
|
+
it "should behave pretty much like any other 16 bit int" do
|
144
|
+
@int.to_s.should == "\x0b\x00"
|
145
|
+
end
|
146
|
+
|
147
|
+
it "should raise when you try to change endianness" do
|
148
|
+
expect { @int.endian = :big }.to raise_error
|
149
|
+
expect { @int.endian = :little }.to raise_error
|
150
|
+
end
|
151
|
+
|
152
|
+
end
|
153
|
+
|
154
|
+
describe StructFu::Int16be, "2 byte big-endian value" do
|
155
|
+
|
156
|
+
before :each do
|
157
|
+
@int = StructFu::Int16be.new(11)
|
158
|
+
end
|
159
|
+
|
160
|
+
it "should behave pretty much like any other 16 bit int" do
|
161
|
+
@int.to_s.should == "\x00\x0b"
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should raise when you try to change endianness" do
|
165
|
+
expect { @int.endian = :big }.to raise_error
|
166
|
+
expect { @int.endian = :little }.to raise_error
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
describe StructFu::Int32, "four byte value" do
|
172
|
+
|
173
|
+
before :each do
|
174
|
+
@int = StructFu::Int32.new(11)
|
175
|
+
end
|
176
|
+
|
177
|
+
it "should have an initial state" do
|
178
|
+
new_int = StructFu::Int32.new
|
179
|
+
new_int.value.should be_nil
|
180
|
+
new_int.endian.should == :big
|
181
|
+
new_int.width.should == 4
|
182
|
+
new_int.default.should == 0
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should print a four character packed string" do
|
186
|
+
@int.to_s.should == "\x00\x00\x00\x0b"
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should have a value of 11" do
|
190
|
+
@int.value.should == 11
|
191
|
+
@int.to_i.should == 11
|
192
|
+
@int.to_f.to_s.should == "11.0"
|
193
|
+
end
|
194
|
+
|
195
|
+
it "should reset with a new integer" do
|
196
|
+
@int.read(2)
|
197
|
+
@int.to_i.should == 2
|
198
|
+
@int.to_s.should == "\x00\x00\x00\x02"
|
199
|
+
@int.read(254)
|
200
|
+
@int.to_i.should == 254
|
201
|
+
@int.to_s.should == "\x00\x00\x00\xfe"
|
202
|
+
end
|
203
|
+
|
204
|
+
it "should be able to set endianness" do
|
205
|
+
int_be = StructFu::Int32.new(11,:big)
|
206
|
+
int_be.to_s.should == "\x00\x00\x00\x0b"
|
207
|
+
int_le = StructFu::Int32.new(11,:little)
|
208
|
+
int_le.to_s.should == "\x0b\x00\x00\x00"
|
209
|
+
end
|
210
|
+
|
211
|
+
it "should be able to switch endianness" do
|
212
|
+
@int.endian.should == :big
|
213
|
+
@int.to_s.should == "\x00\x00\x00\x0b"
|
214
|
+
@int.endian = :little
|
215
|
+
@int.endian.should == :little
|
216
|
+
@int.read(11)
|
217
|
+
@int.to_s.should == "\x0b\x00\x00\x00"
|
218
|
+
end
|
219
|
+
|
220
|
+
end
|
221
|
+
|
222
|
+
describe StructFu::Int32le, "4 byte little-endian value" do
|
223
|
+
|
224
|
+
before :each do
|
225
|
+
@int = StructFu::Int32le.new(11)
|
226
|
+
end
|
227
|
+
|
228
|
+
it "should behave pretty much like any other 32 bit int" do
|
229
|
+
@int.to_s.should == "\x0b\x00\x00\x00"
|
230
|
+
end
|
231
|
+
|
232
|
+
it "should raise when you try to change endianness" do
|
233
|
+
expect { @int.endian = :big }.to raise_error
|
234
|
+
expect { @int.endian = :little }.to raise_error
|
235
|
+
end
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
describe StructFu::Int32be, "4 byte big-endian value" do
|
240
|
+
|
241
|
+
before :each do
|
242
|
+
@int = StructFu::Int32be.new(11)
|
243
|
+
end
|
244
|
+
|
245
|
+
it "should behave pretty much like any other 32 bit int" do
|
246
|
+
@int.to_s.should == "\x00\x00\x00\x0b"
|
247
|
+
end
|
248
|
+
|
249
|
+
it "should raise when you try to change endianness" do
|
250
|
+
expect { @int.endian = :big }.to raise_error
|
251
|
+
expect { @int.endian = :little }.to raise_error
|
252
|
+
end
|
253
|
+
|
254
|
+
end
|
255
|
+
|
256
|
+
describe StructFu::String, "a sligtly more special String" do
|
257
|
+
|
258
|
+
before :each do
|
259
|
+
@str = StructFu::String.new("Oi, a string")
|
260
|
+
end
|
261
|
+
|
262
|
+
it "should behave pretty much like a string" do
|
263
|
+
@str.should be_kind_of(String)
|
264
|
+
end
|
265
|
+
|
266
|
+
it "should have a read method" do
|
267
|
+
@str.should respond_to(:read)
|
268
|
+
end
|
269
|
+
|
270
|
+
it "should read data like other StructFu things" do
|
271
|
+
@str.read("hello")
|
272
|
+
@str.should == "hello"
|
273
|
+
end
|
274
|
+
|
275
|
+
end
|
276
|
+
|
277
|
+
describe StructFu::IntString do
|
278
|
+
|
279
|
+
it "should be" do
|
280
|
+
StructFu::IntString.should be
|
281
|
+
end
|
282
|
+
|
283
|
+
it "should have a length and value" do
|
284
|
+
istr = StructFu::IntString.new("Avast!")
|
285
|
+
istr.to_s.should == "\x06Avast!"
|
286
|
+
end
|
287
|
+
|
288
|
+
it "should have a 16-bit length and a value" do
|
289
|
+
istr = StructFu::IntString.new("Avast!",StructFu::Int16)
|
290
|
+
istr.to_s.should == "\x00\x06Avast!"
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should have a 32-bit length and a value" do
|
294
|
+
istr = StructFu::IntString.new("Avast!",StructFu::Int32)
|
295
|
+
istr.to_s.should == "\x00\x00\x00\x06Avast!"
|
296
|
+
end
|
297
|
+
|
298
|
+
before :each do
|
299
|
+
@istr = StructFu::IntString.new("Avast!",StructFu::Int32)
|
300
|
+
end
|
301
|
+
|
302
|
+
it "should report the correct length with a new string" do
|
303
|
+
@istr.to_s.should == "\x00\x00\x00\x06Avast!"
|
304
|
+
@istr.string = "Ahoy!"
|
305
|
+
@istr.to_s.should == "\x00\x00\x00\x05Ahoy!"
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should report the correct length with a new string" do
|
309
|
+
@istr.string = "Ahoy!"
|
310
|
+
@istr.to_s.should == "\x00\x00\x00\x05Ahoy!"
|
311
|
+
end
|
312
|
+
|
313
|
+
it "should keep the old length with a new string" do
|
314
|
+
@istr[:string] = "Ahoy!"
|
315
|
+
@istr.to_s.should == "\x00\x00\x00\x06Ahoy!"
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should allow for adjusting the length manually" do
|
319
|
+
@istr.len = 16
|
320
|
+
@istr.to_s.should == "\x00\x00\x00\x10Avast!"
|
321
|
+
end
|
322
|
+
|
323
|
+
it "should read in an expected string" do
|
324
|
+
data = "\x00\x00\x00\x09Yo ho ho!"
|
325
|
+
@istr.read(data)
|
326
|
+
@istr.to_s.should == data
|
327
|
+
end
|
328
|
+
|
329
|
+
it "should raise when a string is too short" do
|
330
|
+
data = "\x01A"
|
331
|
+
expect { @istr.read(data) }.to raise_error
|
332
|
+
end
|
333
|
+
|
334
|
+
# So far, not implemented anywhere. In fact, none of this IntString
|
335
|
+
# business is. Ah well.
|
336
|
+
it "should parse when something actually needs it"
|
337
|
+
|
338
|
+
end
|