websocket-driver 0.6.5-java → 0.7.4-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/CHANGELOG.md +73 -44
- data/LICENSE.md +9 -19
- data/README.md +46 -26
- data/ext/websocket-driver/WebsocketMaskService.java +31 -29
- data/ext/websocket-driver/websocket_mask.c +23 -32
- data/lib/websocket/driver.rb +45 -14
- data/lib/websocket/driver/client.rb +8 -8
- data/lib/websocket/driver/draft75.rb +1 -1
- data/lib/websocket/driver/draft76.rb +12 -9
- data/lib/websocket/driver/headers.rb +1 -1
- data/lib/websocket/driver/hybi.rb +56 -44
- data/lib/websocket/driver/hybi/message.rb +1 -1
- data/lib/websocket/driver/proxy.rb +4 -4
- data/lib/websocket/driver/server.rb +3 -3
- data/lib/websocket/driver/stream_reader.rb +3 -3
- data/lib/websocket/http/request.rb +2 -2
- data/lib/websocket/http/response.rb +1 -1
- data/lib/websocket_mask.jar +0 -0
- metadata +29 -31
- data/examples/tcp_server.rb +0 -28
@@ -1,41 +1,32 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
|
3
|
-
VALUE
|
4
|
-
VALUE WebSocketMask = Qnil;
|
5
|
-
|
6
|
-
void Init_websocket_mask();
|
7
|
-
VALUE method_websocket_mask(VALUE self, VALUE payload, VALUE mask);
|
8
|
-
|
9
|
-
void
|
10
|
-
Init_websocket_mask()
|
3
|
+
VALUE method_websocket_mask(VALUE self, VALUE payload, VALUE mask)
|
11
4
|
{
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
5
|
+
char *payload_s, *mask_s, *unmasked_s;
|
6
|
+
long i, n;
|
7
|
+
VALUE unmasked;
|
16
8
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
VALUE mask)
|
21
|
-
{
|
22
|
-
char *payload_s, *mask_s, *unmasked_s;
|
23
|
-
long i, n;
|
24
|
-
VALUE unmasked;
|
9
|
+
if (mask == Qnil || RSTRING_LEN(mask) != 4) {
|
10
|
+
return payload;
|
11
|
+
}
|
25
12
|
|
26
|
-
|
27
|
-
|
28
|
-
|
13
|
+
payload_s = RSTRING_PTR(payload);
|
14
|
+
mask_s = RSTRING_PTR(mask);
|
15
|
+
n = RSTRING_LEN(payload);
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
n = RSTRING_LEN(payload);
|
17
|
+
unmasked = rb_str_new(0, n);
|
18
|
+
unmasked_s = RSTRING_PTR(unmasked);
|
33
19
|
|
34
|
-
|
35
|
-
|
20
|
+
for (i = 0; i < n; i++) {
|
21
|
+
unmasked_s[i] = payload_s[i] ^ mask_s[i % 4];
|
22
|
+
}
|
23
|
+
return unmasked;
|
24
|
+
}
|
25
|
+
|
26
|
+
void Init_websocket_mask()
|
27
|
+
{
|
28
|
+
VALUE WebSocket = rb_define_module("WebSocket");
|
29
|
+
VALUE Mask = rb_define_module_under(WebSocket, "Mask");
|
36
30
|
|
37
|
-
|
38
|
-
unmasked_s[i] = payload_s[i] ^ mask_s[i % 4];
|
39
|
-
}
|
40
|
-
return unmasked;
|
31
|
+
rb_define_singleton_method(Mask, "mask", method_websocket_mask, 2);
|
41
32
|
}
|
data/lib/websocket/driver.rb
CHANGED
@@ -44,12 +44,11 @@ module WebSocket
|
|
44
44
|
MAX_LENGTH = 0x3ffffff
|
45
45
|
STATES = [:connecting, :open, :closing, :closed]
|
46
46
|
|
47
|
-
BINARY = 'ASCII-8BIT'
|
48
|
-
UNICODE = 'UTF-8'
|
49
|
-
|
50
47
|
ConnectEvent = Struct.new(nil)
|
51
48
|
OpenEvent = Struct.new(nil)
|
52
49
|
MessageEvent = Struct.new(:data)
|
50
|
+
PingEvent = Struct.new(:data)
|
51
|
+
PongEvent = Struct.new(:data)
|
53
52
|
CloseEvent = Struct.new(:code, :reason)
|
54
53
|
|
55
54
|
ProtocolError = Class.new(StandardError)
|
@@ -99,15 +98,24 @@ module WebSocket
|
|
99
98
|
|
100
99
|
def start
|
101
100
|
return false unless @ready_state == 0
|
102
|
-
|
103
|
-
|
101
|
+
|
102
|
+
unless Driver.websocket?(@socket.env)
|
103
|
+
return fail_handshake(ProtocolError.new('Not a WebSocket request'))
|
104
|
+
end
|
105
|
+
|
106
|
+
begin
|
107
|
+
response = handshake_response
|
108
|
+
rescue => error
|
109
|
+
return fail_handshake(error)
|
110
|
+
end
|
111
|
+
|
104
112
|
@socket.write(response)
|
105
113
|
open unless @stage == -1
|
106
114
|
true
|
107
115
|
end
|
108
116
|
|
109
117
|
def text(message)
|
110
|
-
message = message.encode(
|
118
|
+
message = message.encode(Encoding::UTF_8) unless message.encoding == Encoding::UTF_8
|
111
119
|
frame(message, :text)
|
112
120
|
end
|
113
121
|
|
@@ -132,6 +140,24 @@ module WebSocket
|
|
132
140
|
|
133
141
|
private
|
134
142
|
|
143
|
+
def fail_handshake(error)
|
144
|
+
headers = Headers.new
|
145
|
+
headers['Content-Type'] = 'text/plain'
|
146
|
+
headers['Content-Length'] = error.message.bytesize
|
147
|
+
|
148
|
+
headers = ['HTTP/1.1 400 Bad Request', headers.to_s, error.message]
|
149
|
+
@socket.write(headers.join("\r\n"))
|
150
|
+
fail(:protocol_error, error.message)
|
151
|
+
|
152
|
+
false
|
153
|
+
end
|
154
|
+
|
155
|
+
def fail(type, message)
|
156
|
+
@ready_state = 2
|
157
|
+
emit(:error, ProtocolError.new(message))
|
158
|
+
close
|
159
|
+
end
|
160
|
+
|
135
161
|
def open
|
136
162
|
@ready_state = 1
|
137
163
|
@queue.each { |message| frame(*message) }
|
@@ -153,10 +179,15 @@ module WebSocket
|
|
153
179
|
end
|
154
180
|
|
155
181
|
def self.rack(socket, options = {})
|
156
|
-
env
|
157
|
-
|
182
|
+
env = socket.env
|
183
|
+
version = env['HTTP_SEC_WEBSOCKET_VERSION']
|
184
|
+
key = env['HTTP_SEC_WEBSOCKET_KEY']
|
185
|
+
key1 = env['HTTP_SEC_WEBSOCKET_KEY1']
|
186
|
+
key2 = env['HTTP_SEC_WEBSOCKET_KEY2']
|
187
|
+
|
188
|
+
if version or key
|
158
189
|
Hybi.new(socket, options.merge(:require_masking => true))
|
159
|
-
elsif
|
190
|
+
elsif key1 or key2
|
160
191
|
Draft76.new(socket, options)
|
161
192
|
else
|
162
193
|
Draft75.new(socket, options)
|
@@ -167,21 +198,21 @@ module WebSocket
|
|
167
198
|
case string
|
168
199
|
when Array then
|
169
200
|
string = string.pack('C*')
|
170
|
-
encoding ||= BINARY
|
201
|
+
encoding ||= Encoding::BINARY
|
171
202
|
when String then
|
172
|
-
encoding ||=
|
203
|
+
encoding ||= Encoding::UTF_8
|
173
204
|
end
|
174
|
-
unless string.encoding
|
205
|
+
unless string.encoding == encoding
|
175
206
|
string = string.dup if string.frozen?
|
176
207
|
string.force_encoding(encoding)
|
177
208
|
end
|
178
|
-
string
|
209
|
+
string
|
179
210
|
end
|
180
211
|
|
181
212
|
def self.validate_options(options, valid_keys)
|
182
213
|
options.keys.each do |key|
|
183
214
|
unless valid_keys.include?(key)
|
184
|
-
raise ConfigurationError, "Unrecognized option: #{key.inspect}"
|
215
|
+
raise ConfigurationError, "Unrecognized option: #{ key.inspect }"
|
185
216
|
end
|
186
217
|
end
|
187
218
|
end
|
@@ -20,10 +20,10 @@ module WebSocket
|
|
20
20
|
|
21
21
|
uri = URI.parse(@socket.url)
|
22
22
|
unless VALID_SCHEMES.include?(uri.scheme)
|
23
|
-
raise URIError, "#{socket.url} is not a valid WebSocket URL"
|
23
|
+
raise URIError, "#{ socket.url } is not a valid WebSocket URL"
|
24
24
|
end
|
25
25
|
|
26
|
-
host = uri.host + (uri.port ? ":#{uri.port}" : '')
|
26
|
+
host = uri.host + (uri.port ? ":#{ uri.port }" : '')
|
27
27
|
path = (uri.path == '') ? '/' : uri.path
|
28
28
|
@pathname = path + (uri.query ? '?' + uri.query : '')
|
29
29
|
|
@@ -31,7 +31,7 @@ module WebSocket
|
|
31
31
|
@headers['Upgrade'] = 'websocket'
|
32
32
|
@headers['Connection'] = 'Upgrade'
|
33
33
|
@headers['Sec-WebSocket-Key'] = @key
|
34
|
-
@headers['Sec-WebSocket-Version'] =
|
34
|
+
@headers['Sec-WebSocket-Version'] = VERSION
|
35
35
|
|
36
36
|
if @protocols.size > 0
|
37
37
|
@headers['Sec-WebSocket-Protocol'] = @protocols * ', '
|
@@ -44,7 +44,7 @@ module WebSocket
|
|
44
44
|
end
|
45
45
|
|
46
46
|
def version
|
47
|
-
|
47
|
+
"hybi-#{ VERSION }"
|
48
48
|
end
|
49
49
|
|
50
50
|
def proxy(origin, options = {})
|
@@ -73,19 +73,19 @@ module WebSocket
|
|
73
73
|
parse(@http.body)
|
74
74
|
end
|
75
75
|
|
76
|
-
private
|
76
|
+
private
|
77
77
|
|
78
78
|
def handshake_request
|
79
79
|
extensions = @extensions.generate_offer
|
80
80
|
@headers['Sec-WebSocket-Extensions'] = extensions if extensions
|
81
81
|
|
82
|
-
start = "GET #{@pathname} HTTP/1.1"
|
82
|
+
start = "GET #{ @pathname } HTTP/1.1"
|
83
83
|
headers = [start, @headers.to_s, '']
|
84
84
|
headers.join("\r\n")
|
85
85
|
end
|
86
86
|
|
87
87
|
def fail_handshake(message)
|
88
|
-
message = "Error during WebSocket handshake: #{message}"
|
88
|
+
message = "Error during WebSocket handshake: #{ message }"
|
89
89
|
@ready_state = 3
|
90
90
|
emit(:error, ProtocolError.new(message))
|
91
91
|
emit(:close, CloseEvent.new(ERRORS[:protocol_error], message))
|
@@ -96,7 +96,7 @@ module WebSocket
|
|
96
96
|
@headers = Headers.new(@http.headers)
|
97
97
|
|
98
98
|
unless @http.code == 101
|
99
|
-
return fail_handshake("Unexpected response code: #{@http.code}")
|
99
|
+
return fail_handshake("Unexpected response code: #{ @http.code }")
|
100
100
|
end
|
101
101
|
|
102
102
|
upgrade = @http['Upgrade'] || ''
|
@@ -6,9 +6,10 @@ module WebSocket
|
|
6
6
|
|
7
7
|
def initialize(socket, options = {})
|
8
8
|
super
|
9
|
-
input = @socket.env['rack.input']
|
9
|
+
input = (@socket.env['rack.input'] || StringIO.new('')).read
|
10
|
+
input = input.dup if input.frozen?
|
10
11
|
@stage = -1
|
11
|
-
@body =
|
12
|
+
@body = input.force_encoding(Encoding::BINARY)
|
12
13
|
|
13
14
|
@headers.clear
|
14
15
|
@headers['Upgrade'] = 'WebSocket'
|
@@ -29,7 +30,7 @@ module WebSocket
|
|
29
30
|
|
30
31
|
def close(reason = nil, code = nil)
|
31
32
|
return false if @ready_state == 3
|
32
|
-
@socket.write([0xFF, 0x00].pack('C*'))
|
33
|
+
@socket.write([0xFF, 0x00].pack('C*')) if @ready_state == 1
|
33
34
|
@ready_state = 3
|
34
35
|
emit(:close, CloseEvent.new(nil, nil))
|
35
36
|
true
|
@@ -39,19 +40,20 @@ module WebSocket
|
|
39
40
|
|
40
41
|
def handshake_response
|
41
42
|
env = @socket.env
|
42
|
-
|
43
43
|
key1 = env['HTTP_SEC_WEBSOCKET_KEY1']
|
44
|
+
key2 = env['HTTP_SEC_WEBSOCKET_KEY2']
|
45
|
+
|
46
|
+
raise ProtocolError.new('Missing required header: Sec-WebSocket-Key1') unless key1
|
47
|
+
raise ProtocolError.new('Missing required header: Sec-WebSocket-Key2') unless key2
|
48
|
+
|
44
49
|
number1 = number_from_key(key1)
|
45
50
|
spaces1 = spaces_in_key(key1)
|
46
51
|
|
47
|
-
key2 = env['HTTP_SEC_WEBSOCKET_KEY2']
|
48
52
|
number2 = number_from_key(key2)
|
49
53
|
spaces2 = spaces_in_key(key2)
|
50
54
|
|
51
55
|
if number1 % spaces1 != 0 or number2 % spaces2 != 0
|
52
|
-
|
53
|
-
close
|
54
|
-
return nil
|
56
|
+
raise ProtocolError.new('Client sent invalid Sec-WebSocket-Key headers')
|
55
57
|
end
|
56
58
|
|
57
59
|
@key_values = [number1 / spaces1, number2 / spaces2]
|
@@ -84,7 +86,8 @@ module WebSocket
|
|
84
86
|
end
|
85
87
|
|
86
88
|
def number_from_key(key)
|
87
|
-
key.scan(/[0-9]/).join('')
|
89
|
+
number = key.scan(/[0-9]/).join('')
|
90
|
+
number == '' ? Float::NAN : number.to_i(10)
|
88
91
|
end
|
89
92
|
|
90
93
|
def spaces_in_key(key)
|
@@ -25,7 +25,7 @@ module WebSocket
|
|
25
25
|
return if value.nil?
|
26
26
|
key = HTTP.normalize_header(name)
|
27
27
|
return unless @sent.add?(key) or ALLOWED_DUPLICATES.include?(key)
|
28
|
-
@lines << "#{name.strip}: #{value.to_s.strip}\r\n"
|
28
|
+
@lines << "#{ name.strip }: #{ value.to_s.strip }\r\n"
|
29
29
|
end
|
30
30
|
|
31
31
|
def inspect
|
@@ -11,7 +11,8 @@ module WebSocket
|
|
11
11
|
Base64.strict_encode64(Digest::SHA1.digest(key + GUID))
|
12
12
|
end
|
13
13
|
|
14
|
-
|
14
|
+
VERSION = '13'
|
15
|
+
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
15
16
|
|
16
17
|
BYTE = 0b11111111
|
17
18
|
FIN = MASK = 0b10000000
|
@@ -51,7 +52,7 @@ module WebSocket
|
|
51
52
|
MIN_RESERVED_ERROR = 3000
|
52
53
|
MAX_RESERVED_ERROR = 4999
|
53
54
|
|
54
|
-
PACK_FORMATS = {2 => '
|
55
|
+
PACK_FORMATS = { 2 => 'S>', 8 => 'Q>' }
|
55
56
|
|
56
57
|
def initialize(socket, options = {})
|
57
58
|
super
|
@@ -68,22 +69,16 @@ module WebSocket
|
|
68
69
|
|
69
70
|
return unless @socket.respond_to?(:env)
|
70
71
|
|
71
|
-
sec_key = @socket.env['HTTP_SEC_WEBSOCKET_KEY']
|
72
|
-
protos = @socket.env['HTTP_SEC_WEBSOCKET_PROTOCOL']
|
73
|
-
|
74
|
-
@headers['Upgrade'] = 'websocket'
|
75
|
-
@headers['Connection'] = 'Upgrade'
|
76
|
-
@headers['Sec-WebSocket-Accept'] = Hybi.generate_accept(sec_key)
|
77
|
-
|
78
72
|
if protos = @socket.env['HTTP_SEC_WEBSOCKET_PROTOCOL']
|
79
73
|
protos = protos.split(/ *, */) if String === protos
|
80
74
|
@protocol = protos.find { |p| @protocols.include?(p) }
|
81
|
-
|
75
|
+
else
|
76
|
+
@protocol = nil
|
82
77
|
end
|
83
78
|
end
|
84
79
|
|
85
80
|
def version
|
86
|
-
"hybi-#{
|
81
|
+
"hybi-#{ VERSION }"
|
87
82
|
end
|
88
83
|
|
89
84
|
def add_extension(extension)
|
@@ -165,14 +160,13 @@ module WebSocket
|
|
165
160
|
|
166
161
|
message = Message.new
|
167
162
|
frame = Frame.new
|
168
|
-
is_text = String === buffer
|
169
163
|
|
170
164
|
message.rsv1 = message.rsv2 = message.rsv3 = false
|
171
|
-
message.opcode = OPCODES[type || (
|
165
|
+
message.opcode = OPCODES[type || (String === buffer ? :text : :binary)]
|
172
166
|
|
173
|
-
payload =
|
174
|
-
payload = [code].pack(
|
175
|
-
message.data = payload
|
167
|
+
payload = Driver.encode(buffer, Encoding::BINARY)
|
168
|
+
payload = [code, payload].pack('S>a*') if code
|
169
|
+
message.data = payload
|
176
170
|
|
177
171
|
if MESSAGE_OPCODES.include?(message.opcode)
|
178
172
|
message = @extensions.process_outgoing_message(message)
|
@@ -199,43 +193,59 @@ module WebSocket
|
|
199
193
|
|
200
194
|
def send_frame(frame)
|
201
195
|
length = frame.length
|
202
|
-
|
196
|
+
values = []
|
197
|
+
format = 'C2'
|
203
198
|
masked = frame.masked ? MASK : 0
|
204
199
|
|
205
|
-
|
200
|
+
values[0] = (frame.final ? FIN : 0) |
|
206
201
|
(frame.rsv1 ? RSV1 : 0) |
|
207
202
|
(frame.rsv2 ? RSV2 : 0) |
|
208
203
|
(frame.rsv3 ? RSV3 : 0) |
|
209
204
|
frame.opcode
|
210
205
|
|
211
206
|
if length <= 125
|
212
|
-
|
207
|
+
values[1] = masked | length
|
213
208
|
elsif length <= 65535
|
214
|
-
|
215
|
-
|
209
|
+
values[1] = masked | 126
|
210
|
+
values[2] = length
|
211
|
+
format << 'S>'
|
216
212
|
else
|
217
|
-
|
218
|
-
|
213
|
+
values[1] = masked | 127
|
214
|
+
values[2] = length
|
215
|
+
format << 'Q>'
|
219
216
|
end
|
220
217
|
|
221
218
|
if frame.masked
|
222
|
-
|
223
|
-
|
219
|
+
values << frame.masking_key
|
220
|
+
values << Mask.mask(frame.payload, frame.masking_key)
|
221
|
+
format << 'a4a*'
|
224
222
|
else
|
225
|
-
|
223
|
+
values << frame.payload
|
224
|
+
format << 'a*'
|
226
225
|
end
|
227
226
|
|
228
|
-
@socket.write(
|
227
|
+
@socket.write(values.pack(format))
|
229
228
|
end
|
230
229
|
|
231
230
|
def handshake_response
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
231
|
+
sec_key = @socket.env['HTTP_SEC_WEBSOCKET_KEY']
|
232
|
+
version = @socket.env['HTTP_SEC_WEBSOCKET_VERSION']
|
233
|
+
|
234
|
+
unless version == VERSION
|
235
|
+
raise ProtocolError.new("Unsupported WebSocket version: #{ VERSION }")
|
236
|
+
end
|
237
|
+
|
238
|
+
unless sec_key
|
239
|
+
raise ProtocolError.new('Missing handshake request header: Sec-WebSocket-Key')
|
237
240
|
end
|
238
241
|
|
242
|
+
@headers['Upgrade'] = 'websocket'
|
243
|
+
@headers['Connection'] = 'Upgrade'
|
244
|
+
@headers['Sec-WebSocket-Accept'] = Hybi.generate_accept(sec_key)
|
245
|
+
|
246
|
+
@headers['Sec-WebSocket-Protocol'] = @protocol if @protocol
|
247
|
+
|
248
|
+
extensions = @extensions.generate_response(@socket.env['HTTP_SEC_WEBSOCKET_EXTENSIONS'])
|
239
249
|
@headers['Sec-WebSocket-Extensions'] = extensions if extensions
|
240
250
|
|
241
251
|
start = 'HTTP/1.1 101 Switching Protocols'
|
@@ -275,17 +285,17 @@ module WebSocket
|
|
275
285
|
|
276
286
|
unless @extensions.valid_frame_rsv?(@frame)
|
277
287
|
return fail(:protocol_error,
|
278
|
-
"One or more reserved bits are on: reserved1 = #{@frame.rsv1 ? 1 : 0}" +
|
279
|
-
", reserved2 = #{@frame.rsv2 ? 1 : 0 }" +
|
280
|
-
", reserved3 = #{@frame.rsv3 ? 1 : 0 }")
|
288
|
+
"One or more reserved bits are on: reserved1 = #{ @frame.rsv1 ? 1 : 0 }" +
|
289
|
+
", reserved2 = #{ @frame.rsv2 ? 1 : 0 }" +
|
290
|
+
", reserved3 = #{ @frame.rsv3 ? 1 : 0 }")
|
281
291
|
end
|
282
292
|
|
283
293
|
unless OPCODES.values.include?(@frame.opcode)
|
284
|
-
return fail(:protocol_error, "Unrecognized frame opcode: #{@frame.opcode}")
|
294
|
+
return fail(:protocol_error, "Unrecognized frame opcode: #{ @frame.opcode }")
|
285
295
|
end
|
286
296
|
|
287
297
|
unless MESSAGE_OPCODES.include?(@frame.opcode) or @frame.final
|
288
|
-
return fail(:protocol_error, "Received fragmented control frame: opcode = #{@frame.opcode}")
|
298
|
+
return fail(:protocol_error, "Received fragmented control frame: opcode = #{ @frame.opcode }")
|
289
299
|
end
|
290
300
|
|
291
301
|
if @message and OPENING_OPCODES.include?(@frame.opcode)
|
@@ -315,7 +325,7 @@ module WebSocket
|
|
315
325
|
@stage = @frame.masked ? 3 : 4
|
316
326
|
|
317
327
|
unless MESSAGE_OPCODES.include?(@frame.opcode) or @frame.length <= 125
|
318
|
-
return fail(:protocol_error, "Received control frame having too long payload: #{@frame.length}")
|
328
|
+
return fail(:protocol_error, "Received control frame having too long payload: #{ @frame.length }")
|
319
329
|
end
|
320
330
|
|
321
331
|
return unless check_frame_length
|
@@ -337,7 +347,6 @@ module WebSocket
|
|
337
347
|
opcode = frame.opcode
|
338
348
|
payload = frame.payload = Mask.mask(buffer, @frame.masking_key)
|
339
349
|
bytesize = payload.bytesize
|
340
|
-
bytes = payload.bytes.to_a
|
341
350
|
|
342
351
|
@frame = nil
|
343
352
|
|
@@ -351,8 +360,8 @@ module WebSocket
|
|
351
360
|
@message << frame
|
352
361
|
|
353
362
|
when OPCODES[:close] then
|
354
|
-
code
|
355
|
-
reason =
|
363
|
+
code, reason = payload.unpack('S>a*') if bytesize >= 2
|
364
|
+
reason = Driver.encode(reason || '', Encoding::UTF_8)
|
356
365
|
|
357
366
|
unless (bytesize == 0) or
|
358
367
|
(code && code >= MIN_RESERVED_ERROR && code <= MAX_RESERVED_ERROR) or
|
@@ -360,7 +369,7 @@ module WebSocket
|
|
360
369
|
code = ERRORS[:protocol_error]
|
361
370
|
end
|
362
371
|
|
363
|
-
if bytesize > 125 or
|
372
|
+
if bytesize > 125 or !reason.valid_encoding?
|
364
373
|
code = ERRORS[:protocol_error]
|
365
374
|
end
|
366
375
|
|
@@ -368,12 +377,14 @@ module WebSocket
|
|
368
377
|
|
369
378
|
when OPCODES[:ping] then
|
370
379
|
frame(payload, :pong)
|
380
|
+
emit(:ping, PingEvent.new(payload))
|
371
381
|
|
372
382
|
when OPCODES[:pong] then
|
373
|
-
message = Driver.encode(payload,
|
383
|
+
message = Driver.encode(payload, Encoding::UTF_8)
|
374
384
|
callback = @ping_callbacks[message]
|
375
385
|
@ping_callbacks.delete(message)
|
376
386
|
callback.call if callback
|
387
|
+
emit(:pong, PongEvent.new(payload))
|
377
388
|
end
|
378
389
|
|
379
390
|
emit_message if frame.final and MESSAGE_OPCODES.include?(opcode)
|
@@ -387,7 +398,8 @@ module WebSocket
|
|
387
398
|
|
388
399
|
case message.opcode
|
389
400
|
when OPCODES[:text] then
|
390
|
-
payload = Driver.encode(payload,
|
401
|
+
payload = Driver.encode(payload, Encoding::UTF_8)
|
402
|
+
payload = nil unless payload.valid_encoding?
|
391
403
|
when OPCODES[:binary]
|
392
404
|
payload = payload.bytes.to_a
|
393
405
|
end
|