Files
flexnbd-c/tests/acceptance/flexnbd/fake_source.rb
2018-02-03 20:10:47 +00:00

150 lines
3.5 KiB
Ruby

require 'socket'
require 'timeout'
require 'flexnbd/constants'
module FlexNBD
class FakeSource
def initialize(addr, port, err_msg, source_addr = nil, source_port = 0)
timing_out(2, err_msg) do
begin
@sock = if source_addr
TCPSocket.new(addr, port, source_addr, source_port)
else
TCPSocket.new(addr, port)
end
rescue Errno::ECONNREFUSED
warn 'Connection refused, retrying'
sleep(0.2)
retry
end
end
end
def close
@sock.close
end
def read_hello
timing_out(::FlexNBD::MS_HELLO_TIME_SECS,
'Timed out waiting for hello.') do
raise 'No hello.' unless (hello = @sock.read(152)) &&
hello.length == 152
passwd_s = hello[0..7]
magic = hello[8..15].unpack('Q>').first
size = hello[16..23].unpack('Q>').first
flags = hello[24..27].unpack('L>').first
reserved = hello[28..-1]
return { passwd: passwd_s, magic: magic, size: size, flags: flags, reserved: reserved }
end
end
def send_request(type, handle = 'myhandle', from = 0, len = 0, magic = REQUEST_MAGIC)
raise 'Bad handle' unless handle.length == 8
@sock.write(magic)
@sock.write([type].pack('N'))
@sock.write(handle)
@sock.write([n64(from)].pack('q'))
@sock.write([len].pack('N'))
end
def write_write_request(from, len, handle = 'myhandle')
send_request(1, handle, from, len)
end
def write_flush_request(handle = 'myhandle')
send_request(3, handle, 0, 0)
end
def write_entrust_request(handle = 'myhandle')
send_request(65_536, handle)
end
def write_disconnect_request(handle = 'myhandle')
send_request(2, handle)
end
def write_read_request(from, len, _handle = 'myhandle')
send_request(0, 'myhandle', from, len)
end
def write_data(data)
@sock.write(data)
end
# Handy utility
def read(from, len)
timing_out(2, 'Timed out reading') do
send_request(0, 'myhandle', from, len)
read_raw(len)
end
end
def read_raw(len)
@sock.read(len)
end
def send_mirror
read_hello
write(0, '12345678')
read_response
write_disconnect_request
close
end
def write(from, data)
write_write_request(from, data.length)
write_data(data)
end
def flush
write_flush_request
end
def read_response
magic = @sock.read(4)
error_s = @sock.read(4)
handle = @sock.read(8)
{
magic: magic,
error: error_s.unpack('N').first,
handle: handle
}
end
def disconnected?
result = nil
Timeout.timeout(2) { result = @sock.read(1).nil? }
result
end
def timing_out(time, msg)
Timeout.timeout(time) do
yield
end
rescue Timeout::Error
warn msg
exit 1
end
private
# take a 64-bit number, turn it upside down (due to :
# http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/11920
# )
def n64(b)
((b & 0xff00000000000000) >> 56) |
((b & 0x00ff000000000000) >> 40) |
((b & 0x0000ff0000000000) >> 24) |
((b & 0x000000ff00000000) >> 8) |
((b & 0x00000000ff000000) << 8) |
((b & 0x0000000000ff0000) << 24) |
((b & 0x000000000000ff00) << 40) |
((b & 0x00000000000000ff) << 56)
end
end # class FakeSource
end # module FlexNBD