websocket 1.2.2 → 1.2.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|