websocket 1.2.2 → 1.2.3
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 +4 -4
- data/.rubocop.yml +37 -0
- data/.travis.yml +2 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +1 -1
- data/Rakefile +3 -3
- data/lib/websocket.rb +2 -3
- data/lib/websocket/error.rb +57 -25
- data/lib/websocket/exception_handler.rb +2 -14
- data/lib/websocket/frame.rb +0 -2
- data/lib/websocket/frame/base.rb +12 -13
- data/lib/websocket/frame/data.rb +1 -3
- data/lib/websocket/frame/handler.rb +0 -2
- data/lib/websocket/frame/handler/base.rb +2 -4
- data/lib/websocket/frame/handler/handler03.rb +149 -112
- data/lib/websocket/frame/handler/handler04.rb +3 -3
- data/lib/websocket/frame/handler/handler05.rb +3 -3
- data/lib/websocket/frame/handler/handler07.rb +8 -10
- data/lib/websocket/frame/handler/handler75.rb +10 -12
- data/lib/websocket/frame/incoming.rb +0 -2
- data/lib/websocket/frame/incoming/client.rb +0 -2
- data/lib/websocket/frame/incoming/server.rb +0 -2
- data/lib/websocket/frame/outgoing.rb +1 -3
- data/lib/websocket/frame/outgoing/client.rb +0 -2
- data/lib/websocket/frame/outgoing/server.rb +0 -2
- data/lib/websocket/handshake.rb +0 -2
- data/lib/websocket/handshake/base.rb +10 -9
- data/lib/websocket/handshake/client.rb +22 -35
- data/lib/websocket/handshake/handler.rb +0 -2
- data/lib/websocket/handshake/handler/base.rb +0 -2
- data/lib/websocket/handshake/handler/client.rb +0 -2
- data/lib/websocket/handshake/handler/client01.rb +0 -2
- data/lib/websocket/handshake/handler/client04.rb +3 -5
- data/lib/websocket/handshake/handler/client11.rb +0 -2
- data/lib/websocket/handshake/handler/client75.rb +2 -4
- data/lib/websocket/handshake/handler/client76.rb +6 -8
- data/lib/websocket/handshake/handler/server.rb +0 -1
- data/lib/websocket/handshake/handler/server04.rb +3 -5
- data/lib/websocket/handshake/handler/server75.rb +2 -4
- data/lib/websocket/handshake/handler/server76.rb +7 -9
- data/lib/websocket/handshake/server.rb +19 -24
- data/lib/websocket/version.rb +1 -1
- data/spec/frame/incoming_03_spec.rb +1 -2
- data/spec/frame/incoming_04_spec.rb +1 -2
- data/spec/frame/incoming_05_spec.rb +1 -2
- data/spec/frame/incoming_07_spec.rb +1 -2
- data/spec/frame/incoming_75_spec.rb +1 -2
- data/spec/support/all_client_drafts.rb +1 -1
- data/spec/support/all_server_drafts.rb +7 -10
- data/spec/support/frames_base.rb +0 -2
- data/spec/support/handshake_requests.rb +4 -4
- data/spec/support/outgoing_frames.rb +0 -1
- data/spec/support/overwrites.rb +0 -2
- data/websocket.gemspec +10 -10
- metadata +4 -3
@@ -4,13 +4,13 @@ module WebSocket
|
|
4
4
|
module Frame
|
5
5
|
module Handler
|
6
6
|
class Handler04 < Handler03
|
7
|
-
|
8
7
|
private
|
9
8
|
|
10
9
|
# The only difference between draft 03 framing and draft 04 framing is
|
11
10
|
# that the MORE bit has been changed to a FIN bit
|
12
|
-
def fin
|
13
|
-
|
11
|
+
def fin
|
12
|
+
true
|
13
|
+
end
|
14
14
|
end
|
15
15
|
end
|
16
16
|
end
|
@@ -4,7 +4,6 @@ module WebSocket
|
|
4
4
|
module Frame
|
5
5
|
module Handler
|
6
6
|
class Handler07 < Handler05
|
7
|
-
|
8
7
|
# Hash of frame names and it's opcodes
|
9
8
|
FRAME_TYPES = {
|
10
9
|
continuation: 0,
|
@@ -12,7 +11,7 @@ module WebSocket
|
|
12
11
|
binary: 2,
|
13
12
|
close: 8,
|
14
13
|
ping: 9,
|
15
|
-
pong: 10
|
14
|
+
pong: 10
|
16
15
|
}
|
17
16
|
|
18
17
|
# Hash of frame opcodes and it's names
|
@@ -21,7 +20,7 @@ module WebSocket
|
|
21
20
|
def encode_frame
|
22
21
|
if @frame.type == :close
|
23
22
|
code = @frame.code || 1000
|
24
|
-
|
23
|
+
fail WebSocket::Error::Frame::UnknownCloseCode unless valid_code?(code)
|
25
24
|
@frame.data = Data.new([code].pack('n') + @frame.data.to_s)
|
26
25
|
@frame.code = nil
|
27
26
|
end
|
@@ -30,11 +29,11 @@ module WebSocket
|
|
30
29
|
|
31
30
|
def decode_frame
|
32
31
|
result = super
|
33
|
-
if
|
32
|
+
if close_code?(result)
|
34
33
|
code = result.data.slice!(0..1)
|
35
34
|
result.code = code.unpack('n').first
|
36
|
-
|
37
|
-
|
35
|
+
fail WebSocket::Error::Frame::UnknownCloseCode unless valid_code?(result.code)
|
36
|
+
fail WebSocket::Error::Frame::InvalidPayloadEncoding unless valid_encoding?(result.data)
|
38
37
|
end
|
39
38
|
result
|
40
39
|
end
|
@@ -53,7 +52,7 @@ module WebSocket
|
|
53
52
|
false
|
54
53
|
end
|
55
54
|
|
56
|
-
def
|
55
|
+
def close_code?(frame)
|
57
56
|
frame && frame.type == :close && !frame.data.empty?
|
58
57
|
end
|
59
58
|
|
@@ -62,7 +61,7 @@ module WebSocket
|
|
62
61
|
# @return [Integer] opcode or nil
|
63
62
|
# @raise [WebSocket::Error] if frame opcode is not known
|
64
63
|
def type_to_opcode(frame_type)
|
65
|
-
FRAME_TYPES[frame_type] ||
|
64
|
+
FRAME_TYPES[frame_type] || fail(WebSocket::Error::Frame::UnknownFrameType)
|
66
65
|
end
|
67
66
|
|
68
67
|
# Convert frame opcode to type name
|
@@ -70,9 +69,8 @@ module WebSocket
|
|
70
69
|
# @return [Symbol] Frame type name or nil
|
71
70
|
# @raise [WebSocket::Error] if frame type name is not known
|
72
71
|
def opcode_to_type(opcode)
|
73
|
-
FRAME_TYPES_INVERSE[opcode] ||
|
72
|
+
FRAME_TYPES_INVERSE[opcode] || fail(WebSocket::Error::Frame::UnknownOpcode)
|
74
73
|
end
|
75
|
-
|
76
74
|
end
|
77
75
|
end
|
78
76
|
end
|
@@ -4,7 +4,6 @@ module WebSocket
|
|
4
4
|
module Frame
|
5
5
|
module Handler
|
6
6
|
class Handler75 < Base
|
7
|
-
|
8
7
|
# @see WebSocket::Frame::Base#supported_frames
|
9
8
|
def supported_frames
|
10
9
|
[:text, :close]
|
@@ -13,12 +12,12 @@ module WebSocket
|
|
13
12
|
# @see WebSocket::Frame::Handler::Base#encode_frame
|
14
13
|
def encode_frame
|
15
14
|
case @frame.type
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
when :close then "\xff\x00"
|
16
|
+
when :text then
|
17
|
+
ary = ["\x00", @frame.data, "\xff"]
|
18
|
+
ary.map { |s| s.encode('UTF-8', 'UTF-8', invalid: :replace) }
|
19
|
+
ary.join
|
20
|
+
else fail WebSocket::Error::Frame::UnknownFrameType
|
22
21
|
end
|
23
22
|
end
|
24
23
|
|
@@ -43,9 +42,9 @@ module WebSocket
|
|
43
42
|
break unless (b & 0x80) == 0x80
|
44
43
|
end
|
45
44
|
|
46
|
-
|
45
|
+
fail WebSocket::Error::Frame::TooLong if length > ::WebSocket.max_frame_size
|
47
46
|
|
48
|
-
unless @frame.data.getbyte(pointer + length - 1)
|
47
|
+
unless @frame.data.getbyte(pointer + length - 1).nil?
|
49
48
|
# Straight from spec - I'm sure this isn't crazy...
|
50
49
|
# 6. Read /length/ bytes.
|
51
50
|
# 7. Discard the read bytes.
|
@@ -59,10 +58,10 @@ module WebSocket
|
|
59
58
|
else
|
60
59
|
# If the high-order bit of the /frame type/ byte is _not_ set
|
61
60
|
|
62
|
-
|
61
|
+
fail WebSocket::Error::Frame::Invalid if @frame.data.getbyte(0) != 0x00
|
63
62
|
|
64
63
|
# Addition to the spec to protect against malicious requests
|
65
|
-
|
64
|
+
fail WebSocket::Error::Frame::TooLong if @frame.data.size > ::WebSocket.max_frame_size
|
66
65
|
|
67
66
|
msg = @frame.data.slice!(/\A\x00[^\xff]*\xff/)
|
68
67
|
if msg
|
@@ -72,7 +71,6 @@ module WebSocket
|
|
72
71
|
end
|
73
72
|
end
|
74
73
|
end
|
75
|
-
|
76
74
|
end
|
77
75
|
end
|
78
76
|
end
|
@@ -9,7 +9,6 @@ module WebSocket
|
|
9
9
|
# frame.next # "Hello"
|
10
10
|
# frame.next # "world!""
|
11
11
|
class Incoming < Base
|
12
|
-
|
13
12
|
autoload :Client, "#{::WebSocket::ROOT}/websocket/frame/incoming/client"
|
14
13
|
autoload :Server, "#{::WebSocket::ROOT}/websocket/frame/incoming/server"
|
15
14
|
|
@@ -46,7 +45,6 @@ module WebSocket
|
|
46
45
|
def to_s
|
47
46
|
@data
|
48
47
|
end
|
49
|
-
|
50
48
|
end
|
51
49
|
end
|
52
50
|
end
|
@@ -7,7 +7,6 @@ module WebSocket
|
|
7
7
|
# frame = WebSocket::Frame::Outgoing::Server.new(version: @handshake.version, data: "Hello", type: :text)
|
8
8
|
# frame.to_s # "\x81\x05\x48\x65\x6c\x6c\x6f"
|
9
9
|
class Outgoing < Base
|
10
|
-
|
11
10
|
autoload :Client, "#{::WebSocket::ROOT}/websocket/frame/outgoing/client"
|
12
11
|
autoload :Server, "#{::WebSocket::ROOT}/websocket/frame/outgoing/server"
|
13
12
|
|
@@ -25,11 +24,10 @@ module WebSocket
|
|
25
24
|
|
26
25
|
# Return raw frame formatted for sending.
|
27
26
|
def to_s
|
28
|
-
|
27
|
+
fail WebSocket::Error::Frame::UnknownFrameType unless supported?
|
29
28
|
@handler.encode_frame
|
30
29
|
end
|
31
30
|
rescue_method :to_s
|
32
|
-
|
33
31
|
end
|
34
32
|
end
|
35
33
|
end
|
data/lib/websocket/handshake.rb
CHANGED
@@ -1,10 +1,8 @@
|
|
1
1
|
module WebSocket
|
2
2
|
module Handshake
|
3
|
-
|
4
3
|
autoload :Base, "#{::WebSocket::ROOT}/websocket/handshake/base"
|
5
4
|
autoload :Client, "#{::WebSocket::ROOT}/websocket/handshake/client"
|
6
5
|
autoload :Handler, "#{::WebSocket::ROOT}/websocket/handshake/handler"
|
7
6
|
autoload :Server, "#{::WebSocket::ROOT}/websocket/handshake/server"
|
8
|
-
|
9
7
|
end
|
10
8
|
end
|
@@ -9,16 +9,18 @@ module WebSocket
|
|
9
9
|
|
10
10
|
# Initialize new WebSocket Handshake and set it's state to :new
|
11
11
|
def initialize(args = {})
|
12
|
+
args.each { |k, v| instance_variable_set("@#{k}", v) }
|
13
|
+
|
12
14
|
@state = :new
|
13
15
|
@handler = nil
|
14
16
|
|
15
17
|
@data = ''
|
16
|
-
@headers
|
18
|
+
@headers ||= {}
|
17
19
|
end
|
18
20
|
|
19
21
|
# @abstract Add data to handshake
|
20
22
|
def <<(data)
|
21
|
-
|
23
|
+
@data << data
|
22
24
|
end
|
23
25
|
|
24
26
|
# Return textual representation of handshake request or response
|
@@ -30,8 +32,8 @@ module WebSocket
|
|
30
32
|
|
31
33
|
# Recreate inspect as #to_s was overwritten
|
32
34
|
def inspect
|
33
|
-
vars =
|
34
|
-
insp = "#{self.class}:0x%08x"
|
35
|
+
vars = instance_variables.map { |v| "#{v}=#{instance_variable_get(v).inspect}" }.join(', ')
|
36
|
+
insp = Kernel.format("#{self.class}:0x%08x", __id__)
|
35
37
|
"<#{insp} #{vars}>"
|
36
38
|
end
|
37
39
|
|
@@ -44,19 +46,19 @@ module WebSocket
|
|
44
46
|
# Is parsed data valid?
|
45
47
|
# @return [Boolean] False if some errors occured. Reason for error could be found in error method
|
46
48
|
def valid?
|
47
|
-
finished? && @error
|
49
|
+
finished? && @error.nil? && @handler && @handler.valid?
|
48
50
|
end
|
49
51
|
rescue_method :valid?, return: false
|
50
52
|
|
51
53
|
# @abstract Should send data after parsing is finished?
|
52
54
|
def should_respond?
|
53
|
-
|
55
|
+
fail NotImplementedError
|
54
56
|
end
|
55
57
|
|
56
58
|
# Data left from parsing. Sometimes data that doesn't belong to handshake are added - use this method to retrieve them.
|
57
59
|
# @return [String] String if some data are available. Nil otherwise
|
58
60
|
def leftovers
|
59
|
-
(@leftovers.to_s.split("\n", reserved_leftover_lines + 1)[reserved_leftover_lines] ||
|
61
|
+
(@leftovers.to_s.split("\n", reserved_leftover_lines + 1)[reserved_leftover_lines] || '').strip
|
60
62
|
end
|
61
63
|
|
62
64
|
# URI of request.
|
@@ -82,7 +84,7 @@ module WebSocket
|
|
82
84
|
|
83
85
|
# Changes state to error and sets error message
|
84
86
|
# @param [String] message Error message to set
|
85
|
-
def
|
87
|
+
def error=(message)
|
86
88
|
@state = :error
|
87
89
|
super
|
88
90
|
end
|
@@ -108,7 +110,6 @@ module WebSocket
|
|
108
110
|
@state = :finished
|
109
111
|
true
|
110
112
|
end
|
111
|
-
|
112
113
|
end
|
113
114
|
end
|
114
115
|
end
|
@@ -32,7 +32,6 @@ module WebSocket
|
|
32
32
|
# @handshake.valid?
|
33
33
|
#
|
34
34
|
class Client < Base
|
35
|
-
|
36
35
|
attr_reader :origin, :headers
|
37
36
|
|
38
37
|
# Initialize new WebSocket Client
|
@@ -55,28 +54,19 @@ module WebSocket
|
|
55
54
|
def initialize(args = {})
|
56
55
|
super
|
57
56
|
|
58
|
-
@
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@
|
65
|
-
@host = uri.host
|
66
|
-
@port = uri.port
|
67
|
-
@path = uri.path
|
68
|
-
@query = uri.query
|
57
|
+
if @url || @uri
|
58
|
+
uri = URI.parse(@url || @uri)
|
59
|
+
@secure ||= (uri.scheme == 'wss')
|
60
|
+
@host ||= uri.host
|
61
|
+
@port ||= uri.port
|
62
|
+
@path ||= uri.path
|
63
|
+
@query ||= uri.query
|
69
64
|
end
|
70
65
|
|
71
|
-
@
|
72
|
-
@
|
73
|
-
@port = args[:port] if args[:port]
|
74
|
-
@path = args[:path] if args[:path]
|
75
|
-
@query = args[:query] if args[:query]
|
66
|
+
@path = '/' if @path.nil? || @path.empty?
|
67
|
+
@version ||= DEFAULT_VERSION
|
76
68
|
|
77
|
-
|
78
|
-
|
79
|
-
raise WebSocket::Error::Handshake::NoHostProvided unless @host
|
69
|
+
fail WebSocket::Error::Handshake::NoHostProvided unless @host
|
80
70
|
|
81
71
|
include_version
|
82
72
|
end
|
@@ -95,10 +85,8 @@ module WebSocket
|
|
95
85
|
#
|
96
86
|
# EOF
|
97
87
|
def <<(data)
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
88
|
+
super
|
89
|
+
parse_data
|
102
90
|
end
|
103
91
|
rescue_method :<<
|
104
92
|
|
@@ -114,27 +102,26 @@ module WebSocket
|
|
114
102
|
# @return [Boolean] false if protocol number is unknown, otherwise true
|
115
103
|
def include_version
|
116
104
|
@handler = case @version
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
105
|
+
when 75 then Handler::Client75.new(self)
|
106
|
+
when 76, 0 then Handler::Client76.new(self)
|
107
|
+
when 1..3 then Handler::Client01.new(self)
|
108
|
+
when 4..10 then Handler::Client04.new(self)
|
109
|
+
when 11..17 then Handler::Client11.new(self)
|
110
|
+
else fail WebSocket::Error::Handshake::UnknownVersion
|
111
|
+
end
|
124
112
|
end
|
125
113
|
|
126
|
-
FIRST_LINE =
|
114
|
+
FIRST_LINE = %r{^HTTP\/1\.1 (\d{3})[\w\s]*$}
|
127
115
|
|
128
116
|
# Parse first line of Server response.
|
129
117
|
# @param [String] line Line to parse
|
130
118
|
# @return [Boolean] True if parsed correctly. False otherwise
|
131
119
|
def parse_first_line(line)
|
132
120
|
line_parts = line.match(FIRST_LINE)
|
133
|
-
|
121
|
+
fail WebSocket::Error::Handshake::InvalidHeader unless line_parts
|
134
122
|
status = line_parts[1]
|
135
|
-
|
123
|
+
fail WebSocket::Error::Handshake::InvalidStatusCode unless status == '101'
|
136
124
|
end
|
137
|
-
|
138
125
|
end
|
139
126
|
end
|
140
127
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module WebSocket
|
2
2
|
module Handshake
|
3
3
|
module Handler
|
4
|
-
|
5
4
|
autoload :Base, "#{::WebSocket::ROOT}/websocket/handshake/handler/base"
|
6
5
|
|
7
6
|
autoload :Client, "#{::WebSocket::ROOT}/websocket/handshake/handler/client"
|
@@ -15,7 +14,6 @@ module WebSocket
|
|
15
14
|
autoload :Server04, "#{::WebSocket::ROOT}/websocket/handshake/handler/server04"
|
16
15
|
autoload :Server75, "#{::WebSocket::ROOT}/websocket/handshake/handler/server75"
|
17
16
|
autoload :Server76, "#{::WebSocket::ROOT}/websocket/handshake/handler/server76"
|
18
|
-
|
19
17
|
end
|
20
18
|
end
|
21
19
|
end
|