websocket-driver 0.7.3 → 0.7.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 11392831462e0bee833bdb3ac3f6f09de232e2e8cc7a19799ce0ebb8e7238ea1
4
- data.tar.gz: 3b4555cc645e77d0166ff9657dc23c306bf48296e94a1520de703f9ab72120f1
3
+ metadata.gz: 91c58586ddd290ad5d320267e36706bdbcffb09c7ba5300d6c3fcd50f342ec2f
4
+ data.tar.gz: 7f5afd33de5b0c0e68d7d4cbab726e7ada8200f1b5916e01feb6a3508e3f3e51
5
5
  SHA512:
6
- metadata.gz: 378aaf1b46a663dccd4dbc8ec25e515e9acb7b2c760b7b62c199185e11466d9c2fd6482b17fb51157a03030e0c9065c7f6a6201c61a7f45fc940365cce036626
7
- data.tar.gz: 783523c78a09ced14fe3e4be497b7fb5e6f22755d6b2dafa5b9b02ed72427512d7b70185dbff43e1df3a924fa086a28334403d7c02b5bc2762fbb33dcf339e3a
6
+ metadata.gz: 92ececf04fb09b31c8fd1617a38351d7a04c4306f3a27b7061e1220710a5a703da162ca0b47ee2fbdf63e20606040a022de61c51c651add2356665526adffe46
7
+ data.tar.gz: f89d71520719be104eb649c318ca85bdd107ec875a62405061fe0268d9df08b0487fe333c531d4635950245ef2879c9fc43c8a148a63afc97f508f28cc4c7397
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### 0.7.4 / 2021-05-24
2
+
3
+ - Optimise conversions between strings and byte arrays and related encoding
4
+ operations, to reduce amount of allocation and copying
5
+
1
6
  ### 0.7.3 / 2020-07-09
2
7
 
3
8
  - Let the client accept HTTP responses that have an empty reason phrase
data/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2010-2020 James Coglan
1
+ Copyright 2010-2021 James Coglan
2
2
 
3
3
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4
4
  this file except in compliance with the License. You may obtain a copy of the
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # websocket-driver [![Build Status](https://travis-ci.org/faye/websocket-driver-ruby.svg)](https://travis-ci.org/faye/websocket-driver-ruby)
1
+ # websocket-driver
2
2
 
3
3
  This module provides a complete implementation of the WebSocket protocols that
4
4
  can be hooked up to any TCP library. It aims to simplify things by decoupling
@@ -150,7 +150,16 @@ module Connection
150
150
  if WebSocket::Driver.websocket?(@driver.env)
151
151
  @driver.start
152
152
  else
153
- # handle other HTTP requests
153
+ # handle other HTTP requests, for example
154
+ body = '<h1>hello</h1>'
155
+ response = [
156
+ 'HTTP/1.1 200 OK',
157
+ 'Content-Type: text/plain',
158
+ "Content-Length: #{body.bytesize}",
159
+ '',
160
+ body
161
+ ]
162
+ send_data response.join("\r\n")
154
163
  end
155
164
  end
156
165
 
@@ -44,9 +44,6 @@ 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)
@@ -118,7 +115,7 @@ module WebSocket
118
115
  end
119
116
 
120
117
  def text(message)
121
- message = message.encode(UNICODE) unless message.encoding.name == UNICODE
118
+ message = message.encode(Encoding::UTF_8) unless message.encoding == Encoding::UTF_8
122
119
  frame(message, :text)
123
120
  end
124
121
 
@@ -201,15 +198,15 @@ module WebSocket
201
198
  case string
202
199
  when Array then
203
200
  string = string.pack('C*')
204
- encoding ||= BINARY
201
+ encoding ||= Encoding::BINARY
205
202
  when String then
206
- encoding ||= UNICODE
203
+ encoding ||= Encoding::UTF_8
207
204
  end
208
- unless string.encoding.name == encoding
205
+ unless string.encoding == encoding
209
206
  string = string.dup if string.frozen?
210
207
  string.force_encoding(encoding)
211
208
  end
212
- string.valid_encoding? ? string : nil
209
+ string
213
210
  end
214
211
 
215
212
  def self.validate_options(options, valid_keys)
@@ -56,7 +56,7 @@ module WebSocket
56
56
  when 2 then
