protocol-websocket 0.16.0 → 0.18.0

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: 65d2f2f5247451bba72a1b622fff8caf46fb03d8843531eb107c0a46f4cc5ff1
4
- data.tar.gz: 555d8a9a9a9cd09d678d5d04961af2134a06adf1bf32ba42d0ecb608e35528bb
3
+ metadata.gz: ef7b32c9de28a9b7486a004d8ae53739fbe34de345e32b7a5e4ff056df5c755c
4
+ data.tar.gz: 2b8d07f45527f32e5a4b2cf0bb5d22707083a6fea94bedb1e93413aece140ee1
5
5
  SHA512:
6
- metadata.gz: dd72ffc0701049551abe38408ae500f05dd2d32186cab990f49091e6600357b5c887903fd1e48b23b957b80f8d0deb4d9ddfcd8ac1b2b4c68eb5bbae63cbaf92
7
- data.tar.gz: 647ec40540b3f991b79d96b13022f16c1b4fb7960d53b09cbf773a45b5d5726fbbe328a8129ff22e56c9805cd407d2e1bb998f9bc6dc29d1489d66a7b4dfc2b9
6
+ metadata.gz: dfef8b28cadd857f4d7430cb35e668f14789ce9d70fed4fa2c24c945ff9848ef9d35000e143b0344489c8120b4d940168a07e717a8da22738d1972f1f373bb8d
7
+ data.tar.gz: b3df54c2b5fa01963ffa5f26f15ddd16f3d983b20aeac9d1ee39fb60d052bfb720ee7963c2588708aebb6a9d649c29af81518f3af2bd1dc67c147b9fc6983673
checksums.yaml.gz.sig CHANGED
Binary file
@@ -4,8 +4,8 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2021, by Aurora Nockert.
6
6
 
7
- require_relative 'frame'
8
- require_relative 'message'
7
+ require_relative "frame"
8
+ require_relative "message"
9
9
 
10
10
  module Protocol
11
11
  module WebSocket
@@ -4,7 +4,7 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2021, by Aurora Nockert.
6
6
 
7
- require_relative 'frame'
7
+ require_relative "frame"
8
8
 
9
9
  module Protocol
10
10
  module WebSocket
@@ -59,6 +59,14 @@ module Protocol
59
59
  end
60
60
  end
61
61
 
62
+ # Generate a suitable reply.
63
+ # @returns [CloseFrame]
64
+ def reply(code = Error::NO_ERROR, reason = "")
65
+ frame = CloseFrame.new
66
+ frame.pack(code, reason)
67
+ return frame
68
+ end
69
+
62
70
  # Apply this frame to the specified connection.
63
71
  def apply(connection)
64
72
  connection.receive_close(self)
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2024, by Samuel Williams.
5
5
 
6
- require 'json'
6
+ require "json"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2024, by Samuel Williams.
5
5
 
6
- require_relative 'coder/json'
6
+ require_relative "coder/json"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -5,8 +5,7 @@
5
5
  # Copyright, 2019, by William T. Nelson.
6
6
  # Copyright, 2021, by Aurora Nockert.
7
7
 
8
- require_relative 'framer'
9
- require 'securerandom'
8
+ require_relative "framer"
10
9
 
11
10
  module Protocol
12
11
  module WebSocket
@@ -89,13 +88,34 @@ module Protocol
89
88
  @state == :closed
90
89
  end
91
90
 
92
- # Immediately transition the connection to the closed state *and* close the underlying connection.
91
+ # Immediately transition the connection to the closed state *and* close the underlying connection. Any data not yet read will be lost.
93
92
  def close(...)
94
93
  close!(...)
95
94
 
96
95
  @framer.close
97
96
  end
98
97
 
98
+ # Close the connection gracefully, sending a close frame with the specified error code and reason. If an error occurs while sending the close frame, the connection will be closed immediately. You may continue to read data from the connection after calling this method, but you should not write any more data.
99
+ #
100
+ # @parameter error [Error | Nil] The error that occurred, if any.
101
+ def close_write(error = nil)
102
+ if error
103
+ send_close(Error::INTERNAL_ERROR, error.message)
104
+ else
105
+ send_close
106
+ end
107
+ end
108
+
109
+ # Close the connection gracefully. This will send a close frame and wait for the remote end to respond with a close frame. Any data received after the close frame is sent will be ignored. If you want to process this data, use {#close_write} instead, and read the data before calling {#close}.
110
+ def shutdown
111
+ send_close unless @state == :closed
112
+
113
+ # `read_frame` will return nil after receiving a close frame:
114
+ while read_frame
115
+ # Drain the connection.
116
+ end
117
+ end
118
+
99
119
  # Read a frame from the framer, and apply it to the connection.
