1010
1111module Protocol
1212 module WebSocket
13+ # Represents a single WebSocket frame as defined by RFC 6455.
1314 class Frame
1415 include Comparable
1516
@@ -35,18 +36,28 @@ def initialize(finished = true, payload = nil, flags: 0, opcode: self.class::OPC
3536 @payload = payload
3637 end
3738
39+ # Check whether the specified RSV flag bit is set on this frame.
40+ # @parameter value [Integer] The flag bitmask to test (e.g. `RSV1`).
41+ # @returns [Boolean] `true` if the flag bit is set.
3842 def flag? ( value )
3943 @flags & value != 0
4044 end
4145
46+ # Compare this frame to another frame by their array representation.
47+ # @parameter other [Frame] The frame to compare against.
48+ # @returns [Integer] A comparison result (-1, 0, or 1).
4249 def <=> other
4350 to_ary <=> other . to_ary
4451 end
4552
53+ # Convert this frame to an array of its fields for comparison or inspection.
54+ # @returns [Array] An array of `[finished, flags, opcode, mask, length, payload]`.
4655 def to_ary
4756 [ @finished , @flags , @opcode , @mask , @length , @payload ]
4857 end
4958
59+ # Check whether this is a control frame (opcode has bit 3 set).
60+ # @returns [Boolean] `true` if this is a control frame.
5061 def control?
5162 @opcode & 0x8 != 0
5263 end
@@ -56,10 +67,14 @@ def data?
5667 false
5768 end
5869
70+ # Check whether this is the final frame in a message.
71+ # @returns [Boolean] `true` if the FIN bit is set.
5972 def finished?
6073 @finished == true
6174 end
6275
76+ # Check whether this frame is a continuation fragment (FIN bit not set).
77+ # @returns [Boolean] `true` if the FIN bit is not set.
6378 def continued?
6479 @finished == false
6580 end
@@ -116,6 +131,9 @@ def continued?
116131 end
117132 end
118133
134+ # Pack the given data into this frame's payload, applying masking if configured.
135+ # @parameter data [String] The payload data to pack.
136+ # @returns [Frame] Returns `self`.
119137 def pack ( data = "" )
120138 length = data . bytesize
121139
@@ -134,6 +152,8 @@ def pack(data = "")
134152 return self
135153 end
136154
155+ # Unpack the raw payload, removing masking if present.
156+ # @returns [String] The unmasked payload data.
137157 def unpack
138158 if @mask and !@payload . empty?
139159 return mask_xor ( @payload , @mask )
@@ -142,10 +162,16 @@ def unpack
142162 end
143163 end
144164
165+ # Apply this frame to the connection by dispatching it to the appropriate handler.
166+ # @parameter connection [Connection] The WebSocket connection to receive this frame.
145167 def apply ( connection )
146168 connection . receive_frame ( self )
147169 end
148170
171+ # Parse the first byte of a frame header to extract FIN, RSV flags, and opcode.
172+ # @parameter buffer [String] A 1-byte binary string.
173+ # @returns [Array] A tuple of `[finished, flags, opcode]`.
174+ # @raises [ProtocolError] If the opcode is a reserved non-control or control opcode.
149175 def self . parse_header ( buffer )
150176 byte = buffer . unpack ( "C" ) . first
151177
@@ -162,6 +188,15 @@ def self.parse_header(buffer)
162188 return finished , flags , opcode
163189 end
164190
191+ # Read a full frame from the stream given pre-parsed header fields.
192+ # @parameter finished [Boolean] Whether the FIN bit was set.
193+ # @parameter flags [Integer] The RSV flag bits.
194+ # @parameter opcode [Integer] The frame opcode.
195+ # @parameter stream [IO] The stream to read from.
196+ # @parameter maximum_frame_size [Integer] The maximum allowed payload size in bytes.
197+ # @returns [Frame] The fully read and populated frame.
198+ # @raises [ProtocolError] If the frame violates protocol constraints.
199+ # @raises [EOFError] If the stream ends unexpectedly.
165200 def self . read ( finished , flags , opcode , stream , maximum_frame_size )
166201 buffer = stream . read ( 1 ) or raise EOFError , "Could not read header!"
167202 byte = buffer . unpack ( "C" ) . first
@@ -202,6 +237,9 @@ def self.read(finished, flags, opcode, stream, maximum_frame_size)
202237 return self . new ( finished , payload , flags : flags , opcode : opcode , mask : mask )
203238 end
204239
240+ # Write this frame to the given stream.
241+ # @parameter stream [IO] The stream to write the serialized frame to.
242+ # @raises [ProtocolError] If the frame has invalid length or mask.
205243 def write ( stream )
206244 buffer = String . new ( encoding : Encoding ::BINARY )
207245
0 commit comments