57
57
  if octet == 0xFF
58
58
  @stage = 0
59
- emit(:message, MessageEvent.new(Driver.encode(@buffer, UNICODE)))
59
+ emit(:message, MessageEvent.new(Driver.encode(@buffer, Encoding::UTF_8)))
60
60
  else
61
61
  if @length
62
62
  @skipped += 1
@@ -9,7 +9,7 @@ module WebSocket
9
9
  input = (@socket.env['rack.input'] || StringIO.new('')).read
10
10
  input = input.dup if input.frozen?
11
11
  @stage = -1
12
- @body = input.force_encoding(BINARY)
12
+ @body = input.force_encoding(Encoding::BINARY)
13
13
 
14
14
  @headers.clear
15
15
  @headers['Upgrade'] = 'WebSocket'
@@ -52,7 +52,7 @@ module WebSocket
52
52
  MIN_RESERVED_ERROR = 3000
53
53
  MAX_RESERVED_ERROR = 4999
54
54
 
55
- PACK_FORMATS = { 2 => 'n', 8 => 'Q>' }
55
+ PACK_FORMATS = { 2 => 'S>', 8 => 'Q>' }
56
56
 
57
57
  def initialize(socket, options = {})
58
58
  super
@@ -160,14 +160,13 @@ module WebSocket
160
160
 
161
161
  message = Message.new
162
162
  frame = Frame.new
163
- is_text = String === buffer
164
163
 
165
164
  message.rsv1 = message.rsv2 = message.rsv3 = false
166
- message.opcode = OPCODES[type || (is_text ? :text : :binary)]
165
+ message.opcode = OPCODES[type || (String === buffer ? :text : :binary)]
167
166
 
168
- payload = is_text ? buffer.bytes.to_a : buffer
169
- payload = [code].pack(PACK_FORMATS[2]).bytes.to_a + payload if code
170
- message.data = payload.pack('C*')
167
+ payload = Driver.encode(buffer, Encoding::BINARY)
168
+ payload = [code, payload].pack('S>a*') if code
169
+ message.data = payload
171
170
 
172
171
  if MESSAGE_OPCODES.include?(message.opcode)
173
172
  message = @extensions.process_outgoing_message(message)
@@ -194,33 +193,38 @@ module WebSocket
194
193
 
195
194
  def send_frame(frame)
196
195
  length = frame.length
197
- buffer = []
196
+ values = []
197
+ format = 'C2'
198
198
  masked = frame.masked ? MASK : 0
199
199
 
200
- buffer[0] = (frame.final ? FIN : 0) |
200
+ values[0] = (frame.final ? FIN : 0) |
201
201
  (frame.rsv1 ? RSV1 : 0) |
202
202
  (frame.rsv2 ? RSV2 : 0) |
203
203
  (frame.rsv3 ? RSV3 : 0) |
204
204
  frame.opcode
205
205
 
206
206
  if length <= 125
207
- buffer[1] = masked | length
207
+ values[1] = masked | length
208
208
  elsif length <= 65535
209
- buffer[1] = masked | 126
210
- buffer[2..3] = [length].pack(PACK_FORMATS[2]).bytes.to_a
209
+ values[1] = masked | 126
210
+ values[2] = length
211
+ format << 'S>'
211
212
  else
212
- buffer[1] = masked | 127
213
- buffer[2..9] = [length].pack(PACK_FORMATS[8]).bytes.to_a
213
+ values[1] = masked | 127
214
+ values[2] = length
215
+ format << 'Q>'
214
216
  end
215
217
 
216
218
  if frame.masked
217
- buffer.concat(frame.masking_key.bytes.to_a)
218
- buffer.concat(Mask.mask(frame.payload, frame.masking_key).bytes.to_a)
219
+ values << frame.masking_key
220
+ values << Mask.mask(frame.payload, frame.masking_key)
221
+ format << 'a4a*'
219
222
  else
220
- buffer.concat(frame.payload.bytes.to_a)
223
+ values << frame.payload
224
+ format << 'a*'
221
225
  end
222
226
 
223
- @socket.write(buffer.pack('C*'))
227
+ @socket.write(values.pack(format))
224
228
  end
225
229
 
226
230
  def handshake_response
