websocket-driver 0.5.4-java → 0.6.0-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +26 -16
- data/lib/websocket/driver.rb +6 -0
- data/lib/websocket/driver/client.rb +5 -5
- data/lib/websocket/driver/draft75.rb +4 -2
- data/lib/websocket/driver/event_emitter.rb +8 -4
- data/lib/websocket/driver/hybi.rb +34 -30
- data/lib/websocket/driver/proxy.rb +2 -2
- data/lib/websocket/driver/stream_reader.rb +55 -0
- metadata +3 -3
- data/lib/websocket/driver/hybi/stream_reader.rb +0 -28
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4c10bbc50ea2348fbb23d243ca2c26ca10b7852c
|
4
|
+
data.tar.gz: b4fae4fc45971242b4cd24d142c6abd25818fdb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f53a36ffb90e346faa9662e8fb270b20e3b4ac78eba3c51a1511b432c38bfcfe22ea783eac3a31f035a4d9c65d45f72bbc880ba4c0e71832edc3117614506d78
|
7
|
+
data.tar.gz: 0ad4d8184eeff96b45eb40f308059a84dbe19f12146d10f0edc7496005854e527127e8b26a24b0d526c0a0033c8449dfea91d7e8d3150f3b110dfb8227de7f2f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
### 0.6.0 / 2015-07-08
|
2
|
+
|
3
|
+
* Use `SecureRandom` to generate the `Sec-WebSocket-Key` header
|
4
|
+
* Allow the parser to recover cleanly if event listeners raise an error
|
5
|
+
* Let the `on()` method take a lambda as a positional argument rather than a block
|
6
|
+
* Add a `pong` method for sending unsolicited pong frames
|
7
|
+
|
1
8
|
### 0.5.4 / 2015-03-29
|
2
9
|
|
3
10
|
* Don't emit extra close frames if we receive a close frame after we already
|
data/README.md
CHANGED
@@ -21,7 +21,7 @@ this module up to some I/O object, it will do all of this for you:
|
|
21
21
|
* Deal with proxies that defer delivery of the draft-76 handshake body
|
22
22
|
* Notify you when the socket is open and closed and when messages arrive
|
23
23
|
* Recombine fragmented messages
|
24
|
-
* Dispatch text, binary, ping and close frames
|
24
|
+
* Dispatch text, binary, ping, pong and close frames
|
25
25
|
* Manage the socket-closing handshake process
|
26
26
|
* Automatically reply to ping frames with a matching pong
|
27
27
|
* Apply masking to messages sent by the client
|
@@ -54,6 +54,7 @@ Server-side sockets require one additional method:
|
|
54
54
|
* `HTTP_CONNECTION`
|
55
55
|
* `HTTP_HOST`
|
56
56
|
* `HTTP_ORIGIN`
|
57
|
+
* `HTTP_SEC_WEBSOCKET_EXTENSIONS`
|
57
58
|
* `HTTP_SEC_WEBSOCKET_KEY`
|
58
59
|
* `HTTP_SEC_WEBSOCKET_KEY1`
|
59
60
|
* `HTTP_SEC_WEBSOCKET_KEY2`
|
@@ -145,7 +146,7 @@ module Connection
|
|
145
146
|
def initialize
|
146
147
|
@driver = WebSocket::Driver.server(self)
|
147
148
|
|
148
|
-
@driver.on
|
149
|
+
@driver.on :connect, -> (event) do
|
149
150
|
if WebSocket::Driver.websocket?(@driver.env)
|
150
151
|
@driver.start
|
151
152
|
else
|
@@ -153,8 +154,8 @@ module Connection
|
|
153
154
|
end
|
154
155
|
end
|
155
156
|
|
156
|
-
@driver.on
|
157
|
-
@driver.on
|
157
|
+
@driver.on :message, -> (e) { @driver.text(e.data) }
|
158
|
+
@driver.on :close, -> (e) { close_connection_after_writing }
|
158
159
|
end
|
159
160
|
|
160
161
|
def receive_data(data)
|
@@ -213,7 +214,7 @@ start sending incoming data to `driver.parse(data)` as normal, and call
|
|
213
214
|
```rb
|
214
215
|
proxy = driver.proxy('http://username:password@proxy.example.com')
|
215
216
|
|
216
|
-
proxy.on :connect do
|
217
|
+
proxy.on :connect, -> (event) do
|
217
218
|
driver.start
|
218
219
|
end
|
219
220
|
```
|
@@ -225,7 +226,7 @@ In the event that proxy connection fails, `proxy` will emit an `:error`. You can
|
|
225
226
|
inspect the proxy's response via `proxy.status` and `proxy.headers`.
|
226
227
|
|
227
228
|
```rb
|
228
|
-
proxy.on :error
|
229
|
+
proxy.on :error, -> (error) do
|
229
230
|
puts error.message
|
230
231
|
puts proxy.status
|
231
232
|
puts proxy.headers.inspect
|
@@ -273,25 +274,25 @@ Note that most of these methods are commands: if they produce data that should
|
|
273
274
|
be sent over the socket, they will give this to you by calling
|
274
275
|
`socket.write(string)`.
|
275
276
|
|
276
|
-
#### `driver.on
|
277
|
+
#### `driver.on 'open', -> (event) { }`
|
277
278
|
|
278
|
-
|
279
|
+
Adds a callback block to execute when the socket becomes open.
|
279
280
|
|
280
|
-
#### `driver.on
|
281
|
+
#### `driver.on 'message', -> (event) { }`
|
281
282
|
|
282
|
-
|
283
|
-
|
284
|
-
|
283
|
+
Adds a callback block to execute when a message is received. `event` will have a
|
284
|
+
`data` attribute containing either a string in the case of a text message or an
|
285
|
+
array of integers in the case of a binary message.
|
285
286
|
|
286
|
-
#### `driver.on
|
287
|
+
#### `driver.on 'error', -> (event) { }`
|
287
288
|
|
288
|
-
|
289
|
+
Adds a callback to execute when a protocol error occurs due to the other peer
|
289
290
|
sending an invalid byte sequence. `event` will have a `message` attribute
|
290
291
|
describing the error.
|
291
292
|
|
292
|
-
#### `driver.on
|
293
|
+
#### `driver.on 'close', -> (event) { }`
|
293
294
|
|
294
|
-
|
295
|
+
Adds a callback block to execute when the socket becomes closed. The `event`
|
295
296
|
object has `code` and `reason` attributes.
|
296
297
|
|
297
298
|
#### `driver.add_extension(extension)`
|
@@ -339,6 +340,15 @@ when the socket receives a pong frame whose content matches `string`. Returns
|
|
339
340
|
`false` if frames can no longer be sent, or if the driver does not support
|
340
341
|
ping/pong.
|
341
342
|
|
343
|
+
#### `driver.pong(string = '')`
|
344
|
+
|
345
|
+
Sends a pong frame over the socket, queueing it if necessary. `string` is
|
346
|
+
optional. Returns `false` if frames can no longer be sent, or if the driver does
|
347
|
+
not support ping/pong.
|
348
|
+
|
349
|
+
You don't need to call this when a ping frame is received; pings are replied to
|
350
|
+
automatically by the driver. This method is for sending unsolicited pongs.
|
351
|
+
|
342
352
|
#### `driver.close`
|
343
353
|
|
344
354
|
Initiates the closing handshake if the socket is still open. For drivers with no
|
data/lib/websocket/driver.rb
CHANGED
@@ -56,6 +56,7 @@ module WebSocket
|
|
56
56
|
autoload :Hybi, root + '/hybi'
|
57
57
|
autoload :Proxy, root + '/proxy'
|
58
58
|
autoload :Server, root + '/server'
|
59
|
+
autoload :StreamReader, root + '/stream_reader'
|
59
60
|
|
60
61
|
include EventEmitter
|
61
62
|
attr_reader :protocol, :ready_state
|
@@ -65,6 +66,7 @@ module WebSocket
|
|
65
66
|
Driver.validate_options(options, [:max_length, :masking, :require_masking, :protocols])
|
66
67
|
|
67
68
|
@socket = socket
|
69
|
+
@reader = StreamReader.new
|
68
70
|
@options = options
|
69
71
|
@max_length = options[:max_length] || MAX_LENGTH
|
70
72
|
@headers = Headers.new
|
@@ -108,6 +110,10 @@ module WebSocket
|
|
108
110
|
false
|
109
111
|
end
|
110
112
|
|
113
|
+
def pong(*args)
|
114
|
+
false
|
115
|
+
end
|
116
|
+
|
111
117
|
def close(reason = nil, code = nil)
|
112
118
|
return false unless @ready_state == 1
|
113
119
|
@ready_state = 3
|
@@ -3,7 +3,7 @@ module WebSocket
|
|
3
3
|
|
4
4
|
class Client < Hybi
|
5
5
|
def self.generate_key
|
6
|
-
Base64.
|
6
|
+
Base64.strict_encode64(SecureRandom.random_bytes(16))
|
7
7
|
end
|
8
8
|
|
9
9
|
attr_reader :status, :headers
|
@@ -32,7 +32,7 @@ module WebSocket
|
|
32
32
|
end
|
33
33
|
|
34
34
|
if uri.user
|
35
|
-
auth = Base64.
|
35
|
+
auth = Base64.strict_encode64([uri.user, uri.password] * ':')
|
36
36
|
@headers['Authorization'] = 'Basic ' + auth
|
37
37
|
end
|
38
38
|
end
|
@@ -80,8 +80,8 @@ module WebSocket
|
|
80
80
|
|
81
81
|
def fail_handshake(message)
|
82
82
|
message = "Error during WebSocket handshake: #{message}"
|
83
|
-
emit(:error, ProtocolError.new(message))
|
84
83
|
@ready_state = 3
|
84
|
+
emit(:error, ProtocolError.new(message))
|
85
85
|
emit(:close, CloseEvent.new(ERRORS[:protocol_error], message))
|
86
86
|
end
|
87
87
|
|
@@ -124,8 +124,8 @@ module WebSocket
|
|
124
124
|
|
125
125
|
begin
|
126
126
|
@extensions.activate(@headers['Sec-WebSocket-Extensions'])
|
127
|
-
rescue ::WebSocket::Extensions::ExtensionError =>
|
128
|
-
return fail_handshake(
|
127
|
+
rescue ::WebSocket::Extensions::ExtensionError => error
|
128
|
+
return fail_handshake(error.message)
|
129
129
|
end
|
130
130
|
end
|
131
131
|
end
|
@@ -26,7 +26,9 @@ module WebSocket
|
|
26
26
|
def parse(buffer)
|
27
27
|
return if @ready_state > 1
|
28
28
|
|
29
|
-
buffer
|
29
|
+
@reader.put(buffer)
|
30
|
+
|
31
|
+
@reader.each_byte do |data|
|
30
32
|
case @stage
|
31
33
|
when -1 then
|
32
34
|
@body << data
|
@@ -52,8 +54,8 @@ module WebSocket
|
|
52
54
|
|
53
55
|
when 2 then
|
54
56
|
if data == 0xFF
|
55
|
-
emit(:message, MessageEvent.new(Driver.encode(@buffer, :utf8)))
|
56
57
|
@stage = 0
|
58
|
+
emit(:message, MessageEvent.new(Driver.encode(@buffer, :utf8)))
|
57
59
|
else
|
58
60
|
if @length
|
59
61
|
@skipped += 1
|
@@ -6,16 +6,20 @@ module WebSocket
|
|
6
6
|
@listeners = Hash.new { |h,k| h[k] = [] }
|
7
7
|
end
|
8
8
|
|
9
|
-
def add_listener(event, &
|
9
|
+
def add_listener(event, callable = nil, &block)
|
10
|
+
listener = callable || block
|
10
11
|
@listeners[event.to_s] << listener
|
12
|
+
listener
|
11
13
|
end
|
12
14
|
|
13
|
-
def on(event, &
|
14
|
-
add_listener(event, &
|
15
|
+
def on(event, callable = nil, &block)
|
16
|
+
add_listener(event, callable, &block)
|
15
17
|
end
|
16
18
|
|
17
|
-
def remove_listener(event, &
|
19
|
+
def remove_listener(event, callable = nil, &block)
|
20
|
+
listener = callable || block
|
18
21
|
@listeners[event.to_s].delete(listener)
|
22
|
+
listener
|
19
23
|
end
|
20
24
|
|
21
25
|
def remove_all_listeners(event = nil)
|
@@ -4,12 +4,11 @@ module WebSocket
|
|
4
4
|
class Hybi < Driver
|
5
5
|
root = File.expand_path('../hybi', __FILE__)
|
6
6
|
|
7
|
-
autoload :Frame,
|
8
|
-
autoload :Message,
|
9
|
-
autoload :StreamReader, root + '/stream_reader'
|
7
|
+
autoload :Frame, root + '/frame'
|
8
|
+
autoload :Message, root + '/message'
|
10
9
|
|
11
10
|
def self.generate_accept(key)
|
12
|
-
Base64.
|
11
|
+
Base64.strict_encode64(Digest::SHA1.digest(key + GUID))
|
13
12
|
end
|
14
13
|
|
15
14
|
GUID = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11'
|
@@ -55,7 +54,6 @@ module WebSocket
|
|
55
54
|
super
|
56
55
|
|
57
56
|
@extensions = ::WebSocket::Extensions.new
|
58
|
-
@reader = StreamReader.new
|
59
57
|
@stage = 0
|
60
58
|
@masking = options[:masking]
|
61
59
|
@protocols = options[:protocols] || []
|
@@ -108,15 +106,16 @@ module WebSocket
|
|
108
106
|
when 3 then
|
109
107
|
buffer = @reader.read(4)
|
110
108
|
if buffer
|
111
|
-
@frame.masking_key = buffer
|
112
109
|
@stage = 4
|
110
|
+
@frame.masking_key = buffer
|
113
111
|
end
|
114
112
|
|
115
113
|
when 4 then
|
116
114
|
buffer = @reader.read(@frame.length)
|
115
|
+
|
117
116
|
if buffer
|
118
|
-
emit_frame(buffer)
|
119
117
|
@stage = 0
|
118
|
+
emit_frame(buffer)
|
120
119
|
end
|
121
120
|
|
122
121
|
else
|
@@ -138,6 +137,10 @@ module WebSocket
|
|
138
137
|
frame(message, :ping)
|
139
138
|
end
|
140
139
|
|
140
|
+
def pong(message = '')
|
141
|
+
frame(message, :pong)
|
142
|
+
end
|
143
|
+
|
141
144
|
def close(reason = nil, code = nil)
|
142
145
|
reason ||= ''
|
143
146
|
code ||= ERRORS[:normal_closure]
|
@@ -188,6 +191,9 @@ module WebSocket
|
|
188
191
|
|
189
192
|
send_frame(frame)
|
190
193
|
true
|
194
|
+
|
195
|
+
rescue ::WebSocket::Extensions::ExtensionError => error
|
196
|
+
fail(:extension_error, error.message)
|
191
197
|
end
|
192
198
|
|
193
199
|
private
|
@@ -231,16 +237,13 @@ module WebSocket
|
|
231
237
|
end
|
232
238
|
|
233
239
|
@socket.write(buffer.pack('C*'))
|
234
|
-
|
235
|
-
rescue ::WebSocket::Extensions::ExtensionError => e
|
236
|
-
fail(:extension_error, e.message)
|
237
240
|
end
|
238
241
|
|
239
242
|
def handshake_response
|
240
243
|
begin
|
241
244
|
extensions = @extensions.generate_response(@socket.env['HTTP_SEC_WEBSOCKET_EXTENSIONS'])
|
242
|
-
rescue =>
|
243
|
-
fail(:protocol_error,
|
245
|
+
rescue => error
|
246
|
+
fail(:protocol_error, error.message)
|
244
247
|
return nil
|
245
248
|
end
|
246
249
|
|
@@ -251,19 +254,21 @@ module WebSocket
|
|
251
254
|
headers.join("\r\n")
|
252
255
|
end
|
253
256
|
|
254
|
-
def shutdown(code, reason)
|
255
|
-
frame(reason, :close, code) if @ready_state < 2
|
257
|
+
def shutdown(code, reason, error = false)
|
256
258
|
@frame = @message = nil
|
257
|
-
@ready_state = 3
|
258
259
|
@stage = 5
|
259
|
-
emit(:close, CloseEvent.new(code, reason))
|
260
260
|
@extensions.close
|
261
|
+
|
262
|
+
frame(reason, :close, code) if @ready_state < 2
|
263
|
+
@ready_state = 3
|
264
|
+
|
265
|
+
emit(:error, ProtocolError.new(reason)) if error
|
266
|
+
emit(:close, CloseEvent.new(code, reason))
|
261
267
|
end
|
262
268
|
|
263
269
|
def fail(type, message)
|
264
270
|
return if @ready_state > 1
|
265
|
-
|
266
|
-
shutdown(ERRORS[type], message)
|
271
|
+
shutdown(ERRORS[type], message, true)
|
267
272
|
end
|
268
273
|
|
269
274
|
def parse_opcode(data)
|
@@ -277,6 +282,8 @@ module WebSocket
|
|
277
282
|
@frame.rsv3 = rsvs[2]
|
278
283
|
@frame.opcode = (data & OPCODE)
|
279
284
|
|
285
|
+
@stage = 1
|
286
|
+
|
280
287
|
unless @extensions.valid_frame_rsv?(@frame)
|
281
288
|
return fail(:protocol_error,
|
282
289
|
"One or more reserved bits are on: reserved1 = #{@frame.rsv1 ? 1 : 0}" +
|
@@ -295,37 +302,34 @@ module WebSocket
|
|
295
302
|
if @message and OPENING_OPCODES.include?(@frame.opcode)
|
296
303
|
return fail(:protocol_error, 'Received new data frame but previous continuous frame is unfinished')
|
297
304
|
end
|
298
|
-
|
299
|
-
@stage = 1
|
300
305
|
end
|
301
306
|
|
302
307
|
def parse_length(data)
|
303
308
|
@frame.masked = (data & MASK) == MASK
|
304
|
-
if @require_masking and not @frame.masked
|
305
|
-
return fail(:unacceptable, 'Received unmasked frame but masking is required')
|
306
|
-
end
|
307
|
-
|
308
309
|
@frame.length = (data & LENGTH)
|
309
310
|
|
310
311
|
if @frame.length >= 0 and @frame.length <= 125
|
311
|
-
return unless check_frame_length
|
312
312
|
@stage = @frame.masked ? 3 : 4
|
313
|
+
return unless check_frame_length
|
313
314
|
else
|
314
|
-
@frame.length_bytes = (@frame.length == 126) ? 2 : 8
|
315
315
|
@stage = 2
|
316
|
+
@frame.length_bytes = (@frame.length == 126) ? 2 : 8
|
317
|
+
end
|
318
|
+
|
319
|
+
if @require_masking and not @frame.masked
|
320
|
+
return fail(:unacceptable, 'Received unmasked frame but masking is required')
|
316
321
|
end
|
317
322
|
end
|
318
323
|
|
319
324
|
def parse_extended_length(buffer)
|
320
325
|
@frame.length = integer(buffer)
|
326
|
+
@stage = @frame.masked ? 3 : 4
|
321
327
|
|
322
328
|
unless MESSAGE_OPCODES.include?(@frame.opcode) or @frame.length <= 125
|
323
329
|
return fail(:protocol_error, "Received control frame having too long payload: #{@frame.length}")
|
324
330
|
end
|
325
331
|
|
326
332
|
return unless check_frame_length
|
327
|
-
|
328
|
-
@stage = @frame.masked ? 3 : 4
|
329
333
|
end
|
330
334
|
|
331
335
|
def check_frame_length
|
@@ -404,8 +408,8 @@ module WebSocket
|
|
404
408
|
else
|
405
409
|
fail(:encoding_error, 'Could not decode a text frame as UTF-8')
|
406
410
|
end
|
407
|
-
rescue ::WebSocket::Extensions::ExtensionError =>
|
408
|
-
fail(:extension_error,
|
411
|
+
rescue ::WebSocket::Extensions::ExtensionError => error
|
412
|
+
fail(:extension_error, error.message)
|
409
413
|
end
|
410
414
|
|
411
415
|
def integer(buffer)
|
@@ -25,7 +25,7 @@ module WebSocket
|
|
25
25
|
@headers['Proxy-Connection'] = 'keep-alive'
|
26
26
|
|
27
27
|
if @url.user
|
28
|
-
auth = Base64.
|
28
|
+
auth = Base64.strict_encode64([@url.user, @url.password] * ':')
|
29
29
|
@headers['Proxy-Authorization'] = 'Basic ' + auth
|
30
30
|
end
|
31
31
|
end
|
@@ -56,7 +56,7 @@ module WebSocket
|
|
56
56
|
@headers = Headers.new(@http.headers)
|
57
57
|
|
58
58
|
if @status == 200
|
59
|
-
emit(:connect)
|
59
|
+
emit(:connect, ConnectEvent.new)
|
60
60
|
else
|
61
61
|
message = "Can't establish a connection to the server at #{@socket.url}"
|
62
62
|
emit(:error, ProtocolError.new(message))
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module WebSocket
|
2
|
+
class Driver
|
3
|
+
|
4
|
+
class StreamReader
|
5
|
+
# Try to minimise the number of reallocations done:
|
6
|
+
MINIMUM_AUTOMATIC_PRUNE_OFFSET = 128
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@buffer = Driver.encode('', :binary)
|
10
|
+
@offset = 0
|
11
|
+
end
|
12
|
+
|
13
|
+
def put(buffer)
|
14
|
+
return unless buffer and buffer.bytesize > 0
|
15
|
+
@buffer << Driver.encode(buffer, :binary)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Read bytes from the data:
|
19
|
+
def read(length)
|
20
|
+
return nil if (@offset + length) > @buffer.bytesize
|
21
|
+
|
22
|
+
chunk = @buffer.byteslice(@offset, length)
|
23
|
+
@offset += chunk.bytesize
|
24
|
+
|
25
|
+
prune if @offset > MINIMUM_AUTOMATIC_PRUNE_OFFSET
|
26
|
+
|
27
|
+
return chunk
|
28
|
+
end
|
29
|
+
|
30
|
+
def each_byte
|
31
|
+
prune
|
32
|
+
|
33
|
+
@buffer.each_byte do |value|
|
34
|
+
@offset += 1
|
35
|
+
yield value
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def prune
|
42
|
+
buffer_size = @buffer.bytesize
|
43
|
+
|
44
|
+
if @offset > buffer_size
|
45
|
+
@buffer = Driver.encode('', :binary)
|
46
|
+
else
|
47
|
+
@buffer = @buffer.byteslice(@offset, buffer_size - @offset)
|
48
|
+
end
|
49
|
+
|
50
|
+
@offset = 0
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: websocket-driver
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: java
|
6
6
|
authors:
|
7
7
|
- James Coglan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-07-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: websocket-extensions
|
@@ -102,9 +102,9 @@ files:
|
|
102
102
|
- lib/websocket/driver/hybi.rb
|
103
103
|
- lib/websocket/driver/hybi/frame.rb
|
104
104
|
- lib/websocket/driver/hybi/message.rb
|
105
|
-
- lib/websocket/driver/hybi/stream_reader.rb
|
106
105
|
- lib/websocket/driver/proxy.rb
|
107
106
|
- lib/websocket/driver/server.rb
|
107
|
+
- lib/websocket/driver/stream_reader.rb
|
108
108
|
- lib/websocket/driver/utf8_match.rb
|
109
109
|
- lib/websocket/http.rb
|
110
110
|
- lib/websocket/http/headers.rb
|
@@ -1,28 +0,0 @@
|
|
1
|
-
module WebSocket
|
2
|
-
class Driver
|
3
|
-
|
4
|
-
class Hybi
|
5
|
-
class StreamReader
|
6
|
-
def initialize
|
7
|
-
@buffer = Driver.encode('', :binary)
|
8
|
-
end
|
9
|
-
|
10
|
-
def put(string)
|
11
|
-
return unless string and string.bytesize > 0
|
12
|
-
@buffer << Driver.encode(string, :binary)
|
13
|
-
end
|
14
|
-
|
15
|
-
def read(length)
|
16
|
-
buffer_size = @buffer.bytesize
|
17
|
-
return nil if length > buffer_size
|
18
|
-
|
19
|
-
chunk = @buffer.byteslice(0, length)
|
20
|
-
@buffer = @buffer.byteslice(length, buffer_size - length)
|
21
|
-
|
22
|
-
chunk
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|