100
120
  def read_frame
101
121
  return nil if closed?
@@ -246,7 +266,7 @@ module Protocol
246
266
  def write(message, **options)
247
267
  case message
248
268
  when String
249
- # This is a compatibility shim for the previous implementation. We may want to eventually deprecate this use case... or maybe it's convenient enough to leave it around.
269
+ # This is a compatibility shim for the previous implementation. We may want to eventually deprecate this use case... or maybe it's convenient enough to leave it around.
250
270
  if message.encoding == Encoding::UTF_8
251
271
  return send_text(message, **options)
252
272
  else
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'frame'
6
+ require_relative "frame"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require 'protocol/http/error'
6
+ require "protocol/http/error"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -19,10 +19,24 @@ module Protocol
19
19
  # Indicates that an endpoint is terminating the connection due to a protocol error.
20
20
  PROTOCOL_ERROR = 1002
21
21
 
22
- # Indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept.
22
+ # Indicates that an endpoint is terminating the connection because it has received a type of data it cannot accept. (e.g., an endpoint that understands only text data MAY send this if it receives a binary message).
23
23
  INVALID_DATA = 1003
24
24
 
25
- # There are other status codes but most of them are "implementation specific".
25
+
26
+ # Indicates that an endpoint is terminating the connection because it has received data within a message that was not consistent with the type of the message (e.g., non-UTF-8 data within a text message).
27
+ INVALID_PAYLOAD = 1007
28
+
29
+ # Indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the policy.
30
+ POLICY_VIOLATION = 1008
31
+
32
+ # Indicates that an endpoint is terminating the connection because it has received a message that is too big for it to process.
33
+ MESSAGE_TOO_LARGE = 1009
34
+
35
+ # Indicates that an endpoint (client) is terminating the connection because it has expected the server to negotiate one or more extension, but the server didn't return them in the response message of the WebSocket handshake. The list of extensions that are needed should appear in the /reason/ part of the Close frame. Note that this status code is not used by the server, because it can fail the WebSocket handshake instead.
36
+ MISSING_EXTENSION = 1010
37
+
38
+ # Indicates that a server is terminating the connection because it encountered an unexpected condition that prevented it from fulfilling the request.
39
+ INTERNAL_ERROR = 1011
26
40
  end
27
41
 
28
42
  # Raised by stream or connection handlers, results in GOAWAY frame which signals termination of the current connection. You *cannot* recover from this exception, or any exceptions subclassed from it.
@@ -1,15 +1,15 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022-2023, by Samuel Williams.
4
+ # Copyright, 2022-2024, by Samuel Williams.
5
5
 
6
- require 'zlib'
6
+ require "zlib"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
10
10
  module Extension
11
11
  module Compression
12
- NAME = 'permessage-deflate'
12
+ NAME = "permessage-deflate"
13
13
 
14
14
  # Zlib is not capable of handling < 9 window bits.
15
15
  MINIMUM_WINDOW_BITS = 9
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022-2023, by Samuel Williams.
4
+ # Copyright, 2022-2024, by Samuel Williams.
5
5
 
6
- require_relative 'constants'
6
+ require_relative "constants"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2022-2023, by Samuel Williams.
4
+ # Copyright, 2022-2024, by Samuel Williams.
5
5
 
6
- require_relative 'constants'
6
+ require_relative "constants"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -26,7 +26,7 @@ module Protocol
26
26
  )
27
27
  end
28
28
 
29
- TRAILER = [0x00, 0x00, 0xff, 0xff].pack('C*')
29
+ TRAILER = [0x00, 0x00, 0xff, 0xff].pack("C*")
30
30
 
31
31
  def initialize(parent, context_takeover: true, window_bits: 15)
32
32
  @parent = parent
@@ -3,9 +3,9 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2022-2024, by Samuel Williams.
5
5
 
6
- require_relative 'compression/constants'
7
- require_relative 'compression/inflate'
8
- require_relative 'compression/deflate'
6
+ require_relative "compression/constants"
7
+ require_relative "compression/inflate"
8
+ require_relative "compression/deflate"
9
9
 
10
10
  module Protocol
11
11
  module WebSocket
@@ -22,13 +22,13 @@ module Protocol
22
22
  when 8..15
23
23
  header << "client_max_window_bits=#{client_max_window_bits}"
24
24
  when true
