Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions lib/protocol/websocket/close_frame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ module WebSocket
class CloseFrame < Frame
OPCODE = 0x8
FORMAT = "na*"
MAXIMUM_REASON_LENGTH = 123

# Unpack the frame data into a close code and reason.
# @returns [Tuple(Integer, String)] The close code and reason.
Expand Down Expand Up @@ -45,6 +46,7 @@ def unpack

# Pack a close code and reason into the frame data.
# If code is missing, reason is ignored.
# The reason is truncated to 123 bytes.
# @parameter code [Integer | Nil] The close code.
# @parameter reason [String | Nil] The close reason.
def pack(code = nil, reason = nil)
Expand All @@ -53,6 +55,10 @@ def pack(code = nil, reason = nil)
reason = reason.encode(Encoding::UTF_8)
end

if reason and reason.bytesize > MAXIMUM_REASON_LENGTH
reason = reason.byteslice(0, MAXIMUM_REASON_LENGTH).scrub("")
end

super([code, reason].pack(FORMAT))
else
super()
Expand Down
19 changes: 19 additions & 0 deletions test/protocol/websocket/close_frame.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@

expect(frame.payload).to be == "\x03\xE8Hello World".b
end

it "truncates the reason to fit in a control frame" do
frame.pack(1000, "x" * 200)

expect(frame.payload.bytesize).to be == 125

code, reason = frame.unpack
expect(code).to be == 1000
expect(reason).to be == "x" * 123
end

it "doesn't split a multibyte character when truncating the reason" do
frame.pack(1000, ("x" * 122) + "é")

expect(frame.payload.bytesize).to be == 124

code, reason = frame.unpack
expect(reason).to be == "x" * 122
end
end

with "#unpack" do
Expand Down
11 changes: 11 additions & 0 deletions test/protocol/websocket/connection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,17 @@
expect(connection).to be(:closed?)
end

it "truncates a long error message to fit in the close frame" do
connection.close_write(RuntimeError.new("x" * 200))

frame = client.read_frame
expect(frame).to be_a(Protocol::WebSocket::CloseFrame)

code, reason = frame.unpack
expect(code).to be == Protocol::WebSocket::Error::INTERNAL_ERROR
expect(reason).to be == "x" * 123
end

it "is not closed when close_write succeeds" do
connection.close_write

Expand Down
Loading