Skip to content

Commit 8faa78e

Browse files
committed
std: support close messages on websocket server
1 parent 7c3e021 commit 8faa78e

File tree

2 files changed

+24
-8
lines changed

2 files changed

+24
-8
lines changed

lib/std/Build/WebServer.zig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ fn accept(ws: *WebServer, connection: std.net.Server.Connection) void {
256256
var web_socket = request.respondWebSocket(.{ .key = key, .allocator = ws.gpa }) catch {
257257
return log.err("failed to respond web socket: {t}", .{connection_writer.err.?});
258258
};
259-
defer web_socket.close(0);
259+
defer web_socket.close(.{ .exit_code = 0 });
260260
ws.serveWebSocket(&web_socket) catch |err| {
261261
log.err("failed to serve websocket: {t}", .{err});
262262
return;

lib/std/http/Server.zig

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -750,14 +750,19 @@ pub const WebSocket = struct {
750750
}
751751
};
752752

753+
pub const CloseMessage = struct {
754+
exit_code: u16,
755+
data: []const u8 = "",
756+
};
757+
753758
pub const WebsocketMessage = struct {
754759
opcode: Opcode,
755760
data: []u8,
756761
};
757762

758763
/// Sends close frame with the exit code and frees any allocated memory
759-
pub fn close(ws: *WebSocket, exit_code: u16) void {
760-
ws.writeCloseFrame(exit_code) catch {};
764+
pub fn close(ws: *WebSocket, options: CloseMessage) void {
765+
ws.writeCloseFrame(options) catch {};
761766
ws.deinit();
762767
}
763768

@@ -787,6 +792,7 @@ pub const WebSocket = struct {
787792
if (!payload_head.mask)
788793
return error.MissingMaskBit;
789794

795+
// TODO: Remove check here for op_head.rsv1 once compression is readded.
790796
if (@bitCast(op_head.rsv1) or @bitCast(op_head.rsv2) or @bitCast(op_head.rsv3))
791797
return error.UnnegociatedReservedBits;
792798

@@ -821,6 +827,9 @@ pub const WebSocket = struct {
821827
.binary,
822828
=> {
823829
if (!op_head.fin) {
830+
if (ws.fragment.message_type != null)
831+
return error.UnexpectedFragment;
832+
824833
try ws.fragment.writeAll(payload);
825834
ws.fragment.message_type = op_head.opcode;
826835

@@ -843,6 +852,9 @@ pub const WebSocket = struct {
843852
const message_type = ws.fragment.message_type orelse return error.FragmentedControl;
844853

845854
if (!op_head.fin) {
855+
if (ws.fragment.message_type == null)
856+
return error.UnexpectedFragment;
857+
846858
try ws.fragment.writeAll(payload);
847859
continue;
848860
}
@@ -880,17 +892,21 @@ pub const WebSocket = struct {
880892
/// Writes to the server a close frame with a provided `exit_code`.
881893
///
882894
/// For more details please see: https://www.rfc-editor.org/rfc/rfc6455#section-5.5.1
883-
pub fn writeCloseFrame(ws: *WebSocket, exit_code: u16) Writer.Error!void {
884-
if (exit_code == 0) {
895+
pub fn writeCloseFrame(ws: *WebSocket, options: CloseMessage) Writer.Error!void {
896+
if (options.exit_code == 0) {
885897
@branchHint(.likely);
886898

887-
return ws.writeFrame("", .connection_close);
899+
return ws.writeFrame(options.data, .connection_close);
888900
}
889901

890902
var buffer: [2]u8 = undefined;
891-
std.mem.writeInt(u16, buffer[0..2], exit_code, .big);
903+
std.mem.writeInt(u16, buffer[0..2], options.exit_code, .big);
904+
905+
var bufs: [2][]const u8 = .{ buffer[0..], options.data };
906+
try ws.writeHeaderFrameVecUnflushed(&bufs, .connection_close, true);
907+
try ws.writeBodyVecUnflushed(&bufs);
892908

893-
return ws.writeFrame(buffer[0..], .connection_close);
909+
return ws.flush();
894910
}
895911

896912
/// Writes a websocket frame directly to the socket.

0 commit comments

Comments
 (0)