25
- header << 'client_max_window_bits'
25
+ header << "client_max_window_bits"
26
26
  else
27
27
  raise ArgumentError, "Invalid local maximum window bits!"
28
28
  end
29
29
 
30
30
  if client_no_context_takeover
31
- header << 'client_no_context_takeover'
31
+ header << "client_no_context_takeover"
32
32
  end
33
33
 
34
34
  case server_max_window_bits
@@ -41,7 +41,7 @@ module Protocol
41
41
  end
42
42
 
43
43
  if server_no_context_takeover
44
- header << 'server_no_context_takeover'
44
+ header << "server_no_context_takeover"
45
45
  end
46
46
 
47
47
  return header
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2022-2024, by Samuel Williams.
5
5
 
6
- require_relative 'extension/compression'
7
- require_relative 'headers'
6
+ require_relative "extension/compression"
7
+ require_relative "headers"
8
8
 
9
9
  module Protocol
10
10
  module WebSocket
@@ -16,7 +16,7 @@ module Protocol
16
16
  name, *arguments = header.split(/\s*;\s*/)
17
17
 
18
18
  arguments = arguments.map do |argument|
19
- argument.split('=', 2)
19
+ argument.split("=", 2)
20
20
  end
21
21
 
22
22
  yield name, arguments
@@ -5,7 +5,7 @@
5
5
  # Copyright, 2019, by Soumya.
6
6
  # Copyright, 2021, by Aurora Nockert.
7
7
 
8
- require_relative 'error'
8
+ require_relative "error"
9
9
 
10
10
  module Protocol
11
11
  module WebSocket
@@ -178,10 +178,10 @@ module Protocol
178
178
 
179
179
  if length == 126
180
180
  buffer = stream.read(2) or raise EOFError, "Could not read length!"
181
- length = buffer.unpack('n').first
181
+ length = buffer.unpack("n").first
182
182
  elsif length == 127
183
183
  buffer = stream.read(8) or raise EOFError, "Could not read length!"
184
- length = buffer.unpack('Q>').first
184
+ length = buffer.unpack("Q>").first
185
185
  end
186
186
 
187
187
  if length > maximum_frame_size
@@ -223,12 +223,12 @@ module Protocol
223
223
  buffer << [
224
224
  (@finished ? 0b1000_0000 : 0) | (@flags << 4) | @opcode,
225
225
  (@mask ? 0b1000_0000 : 0) | short_length,
226
- ].pack('CC')
226
+ ].pack("CC")
227
227
 
228
228
  if short_length == 126
229
- buffer << [@length].pack('n')
229
+ buffer << [@length].pack("n")
230
230
  elsif short_length == 127
231
- buffer << [@length].pack('Q>')
231
+ buffer << [@length].pack("Q>")
232
232
  end
233
233
 
234
234
  buffer << @mask if @mask
@@ -3,14 +3,14 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'frame'
6
+ require_relative "frame"
7
7
 
8
- require_relative 'continuation_frame'
9
- require_relative 'text_frame'
10
- require_relative 'binary_frame'
11
- require_relative 'close_frame'
12
- require_relative 'ping_frame'
13
- require_relative 'pong_frame'
8
+ require_relative "continuation_frame"
9
+ require_relative "text_frame"
10
+ require_relative "binary_frame"
11
+ require_relative "close_frame"
12
+ require_relative "ping_frame"
13
+ require_relative "pong_frame"
14
14
 
15
15
  module Protocol
16
16
  module WebSocket
@@ -1,27 +1,27 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Released under the MIT License.
4
- # Copyright, 2019-2023, by Samuel Williams.
4
+ # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require 'digest/sha1'
7
- require 'securerandom'
6
+ require "digest/sha1"
7
+ require "securerandom"
8
8
 
9
9
  module Protocol
10
10
  module WebSocket
11
11
  module Headers
12
12
  # The protocol string used for the `upgrade:` header (HTTP/1) and `:protocol` pseudo-header (HTTP/2).
13
- PROTOCOL = "websocket".freeze
13
+ PROTOCOL = "websocket"
14
14
 
15
15
  # The WebSocket protocol header, used for application level protocol negotiation.
16
- SEC_WEBSOCKET_PROTOCOL = 'sec-websocket-protocol'.freeze
16
+ SEC_WEBSOCKET_PROTOCOL = "sec-websocket-protocol"
17
17
 
18
18
  # The WebSocket version header. Used for negotiating binary protocol version.
19
- SEC_WEBSOCKET_VERSION = 'sec-websocket-version'.freeze
19
+ SEC_WEBSOCKET_VERSION = "sec-websocket-version"
20
20
 
