faye-websocket 0.4.7 → 0.5.0
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.
Potentially problematic release.
This version of faye-websocket might be problematic. Click here for more details.
- data/CHANGELOG.md +81 -0
- data/README.md +408 -0
- data/examples/app.rb +4 -1
- data/examples/autobahn_client.rb +8 -6
- data/examples/client.rb +2 -1
- data/examples/config.ru +6 -9
- data/{spec → examples}/rainbows.conf +0 -0
- data/examples/server.rb +10 -1
- data/lib/faye/adapters/rainbows.rb +15 -16
- data/lib/faye/adapters/rainbows_client.rb +15 -16
- data/lib/faye/adapters/thin.rb +15 -16
- data/lib/faye/eventsource.rb +38 -46
- data/lib/faye/rack_stream.rb +70 -0
- data/lib/faye/websocket.rb +39 -162
- data/lib/faye/websocket/api.rb +70 -60
- data/lib/faye/websocket/api/event.rb +1 -1
- data/lib/faye/websocket/api/event_target.rb +35 -12
- data/lib/faye/websocket/client.rb +5 -38
- metadata +62 -45
- data/CHANGELOG.txt +0 -74
- data/README.rdoc +0 -366
- data/ext/faye_websocket_mask/FayeWebsocketMaskService.java +0 -61
- data/ext/faye_websocket_mask/extconf.rb +0 -5
- data/ext/faye_websocket_mask/faye_websocket_mask.c +0 -33
- data/lib/faye/websocket/draft75_parser.rb +0 -87
- data/lib/faye/websocket/draft76_parser.rb +0 -84
- data/lib/faye/websocket/hybi_parser.rb +0 -321
- data/lib/faye/websocket/hybi_parser/handshake.rb +0 -78
- data/lib/faye/websocket/hybi_parser/stream_reader.rb +0 -29
- data/lib/faye/websocket/utf8_match.rb +0 -8
- data/spec/faye/websocket/client_spec.rb +0 -162
- data/spec/faye/websocket/draft75_parser_examples.rb +0 -48
- data/spec/faye/websocket/draft75_parser_spec.rb +0 -27
- data/spec/faye/websocket/draft76_parser_spec.rb +0 -34
- data/spec/faye/websocket/hybi_parser_spec.rb +0 -149
- data/spec/server.crt +0 -15
- data/spec/server.key +0 -15
- data/spec/spec_helper.rb +0 -68
@@ -1,78 +0,0 @@
|
|
1
|
-
module Faye
|
2
|
-
class WebSocket
|
3
|
-
class HybiParser
|
4
|
-
|
5
|
-
class Handshake
|
6
|
-
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
7
|
-
|
8
|
-
attr_reader :protocol
|
9
|
-
|
10
|
-
def initialize(uri, protocols)
|
11
|
-
@uri = uri
|
12
|
-
@protocols = protocols
|
13
|
-
@key = Base64.encode64((1..16).map { rand(255).chr } * '').strip
|
14
|
-
@accept = Base64.encode64(Digest::SHA1.digest(@key + GUID)).strip
|
15
|
-
@buffer = []
|
16
|
-
end
|
17
|
-
|
18
|
-
def request_data
|
19
|
-
hostname = @uri.host + (@uri.port ? ":#{@uri.port}" : '')
|
20
|
-
path = (@uri.path == '') ? '/' : @uri.path
|
21
|
-
headers = [
|
22
|
-
"GET #{path}#{@uri.query ? '?' : ''}#{@uri.query} HTTP/1.1",
|
23
|
-
"Host: #{hostname}",
|
24
|
-
"Upgrade: websocket",
|
25
|
-
"Connection: Upgrade",
|
26
|
-
"Sec-WebSocket-Key: #{@key}",
|
27
|
-
"Sec-WebSocket-Version: 13"
|
28
|
-
]
|
29
|
-
|
30
|
-
if @protocols
|
31
|
-
headers << "Sec-WebSocket-Protocol: #{@protocols * ', '}"
|
32
|
-
end
|
33
|
-
|
34
|
-
(headers + ['','']).join("\r\n")
|
35
|
-
end
|
36
|
-
|
37
|
-
def parse(data)
|
38
|
-
message = []
|
39
|
-
complete = false
|
40
|
-
data.each_byte do |byte|
|
41
|
-
if complete
|
42
|
-
message << byte
|
43
|
-
else
|
44
|
-
@buffer << byte
|
45
|
-
complete ||= complete?
|
46
|
-
end
|
47
|
-
end
|
48
|
-
message
|
49
|
-
end
|
50
|
-
|
51
|
-
def complete?
|
52
|
-
@buffer[-4..-1] == [0x0D, 0x0A, 0x0D, 0x0A]
|
53
|
-
end
|
54
|
-
|
55
|
-
def valid?
|
56
|
-
data = WebSocket.encode(@buffer)
|
57
|
-
|
58
|
-
response = Net::HTTPResponse.read_new(Net::BufferedIO.new(StringIO.new(data)))
|
59
|
-
return false unless response.code.to_i == 101
|
60
|
-
|
61
|
-
upgrade = response['Upgrade']
|
62
|
-
connection = response['Connection']
|
63
|
-
protocol = response['Sec-WebSocket-Protocol']
|
64
|
-
|
65
|
-
@protocol = @protocols && @protocols.include?(protocol) ?
|
66
|
-
protocol :
|
67
|
-
nil
|
68
|
-
|
69
|
-
upgrade and upgrade =~ /^websocket$/i and
|
70
|
-
connection and connection.split(/\s*,\s*/).include?('Upgrade') and
|
71
|
-
((!@protocols and !protocol) or @protocol) and
|
72
|
-
response['Sec-WebSocket-Accept'] == @accept
|
73
|
-
end
|
74
|
-
end
|
75
|
-
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
@@ -1,29 +0,0 @@
|
|
1
|
-
module Faye
|
2
|
-
class WebSocket
|
3
|
-
class HybiParser
|
4
|
-
|
5
|
-
class StreamReader
|
6
|
-
def initialize
|
7
|
-
@queue = []
|
8
|
-
end
|
9
|
-
|
10
|
-
def read(length)
|
11
|
-
read_bytes(length)
|
12
|
-
end
|
13
|
-
|
14
|
-
def put(bytes)
|
15
|
-
return unless bytes and bytes.size > 0
|
16
|
-
@queue.concat(bytes)
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
def read_bytes(length)
|
22
|
-
return nil if length > @queue.size
|
23
|
-
@queue.shift(length)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
@@ -1,8 +0,0 @@
|
|
1
|
-
module Faye
|
2
|
-
class WebSocket
|
3
|
-
|
4
|
-
# http://www.w3.org/International/questions/qa-forms-utf-8.en.php
|
5
|
-
UTF8_MATCH = /^([\x00-\x7F]|[\xC2-\xDF][\x80-\xBF]|\xE0[\xA0-\xBF][\x80-\xBF]|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}|\xED[\x80-\x9F][\x80-\xBF]|\xF0[\x90-\xBF][\x80-\xBF]{2}|[\xF1-\xF3][\x80-\xBF]{3}|\xF4[\x80-\x8F][\x80-\xBF]{2})*$/
|
6
|
-
|
7
|
-
end
|
8
|
-
end
|
@@ -1,162 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
WebSocketSteps = EM::RSpec.async_steps do
|
6
|
-
def server(port, backend, secure, &callback)
|
7
|
-
@server = EchoServer.new
|
8
|
-
@server.listen(port, backend, secure)
|
9
|
-
@port = port
|
10
|
-
EM.add_timer(0.1, &callback)
|
11
|
-
end
|
12
|
-
|
13
|
-
def stop(&callback)
|
14
|
-
@server.stop
|
15
|
-
EM.next_tick(&callback)
|
16
|
-
end
|
17
|
-
|
18
|
-
def open_socket(url, protocols, &callback)
|
19
|
-
done = false
|
20
|
-
|
21
|
-
resume = lambda do |open|
|
22
|
-
unless done
|
23
|
-
done = true
|
24
|
-
@open = open
|
25
|
-
callback.call
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
@ws = Faye::WebSocket::Client.new(url, protocols)
|
30
|
-
|
31
|
-
@ws.onopen = lambda { |e| resume.call(true) }
|
32
|
-
@ws.onclose = lambda { |e| resume.call(false) }
|
33
|
-
end
|
34
|
-
|
35
|
-
def close_socket(&callback)
|
36
|
-
@ws.onclose = lambda do |e|
|
37
|
-
@open = false
|
38
|
-
callback.call
|
39
|
-
end
|
40
|
-
@ws.close
|
41
|
-
end
|
42
|
-
|
43
|
-
def check_open(&callback)
|
44
|
-
@open.should == true
|
45
|
-
callback.call
|
46
|
-
end
|
47
|
-
|
48
|
-
def check_closed(&callback)
|
49
|
-
@open.should == false
|
50
|
-
callback.call
|
51
|
-
end
|
52
|
-
|
53
|
-
def check_protocol(protocol, &callback)
|
54
|
-
@ws.protocol.should == protocol
|
55
|
-
callback.call
|
56
|
-
end
|
57
|
-
|
58
|
-
def listen_for_message(&callback)
|
59
|
-
@ws.add_event_listener('message', lambda { |e| @message = e.data })
|
60
|
-
callback.call
|
61
|
-
end
|
62
|
-
|
63
|
-
def send_message(message, &callback)
|
64
|
-
@ws.send(message)
|
65
|
-
EM.add_timer(0.1, &callback)
|
66
|
-
end
|
67
|
-
|
68
|
-
def check_response(message, &callback)
|
69
|
-
@message.should == message
|
70
|
-
callback.call
|
71
|
-
end
|
72
|
-
|
73
|
-
def check_no_response(&callback)
|
74
|
-
@message.should == nil
|
75
|
-
callback.call
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
describe Faye::WebSocket::Client do
|
80
|
-
next if Faye::WebSocket.jruby?
|
81
|
-
include WebSocketSteps
|
82
|
-
|
83
|
-
let(:protocols) { ["foo", "echo"] }
|
84
|
-
let(:plain_text_url) { "ws://0.0.0.0:8000/" }
|
85
|
-
let(:secure_url) { "wss://0.0.0.0:8000/" }
|
86
|
-
|
87
|
-
shared_examples_for "socket client" do
|
88
|
-
it "can open a connection" do
|
89
|
-
open_socket(socket_url, protocols)
|
90
|
-
check_open
|
91
|
-
check_protocol("echo")
|
92
|
-
end
|
93
|
-
|
94
|
-
it "cannot open a connection to the wrong host" do
|
95
|
-
open_socket(blocked_url, protocols)
|
96
|
-
check_closed
|
97
|
-
end
|
98
|
-
|
99
|
-
it "cannot open a connection with unacceptable protocols" do
|
100
|
-
open_socket(socket_url, ["foo"])
|
101
|
-
check_closed
|
102
|
-
end
|
103
|
-
|
104
|
-
it "can close the connection" do
|
105
|
-
open_socket(socket_url, protocols)
|
106
|
-
close_socket
|
107
|
-
check_closed
|
108
|
-
end
|
109
|
-
|
110
|
-
describe "in the OPEN state" do
|
111
|
-
before { open_socket(socket_url, protocols) }
|
112
|
-
|
113
|
-
it "can send and receive messages" do
|
114
|
-
listen_for_message
|
115
|
-
send_message "I expect this to be echoed"
|
116
|
-
check_response "I expect this to be echoed"
|
117
|
-
end
|
118
|
-
|
119
|
-
it "sends numbers as strings" do
|
120
|
-
listen_for_message
|
121
|
-
send_message 13
|
122
|
-
check_response "13"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe "in the CLOSED state" do
|
127
|
-
before do
|
128
|
-
open_socket(socket_url, protocols)
|
129
|
-
close_socket
|
130
|
-
end
|
131
|
-
|
132
|
-
it "cannot send and receive messages" do
|
133
|
-
listen_for_message
|
134
|
-
send_message "I expect this to be echoed"
|
135
|
-
check_no_response
|
136
|
-
end
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe "with a plain-text Thin server" do
|
141
|
-
let(:socket_url) { plain_text_url }
|
142
|
-
let(:blocked_url) { secure_url }
|
143
|
-
|
144
|
-
before { server 8000, :thin, false }
|
145
|
-
after { stop }
|
146
|
-
|
147
|
-
it_should_behave_like "socket client"
|
148
|
-
end
|
149
|
-
|
150
|
-
describe "with a secure Thin server" do
|
151
|
-
next if Faye::WebSocket.rbx?
|
152
|
-
|
153
|
-
let(:socket_url) { secure_url }
|
154
|
-
let(:blocked_url) { plain_text_url }
|
155
|
-
|
156
|
-
before { server 8000, :thin, true }
|
157
|
-
after { stop }
|
158
|
-
|
159
|
-
it_should_behave_like "socket client"
|
160
|
-
end
|
161
|
-
end
|
162
|
-
|
@@ -1,48 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
shared_examples_for "draft-75 parser" do
|
6
|
-
it "parses text frames" do
|
7
|
-
@web_socket.should_receive(:receive).with("Hello")
|
8
|
-
parse [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
9
|
-
end
|
10
|
-
|
11
|
-
it "parses multiple frames from the same packet" do
|
12
|
-
@web_socket.should_receive(:receive).with("Hello").exactly(2)
|
13
|
-
parse [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
14
|
-
end
|
15
|
-
|
16
|
-
it "parses text frames beginning 0x00-0x7F" do
|
17
|
-
@web_socket.should_receive(:receive).with("Hello")
|
18
|
-
parse [0x66, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
19
|
-
end
|
20
|
-
|
21
|
-
it "ignores frames with a length header" do
|
22
|
-
@web_socket.should_not_receive(:receive)
|
23
|
-
parse [0x80, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
24
|
-
end
|
25
|
-
|
26
|
-
it "parses text following an ignored block" do
|
27
|
-
@web_socket.should_receive(:receive).with("Hello")
|
28
|
-
parse [0x80, 0x02, 0x48, 0x65, 0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
29
|
-
end
|
30
|
-
|
31
|
-
it "parses multibyte text frames" do
|
32
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
33
|
-
parse [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]
|
34
|
-
end
|
35
|
-
|
36
|
-
it "parses frames received in several packets" do
|
37
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
38
|
-
parse [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65]
|
39
|
-
parse [0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]
|
40
|
-
end
|
41
|
-
|
42
|
-
it "parses fragmented frames" do
|
43
|
-
@web_socket.should_receive(:receive).with("Hello")
|
44
|
-
parse [0x00, 0x48, 0x65, 0x6c]
|
45
|
-
parse [0x6c, 0x6f, 0xff]
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
@@ -1,27 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
describe Faye::WebSocket::Draft75Parser do
|
6
|
-
include EncodingHelper
|
7
|
-
|
8
|
-
before do
|
9
|
-
@web_socket = mock Faye::WebSocket
|
10
|
-
@parser = Faye::WebSocket::Draft75Parser.new(@web_socket)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe :parse do
|
14
|
-
it_should_behave_like "draft-75 parser"
|
15
|
-
end
|
16
|
-
|
17
|
-
describe :frame do
|
18
|
-
it "returns the given string formatted as a WebSocket frame" do
|
19
|
-
bytes(@parser.frame "Hello").should == [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
20
|
-
end
|
21
|
-
|
22
|
-
it "encodes multibyte characters correctly" do
|
23
|
-
message = encode "Apple = "
|
24
|
-
bytes(@parser.frame message).should == [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
describe Faye::WebSocket::Draft76Parser do
|
6
|
-
include EncodingHelper
|
7
|
-
|
8
|
-
before do
|
9
|
-
@web_socket = mock Faye::WebSocket
|
10
|
-
@parser = Faye::WebSocket::Draft76Parser.new(@web_socket)
|
11
|
-
@parser.instance_eval { @handshake_complete = true }
|
12
|
-
end
|
13
|
-
|
14
|
-
describe :parse do
|
15
|
-
it_should_behave_like "draft-75 parser"
|
16
|
-
|
17
|
-
it "closes the socket if a close frame is received" do
|
18
|
-
@web_socket.should_receive(:close)
|
19
|
-
parse [0xFF, 0x00]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
describe :frame do
|
24
|
-
it "returns the given string formatted as a WebSocket frame" do
|
25
|
-
bytes(@parser.frame "Hello").should == [0x00, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0xff]
|
26
|
-
end
|
27
|
-
|
28
|
-
it "encodes multibyte characters correctly" do
|
29
|
-
message = encode "Apple = "
|
30
|
-
bytes(@parser.frame message).should == [0x00, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf, 0xff]
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
@@ -1,149 +0,0 @@
|
|
1
|
-
# encoding=utf-8
|
2
|
-
|
3
|
-
require "spec_helper"
|
4
|
-
|
5
|
-
describe Faye::WebSocket::HybiParser do
|
6
|
-
include EncodingHelper
|
7
|
-
|
8
|
-
before do
|
9
|
-
@web_socket = mock Faye::WebSocket
|
10
|
-
@parser = Faye::WebSocket::HybiParser.new(@web_socket)
|
11
|
-
end
|
12
|
-
|
13
|
-
describe :parse do
|
14
|
-
let(:mask) { (1..4).map { rand 255 } }
|
15
|
-
|
16
|
-
def mask_message(*bytes)
|
17
|
-
output = []
|
18
|
-
bytes.each_with_index do |byte, i|
|
19
|
-
output[i] = byte ^ mask[i % 4]
|
20
|
-
end
|
21
|
-
output
|
22
|
-
end
|
23
|
-
|
24
|
-
it "parses unmasked text frames" do
|
25
|
-
@web_socket.should_receive(:receive).with("Hello")
|
26
|
-
parse [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
27
|
-
end
|
28
|
-
|
29
|
-
it "parses multiple frames from the same packet" do
|
30
|
-
@web_socket.should_receive(:receive).with("Hello").exactly(2)
|
31
|
-
parse [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
32
|
-
end
|
33
|
-
|
34
|
-
it "parses empty text frames" do
|
35
|
-
@web_socket.should_receive(:receive).with("")
|
36
|
-
parse [0x81, 0x00]
|
37
|
-
end
|
38
|
-
|
39
|
-
it "parses fragmented text frames" do
|
40
|
-
@web_socket.should_receive(:receive).with("Hello")
|
41
|
-
parse [0x01, 0x03, 0x48, 0x65, 0x6c]
|
42
|
-
parse [0x80, 0x02, 0x6c, 0x6f]
|
43
|
-
end
|
44
|
-
|
45
|
-
it "parses masked text frames" do
|
46
|
-
@web_socket.should_receive(:receive).with("Hello")
|
47
|
-
parse [0x81, 0x85] + mask + mask_message(0x48, 0x65, 0x6c, 0x6c, 0x6f)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "parses masked empty text frames" do
|
51
|
-
@web_socket.should_receive(:receive).with("")
|
52
|
-
parse [0x81, 0x80] + mask + mask_message()
|
53
|
-
end
|
54
|
-
|
55
|
-
it "parses masked fragmented text frames" do
|
56
|
-
@web_socket.should_receive(:receive).with("Hello")
|
57
|
-
parse [0x01, 0x81] + mask + mask_message(0x48)
|
58
|
-
parse [0x80, 0x84] + mask + mask_message(0x65, 0x6c, 0x6c, 0x6f)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "closes the socket if the frame has an unrecognized opcode" do
|
62
|
-
@web_socket.should_receive(:close).with(1002, nil, false)
|
63
|
-
parse [0x83, 0x00]
|
64
|
-
end
|
65
|
-
|
66
|
-
it "closes the socket if a close frame is received" do
|
67
|
-
@web_socket.should_receive(:close).with(1000, "Hello", false)
|
68
|
-
parse [0x88, 0x07, 0x03, 0xe8, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
69
|
-
end
|
70
|
-
|
71
|
-
it "parses unmasked multibyte text frames" do
|
72
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
73
|
-
parse [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]
|
74
|
-
end
|
75
|
-
|
76
|
-
it "parses frames received in several packets" do
|
77
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
78
|
-
parse [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c]
|
79
|
-
parse [0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]
|
80
|
-
end
|
81
|
-
|
82
|
-
it "parses fragmented multibyte text frames" do
|
83
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
84
|
-
parse [0x01, 0x0a, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3]
|
85
|
-
parse [0x80, 0x01, 0xbf]
|
86
|
-
end
|
87
|
-
|
88
|
-
it "parses masked multibyte text frames" do
|
89
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
90
|
-
parse [0x81, 0x8b] + mask + mask_message(0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf)
|
91
|
-
end
|
92
|
-
|
93
|
-
it "parses masked fragmented multibyte text frames" do
|
94
|
-
@web_socket.should_receive(:receive).with(encode "Apple = ")
|
95
|
-
parse [0x01, 0x8a] + mask + mask_message(0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3)
|
96
|
-
parse [0x80, 0x81] + mask + mask_message(0xbf)
|
97
|
-
end
|
98
|
-
|
99
|
-
it "parses unmasked medium-length text frames" do
|
100
|
-
@web_socket.should_receive(:receive).with("Hello" * 40)
|
101
|
-
parse [0x81, 0x7e, 0x00, 0xc8] + [0x48, 0x65, 0x6c, 0x6c, 0x6f] * 40
|
102
|
-
end
|
103
|
-
|
104
|
-
it "parses masked medium-length text frames" do
|
105
|
-
@web_socket.should_receive(:receive).with("Hello" * 40)
|
106
|
-
parse [0x81, 0xfe, 0x00, 0xc8] + mask + mask_message(*([0x48, 0x65, 0x6c, 0x6c, 0x6f] * 40))
|
107
|
-
end
|
108
|
-
|
109
|
-
it "replies to pings with a pong" do
|
110
|
-
@web_socket.should_receive(:send).with([0x4f, 0x48, 0x41, 0x49], :pong)
|
111
|
-
parse [0x89, 0x04, 0x4f, 0x48, 0x41, 0x49]
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
describe :frame do
|
116
|
-
it "returns the given string formatted as a WebSocket frame" do
|
117
|
-
bytes(@parser.frame "Hello").should == [0x81, 0x05, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
118
|
-
end
|
119
|
-
|
120
|
-
it "encodes multibyte characters correctly" do
|
121
|
-
message = encode "Apple = "
|
122
|
-
bytes(@parser.frame message).should == [0x81, 0x0b, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x20, 0x3d, 0x20, 0xef, 0xa3, 0xbf]
|
123
|
-
end
|
124
|
-
|
125
|
-
it "encodes medium-length strings using extra length bytes" do
|
126
|
-
message = "Hello" * 40
|
127
|
-
bytes(@parser.frame message).should == [0x81, 0x7e, 0x00, 0xc8] + [0x48, 0x65, 0x6c, 0x6c, 0x6f] * 40
|
128
|
-
end
|
129
|
-
|
130
|
-
it "encodes close frames with an error code" do
|
131
|
-
frame = @parser.frame "Hello", :close, 1002
|
132
|
-
bytes(frame).should == [0x88, 0x07, 0x03, 0xea, 0x48, 0x65, 0x6c, 0x6c, 0x6f]
|
133
|
-
end
|
134
|
-
|
135
|
-
it "encodes pong frames" do
|
136
|
-
bytes(@parser.frame '', :pong).should == [0x8a, 0x00]
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
describe :utf8 do
|
141
|
-
it "detects valid UTF-8" do
|
142
|
-
Faye::WebSocket.valid_utf8?( [72, 101, 108, 108, 111, 45, 194, 181, 64, 195, 159, 195, 182, 195, 164, 195, 188, 195, 160, 195, 161, 45, 85, 84, 70, 45, 56, 33, 33] ).should be_true
|
143
|
-
end
|
144
|
-
|
145
|
-
it "detects invalid UTF-8" do
|
146
|
-
Faye::WebSocket.valid_utf8?( [206, 186, 225, 189, 185, 207, 131, 206, 188, 206, 181, 237, 160, 128, 101, 100, 105, 116, 101, 100] ).should be_false
|
147
|
-
end
|
148
|
-
end
|
149
|
-
end
|