@@ -343,7 +347,6 @@ module WebSocket
343
347
  opcode = frame.opcode
344
348
  payload = frame.payload = Mask.mask(buffer, @frame.masking_key)
345
349
  bytesize = payload.bytesize
346
- bytes = payload.bytes.to_a
347
350
 
348
351
  @frame = nil
349
352
 
@@ -357,8 +360,8 @@ module WebSocket
357
360
  @message << frame
358
361
 
359
362
  when OPCODES[:close] then
360
- code = (bytesize >= 2) ? payload.unpack(PACK_FORMATS[2]).first : nil
361
- reason = (bytesize > 2) ? Driver.encode(bytes[2..-1] || [], UNICODE) : nil
363
+ code, reason = payload.unpack('S>a*') if bytesize >= 2
364
+ reason = Driver.encode(reason || '', Encoding::UTF_8)
362
365
 
363
366
  unless (bytesize == 0) or
364
367
  (code && code >= MIN_RESERVED_ERROR && code <= MAX_RESERVED_ERROR) or
@@ -366,7 +369,7 @@ module WebSocket
366
369
  code = ERRORS[:protocol_error]
367
370
  end
368
371
 
369
- if bytesize > 125 or (bytesize > 2 and reason.nil?)
372
+ if bytesize > 125 or !reason.valid_encoding?
370
373
  code = ERRORS[:protocol_error]
371
374
  end
372
375
 
@@ -377,7 +380,7 @@ module WebSocket
377
380
  emit(:ping, PingEvent.new(payload))
378
381
 
379
382
  when OPCODES[:pong] then
380
- message = Driver.encode(payload, UNICODE)
383
+ message = Driver.encode(payload, Encoding::UTF_8)
381
384
  callback = @ping_callbacks[message]
382
385
  @ping_callbacks.delete(message)
383
386
  callback.call if callback
@@ -395,7 +398,8 @@ module WebSocket
395
398
 
396
399
  case message.opcode
397
400
  when OPCODES[:text] then
398
- payload = Driver.encode(payload, UNICODE)
401
+ payload = Driver.encode(payload, Encoding::UTF_8)
402
+ payload = nil unless payload.valid_encoding?
399
403
  when OPCODES[:binary]
400
404
  payload = payload.bytes.to_a
401
405
  end
@@ -14,7 +14,7 @@ module WebSocket
14
14
  @rsv2 = false
15
15
  @rsv3 = false
16
16
  @opcode = nil
17
- @data = String.new('').force_encoding(BINARY)
17
+ @data = String.new('').force_encoding(Encoding::BINARY)
18
18
  end
19
19
 
20
20
  def <<(frame)
@@ -6,13 +6,13 @@ module WebSocket
6
6
  MINIMUM_AUTOMATIC_PRUNE_OFFSET = 128
7
7
 
8
8
  def initialize
9
- @buffer = String.new('').force_encoding(BINARY)
9
+ @buffer = String.new('').force_encoding(Encoding::BINARY)
10
10
  @offset = 0
11
11
  end
12
12
 
13
13
  def put(chunk)
14
14
  return unless chunk and chunk.bytesize > 0
15
- @buffer << chunk.force_encoding(BINARY)
15
+ @buffer << chunk.force_encoding(Encoding::BINARY)
16
16
  end
17
17
 
18
18
  # Read bytes from the data:
@@ -42,7 +42,7 @@ module WebSocket
42
42
  buffer_size = @buffer.bytesize
43
43
 
44
44
  if @offset > buffer_size
45
- @buffer = String.new('').force_encoding(BINARY)
45
+ @buffer = String.new('').force_encoding(Encoding::BINARY)
46
46
  else
47
47
  @buffer = @buffer.byteslice(@offset, buffer_size - @offset)
48
48
  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.7.3
4
+ version: 0.7.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Coglan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-09 00:00:00.000000000 Z
11
+ date: 2021-05-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: websocket-extensions
@@ -135,7 +135,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
135
135
  - !ruby/object:Gem::Version
136
136
  version: '0'
137
137
  requirements: []
138
- rubygems_version: 3.1.2
138
+ rubygems_version: 3.1.6
139
139
  signing_key:
140
140
  specification_version: 4
141
141
  summary: WebSocket protocol handler with pluggable I/O