woolen_common 0.0.1
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.
- checksums.yaml +15 -0
- data/README.md +31 -0
- data/ext/woolen_common/extconf.rb +26 -0
- data/ext/woolen_common/linux.h +3 -0
- data/ext/woolen_common/win.c +18 -0
- data/ext/woolen_common/win.h +4 -0
- data/ext/woolen_common/win/puts_color.c +139 -0
- data/ext/woolen_common/win/puts_color.h +5 -0
- data/ext/woolen_common/woolen_common.c +20 -0
- data/ext/woolen_common/woolen_common.h +7 -0
- data/lib/woolen_common.rb +39 -0
- data/lib/woolen_common/abstract_middleware/builder.rb +138 -0
- data/lib/woolen_common/abstract_middleware/map_cfg_manager.rb +52 -0
- data/lib/woolen_common/abstract_middleware/runner.rb +72 -0
- data/lib/woolen_common/action_pool_proxy.rb +28 -0
- data/lib/woolen_common/actionpool.rb +10 -0
- data/lib/woolen_common/actionpool/pool.rb +295 -0
- data/lib/woolen_common/actionpool/queue.rb +41 -0
- data/lib/woolen_common/actionpool/thread.rb +181 -0
- data/lib/woolen_common/addr_helper.rb +93 -0
- data/lib/woolen_common/cache.rb +305 -0
- data/lib/woolen_common/common_helper.rb +42 -0
- data/lib/woolen_common/config_manager.rb +36 -0
- data/lib/woolen_common/drb_helper.rb +125 -0
- data/lib/woolen_common/ffi/win32_kernel32.rb +86 -0
- data/lib/woolen_common/logger.rb +419 -0
- data/lib/woolen_common/pcap/mu/fixnum_ext.rb +8 -0
- data/lib/woolen_common/pcap/mu/pcap/ethernet.rb +164 -0
- data/lib/woolen_common/pcap/mu/pcap/header.rb +76 -0
- data/lib/woolen_common/pcap/mu/pcap/io_pair.rb +68 -0
- data/lib/woolen_common/pcap/mu/pcap/io_wrapper.rb +77 -0
- data/lib/woolen_common/pcap/mu/pcap/ip.rb +62 -0
- data/lib/woolen_common/pcap/mu/pcap/ipv4.rb +274 -0
- data/lib/woolen_common/pcap/mu/pcap/ipv6.rb +149 -0
- data/lib/woolen_common/pcap/mu/pcap/packet.rb +106 -0
- data/lib/woolen_common/pcap/mu/pcap/pkthdr.rb +162 -0
- data/lib/woolen_common/pcap/mu/pcap/reader.rb +62 -0
- data/lib/woolen_common/pcap/mu/pcap/reader/http_family.rb +175 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp.rb +369 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp/chunk.rb +124 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp/chunk/data.rb +135 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp/chunk/init.rb +101 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp/chunk/init_ack.rb +69 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp/parameter.rb +111 -0
- data/lib/woolen_common/pcap/mu/pcap/sctp/parameter/ip_address.rb +49 -0
- data/lib/woolen_common/pcap/mu/pcap/stream_packetizer.rb +74 -0
- data/lib/woolen_common/pcap/mu/pcap/tcp.rb +522 -0
- data/lib/woolen_common/pcap/mu/pcap/udp.rb +81 -0
- data/lib/woolen_common/pcap/mu/scenario/pcap.rb +175 -0
- data/lib/woolen_common/pcap/mu/scenario/pcap/fields.rb +51 -0
- data/lib/woolen_common/pcap/mu/scenario/pcap/rtp.rb +72 -0
- data/lib/woolen_common/pcap/pcap.rb +115 -0
- data/lib/woolen_common/pcap/readme.md +72 -0
- data/lib/woolen_common/ruby_ext/blank.rb +126 -0
- data/lib/woolen_common/ruby_ext/drb_ext.rb +7 -0
- data/lib/woolen_common/ruby_ext/string.rb +116 -0
- data/lib/woolen_common/ruby_ext/win32_ole.rb +4 -0
- data/lib/woolen_common/ruby_proxy.rb +5 -0
- data/lib/woolen_common/ruby_proxy/client.rb +305 -0
- data/lib/woolen_common/ruby_proxy/config.rb +44 -0
- data/lib/woolen_common/ruby_proxy/exceptions.rb +17 -0
- data/lib/woolen_common/ruby_proxy/proxy.rb +157 -0
- data/lib/woolen_common/ruby_proxy/proxy_global_set.rb +44 -0
- data/lib/woolen_common/ruby_proxy/proxy_load.rb +34 -0
- data/lib/woolen_common/ruby_proxy/server.rb +53 -0
- data/lib/woolen_common/splib.rb +36 -0
- data/lib/woolen_common/splib/Array.rb +33 -0
- data/lib/woolen_common/splib/CodeReloader.rb +59 -0
- data/lib/woolen_common/splib/Constants.rb +44 -0
- data/lib/woolen_common/splib/Conversions.rb +47 -0
- data/lib/woolen_common/splib/Exec.rb +132 -0
- data/lib/woolen_common/splib/Float.rb +13 -0
- data/lib/woolen_common/splib/HumanIdealRandomIterator.rb +40 -0
- data/lib/woolen_common/splib/Monitor.rb +214 -0
- data/lib/woolen_common/splib/PriorityQueue.rb +110 -0
- data/lib/woolen_common/splib/Sleep.rb +10 -0
- data/lib/woolen_common/splib/UrlShorteners.rb +48 -0
- data/lib/woolen_common/ssh_proxy.rb +146 -0
- data/lib/woolen_common/system_helper.rb +123 -0
- data/lib/woolen_common/system_monitor.rb +23 -0
- data/lib/woolen_common/system_monitor/linux_monitor.rb +250 -0
- data/lib/woolen_common/system_monitor/windows_monitor.rb +145 -0
- data/lib/woolen_common/type_helper.rb +42 -0
- data/lib/woolen_common/ver_ctrl_middle_ware.rb +92 -0
- data/lib/woolen_common/version.rb +3 -0
- metadata +210 -0
@@ -0,0 +1,164 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
# http://www.mudynamics.com
|
3
|
+
# http://labs.mudynamics.com
|
4
|
+
# http://www.pcapr.net
|
5
|
+
|
6
|
+
module Mu
|
7
|
+
class Pcap
|
8
|
+
|
9
|
+
class Ethernet < Packet
|
10
|
+
attr_accessor :src, :dst, :type
|
11
|
+
|
12
|
+
ETHERTYPE_IP = 0x0800
|
13
|
+
ETHERTYPE_IP6 = 0x86dd
|
14
|
+
ETHERTYPE_ARP = 0x0806
|
15
|
+
ETHERTYPE_PPPOE_SESSION = 0x8864
|
16
|
+
ETHERTYPE_802_1Q = 0X8100
|
17
|
+
|
18
|
+
PPP_IP = 0x0021
|
19
|
+
PPP_IPV6 = 0x0057
|
20
|
+
|
21
|
+
def initialize src=nil, dst=nil, type=0
|
22
|
+
super()
|
23
|
+
@src = src
|
24
|
+
@dst = dst
|
25
|
+
@type = type
|
26
|
+
@vlan = false
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :vlan
|
30
|
+
|
31
|
+
def vlan?
|
32
|
+
vlan
|
33
|
+
end
|
34
|
+
|
35
|
+
def flow_id
|
36
|
+
if not @payload or @payload.is_a? String
|
37
|
+
return [:ethernet, @src, @dst, @type]
|
38
|
+
else
|
39
|
+
return @payload.flow_id
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
FMT_MAC = "C6"
|
44
|
+
FMT_n = 'n'
|
45
|
+
MAC_TEMPLATE = '%02x:%02x:%02x:%02x:%02x:%02x'
|
46
|
+
|
47
|
+
def self.from_bytes bytes
|
48
|
+
if bytes.length < 14
|
49
|
+
raise ParseError, "Truncated Ethernet header: expected 14 bytes, got #{bytes.length} bytes"
|
50
|
+
end
|
51
|
+
|
52
|
+
dst = bytes.slice!(0, 6).unpack FMT_MAC
|
53
|
+
dst = MAC_TEMPLATE % dst
|
54
|
+
src = bytes.slice!(0, 6).unpack FMT_MAC
|
55
|
+
src = MAC_TEMPLATE % src
|
56
|
+
type = bytes.slice!(0, 2).unpack(FMT_n)[0]
|
57
|
+
if type == ETHERTYPE_802_1Q
|
58
|
+
@vlan = true
|
59
|
+
else
|
60
|
+
@vlan = false
|
61
|
+
end
|
62
|
+
while (type == ETHERTYPE_802_1Q)
|
63
|
+
# Skip 4 bytes for 802.1q vlan tag field
|
64
|
+
bytes.slice!(0, 2)
|
65
|
+
type = bytes.slice!(0, 2).unpack(FMT_n)[0]
|
66
|
+
end
|
67
|
+
ethernet = Ethernet.new src, dst, type
|
68
|
+
ethernet.vlan = @vlan
|
69
|
+
ethernet.payload = bytes
|
70
|
+
ethernet.payload_raw = bytes
|
71
|
+
begin
|
72
|
+
case type
|
73
|
+
when ETHERTYPE_IP
|
74
|
+
ethernet.payload = IPv4.from_bytes bytes
|
75
|
+
when ETHERTYPE_IP6
|
76
|
+
ethernet.payload = IPv6.from_bytes bytes
|
77
|
+
when ETHERTYPE_PPPOE_SESSION
|
78
|
+
# Remove PPPoE/PPP session layer
|
79
|
+
ethernet.payload = bytes
|
80
|
+
ethernet.remove_pppoe!
|
81
|
+
else
|
82
|
+
ethernet.payload = bytes
|
83
|
+
end
|
84
|
+
rescue ParseError => e
|
85
|
+
Pcap.warning e
|
86
|
+
end
|
87
|
+
return ethernet
|
88
|
+
end
|
89
|
+
|
90
|
+
def ip?
|
91
|
+
return payload.is_a?(IP)
|
92
|
+
end
|
93
|
+
|
94
|
+
ADDR_TO_BYTES = {}
|
95
|
+
FMT_HEADER = 'a6a6n'
|
96
|
+
|
97
|
+
def write io
|
98
|
+
dst_mac = ADDR_TO_BYTES[@dst] ||= @dst.split(':').inject('') { |m, b| m << b.to_i(16).chr }
|
99
|
+
src_mac = ADDR_TO_BYTES[@src] ||= @src.split(':').inject('') { |m, b| m << b.to_i(16).chr }
|
100
|
+
bytes = [dst_mac, src_mac, @type].pack(FMT_HEADER)
|
101
|
+
io.write bytes
|
102
|
+
if @payload.is_a? String
|
103
|
+
io.write @payload
|
104
|
+
else
|
105
|
+
@payload.write io
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# Remove the PPPoE and PPP headers. PPPoE is documented in RFC 2516.
|
110
|
+
def remove_pppoe!
|
111
|
+
bytes = self.payload_raw
|
112
|
+
|
113
|
+
# Remove PPPoE header
|
114
|
+
Pcap.assert bytes.length >= 6, 'Truncated PPPoE header: ' +
|
115
|
+
"expected at least 6 bytes, got #{bytes.length} bytes"
|
116
|
+
version_type, code, session_id, length = bytes.unpack 'CCnn'
|
117
|
+
version = version_type >> 4 & 0b1111
|
118
|
+
type = version_type & 0b1111
|
119
|
+
Pcap.assert version == 1, "Unknown PPPoE version: #{version}"
|
120
|
+
Pcap.assert type == 1, "Unknown PPPoE type: #{type}"
|
121
|
+
Pcap.assert code == 0, "Unknown PPPoE code: #{code}"
|
122
|
+
bytes = bytes[6..-1]
|
123
|
+
Pcap.assert bytes.length >= length, 'Truncated PPoE packet: ' +
|
124
|
+
"expected #{length} bytes, got #{bytes.length} bytes"
|
125
|
+
|
126
|
+
# Remove PPP header
|
127
|
+
Pcap.assert bytes.length >= 2, 'Truncated PPP packet: ' +
|
128
|
+
"expected at least bytes, got #{bytes.length} bytes"
|
129
|
+
protocol_id, = bytes.unpack 'n'
|
130
|
+
bytes = bytes[2..-1]
|
131
|
+
case protocol_id
|
132
|
+
when PPP_IP
|
133
|
+
self.payload = IPv4.from_bytes bytes
|
134
|
+
self.payload_raw = bytes
|
135
|
+
self.type = ETHERTYPE_IP
|
136
|
+
when PPP_IPV6
|
137
|
+
self.payload = IPv6.from_bytes bytes
|
138
|
+
self.payload_raw = bytes
|
139
|
+
self.type = ETHERTYPE_IP6
|
140
|
+
else
|
141
|
+
# Failed. Don't update payload or type.
|
142
|
+
raise ParseError, "Unknown PPP protocol: 0x#{'%04x' % protocol_id}"
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_s
|
147
|
+
if @payload.is_a? String
|
148
|
+
payload = @payload.inspect
|
149
|
+
else
|
150
|
+
payload = @payload.to_s
|
151
|
+
end
|
152
|
+
return "ethernet(%s, %s, %d, %s)" % [@src, @dst, @type, payload]
|
153
|
+
end
|
154
|
+
|
155
|
+
def == other
|
156
|
+
return super &&
|
157
|
+
self.src == other.src &&
|
158
|
+
self.dst == other.dst &&
|
159
|
+
self.type == other.type
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
# http://www.mudynamics.com
|
3
|
+
# http://labs.mudynamics.com
|
4
|
+
# http://www.pcapr.net
|
5
|
+
|
6
|
+
module Mu
|
7
|
+
class Pcap
|
8
|
+
|
9
|
+
class Header
|
10
|
+
attr_accessor :magic, :version_major, :version_minor, :thiszone, :sigfigs,
|
11
|
+
:snaplen, :linktype
|
12
|
+
|
13
|
+
BIG_ENDIAN_FORMAT = 'nnNNNN'
|
14
|
+
LITTLE_ENDIAN_FORMAT = 'vvVVVV'
|
15
|
+
|
16
|
+
UNSUPPORTED_FORMATS = {
|
17
|
+
0x474D4255 => "NetMon", # "GMBU"
|
18
|
+
0x5452534E => "NA Sniffer (DOS)" # Starts with "TRSNIFF data"
|
19
|
+
}
|
20
|
+
|
21
|
+
def initialize
|
22
|
+
@magic = BIG_ENDIAN
|
23
|
+
@version_major = 2
|
24
|
+
@version_minor = 4
|
25
|
+
@thiszone = 0
|
26
|
+
@sigfigs = 0
|
27
|
+
@snaplen = 1500
|
28
|
+
@linktype = DLT_NULL
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.read ios
|
32
|
+
header = Header.new
|
33
|
+
bytes = ios.read 24
|
34
|
+
Pcap.assert bytes, 'PCAP header missing'
|
35
|
+
Pcap.assert bytes.length == 24, 'Truncated PCAP header: ' +
|
36
|
+
"expected 24 bytes, got #{bytes.length} bytes"
|
37
|
+
header.magic, _ = bytes[0, 4].unpack 'N'
|
38
|
+
if header.magic == BIG_ENDIAN
|
39
|
+
format = BIG_ENDIAN_FORMAT
|
40
|
+
elsif header.magic == LITTLE_ENDIAN
|
41
|
+
format = LITTLE_ENDIAN_FORMAT
|
42
|
+
else
|
43
|
+
format = UNSUPPORTED_FORMATS[header.magic]
|
44
|
+
if format.nil?
|
45
|
+
err = "Unsupported packet capture format. "
|
46
|
+
else
|
47
|
+
err = "#{format} capture files are not supported. "
|
48
|
+
end
|
49
|
+
raise ParseError, err
|
50
|
+
end
|
51
|
+
header.version_major, header.version_minor, header.thiszone,
|
52
|
+
header.sigfigs, header.snaplen, header.linktype =
|
53
|
+
bytes[4..-1].unpack format
|
54
|
+
return header
|
55
|
+
end
|
56
|
+
|
57
|
+
def write io
|
58
|
+
bytes = [BIG_ENDIAN, @version_major, @version_minor, @thiszone,
|
59
|
+
@sigfigs, @snaplen, DLT_EN10MB].pack('N' + BIG_ENDIAN_FORMAT)
|
60
|
+
io.write bytes
|
61
|
+
end
|
62
|
+
|
63
|
+
def == other
|
64
|
+
return self.class == other.class &&
|
65
|
+
self.magic == other.magic &&
|
66
|
+
self.version_major == other.version_major &&
|
67
|
+
self.version_minor == other.version_minor &&
|
68
|
+
self.thiszone == other.thiszone &&
|
69
|
+
self.sigfigs == other.sigfigs &&
|
70
|
+
self.snaplen == other.snaplen &&
|
71
|
+
self.linktype == other.linktype
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
# http://www.mudynamics.com
|
3
|
+
# http://labs.mudynamics.com
|
4
|
+
# http://www.pcapr.net
|
5
|
+
|
6
|
+
module Mu
|
7
|
+
class Pcap
|
8
|
+
|
9
|
+
# For emulating of a pair of connected sockets. Bytes written
|
10
|
+
# with #write to one side are returned by a subsequent #read on
|
11
|
+
# the other side.
|
12
|
+
#
|
13
|
+
# Use Pair.stream_pair to get a pair with stream semantics.
|
14
|
+
# Use Pair.packet_pair to get a pair with packet semantics.
|
15
|
+
class IOPair
|
16
|
+
attr_reader :read_queue
|
17
|
+
attr_accessor :other
|
18
|
+
|
19
|
+
def initialize
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.stream_pair
|
24
|
+
io1 = Stream.new
|
25
|
+
io2 = Stream.new
|
26
|
+
io1.other = io2
|
27
|
+
io2.other = io1
|
28
|
+
return io1, io2
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.packet_pair
|
32
|
+
io1 = Packet.new
|
33
|
+
io2 = Packet.new
|
34
|
+
io1.other = io2
|
35
|
+
io2.other = io1
|
36
|
+
return io1, io2
|
37
|
+
end
|
38
|
+
|
39
|
+
def write bytes
|
40
|
+
@other.read_queue << bytes
|
41
|
+
bytes.size
|
42
|
+
end
|
43
|
+
|
44
|
+
class Stream < IOPair
|
45
|
+
def initialize
|
46
|
+
@read_queue = ""
|
47
|
+
end
|
48
|
+
|
49
|
+
def read n=nil
|
50
|
+
n ||= @read_queue.size
|
51
|
+
@read_queue.slice!(0, n)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class Packet < IOPair
|
56
|
+
def initialize
|
57
|
+
@read_queue = []
|
58
|
+
end
|
59
|
+
|
60
|
+
def read
|
61
|
+
@read_queue.shift
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
# http://www.mudynamics.com
|
3
|
+
# http://labs.mudynamics.com
|
4
|
+
# http://www.pcapr.net
|
5
|
+
|
6
|
+
require 'mu/pcap/io_pair'
|
7
|
+
|
8
|
+
module Mu
|
9
|
+
class Pcap
|
10
|
+
class IOWrapper
|
11
|
+
attr_reader :ios, :unread, :state
|
12
|
+
|
13
|
+
def initialize ios, reader
|
14
|
+
@ios = ios
|
15
|
+
@reader = reader
|
16
|
+
# parse state for reader
|
17
|
+
@state = {}
|
18
|
+
# read off of underlying io but not yet processed by @reader
|
19
|
+
@unread = ""
|
20
|
+
end
|
21
|
+
|
22
|
+
# Impose upper limit to protect against memory exhaustion.
|
23
|
+
MAX_RECEIVE_SIZE = 1048576 # 1MB
|
24
|
+
|
25
|
+
# Returns next higher level protocol message.
|
26
|
+
def read
|
27
|
+
until message = @reader.read_message!(@unread, @state)
|
28
|
+
bytes = @ios.read
|
29
|
+
if bytes and not bytes.empty?
|
30
|
+
@unread << bytes
|
31
|
+
else
|
32
|
+
return nil
|
33
|
+
end
|
34
|
+
if @unread.size > MAX_RECEIVE_SIZE
|
35
|
+
raise "Maximum message size (#{MAX_RECEIVE_SIZE}) exceeded"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
return message
|
40
|
+
end
|
41
|
+
|
42
|
+
# Parser may need to see requests to understand responses.
|
43
|
+
def record_write bytes
|
44
|
+
@reader.record_write bytes, @state
|
45
|
+
end
|
46
|
+
|
47
|
+
def write bytes, *args
|
48
|
+
w = @ios.write bytes, *args
|
49
|
+
record_write bytes
|
50
|
+
w
|
51
|
+
end
|
52
|
+
|
53
|
+
def write_to bytes, *args
|
54
|
+
w = @ios.write_to bytes, *args
|
55
|
+
record_write bytes
|
56
|
+
w
|
57
|
+
end
|
58
|
+
|
59
|
+
def open
|
60
|
+
if block_given?
|
61
|
+
@ios.open { yield }
|
62
|
+
else
|
63
|
+
@ios.open
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def open?
|
68
|
+
@ios.open?
|
69
|
+
end
|
70
|
+
|
71
|
+
def close
|
72
|
+
@ios.close
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
# http://www.mudynamics.com
|
3
|
+
# http://labs.mudynamics.com
|
4
|
+
# http://www.pcapr.net
|
5
|
+
|
6
|
+
module Mu
|
7
|
+
class Pcap
|
8
|
+
|
9
|
+
class IP < Packet
|
10
|
+
IPPROTO_TCP = 6
|
11
|
+
IPPROTO_UDP = 17
|
12
|
+
IPPROTO_HOPOPTS = 0
|
13
|
+
IPPROTO_ROUTING = 43
|
14
|
+
IPPROTO_FRAGMENT = 44
|
15
|
+
IPPROTO_AH = 51
|
16
|
+
IPPROTO_NONE = 59
|
17
|
+
IPPROTO_DSTOPTS = 60
|
18
|
+
IPPROTO_SCTP = 132
|
19
|
+
|
20
|
+
attr_accessor :src, :dst
|
21
|
+
|
22
|
+
def initialize src=nil, dst=nil
|
23
|
+
super()
|
24
|
+
@src = src
|
25
|
+
@dst = dst
|
26
|
+
end
|
27
|
+
|
28
|
+
def v4?
|
29
|
+
return false
|
30
|
+
end
|
31
|
+
|
32
|
+
def v6?
|
33
|
+
return false
|
34
|
+
end
|
35
|
+
|
36
|
+
def proto
|
37
|
+
raise NotImplementedError
|
38
|
+
end
|
39
|
+
|
40
|
+
def pseudo_header payload_length
|
41
|
+
raise NotImplementedError
|
42
|
+
end
|
43
|
+
|
44
|
+
def == other
|
45
|
+
return super &&
|
46
|
+
self.src == other.src &&
|
47
|
+
self.dst == other.dst
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.checksum bytes
|
51
|
+
if bytes.size & 1 == 1
|
52
|
+
bytes = bytes + "\0"
|
53
|
+
end
|
54
|
+
sum = 0
|
55
|
+
bytes.unpack("n*").each { |n| sum += n }
|
56
|
+
sum = (sum & 0xffff) + (sum >> 16 & 0xffff)
|
57
|
+
~sum & 0xffff
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|