21
- SEC_WEBSOCKET_KEY = 'sec-websocket-key'.freeze
22
- SEC_WEBSOCKET_ACCEPT = 'sec-websocket-accept'.freeze
21
+ SEC_WEBSOCKET_KEY = "sec-websocket-key"
22
+ SEC_WEBSOCKET_ACCEPT = "sec-websocket-accept"
23
23
 
24
- SEC_WEBSOCKET_EXTENSIONS = 'sec-websocket-extensions'.freeze
24
+ SEC_WEBSOCKET_EXTENSIONS = "sec-websocket-extensions"
25
25
 
26
26
  module Nounce
27
27
  GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2022-2024, by Samuel Williams.
5
5
 
6
- require_relative 'frame'
7
- require_relative 'coder'
6
+ require_relative "frame"
7
+ require_relative "coder"
8
8
 
9
9
  module Protocol
10
10
  module WebSocket
@@ -72,5 +72,12 @@ module Protocol
72
72
  connection.send_binary(@buffer, **options)
73
73
  end
74
74
  end
75
+
76
+ # Represents a ping message that can be sent over a WebSocket connection.
77
+ class PingMessage < Message
78
+ def send(connection)
79
+ connection.send_ping(@buffer)
80
+ end
81
+ end
75
82
  end
76
83
  end
@@ -3,8 +3,8 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'frame'
7
- require_relative 'pong_frame'
6
+ require_relative "frame"
7
+ require_relative "pong_frame"
8
8
 
9
9
  module Protocol
10
10
  module WebSocket
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'frame'
6
+ require_relative "frame"
7
7
 
8
8
  module Protocol
9
9
  module WebSocket
@@ -4,8 +4,8 @@
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
  # Copyright, 2021, by Aurora Nockert.
6
6
 
7
- require_relative 'frame'
8
- require_relative 'message'
7
+ require_relative "frame"
8
+ require_relative "message"
9
9
 
10
10
  module Protocol
11
11
  module WebSocket
@@ -5,6 +5,6 @@
5
5
 
6
6
  module Protocol
7
7
  module WebSocket
8
- VERSION = "0.16.0"
8
+ VERSION = "0.18.0"
9
9
  end
10
10
  end
@@ -3,7 +3,7 @@
3
3
  # Released under the MIT License.
4
4
  # Copyright, 2019-2024, by Samuel Williams.
5
5
 
6
- require_relative 'websocket/version'
7
- require_relative 'websocket/framer'
8
- require_relative 'websocket/connection'
9
- require_relative 'websocket/message'
6
+ require_relative "websocket/version"
7
+ require_relative "websocket/framer"
8
+ require_relative "websocket/connection"
9
+ require_relative "websocket/message"
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protocol-websocket
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.0
4
+ version: 0.18.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
@@ -41,7 +41,7 @@ cert_chain:
41
41
  Q2K9NVun/S785AP05vKkXZEFYxqG6EW012U4oLcFl5MySFajYXRYbuUpH6AY+HP8
42
42
  voD0MPg1DssDLKwXyt1eKD/+Fq0bFWhwVM/1XiAXL7lyYUyOq24KHgQ2Csg=
43
43
  -----END CERTIFICATE-----
44
- date: 2024-09-03 00:00:00.000000000 Z
44
+ date: 2024-09-25 00:00:00.000000000 Z
45
45
  dependencies:
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: protocol-http
@@ -79,7 +79,6 @@ files:
79
79
  - lib/protocol/websocket/frame.rb
80
80
  - lib/protocol/websocket/framer.rb
81
81
  - lib/protocol/websocket/headers.rb
82
- - lib/protocol/websocket/json_message.rb
83
82
  - lib/protocol/websocket/message.rb
84
83
  - lib/protocol/websocket/ping_frame.rb
85
84
  - lib/protocol/websocket/pong_frame.rb
metadata.gz.sig CHANGED
Binary file
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # Released under the MIT License.
4
- # Copyright, 2022-2024, by Samuel Williams.
5
-
6
- require_relative 'message'
7
-
8
- warn "Protocol::WebSocket::JSONMessage is deprecated. Use Protocol::WebSocket::TextMessage instead."
9
-
10
- module Protocol
11
- module WebSocket
12
- # @deprecated Use {TextMessage} instead.
13
- class JSONMessage < TextMessage
14
- def self.wrap(message)
15
- message
16
- end
17
-
18
- def self.generate(object)
19
- self.new(JSON.generate(object))
20
- end
21
- end
22
- end
23
- end