em-websocket 0.3.2 → 0.3.5
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +5 -0
- data/examples/flash_policy_file_server.rb +21 -0
- data/examples/multicast.rb +5 -3
- data/lib/em-websocket.rb +1 -1
- data/lib/em-websocket/handler13.rb +10 -0
- data/lib/em-websocket/handler_factory.rb +6 -0
- data/lib/em-websocket/version.rb +1 -1
- data/spec/helper.rb +27 -5
- data/spec/integration/common_spec.rb +18 -15
- data/spec/integration/draft03_spec.rb +28 -25
- data/spec/integration/draft05_spec.rb +5 -2
- data/spec/integration/draft06_spec.rb +12 -7
- data/spec/integration/draft13_spec.rb +65 -0
- data/spec/integration/draft75_spec.rb +15 -13
- data/spec/integration/draft76_spec.rb +27 -24
- data/spec/integration/shared_examples.rb +9 -9
- metadata +40 -14
data/CHANGELOG.rdoc
CHANGED
@@ -0,0 +1,21 @@
|
|
1
|
+
# Super simple flash policy file server
|
2
|
+
# See https://github.com/igrigorik/em-websocket/issues/61
|
3
|
+
|
4
|
+
require 'eventmachine'
|
5
|
+
|
6
|
+
module FlashPolicy
|
7
|
+
def post_init
|
8
|
+
cross_domain_xml =<<-EOF
|
9
|
+
<cross-domain-policy>
|
10
|
+
<allow-access-from domain="*" to-ports="*" />
|
11
|
+
</cross-domain-policy>
|
12
|
+
EOF
|
13
|
+
|
14
|
+
send_data cross_domain_xml
|
15
|
+
close_connection_after_writing
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
EM.run {
|
20
|
+
EventMachine::start_server '0.0.0.0', 843, FlashPolicy
|
21
|
+
}
|
data/examples/multicast.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'em-websocket'
|
2
|
+
# requires the twitter-stream gem
|
2
3
|
require 'twitter/json_stream'
|
3
4
|
require 'json'
|
4
5
|
|
@@ -15,7 +16,8 @@ EventMachine.run {
|
|
15
16
|
|
16
17
|
@twitter = Twitter::JSONStream.connect(
|
17
18
|
:path => '/1/statuses/filter.json?track=ruby',
|
18
|
-
:auth => "#{username}:#{password}"
|
19
|
+
:auth => "#{username}:#{password}",
|
20
|
+
:ssl => true
|
19
21
|
)
|
20
22
|
|
21
23
|
@twitter.each_item do |status|
|
@@ -37,8 +39,8 @@ EventMachine.run {
|
|
37
39
|
ws.onclose {
|
38
40
|
@channel.unsubscribe(sid)
|
39
41
|
}
|
40
|
-
|
41
42
|
}
|
43
|
+
|
42
44
|
end
|
43
45
|
|
44
46
|
puts "Server started"
|
data/lib/em-websocket.rb
CHANGED
@@ -9,7 +9,7 @@ require "eventmachine"
|
|
9
9
|
close75 close03 close05 close06
|
10
10
|
masking04
|
11
11
|
message_processor_03 message_processor_06
|
12
|
-
handler_factory handler handler75 handler76 handler03 handler05 handler06 handler07 handler08
|
12
|
+
handler_factory handler handler75 handler76 handler03 handler05 handler06 handler07 handler08 handler13
|
13
13
|
].each do |file|
|
14
14
|
require "em-websocket/#{file}"
|
15
15
|
end
|
@@ -90,7 +90,13 @@ module EventMachine
|
|
90
90
|
when 7
|
91
91
|
Handler07.new(connection, request, debug)
|
92
92
|
when 8
|
93
|
+
# drafts 9, 10, 11 and 12 should never change the version
|
94
|
+
# number as they are all the same as version 08.
|
93
95
|
Handler08.new(connection, request, debug)
|
96
|
+
when 13
|
97
|
+
# drafts 13 to 17 all identify as version 13 as they are
|
98
|
+
# only minor changes or text changes.
|
99
|
+
Handler13.new(connection, request, debug)
|
94
100
|
else
|
95
101
|
# According to spec should abort the connection
|
96
102
|
raise WebSocketError, "Protocol version #{version} not supported"
|
data/lib/em-websocket/version.rb
CHANGED
data/spec/helper.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rspec'
|
3
|
+
require 'em-spec/rspec'
|
3
4
|
require 'pp'
|
4
5
|
require 'em-http'
|
5
6
|
|
@@ -68,6 +69,32 @@ class Draft03FakeWebSocketClient < FakeWebSocketClient
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
72
|
+
class Draft07FakeWebSocketClient < FakeWebSocketClient
|
73
|
+
def send(application_data)
|
74
|
+
frame = ''
|
75
|
+
opcode = 1 # fake only supports text frames
|
76
|
+
byte1 = opcode | 0b10000000 # since more, rsv1-3 are 0
|
77
|
+
frame << byte1
|
78
|
+
|
79
|
+
length = application_data.size
|
80
|
+
if length <= 125
|
81
|
+
byte2 = length # since rsv4 is 0
|
82
|
+
frame << byte2
|
83
|
+
elsif length < 65536 # write 2 byte length
|
84
|
+
frame << 126
|
85
|
+
frame << [length].pack('n')
|
86
|
+
else # write 8 byte length
|
87
|
+
frame << 127
|
88
|
+
frame << [length >> 32, length & 0xFFFFFFFF].pack("NN")
|
89
|
+
end
|
90
|
+
|
91
|
+
frame << application_data
|
92
|
+
|
93
|
+
send_data(frame)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
71
98
|
# Wrap EM:HttpRequest in a websocket like interface so that it can be used in the specs with the same interface as FakeWebSocketClient
|
72
99
|
class Draft75WebSocketClient
|
73
100
|
def onopen(&blk); @onopen = blk; end
|
@@ -91,11 +118,6 @@ class Draft75WebSocketClient
|
|
91
118
|
end
|
92
119
|
end
|
93
120
|
|
94
|
-
def failed
|
95
|
-
EventMachine.stop
|
96
|
-
fail
|
97
|
-
end
|
98
|
-
|
99
121
|
def format_request(r)
|
100
122
|
data = "#{r[:method]} #{r[:path]} HTTP/1.1\r\n"
|
101
123
|
header_lines = r[:headers].map { |k,v| "#{k}: #{v}" }
|
@@ -3,23 +3,26 @@ require 'helper'
|
|
3
3
|
# These tests are not specifi to any particular draft of the specification
|
4
4
|
#
|
5
5
|
describe "WebSocket server" do
|
6
|
+
include EM::SpecHelper
|
7
|
+
default_timeout 1
|
8
|
+
|
6
9
|
it "should fail on non WebSocket requests" do
|
7
|
-
|
10
|
+
em {
|
8
11
|
EventMachine.add_timer(0.1) do
|
9
12
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:12345/').get :timeout => 0
|
10
|
-
http.errback {
|
11
|
-
http.callback {
|
13
|
+
http.errback { done }
|
14
|
+
http.callback { fail }
|
12
15
|
end
|
13
16
|
|
14
17
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) {}
|
15
|
-
|
18
|
+
}
|
16
19
|
end
|
17
20
|
|
18
21
|
it "should populate ws.request with appropriate headers" do
|
19
|
-
|
22
|
+
em {
|
20
23
|
EventMachine.add_timer(0.1) do
|
21
24
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
22
|
-
http.errback {
|
25
|
+
http.errback { fail }
|
23
26
|
http.callback {
|
24
27
|
http.response_header.status.should == 101
|
25
28
|
http.close_connection
|
@@ -41,14 +44,14 @@ describe "WebSocket server" do
|
|
41
44
|
EventMachine.stop
|
42
45
|
}
|
43
46
|
end
|
44
|
-
|
47
|
+
}
|
45
48
|
end
|
46
49
|
|
47
50
|
it "should allow sending and retrieving query string args passed in on the connection request." do
|
48
|
-
|
51
|
+
em {
|
49
52
|
EventMachine.add_timer(0.1) do
|
50
53
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get(:query => {'foo' => 'bar', 'baz' => 'qux'}, :timeout => 0)
|
51
|
-
http.errback {
|
54
|
+
http.errback { fail }
|
52
55
|
http.callback {
|
53
56
|
http.response_header.status.should == 101
|
54
57
|
http.close_connection
|
@@ -69,14 +72,14 @@ describe "WebSocket server" do
|
|
69
72
|
EventMachine.stop
|
70
73
|
}
|
71
74
|
end
|
72
|
-
|
75
|
+
}
|
73
76
|
end
|
74
77
|
|
75
78
|
it "should ws.response['Query'] to empty hash when no query string params passed in connection URI" do
|
76
|
-
|
79
|
+
em {
|
77
80
|
EventMachine.add_timer(0.1) do
|
78
81
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get(:timeout => 0)
|
79
|
-
http.errback {
|
82
|
+
http.errback { fail }
|
80
83
|
http.callback {
|
81
84
|
http.response_header.status.should == 101
|
82
85
|
http.close_connection
|
@@ -94,18 +97,18 @@ describe "WebSocket server" do
|
|
94
97
|
EventMachine.stop
|
95
98
|
}
|
96
99
|
end
|
97
|
-
|
100
|
+
}
|
98
101
|
end
|
99
102
|
|
100
103
|
it "should raise an exception if frame sent before handshake complete" do
|
101
|
-
|
104
|
+
em {
|
102
105
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |c|
|
103
106
|
# We're not using a real client so the handshake will not be sent
|
104
107
|
EM.add_timer(0.1) {
|
105
108
|
lambda {
|
106
109
|
c.send('early message')
|
107
110
|
}.should raise_error('Cannot send data before onopen callback')
|
108
|
-
|
111
|
+
done
|
109
112
|
}
|
110
113
|
}
|
111
114
|
|
@@ -2,6 +2,9 @@ require 'helper'
|
|
2
2
|
require 'integration/shared_examples'
|
3
3
|
|
4
4
|
describe "draft03" do
|
5
|
+
include EM::SpecHelper
|
6
|
+
default_timeout 1
|
7
|
+
|
5
8
|
before :each do
|
6
9
|
@request = {
|
7
10
|
:port => 80,
|
@@ -50,11 +53,11 @@ describe "draft03" do
|
|
50
53
|
# http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-03#section-4.6
|
51
54
|
describe "examples from the spec" do
|
52
55
|
it "should accept a single-frame text message" do
|
53
|
-
|
56
|
+
em {
|
54
57
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
55
58
|
ws.onmessage { |msg|
|
56
59
|
msg.should == 'Hello'
|
57
|
-
|
60
|
+
done
|
58
61
|
}
|
59
62
|
}
|
60
63
|
|
@@ -66,15 +69,15 @@ describe "draft03" do
|
|
66
69
|
connection.onopen {
|
67
70
|
connection.send_data("\x04\x05Hello")
|
68
71
|
}
|
69
|
-
|
72
|
+
}
|
70
73
|
end
|
71
74
|
|
72
75
|
it "should accept a fragmented text message" do
|
73
|
-
|
76
|
+
em {
|
74
77
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
75
78
|
ws.onmessage { |msg|
|
76
79
|
msg.should == 'Hello'
|
77
|
-
|
80
|
+
done
|
78
81
|
}
|
79
82
|
}
|
80
83
|
|
@@ -87,11 +90,11 @@ describe "draft03" do
|
|
87
90
|
connection.send_data("\x84\x03Hel")
|
88
91
|
connection.send_data("\x00\x02lo")
|
89
92
|
}
|
90
|
-
|
93
|
+
}
|
91
94
|
end
|
92
95
|
|
93
96
|
it "should accept a ping request and respond with the same body" do
|
94
|
-
|
97
|
+
em {
|
95
98
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws| }
|
96
99
|
|
97
100
|
# Create a fake client which sends draft 76 handshake
|
@@ -106,19 +109,19 @@ describe "draft03" do
|
|
106
109
|
connection.onmessage { |frame|
|
107
110
|
next if frame.nil?
|
108
111
|
frame.should == "\x03\x05Hello"
|
109
|
-
|
112
|
+
done
|
110
113
|
}
|
111
|
-
|
114
|
+
}
|
112
115
|
end
|
113
116
|
|
114
117
|
it "should accept a 256 bytes binary message in a single frame" do
|
115
|
-
|
118
|
+
em {
|
116
119
|
data = "a" * 256
|
117
120
|
|
118
121
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
119
122
|
ws.onmessage { |msg|
|
120
123
|
msg.should == data
|
121
|
-
|
124
|
+
done
|
122
125
|
}
|
123
126
|
}
|
124
127
|
|
@@ -130,17 +133,17 @@ describe "draft03" do
|
|
130
133
|
connection.onopen {
|
131
134
|
connection.send_data("\x05\x7E\x01\x00" + data)
|
132
135
|
}
|
133
|
-
|
136
|
+
}
|
134
137
|
end
|
135
138
|
|
136
139
|
it "should accept a 64KiB binary message in a single frame" do
|
137
|
-
|
140
|
+
em {
|
138
141
|
data = "a" * 65536
|
139
142
|
|
140
143
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
141
144
|
ws.onmessage { |msg|
|
142
145
|
msg.should == data
|
143
|
-
|
146
|
+
done
|
144
147
|
}
|
145
148
|
}
|
146
149
|
|
@@ -152,13 +155,13 @@ describe "draft03" do
|
|
152
155
|
connection.onopen {
|
153
156
|
connection.send_data("\x05\x7F\x00\x00\x00\x00\x00\x01\x00\x00" + data)
|
154
157
|
}
|
155
|
-
|
158
|
+
}
|
156
159
|
end
|
157
160
|
end
|
158
161
|
|
159
162
|
describe "close handling" do
|
160
163
|
it "should respond to a new close frame with a close frame" do
|
161
|
-
|
164
|
+
em {
|
162
165
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws| }
|
163
166
|
|
164
167
|
# Create a fake client which sends draft 76 handshake
|
@@ -173,13 +176,13 @@ describe "draft03" do
|
|
173
176
|
# Check that close ack received
|
174
177
|
connection.onmessage { |frame|
|
175
178
|
frame.should == "\x01\x00"
|
176
|
-
|
179
|
+
done
|
177
180
|
}
|
178
|
-
|
181
|
+
}
|
179
182
|
end
|
180
183
|
|
181
184
|
it "should close the connection on receiving a close acknowlegement" do
|
182
|
-
|
185
|
+
em {
|
183
186
|
ack_received = false
|
184
187
|
|
185
188
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
@@ -205,13 +208,13 @@ describe "draft03" do
|
|
205
208
|
# 4. Check that connection is closed _after_ the ack
|
206
209
|
connection.onclose {
|
207
210
|
ack_received.should == true
|
208
|
-
|
211
|
+
done
|
209
212
|
}
|
210
|
-
|
213
|
+
}
|
211
214
|
end
|
212
215
|
|
213
216
|
it "should not allow data frame to be sent after close frame sent" do
|
214
|
-
|
217
|
+
em {
|
215
218
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
216
219
|
ws.onopen {
|
217
220
|
# 2. Send a close frame
|
@@ -224,7 +227,7 @@ describe "draft03" do
|
|
224
227
|
lambda {
|
225
228
|
ws.send('hello world')
|
226
229
|
}.should raise_error(EM::WebSocket::WebSocketError, 'Cannot send data frame since connection is closing')
|
227
|
-
|
230
|
+
done
|
228
231
|
}
|
229
232
|
}
|
230
233
|
}
|
@@ -236,7 +239,7 @@ describe "draft03" do
|
|
236
239
|
end
|
237
240
|
|
238
241
|
it "should still respond to control frames after close frame sent" do
|
239
|
-
|
242
|
+
em {
|
240
243
|
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
241
244
|
ws.onopen {
|
242
245
|
# 2. Send a close frame
|
@@ -258,7 +261,7 @@ describe "draft03" do
|
|
258
261
|
else
|
259
262
|
# 4. Check that the pong is received
|
260
263
|
frame.should == "\x03\x05Hello"
|
261
|
-
|
264
|
+
done
|
262
265
|
end
|
263
266
|
}
|
264
267
|
}
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe "draft05" do
|
4
|
+
include EM::SpecHelper
|
5
|
+
default_timeout 1
|
6
|
+
|
4
7
|
before :each do
|
5
8
|
@request = {
|
6
9
|
:port => 80,
|
@@ -31,11 +34,11 @@ describe "draft05" do
|
|
31
34
|
end
|
32
35
|
|
33
36
|
it "should open connection" do
|
34
|
-
|
37
|
+
em {
|
35
38
|
start_server { |server|
|
36
39
|
server.onopen {
|
37
40
|
server.instance_variable_get(:@handler).class.should == EventMachine::WebSocket::Handler05
|
38
|
-
|
41
|
+
done
|
39
42
|
}
|
40
43
|
}
|
41
44
|
|
@@ -1,6 +1,9 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
describe "draft06" do
|
4
|
+
include EM::SpecHelper
|
5
|
+
default_timeout 1
|
6
|
+
|
4
7
|
before :each do
|
5
8
|
@request = {
|
6
9
|
:port => 80,
|
@@ -40,7 +43,7 @@ describe "draft06" do
|
|
40
43
|
end
|
41
44
|
|
42
45
|
it "should open connection" do
|
43
|
-
|
46
|
+
em {
|
44
47
|
start_server { |server|
|
45
48
|
server.onopen {
|
46
49
|
server.instance_variable_get(:@handler).class.should == EventMachine::WebSocket::Handler06
|
@@ -51,22 +54,24 @@ describe "draft06" do
|
|
51
54
|
client.onopen {
|
52
55
|
client.handshake_response.lines.sort.
|
53
56
|
should == format_response(@response).lines.sort
|
54
|
-
|
57
|
+
done
|
55
58
|
}
|
56
59
|
}
|
57
60
|
}
|
58
61
|
end
|
59
62
|
|
60
63
|
it "should accept a single-frame text message (masked)" do
|
61
|
-
|
64
|
+
em {
|
62
65
|
start_server { |server|
|
63
66
|
server.onmessage { |msg|
|
64
67
|
msg.should == 'Hello'
|
65
|
-
msg.encoding
|
66
|
-
|
68
|
+
if msg.respond_to?(:encoding)
|
69
|
+
msg.encoding.should == Encoding.find("UTF-8")
|
70
|
+
end
|
71
|
+
done
|
67
72
|
}
|
68
73
|
server.onerror {
|
69
|
-
|
74
|
+
fail
|
70
75
|
}
|
71
76
|
}
|
72
77
|
|
@@ -75,6 +80,6 @@ describe "draft06" do
|
|
75
80
|
client.send_data("\x00\x00\x01\x00\x84\x05Ielln")
|
76
81
|
}
|
77
82
|
}
|
78
|
-
|
83
|
+
}
|
79
84
|
end
|
80
85
|
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'integration/shared_examples'
|
3
|
+
|
4
|
+
describe "draft13" do
|
5
|
+
include EM::SpecHelper
|
6
|
+
default_timeout 1
|
7
|
+
|
8
|
+
before :each do
|
9
|
+
@request = {
|
10
|
+
:port => 80,
|
11
|
+
:method => "GET",
|
12
|
+
:path => "/demo",
|
13
|
+
:headers => {
|
14
|
+
'Host' => 'example.com',
|
15
|
+
'Upgrade' => 'websocket',
|
16
|
+
'Connection' => 'Upgrade',
|
17
|
+
'Sec-WebSocket-Key' => 'dGhlIHNhbXBsZSBub25jZQ==',
|
18
|
+
'Sec-WebSocket-Protocol' => 'sample',
|
19
|
+
'Sec-WebSocket-Origin' => 'http://example.com',
|
20
|
+
'Sec-WebSocket-Version' => '13'
|
21
|
+
}
|
22
|
+
}
|
23
|
+
|
24
|
+
@response = {
|
25
|
+
:protocol => "HTTP/1.1 101 Switching Protocols\r\n",
|
26
|
+
:headers => {
|
27
|
+
"Upgrade" => "websocket",
|
28
|
+
"Connection" => "Upgrade",
|
29
|
+
"Sec-WebSocket-Accept" => "s3pPLMBiTxaQ9kYGzzhZRbK+xOo=",
|
30
|
+
}
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
it_behaves_like "a websocket server" do
|
35
|
+
def start_server
|
36
|
+
EM::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
37
|
+
yield ws
|
38
|
+
}
|
39
|
+
end
|
40
|
+
|
41
|
+
def start_client
|
42
|
+
client = EM.connect('0.0.0.0', 12345, Draft07FakeWebSocketClient)
|
43
|
+
client.send_data(format_request(@request))
|
44
|
+
yield client if block_given?
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should send back the correct handshake response" do
|
49
|
+
em {
|
50
|
+
EM.add_timer(0.1) do
|
51
|
+
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
|
52
|
+
|
53
|
+
# Create a fake client which sends draft 07 handshake
|
54
|
+
connection = EM.connect('0.0.0.0', 12345, Draft07FakeWebSocketClient)
|
55
|
+
connection.send_data(format_request(@request))
|
56
|
+
|
57
|
+
connection.onopen {
|
58
|
+
connection.handshake_response.lines.sort.
|
59
|
+
should == format_response(@response).lines.sort
|
60
|
+
done
|
61
|
+
}
|
62
|
+
end
|
63
|
+
}
|
64
|
+
end
|
65
|
+
end
|
@@ -6,6 +6,8 @@ require 'integration/shared_examples'
|
|
6
6
|
# to currently estabish a websocket connection using the draft75 protocol.
|
7
7
|
#
|
8
8
|
describe "WebSocket server draft75" do
|
9
|
+
include EM::SpecHelper
|
10
|
+
default_timeout 1
|
9
11
|
|
10
12
|
it_behaves_like "a websocket server" do
|
11
13
|
def start_server
|
@@ -21,11 +23,11 @@ describe "WebSocket server draft75" do
|
|
21
23
|
end
|
22
24
|
|
23
25
|
it "should automatically complete WebSocket handshake" do
|
24
|
-
|
26
|
+
em {
|
25
27
|
MSG = "Hello World!"
|
26
28
|
EventMachine.add_timer(0.1) do
|
27
29
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
28
|
-
http.errback {
|
30
|
+
http.errback { fail }
|
29
31
|
http.callback { http.response_header.status.should == 101 }
|
30
32
|
|
31
33
|
http.stream { |msg|
|
@@ -39,17 +41,17 @@ describe "WebSocket server draft75" do
|
|
39
41
|
ws.send MSG
|
40
42
|
}
|
41
43
|
end
|
42
|
-
|
44
|
+
}
|
43
45
|
end
|
44
46
|
|
45
47
|
it "should split multiple messages into separate callbacks" do
|
46
|
-
|
48
|
+
em {
|
47
49
|
messages = %w[1 2]
|
48
50
|
received = []
|
49
51
|
|
50
52
|
EventMachine.add_timer(0.1) do
|
51
53
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
52
|
-
http.errback {
|
54
|
+
http.errback { fail }
|
53
55
|
http.stream {|msg|}
|
54
56
|
http.callback {
|
55
57
|
http.response_header.status.should == 101
|
@@ -68,14 +70,14 @@ describe "WebSocket server draft75" do
|
|
68
70
|
EventMachine.stop if received.size == messages.size
|
69
71
|
}
|
70
72
|
end
|
71
|
-
|
73
|
+
}
|
72
74
|
end
|
73
75
|
|
74
76
|
it "should call onclose callback when client closes connection" do
|
75
|
-
|
77
|
+
em {
|
76
78
|
EventMachine.add_timer(0.1) do
|
77
79
|
http = EventMachine::HttpRequest.new('ws://127.0.0.1:12345/').get :timeout => 0
|
78
|
-
http.errback {
|
80
|
+
http.errback { fail }
|
79
81
|
http.callback {
|
80
82
|
http.response_header.status.should == 101
|
81
83
|
http.close_connection
|
@@ -90,19 +92,19 @@ describe "WebSocket server draft75" do
|
|
90
92
|
EventMachine.stop
|
91
93
|
}
|
92
94
|
end
|
93
|
-
|
95
|
+
}
|
94
96
|
end
|
95
97
|
|
96
98
|
it "should call onerror callback with raised exception and close connection on bad handshake" do
|
97
|
-
|
99
|
+
em {
|
98
100
|
EventMachine.add_timer(0.1) do
|
99
101
|
http = EventMachine::HttpRequest.new('http://127.0.0.1:12345/').get :timeout => 0
|
100
102
|
http.errback { http.response_header.status.should == 0 }
|
101
|
-
http.callback {
|
103
|
+
http.callback { fail }
|
102
104
|
end
|
103
105
|
|
104
106
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) do |ws|
|
105
|
-
ws.onopen {
|
107
|
+
ws.onopen { fail }
|
106
108
|
ws.onclose { EventMachine.stop }
|
107
109
|
ws.onerror {|e|
|
108
110
|
e.should be_an_instance_of EventMachine::WebSocket::HandshakeError
|
@@ -110,6 +112,6 @@ describe "WebSocket server draft75" do
|
|
110
112
|
EventMachine.stop
|
111
113
|
}
|
112
114
|
end
|
113
|
-
|
115
|
+
}
|
114
116
|
end
|
115
117
|
end
|
@@ -2,6 +2,9 @@ require 'helper'
|
|
2
2
|
require 'integration/shared_examples'
|
3
3
|
|
4
4
|
describe "WebSocket server draft76" do
|
5
|
+
include EM::SpecHelper
|
6
|
+
default_timeout 1
|
7
|
+
|
5
8
|
before :each do
|
6
9
|
@request = {
|
7
10
|
:port => 80,
|
@@ -46,7 +49,7 @@ describe "WebSocket server draft76" do
|
|
46
49
|
end
|
47
50
|
|
48
51
|
it "should send back the correct handshake response" do
|
49
|
-
|
52
|
+
em {
|
50
53
|
EM.add_timer(0.1) do
|
51
54
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
|
52
55
|
|
@@ -57,14 +60,14 @@ describe "WebSocket server draft76" do
|
|
57
60
|
connection.onopen {
|
58
61
|
connection.handshake_response.lines.sort.
|
59
62
|
should == format_response(@response).lines.sort
|
60
|
-
|
63
|
+
done
|
61
64
|
}
|
62
65
|
end
|
63
|
-
|
66
|
+
}
|
64
67
|
end
|
65
68
|
|
66
69
|
it "should send closing frame back and close the connection after recieving closing frame" do
|
67
|
-
|
70
|
+
em {
|
68
71
|
EM.add_timer(0.1) do
|
69
72
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
|
70
73
|
|
@@ -82,19 +85,19 @@ describe "WebSocket server draft76" do
|
|
82
85
|
connection.onclose {
|
83
86
|
connection.packets[0].should ==
|
84
87
|
EM::WebSocket::Handler76::TERMINATE_STRING
|
85
|
-
|
88
|
+
done
|
86
89
|
}
|
87
90
|
end
|
88
|
-
|
91
|
+
}
|
89
92
|
end
|
90
93
|
|
91
94
|
it "should ignore any data received after the closing frame" do
|
92
|
-
|
95
|
+
em {
|
93
96
|
EM.add_timer(0.1) do
|
94
97
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
95
98
|
# Fail if foobar message is received
|
96
99
|
ws.onmessage { |msg|
|
97
|
-
|
100
|
+
fail
|
98
101
|
}
|
99
102
|
}
|
100
103
|
|
@@ -109,14 +112,14 @@ describe "WebSocket server draft76" do
|
|
109
112
|
}
|
110
113
|
|
111
114
|
connection.onclose {
|
112
|
-
|
115
|
+
done
|
113
116
|
}
|
114
117
|
end
|
115
|
-
|
118
|
+
}
|
116
119
|
end
|
117
120
|
|
118
121
|
it "should accept null bytes within the frame after a line return" do
|
119
|
-
|
122
|
+
em {
|
120
123
|
EM.add_timer(0.1) do
|
121
124
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |ws|
|
122
125
|
ws.onmessage { |msg|
|
@@ -135,19 +138,19 @@ describe "WebSocket server draft76" do
|
|
135
138
|
}
|
136
139
|
|
137
140
|
connection.onclose {
|
138
|
-
|
141
|
+
done
|
139
142
|
}
|
140
143
|
end
|
141
|
-
|
144
|
+
}
|
142
145
|
end
|
143
146
|
|
144
147
|
it "should handle unreasonable frame lengths by calling onerror callback" do
|
145
|
-
|
148
|
+
em {
|
146
149
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
|
147
150
|
server.onerror { |error|
|
148
151
|
error.should be_an_instance_of EM::WebSocket::DataError
|
149
152
|
error.message.should == "Frame length too long (1180591620717411303296 bytes)"
|
150
|
-
|
153
|
+
done
|
151
154
|
}
|
152
155
|
}
|
153
156
|
|
@@ -162,16 +165,16 @@ describe "WebSocket server draft76" do
|
|
162
165
|
client.onopen {
|
163
166
|
client.send_data("\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\x00")
|
164
167
|
}
|
165
|
-
|
168
|
+
}
|
166
169
|
end
|
167
170
|
|
168
171
|
it "should handle impossible frames by calling onerror callback" do
|
169
|
-
|
172
|
+
em {
|
170
173
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
|
171
174
|
server.onerror { |error|
|
172
175
|
error.should be_an_instance_of EM::WebSocket::DataError
|
173
176
|
error.message.should == "Invalid frame received"
|
174
|
-
|
177
|
+
done
|
175
178
|
}
|
176
179
|
}
|
177
180
|
|
@@ -182,16 +185,16 @@ describe "WebSocket server draft76" do
|
|
182
185
|
client.onopen {
|
183
186
|
client.send_data("foobar") # Does not start with \x00 or \xff
|
184
187
|
}
|
185
|
-
|
188
|
+
}
|
186
189
|
end
|
187
190
|
|
188
191
|
it "should handle invalid http requests by raising HandshakeError passed to onerror callback" do
|
189
|
-
|
192
|
+
em {
|
190
193
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { |server|
|
191
194
|
server.onerror { |error|
|
192
195
|
error.should be_an_instance_of EM::WebSocket::HandshakeError
|
193
196
|
error.message.should == "Invalid HTTP header"
|
194
|
-
|
197
|
+
done
|
195
198
|
}
|
196
199
|
}
|
197
200
|
|
@@ -201,7 +204,7 @@ describe "WebSocket server draft76" do
|
|
201
204
|
end
|
202
205
|
|
203
206
|
it "should handle handshake request split into two TCP packets" do
|
204
|
-
|
207
|
+
em {
|
205
208
|
EM.add_timer(0.1) do
|
206
209
|
EventMachine::WebSocket.start(:host => "0.0.0.0", :port => 12345) { }
|
207
210
|
|
@@ -214,7 +217,7 @@ describe "WebSocket server draft76" do
|
|
214
217
|
connection.onopen {
|
215
218
|
connection.handshake_response.lines.sort.
|
216
219
|
should == format_response(@response).lines.sort
|
217
|
-
|
220
|
+
done
|
218
221
|
}
|
219
222
|
|
220
223
|
EM.add_timer(0.1) do
|
@@ -222,6 +225,6 @@ describe "WebSocket server draft76" do
|
|
222
225
|
connection.send_data(data[(data.length / 2)..-1])
|
223
226
|
end
|
224
227
|
end
|
225
|
-
|
228
|
+
}
|
226
229
|
end
|
227
230
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
shared_examples_for "a websocket server" do
|
4
4
|
it "should call onerror if an application error raised in onopen" do
|
5
|
-
|
5
|
+
em {
|
6
6
|
start_server { |ws|
|
7
7
|
ws.onopen {
|
8
8
|
raise "application error"
|
@@ -10,7 +10,7 @@ shared_examples_for "a websocket server" do
|
|
10
10
|
|
11
11
|
ws.onerror { |e|
|
12
12
|
e.message.should == "application error"
|
13
|
-
|
13
|
+
done
|
14
14
|
}
|
15
15
|
}
|
16
16
|
|
@@ -19,7 +19,7 @@ shared_examples_for "a websocket server" do
|
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should call onerror if an application error raised in onmessage" do
|
22
|
-
|
22
|
+
em {
|
23
23
|
start_server { |server|
|
24
24
|
server.onmessage {
|
25
25
|
raise "application error"
|
@@ -27,7 +27,7 @@ shared_examples_for "a websocket server" do
|
|
27
27
|
|
28
28
|
server.onerror { |e|
|
29
29
|
e.message.should == "application error"
|
30
|
-
|
30
|
+
done
|
31
31
|
}
|
32
32
|
}
|
33
33
|
|
@@ -40,7 +40,7 @@ shared_examples_for "a websocket server" do
|
|
40
40
|
end
|
41
41
|
|
42
42
|
it "should call onerror in an application error raised in onclose" do
|
43
|
-
|
43
|
+
em {
|
44
44
|
start_server { |server|
|
45
45
|
server.onclose {
|
46
46
|
raise "application error"
|
@@ -48,7 +48,7 @@ shared_examples_for "a websocket server" do
|
|
48
48
|
|
49
49
|
server.onerror { |e|
|
50
50
|
e.message.should == "application error"
|
51
|
-
|
51
|
+
done
|
52
52
|
}
|
53
53
|
}
|
54
54
|
|
@@ -65,7 +65,7 @@ shared_examples_for "a websocket server" do
|
|
65
65
|
# Only run these tests on ruby 1.9
|
66
66
|
if "a".respond_to?(:force_encoding)
|
67
67
|
it "should raise error if you try to send non utf8 text data to ws" do
|
68
|
-
|
68
|
+
em {
|
69
69
|
start_server { |server|
|
70
70
|
server.onopen {
|
71
71
|
# Create a string which claims to be UTF-8 but which is not
|
@@ -80,12 +80,12 @@ shared_examples_for "a websocket server" do
|
|
80
80
|
server.onerror { |error|
|
81
81
|
error.class.should == EventMachine::WebSocket::WebSocketError
|
82
82
|
error.message.should == "Data sent to WebSocket must be valid UTF-8 but was UTF-8 (valid: false)"
|
83
|
-
|
83
|
+
done
|
84
84
|
}
|
85
85
|
}
|
86
86
|
|
87
87
|
start_client { }
|
88
|
-
|
88
|
+
}
|
89
89
|
end
|
90
90
|
end
|
91
91
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: em-websocket
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-10-
|
13
|
+
date: 2011-10-24 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: eventmachine
|
17
|
-
requirement: &
|
17
|
+
requirement: &70358050200200 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 0.12.9
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70358050200200
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: addressable
|
28
|
-
requirement: &
|
28
|
+
requirement: &70358050199560 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,32 @@ dependencies:
|
|
33
33
|
version: 2.1.1
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70358050199560
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: em-spec
|
39
|
+
requirement: &70358050199080 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 0.2.5
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *70358050199080
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: eventmachine
|
50
|
+
requirement: &70358050198540 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ~>
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.12.10
|
56
|
+
type: :development
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *70358050198540
|
37
59
|
- !ruby/object:Gem::Dependency
|
38
60
|
name: em-http-request
|
39
|
-
requirement: &
|
61
|
+
requirement: &70358050197960 !ruby/object:Gem::Requirement
|
40
62
|
none: false
|
41
63
|
requirements:
|
42
64
|
- - ~>
|
@@ -44,21 +66,21 @@ dependencies:
|
|
44
66
|
version: 0.2.6
|
45
67
|
type: :development
|
46
68
|
prerelease: false
|
47
|
-
version_requirements: *
|
69
|
+
version_requirements: *70358050197960
|
48
70
|
- !ruby/object:Gem::Dependency
|
49
71
|
name: rspec
|
50
|
-
requirement: &
|
72
|
+
requirement: &70358050197280 !ruby/object:Gem::Requirement
|
51
73
|
none: false
|
52
74
|
requirements:
|
53
75
|
- - ~>
|
54
76
|
- !ruby/object:Gem::Version
|
55
|
-
version: 2.
|
77
|
+
version: 2.6.0
|
56
78
|
type: :development
|
57
79
|
prerelease: false
|
58
|
-
version_requirements: *
|
80
|
+
version_requirements: *70358050197280
|
59
81
|
- !ruby/object:Gem::Dependency
|
60
82
|
name: rake
|
61
|
-
requirement: &
|
83
|
+
requirement: &70358050176420 !ruby/object:Gem::Requirement
|
62
84
|
none: false
|
63
85
|
requirements:
|
64
86
|
- - ! '>='
|
@@ -66,7 +88,7 @@ dependencies:
|
|
66
88
|
version: '0'
|
67
89
|
type: :development
|
68
90
|
prerelease: false
|
69
|
-
version_requirements: *
|
91
|
+
version_requirements: *70358050176420
|
70
92
|
description: EventMachine based WebSocket server
|
71
93
|
email:
|
72
94
|
- ilya@igvita.com
|
@@ -82,6 +104,7 @@ files:
|
|
82
104
|
- Rakefile
|
83
105
|
- em-websocket.gemspec
|
84
106
|
- examples/echo.rb
|
107
|
+
- examples/flash_policy_file_server.rb
|
85
108
|
- examples/js/FABridge.js
|
86
109
|
- examples/js/WebSocketMain.swf
|
87
110
|
- examples/js/swfobject.js
|
@@ -106,6 +129,7 @@ files:
|
|
106
129
|
- lib/em-websocket/handler06.rb
|
107
130
|
- lib/em-websocket/handler07.rb
|
108
131
|
- lib/em-websocket/handler08.rb
|
132
|
+
- lib/em-websocket/handler13.rb
|
109
133
|
- lib/em-websocket/handler75.rb
|
110
134
|
- lib/em-websocket/handler76.rb
|
111
135
|
- lib/em-websocket/handler_factory.rb
|
@@ -122,6 +146,7 @@ files:
|
|
122
146
|
- spec/integration/draft03_spec.rb
|
123
147
|
- spec/integration/draft05_spec.rb
|
124
148
|
- spec/integration/draft06_spec.rb
|
149
|
+
- spec/integration/draft13_spec.rb
|
125
150
|
- spec/integration/draft75_spec.rb
|
126
151
|
- spec/integration/draft76_spec.rb
|
127
152
|
- spec/integration/shared_examples.rb
|
@@ -148,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
148
173
|
version: '0'
|
149
174
|
requirements: []
|
150
175
|
rubyforge_project: em-websocket
|
151
|
-
rubygems_version: 1.8.
|
176
|
+
rubygems_version: 1.8.11
|
152
177
|
signing_key:
|
153
178
|
specification_version: 3
|
154
179
|
summary: EventMachine based WebSocket server
|
@@ -158,6 +183,7 @@ test_files:
|
|
158
183
|
- spec/integration/draft03_spec.rb
|
159
184
|
- spec/integration/draft05_spec.rb
|
160
185
|
- spec/integration/draft06_spec.rb
|
186
|
+
- spec/integration/draft13_spec.rb
|
161
187
|
- spec/integration/draft75_spec.rb
|
162
188
|
- spec/integration/draft76_spec.rb
|
163
189
|
- spec/integration/shared_examples.rb
|