websocket-driver 0.6.5-java → 0.7.4-java
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.
- 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
|