readSmallMessage
Reads the next message from the WebSocket stream, failing if the message does not fit into the input buffer. The returned memory points into the input buffer and is invalidated on the next read.
Function parameters
Parameters
- ws:*WebSocket
Type definitions in this namespace
Types
Initialize an HTTP server that can respond to multiple requests on the same
Functions
- init
- Initialize an HTTP server that can respond to multiple requests on the same
Error sets in this namespace
Error Sets
Source
Implementation
pub fn readSmallMessage(ws: *WebSocket) ReadSmallTextMessageError!SmallMessage {
const in = ws.input;
while (true) {
const header = try in.takeArray(2);
const h0: Header0 = @bitCast(header[0]);
const h1: Header1 = @bitCast(header[1]);
switch (h0.opcode) {
.text, .binary, .pong, .ping => {},
.connection_close => return error.ConnectionClose,
.continuation => return error.UnexpectedOpCode,
_ => return error.UnexpectedOpCode,
}
if (!h0.fin) return error.MessageTooBig;
if (!h1.mask) return error.MissingMaskBit;
const len: usize = switch (h1.payload_len) {
.len16 => try in.takeInt(u16, .big),
.len64 => std.math.cast(usize, try in.takeInt(u64, .big)) orelse return error.MessageTooBig,
else => @intFromEnum(h1.payload_len),
};
if (len > in.buffer.len) return error.MessageTooBig;
const mask: u32 = @bitCast((try in.takeArray(4)).*);
const payload = try in.take(len);
// Skip pongs.
if (h0.opcode == .pong) continue;
// The last item may contain a partial word of unused data.
const floored_len = (payload.len / 4) * 4;
const u32_payload: []align(1) u32 = @ptrCast(payload[0..floored_len]);
for (u32_payload) |*elem| elem.* ^= mask;
const mask_bytes: []const u8 = @ptrCast(&mask);
for (payload[floored_len..], mask_bytes[0 .. payload.len - floored_len]) |*leftover, m|
leftover.* ^= m;
return .{
.opcode = h0.opcode,
.data = payload,
};
}
}