299 lines
7.2 KiB
Ruby
299 lines
7.2 KiB
Ruby
require 'helper'
|
|
|
|
describe "draft03" do
|
|
include EM::SpecHelper
|
|
default_timeout 1
|
|
|
|
before :each do
|
|
@request = {
|
|
:port => 80,
|
|
:method => "GET",
|
|
:path => "/demo",
|
|
:headers => {
|
|
'Host' => 'example.com',
|
|
'Connection' => 'Upgrade',
|
|
'Sec-WebSocket-Key2' => '12998 5 Y3 1 .P00',
|
|
'Sec-WebSocket-Protocol' => 'sample',
|
|
'Upgrade' => 'WebSocket',
|
|
'Sec-WebSocket-Key1' => '4 @1 46546xW%0l 1 5',
|
|
'Origin' => 'http://example.com',
|
|
'Sec-WebSocket-Draft' => '3'
|
|
},
|
|
:body => '^n:ds[4U'
|
|
}
|
|
|
|
@response = {
|
|
:headers => {
|
|
"Upgrade" => "WebSocket",
|
|
"Connection" => "Upgrade",
|
|
"Sec-WebSocket-Location" => "ws://example.com/demo",
|
|
"Sec-WebSocket-Origin" => "http://example.com",
|
|
"Sec-WebSocket-Protocol" => "sample"
|
|
},
|
|
:body => "8jKS\'y:G*Co,Wxa-"
|
|
}
|
|
end
|
|
|
|
def start_client
|
|
client = EM.connect('0.0.0.0', 12345, Draft03FakeWebSocketClient)
|
|
client.send_data(format_request(@request))
|
|
yield client if block_given?
|
|
return client
|
|
end
|
|
|
|
it_behaves_like "a websocket server" do
|
|
let(:version) { 3 }
|
|
end
|
|
|
|
it_behaves_like "a WebSocket server drafts 3 and above" do
|
|
let(:version) { 3 }
|
|
end
|
|
|
|
# These examples are straight from the spec
|
|
# http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6
|
|
describe "examples from the spec" do
|
|
it "should accept a single-frame text message" do
|
|
em {
|
|
start_server { |ws|
|
|
ws.onmessage { |msg|
|
|
msg.should == 'Hello'
|
|
done
|
|
}
|
|
}
|
|
start_client { |client|
|
|
client.onopen {
|
|
client.send_data("\x04\x05Hello")
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should accept a fragmented text message" do
|
|
em {
|
|
start_server { |ws|
|
|
ws.onmessage { |msg|
|
|
msg.should == 'Hello'
|
|
done
|
|
}
|
|
}
|
|
|
|
connection = start_client
|
|
|
|
# Send frame
|
|
connection.onopen {
|
|
connection.send_data("\x84\x03Hel")
|
|
connection.send_data("\x00\x02lo")
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should accept a ping request and respond with the same body" do
|
|
em {
|
|
start_server
|
|
|
|
connection = start_client
|
|
|
|
# Send frame
|
|
connection.onopen {
|
|
connection.send_data("\x02\x05Hello")
|
|
}
|
|
|
|
connection.onmessage { |frame|
|
|
next if frame.nil?
|
|
frame.should == "\x03\x05Hello"
|
|
done
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should accept a 256 bytes binary message in a single frame" do
|
|
em {
|
|
data = "a" * 256
|
|
|
|
start_server { |ws|
|
|
ws.onbinary { |msg|
|
|
msg.encoding.should == Encoding.find("BINARY") if defined?(Encoding)
|
|
msg.should == data
|
|
done
|
|
}
|
|
}
|
|
|
|
connection = start_client
|
|
|
|
# Send frame
|
|
connection.onopen {
|
|
connection.send_data("\x05\x7E\x01\x00" + data)
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should accept a 64KiB binary message in a single frame" do
|
|
em {
|
|
data = "a" * 65536
|
|
|
|
start_server { |ws|
|
|
ws.onbinary { |msg|
|
|
msg.encoding.should == Encoding.find("BINARY") if defined?(Encoding)
|
|
msg.should == data
|
|
done
|
|
}
|
|
}
|
|
|
|
connection = start_client
|
|
|
|
# Send frame
|
|
connection.onopen {
|
|
connection.send_data("\x05\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data)
|
|
}
|
|
}
|
|
end
|
|
end
|
|
|
|
describe "close handling" do
|
|
it "should respond to a new close frame with a close frame" do
|
|
em {
|
|
start_server
|
|
|
|
connection = start_client
|
|
|
|
# Send close frame
|
|
connection.onopen {
|
|
connection.send_data("\x01\x00")
|
|
}
|
|
|
|
# Check that close ack received
|
|
connection.onmessage { |frame|
|
|
frame.should == "\x01\x00"
|
|
done
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should close the connection on receiving a close acknowlegement and call onclose with close code 1005 and was_clean=true (initiated by server)" do
|
|
em {
|
|
ack_received = false
|
|
|
|
start_server { |ws|
|
|
ws.onopen {
|
|
# 2. Send a close frame
|
|
EM.next_tick {
|
|
ws.close
|
|
}
|
|
}
|
|
|
|
# 5. Onclose event on server
|
|
ws.onclose { |event|
|
|
event.should == {
|
|
:code => 1005,
|
|
:reason => "",
|
|
:was_clean => true,
|
|
}
|
|
done
|
|
}
|
|
}
|
|
|
|
# 1. Create a fake client which sends draft 76 handshake
|
|
connection = start_client
|
|
|
|
# 3. Check that close frame recieved and acknowlege it
|
|
connection.onmessage { |frame|
|
|
frame.should == "\x01\x00"
|
|
ack_received = true
|
|
connection.send_data("\x01\x00")
|
|
}
|
|
|
|
# 4. Check that connection is closed _after_ the ack
|
|
connection.onclose {
|
|
ack_received.should == true
|
|
}
|
|
}
|
|
end
|
|
|
|
# it "should repur"
|
|
#
|
|
it "should return close code 1005 and was_clean=true after closing handshake (initiated by client)" do
|
|
em {
|
|
start_server { |ws|
|
|
ws.onclose { |event|
|
|
event.should == {
|
|
:code => 1005,
|
|
:reason => "",
|
|
:was_clean => true,
|
|
}
|
|
done
|
|
}
|
|
}
|
|
start_client { |client|
|
|
client.onopen {
|
|
client.send_data("\x01\x00")
|
|
}
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should not allow data frame to be sent after close frame sent" do
|
|
em {
|
|
start_server { |ws|
|
|
ws.onopen {
|
|
# 2. Send a close frame
|
|
EM.next_tick {
|
|
ws.close
|
|
}
|
|
|
|
# 3. Check that exception raised if I attempt to send more data
|
|
EM.add_timer(0.1) {
|
|
lambda {
|
|
ws.send('hello world')
|
|
}.should raise_error(EM::WebSocket::WebSocketError, 'Cannot send data frame since connection is closing')
|
|
done
|
|
}
|
|
}
|
|
}
|
|
|
|
# 1. Create a fake client which sends draft 76 handshake
|
|
start_client
|
|
}
|
|
end
|
|
|
|
it "should still respond to control frames after close frame sent" do
|
|
em {
|
|
start_server { |ws|
|
|
ws.onopen {
|
|
# 2. Send a close frame
|
|
EM.next_tick {
|
|
ws.close
|
|
}
|
|
}
|
|
}
|
|
|
|
# 1. Create a fake client which sends draft 76 handshake
|
|
connection = start_client
|
|
|
|
connection.onmessage { |frame|
|
|
if frame == "\x01\x00"
|
|
# 3. After the close frame is received send a ping frame, but
|
|
# don't respond with a close ack
|
|
connection.send_data("\x02\x05Hello")
|
|
else
|
|
# 4. Check that the pong is received
|
|
frame.should == "\x03\x05Hello"
|
|
done
|
|
end
|
|
}
|
|
}
|
|
end
|
|
|
|
it "should report that close codes are not supported" do
|
|
em {
|
|
start_server { |ws|
|
|
ws.onopen {
|
|
ws.supports_close_codes?.should == false
|
|
done
|
|
}
|
|
}
|
|
start_client
|
|
}
|
|
end
|
|
end
|
|
end
|