websocket 1.2.3 → 1.2.9
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/.codeclimate.yml +17 -0
- data/.github/workflows/publish.yml +17 -0
- data/.rubocop.yml +35 -3
- data/.travis.yml +14 -7
- data/CHANGELOG.md +24 -0
- data/Gemfile +12 -4
- data/README.md +3 -2
- data/Rakefile +8 -3
- data/lib/websocket.rb +4 -1
- data/lib/websocket/error.rb +8 -0
- data/lib/websocket/exception_handler.rb +3 -1
- data/lib/websocket/frame.rb +2 -0
- data/lib/websocket/frame/base.rb +5 -9
- data/lib/websocket/frame/data.rb +5 -2
- data/lib/websocket/frame/handler.rb +2 -0
- data/lib/websocket/frame/handler/base.rb +6 -4
- data/lib/websocket/frame/handler/handler03.rb +23 -16
- data/lib/websocket/frame/handler/handler04.rb +1 -0
- data/lib/websocket/frame/handler/handler05.rb +1 -0
- data/lib/websocket/frame/handler/handler07.rb +10 -9
- data/lib/websocket/frame/handler/handler75.rb +8 -7
- data/lib/websocket/frame/incoming.rb +2 -0
- data/lib/websocket/frame/incoming/client.rb +2 -0
- data/lib/websocket/frame/incoming/server.rb +2 -0
- data/lib/websocket/frame/outgoing.rb +3 -1
- data/lib/websocket/frame/outgoing/client.rb +2 -0
- data/lib/websocket/frame/outgoing/server.rb +2 -0
- data/lib/websocket/handshake.rb +2 -0
- data/lib/websocket/handshake/base.rb +26 -13
- data/lib/websocket/handshake/client.rb +17 -14
- data/lib/websocket/handshake/handler.rb +2 -0
- data/lib/websocket/handshake/handler/base.rb +2 -0
- data/lib/websocket/handshake/handler/client.rb +11 -0
- data/lib/websocket/handshake/handler/client01.rb +2 -0
- data/lib/websocket/handshake/handler/client04.rb +15 -4
- data/lib/websocket/handshake/handler/client11.rb +2 -0
- data/lib/websocket/handshake/handler/client75.rb +18 -2
- data/lib/websocket/handshake/handler/client76.rb +11 -5
- data/lib/websocket/handshake/handler/server.rb +2 -0
- data/lib/websocket/handshake/handler/server04.rb +12 -4
- data/lib/websocket/handshake/handler/server75.rb +21 -5
- data/lib/websocket/handshake/handler/server76.rb +14 -16
- data/lib/websocket/handshake/server.rb +7 -4
- data/lib/websocket/nice_inspect.rb +12 -0
- data/lib/websocket/version.rb +3 -1
- data/spec/frame/incoming_03_spec.rb +20 -17
- data/spec/frame/incoming_04_spec.rb +20 -17
- data/spec/frame/incoming_05_spec.rb +22 -19
- data/spec/frame/incoming_07_spec.rb +24 -21
- data/spec/frame/incoming_75_spec.rb +13 -10
- data/spec/frame/incoming_common_spec.rb +18 -8
- data/spec/frame/masking_spec.rb +3 -1
- data/spec/frame/outgoing_03_spec.rb +13 -10
- data/spec/frame/outgoing_04_spec.rb +13 -10
- data/spec/frame/outgoing_05_spec.rb +12 -9
- data/spec/frame/outgoing_07_spec.rb +13 -10
- data/spec/frame/outgoing_75_spec.rb +8 -5
- data/spec/frame/outgoing_common_spec.rb +11 -4
- data/spec/handshake/client_04_spec.rb +46 -3
- data/spec/handshake/client_11_spec.rb +5 -3
- data/spec/handshake/client_75_spec.rb +28 -1
- data/spec/handshake/client_76_spec.rb +30 -3
- data/spec/handshake/server_04_spec.rb +37 -4
- data/spec/handshake/server_75_spec.rb +25 -1
- data/spec/handshake/server_76_spec.rb +33 -9
- data/spec/spec_helper.rb +2 -2
- data/spec/support/all_client_drafts.rb +23 -21
- data/spec/support/all_server_drafts.rb +21 -16
- data/spec/support/frames_base.rb +2 -0
- data/spec/support/handshake_requests.rb +19 -17
- data/spec/support/incoming_frames.rb +46 -25
- data/spec/support/outgoing_frames.rb +30 -8
- data/spec/support/overwrites.rb +2 -0
- data/websocket.gemspec +4 -1
- metadata +7 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7060e7e52081f894382fcfd1d67a8f3eda15b3b0c86abf4e5dea1f44e6f1c204
|
4
|
+
data.tar.gz: 93981161e7d5ded1e8182d67dd357ffc9a4c606b6bbbe6e84e7c03244db0a949
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b260ffa5fac7b49981fd876ebc6adc55ced481e84fce368b8d974565edd431b9b4c563c718e889c7fd6eb28f80d8a2f20f2734d0d261610068c2f37e40c380be
|
7
|
+
data.tar.gz: d3c905e52be9abe45ac1f8575b31876d7efffcebc1554a124620c6b19b7d2b4b38037a2a0c5bc2a181532af79b484ea951dfb47864aecd3c6a00686f929246d1
|
data/.codeclimate.yml
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
name: Publish Gem
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
tags:
|
6
|
+
- v*
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
build:
|
10
|
+
runs-on: ubuntu-latest
|
11
|
+
steps:
|
12
|
+
- uses: actions/checkout@v2
|
13
|
+
- name: Release Gem
|
14
|
+
uses: cadwallion/publish-rubygems-action@master
|
15
|
+
env:
|
16
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
17
|
+
RUBYGEMS_API_KEY: ${{secrets.RUBYGEMS_API_KEY}}
|
data/.rubocop.yml
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
|
3
|
+
AllCops:
|
4
|
+
DisplayCopNames: true
|
5
|
+
TargetRubyVersion: 2.1
|
6
|
+
|
7
|
+
# New version of Rubocop does not support 2.0
|
8
|
+
Gemspec/RequiredRubyVersion:
|
9
|
+
Enabled: false
|
10
|
+
|
11
|
+
Layout/IndentHeredoc:
|
12
|
+
Enabled: false
|
13
|
+
|
1
14
|
# Target: 15
|
2
15
|
Metrics/AbcSize:
|
3
16
|
Max: 24
|
@@ -5,6 +18,10 @@ Metrics/AbcSize:
|
|
5
18
|
- lib/websocket/frame/handler/handler75.rb
|
6
19
|
- spec/**/*
|
7
20
|
|
21
|
+
Metrics/BlockLength:
|
22
|
+
Exclude:
|
23
|
+
- spec/**/*
|
24
|
+
|
8
25
|
Metrics/ClassLength:
|
9
26
|
Enabled: false
|
10
27
|
|
@@ -30,8 +47,23 @@ Metrics/PerceivedComplexity:
|
|
30
47
|
- lib/websocket/frame/handler/handler75.rb
|
31
48
|
- spec/support/handshake_requests.rb
|
32
49
|
|
33
|
-
|
50
|
+
RSpec/ContextWording:
|
51
|
+
Enabled: false
|
52
|
+
|
53
|
+
RSpec/DescribeClass:
|
54
|
+
Enabled: false
|
55
|
+
|
56
|
+
RSpec/ExampleLength:
|
34
57
|
Enabled: false
|
35
58
|
|
36
|
-
|
37
|
-
|
59
|
+
RSpec/InstanceVariable:
|
60
|
+
Enabled: false
|
61
|
+
|
62
|
+
RSpec/MultipleExpectations:
|
63
|
+
Enabled: false
|
64
|
+
|
65
|
+
RSpec/NamedSubject:
|
66
|
+
Enabled: false
|
67
|
+
|
68
|
+
Style/Documentation:
|
69
|
+
Enabled: false
|
data/.travis.yml
CHANGED
@@ -1,12 +1,19 @@
|
|
1
|
+
dist: trusty
|
1
2
|
language: ruby
|
2
|
-
script: "bundle exec rake
|
3
|
+
script: "bundle exec rake"
|
3
4
|
rvm:
|
4
|
-
- 1.9.3
|
5
|
-
- 2.0
|
6
5
|
- 2.1
|
7
6
|
- 2.2
|
8
|
-
-
|
9
|
-
-
|
7
|
+
- 2.3
|
8
|
+
- 2.4
|
9
|
+
- 2.5
|
10
10
|
- ruby-head
|
11
|
-
|
12
|
-
-
|
11
|
+
- jruby-9.1.9.0 # https://github.com/travis-ci/travis-ci/issues/8446
|
12
|
+
- jruby-head
|
13
|
+
- rbx-3
|
14
|
+
|
15
|
+
matrix:
|
16
|
+
allow_failures:
|
17
|
+
- rvm: ruby-head
|
18
|
+
- rvm: jruby-head
|
19
|
+
- rvm: rbx-3
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,29 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 1.2.9
|
4
|
+
|
5
|
+
- avoid ruby -w warnings
|
6
|
+
|
7
|
+
## 1.2.8
|
8
|
+
|
9
|
+
- restore support for Ruby 2.0+
|
10
|
+
|
11
|
+
## 1.2.7
|
12
|
+
|
13
|
+
- fix bug in previous version for Ruby 2.3
|
14
|
+
|
15
|
+
## 1.2.6
|
16
|
+
|
17
|
+
- duplicate variables passed in initializers to avoid changing them
|
18
|
+
|
19
|
+
## 1.2.5
|
20
|
+
|
21
|
+
- make handshake server resilient to non-string Rack env keys
|
22
|
+
|
23
|
+
## 1.2.4
|
24
|
+
|
25
|
+
- add subprotocol handling for both server and client
|
26
|
+
|
3
27
|
## 1.2.3
|
4
28
|
|
5
29
|
- fix for draft 76 when challenge might sometimes fail
|
data/Gemfile
CHANGED
@@ -1,7 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
source 'http://rubygems.org'
|
2
4
|
|
3
|
-
|
5
|
+
group :development do
|
6
|
+
gem 'rake'
|
7
|
+
gem 'rspec', '~> 3.7'
|
4
8
|
|
5
|
-
|
6
|
-
|
7
|
-
gem '
|
9
|
+
# Use same version as Code Climate for consistency with CI
|
10
|
+
# https://github.com/codeclimate/codeclimate-rubocop/blob/master/Gemfile.lock
|
11
|
+
gem 'rubocop', '0.52.1', require: false
|
12
|
+
gem 'rubocop-rspec', '1.21.0', require: false
|
13
|
+
end
|
14
|
+
|
15
|
+
gemspec
|
data/README.md
CHANGED
@@ -3,8 +3,9 @@
|
|
3
3
|
Universal Ruby library to handle WebSocket protocol. It focuses on providing abstraction layer over [WebSocket API](http://dev.w3.org/html5/websockets/) instead of providing server or client functionality.
|
4
4
|
|
5
5
|
[](http://badge.fury.io/rb/websocket)
|
6
|
-
[](https://rubygems.org/gems/websocket)
|
7
|
+
[](http://travis-ci.org/imanel/websocket-ruby)
|
8
|
+
[](https://codeclimate.com/github/imanel/websocket-ruby)
|
8
9
|
|
9
10
|
**Autobahn tests:** [server](http://imanel.github.com/websocket-ruby/autobahn/server/), [client](http://imanel.github.com/websocket-ruby/autobahn/client/)
|
10
11
|
|
data/Rakefile
CHANGED
@@ -1,14 +1,19 @@
|
|
1
|
-
|
2
|
-
Bundler::GemHelper.install_tasks
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
3
|
+
require 'bundler'
|
4
4
|
require 'rspec/core/rake_task'
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
|
7
|
+
Bundler::GemHelper.install_tasks
|
5
8
|
|
6
9
|
RSpec::Core::RakeTask.new do |t|
|
7
10
|
t.rspec_opts = ['-c', '-f progress']
|
8
11
|
t.pattern = 'spec/**/*_spec.rb'
|
9
12
|
end
|
10
13
|
|
11
|
-
|
14
|
+
RuboCop::RakeTask.new
|
15
|
+
|
16
|
+
task default: %i[spec rubocop]
|
12
17
|
|
13
18
|
namespace :autobahn do
|
14
19
|
desc 'Run autobahn tests for client'
|
data/lib/websocket.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# WebSocket protocol implementation in Ruby
|
2
4
|
# This module does not provide a WebSocket server or client, but is made for using
|
3
5
|
# in http servers or clients to provide WebSocket support.
|
@@ -6,12 +8,13 @@
|
|
6
8
|
module WebSocket
|
7
9
|
# Default WebSocket version to use
|
8
10
|
DEFAULT_VERSION = 13
|
9
|
-
ROOT =
|
11
|
+
ROOT = __dir__
|
10
12
|
|
11
13
|
autoload :Error, "#{ROOT}/websocket/error"
|
12
14
|
autoload :ExceptionHandler, "#{ROOT}/websocket/exception_handler"
|
13
15
|
autoload :Frame, "#{ROOT}/websocket/frame"
|
14
16
|
autoload :Handshake, "#{ROOT}/websocket/handshake"
|
17
|
+
autoload :NiceInspect, "#{ROOT}/websocket/nice_inspect"
|
15
18
|
|
16
19
|
# Limit of frame size payload in bytes
|
17
20
|
def self.max_frame_size
|
data/lib/websocket/error.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WebSocket
|
2
4
|
class Error < RuntimeError
|
3
5
|
class Frame < ::WebSocket::Error
|
@@ -99,6 +101,12 @@ module WebSocket
|
|
99
101
|
end
|
100
102
|
end
|
101
103
|
|
104
|
+
class UnsupportedProtocol < ::WebSocket::Error::Handshake
|
105
|
+
def message
|
106
|
+
:unsupported_protocol
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
102
110
|
class InvalidStatusCode < ::WebSocket::Error::Handshake
|
103
111
|
def message
|
104
112
|
:invalid_status_code
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WebSocket
|
2
4
|
module ExceptionHandler
|
3
5
|
attr_accessor :error
|
@@ -12,7 +14,7 @@ module WebSocket
|
|
12
14
|
# @param [String] method_name Name of method that should be wrapped and rescued
|
13
15
|
# @param [Hash] options Options for rescue
|
14
16
|
#
|
15
|
-
# @
|
17
|
+
# @option options [Any] :return Value that should be returned instead of raised error
|
16
18
|
def rescue_method(method_name, options = {})
|
17
19
|
define_method "#{method_name}_with_rescue" do |*args|
|
18
20
|
begin
|
data/lib/websocket/frame.rb
CHANGED
data/lib/websocket/frame/base.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WebSocket
|
2
4
|
module Frame
|
3
5
|
# @abstract Subclass and override to implement custom frames
|
4
6
|
class Base
|
5
7
|
include ExceptionHandler
|
8
|
+
include NiceInspect
|
6
9
|
|
7
10
|
attr_reader :type, :version, :error
|
8
11
|
attr_accessor :data, :code
|
@@ -36,14 +39,7 @@ module WebSocket
|
|
36
39
|
|
37
40
|
# Implement in submodules
|
38
41
|
def supported_frames
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
# Recreate inspect as #to_s was overwritten
|
43
|
-
def inspect
|
44
|
-
vars = instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
|
45
|
-
insp = Kernel.format("#{self.class}:0x%08x", __id__)
|
46
|
-
"<#{insp} #{vars}>"
|
42
|
+
raise NotImplementedError
|
47
43
|
end
|
48
44
|
|
49
45
|
private
|
@@ -58,7 +54,7 @@ module WebSocket
|
|
58
54
|
when 4 then Handler::Handler04.new(self)
|
59
55
|
when 5..6 then Handler::Handler05.new(self)
|
60
56
|
when 7..13 then Handler::Handler07.new(self)
|
61
|
-
else
|
57
|
+
else raise WebSocket::Error::Frame::UnknownVersion
|
62
58
|
end
|
63
59
|
end
|
64
60
|
end
|
data/lib/websocket/frame/data.rb
CHANGED
@@ -1,8 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WebSocket
|
2
4
|
module Frame
|
3
5
|
class Data < String
|
4
6
|
def initialize(*args)
|
5
7
|
super(*convert_args(args))
|
8
|
+
@masking_key = nil
|
6
9
|
end
|
7
10
|
|
8
11
|
def <<(*args)
|
@@ -11,12 +14,12 @@ module WebSocket
|
|
11
14
|
|
12
15
|
# Convert all arguments to ASCII-8BIT for easier traversing
|
13
16
|
def convert_args(args)
|
14
|
-
args.
|
17
|
+
args.collect { |arg| arg.dup.force_encoding('ASCII-8BIT') }
|
15
18
|
end
|
16
19
|
|
17
20
|
# Extract mask from 4 first bytes according to spec
|
18
21
|
def set_mask
|
19
|
-
|
22
|
+
raise WebSocket::Error::Frame::MaskTooShort if bytesize < 4
|
20
23
|
@masking_key = self[0..3].bytes.to_a
|
21
24
|
end
|
22
25
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module WebSocket
|
2
4
|
module Frame
|
3
5
|
module Handler
|
@@ -9,13 +11,13 @@ module WebSocket
|
|
9
11
|
# Convert data to raw frame ready to send to client
|
10
12
|
# @return [String] Encoded frame
|
11
13
|
def encode_frame
|
12
|
-
|
14
|
+
raise NotImplementedError
|
13
15
|
end
|
14
16
|
|
15
17
|
# Convert raw data to decoded frame
|
16
18
|
# @return [WebSocket::Frame::Incoming] Frame if found, nil otherwise
|
17
19
|
def decode_frame
|
18
|
-
|
20
|
+
raise NotImplementedError
|
19
21
|
end
|
20
22
|
|
21
23
|
private
|
@@ -24,14 +26,14 @@ module WebSocket
|
|
24
26
|
# @param [Symbol] frame_type Frame type
|
25
27
|
# @return [Boolean] True if given frame type is control frame
|
26
28
|
def control_frame?(frame_type)
|
27
|
-
|
29
|
+
!%i[text binary continuation].include?(frame_type)
|
28
30
|
end
|
29
31
|
|
30
32
|
# Check if frame is one of data frames
|
31
33
|
# @param [Symbol] frame_type Frame type
|
32
34
|
# @return [Boolean] True if given frame type is data frame
|
33
35
|
def data_frame?(frame_type)
|
34
|
-
[
|
36
|
+
%i[text binary].include?(frame_type)
|
35
37
|
end
|
36
38
|
end
|
37
39
|
end
|
@@ -1,4 +1,6 @@
|
|
1
1
|
# encoding: binary
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
require 'securerandom'
|
3
5
|
|
4
6
|
module WebSocket
|
@@ -13,14 +15,19 @@ module WebSocket
|
|
13
15
|
pong: 3,
|
14
16
|
text: 4,
|
15
17
|
binary: 5
|
16
|
-
}
|
18
|
+
}.freeze
|
17
19
|
|
18
20
|
# Hash of frame opcodes and it's names
|
19
|
-
FRAME_TYPES_INVERSE = FRAME_TYPES.invert
|
21
|
+
FRAME_TYPES_INVERSE = FRAME_TYPES.invert.freeze
|
22
|
+
|
23
|
+
def initialize(frame)
|
24
|
+
super
|
25
|
+
@application_data_buffer = nil
|
26
|
+
end
|
20
27
|
|
21
28
|
# @see WebSocket::Frame::Base#supported_frames
|
22
29
|
def supported_frames
|
23
|
-
[
|
30
|
+
%i[text binary close ping pong]
|
24
31
|
end
|
25
32
|
|
26
33
|
# @see WebSocket::Frame::Handler::Base#encode_frame
|
@@ -50,7 +57,7 @@ module WebSocket
|
|
50
57
|
elsif frame_type == :continuation
|
51
58
|
return decode_finish_continuation_frame(application_data)
|
52
59
|
else
|
53
|
-
|
60
|
+
raise(WebSocket::Error::Frame::InvalidPayloadEncoding) if frame_type == :text && !application_data.valid_encoding?
|
54
61
|
return @frame.class.new(version: @frame.version, type: frame_type, data: application_data, decoded: true)
|
55
62
|
end
|
56
63
|
end
|
@@ -74,7 +81,7 @@ module WebSocket
|
|
74
81
|
# @return [Integer] opcode or nil
|
75
82
|
# @raise [WebSocket::Error] if frame opcode is not known
|
76
83
|
def type_to_opcode(frame_type)
|
77
|
-
FRAME_TYPES[frame_type] ||
|
84
|
+
FRAME_TYPES[frame_type] || raise(WebSocket::Error::Frame::UnknownFrameType)
|
78
85
|
end
|
79
86
|
|
80
87
|
# Convert frame opcode to type name
|
@@ -82,20 +89,20 @@ module WebSocket
|
|
82
89
|
# @return [Symbol] Frame type name or nil
|
83
90
|
# @raise [WebSocket::Error] if frame type name is not known
|
84
91
|
def opcode_to_type(opcode)
|
85
|
-
FRAME_TYPES_INVERSE[opcode] ||
|
92
|
+
FRAME_TYPES_INVERSE[opcode] || raise(WebSocket::Error::Frame::UnknownOpcode)
|
86
93
|
end
|
87
94
|
|
88
95
|
def encode_header
|
89
96
|
mask = @frame.outgoing_masking? ? 0b10000000 : 0b00000000
|
90
97
|
|
91
|
-
output = ''
|
98
|
+
output = String.new('')
|
92
99
|
output << (type_to_opcode(@frame.type) | (fin ? 0b10000000 : 0b00000000)) # since more, rsv1-3 are 0 and 0x80 for Draft 4
|
93
100
|
output << encode_payload_length(@frame.data.size, mask)
|
94
101
|
output
|
95
102
|
end
|
96
103
|
|
97
104
|
def encode_payload_length(length, mask)
|
98
|
-
output = ''
|
105
|
+
output = String.new('')
|
99
106
|
if length <= 125
|
100
107
|
output << (length | mask) # since rsv4 is 0
|
101
108
|
elsif length < 65_536 # write 2 byte length
|
@@ -117,7 +124,7 @@ module WebSocket
|
|
117
124
|
frame_length = header_length + payload_length
|
118
125
|
frame_length += 4 if mask
|
119
126
|
|
120
|
-
|
127
|
+
raise(WebSocket::Error::Frame::TooLong) if frame_length > WebSocket.max_frame_size
|
121
128
|
|
122
129
|
# Check buffer size
|
123
130
|
return unless buffer_exists?(frame_length) # Buffer incomplete
|
@@ -135,13 +142,13 @@ module WebSocket
|
|
135
142
|
def decode_first_byte
|
136
143
|
first_byte = @frame.data.getbyte(0)
|
137
144
|
|
138
|
-
|
145
|
+
raise(WebSocket::Error::Frame::ReservedBitUsed) if first_byte & 0b01110000 != 0b00000000
|
139
146
|
|
140
147
|
more = ((first_byte & 0b10000000) == 0b10000000) ^ fin
|
141
148
|
frame_type = opcode_to_type first_byte & 0b00001111
|
142
149
|
|
143
|
-
|
144
|
-
|
150
|
+
raise(WebSocket::Error::Frame::FragmentedControlFrame) if more && control_frame?(frame_type)
|
151
|
+
raise(WebSocket::Error::Frame::DataFrameInsteadContinuation) if data_frame?(frame_type) && !@application_data_buffer.nil?
|
145
152
|
|
146
153
|
[more, frame_type]
|
147
154
|
end
|
@@ -152,7 +159,7 @@ module WebSocket
|
|
152
159
|
mask = @frame.incoming_masking? && (second_byte & 0b10000000) == 0b10000000
|
153
160
|
length = second_byte & 0b01111111
|
154
161
|
|
155
|
-
|
162
|
+
raise(WebSocket::Error::Frame::ControlFramePayloadTooLong) if length > 125 && control_frame?(frame_type)
|
156
163
|
|
157
164
|
header_length, payload_length = decode_payload_length(length)
|
158
165
|
|
@@ -196,16 +203,16 @@ module WebSocket
|
|
196
203
|
end
|
197
204
|
|
198
205
|
def decode_continuation_frame(application_data, frame_type)
|
199
|
-
@application_data_buffer ||= ''
|
206
|
+
@application_data_buffer ||= String.new('')
|
200
207
|
@application_data_buffer << application_data
|
201
208
|
@frame_type ||= frame_type
|
202
209
|
end
|
203
210
|
|
204
211
|
def decode_finish_continuation_frame(application_data)
|
205
|
-
|
212
|
+
raise(WebSocket::Error::Frame::UnexpectedContinuationFrame) unless @frame_type
|
206
213
|
@application_data_buffer << application_data
|
207
214
|
# Test valid UTF-8 encoding
|
208
|
-
|
215
|
+
raise(WebSocket::Error::Frame::InvalidPayloadEncoding) if @frame_type == :text && !@application_data_buffer.valid_encoding?
|
209
216
|
message = @frame.class.new(version: @frame.version, type: @frame_type, data: @application_data_buffer, decoded: true)
|
210
217
|
@application_data_buffer = nil
|
211
218
|
@frame_type = nil
|