em-websocket 0.3.2 → 0.3.5
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.
- 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
|