Skip to documentation
SLOP

tiny.http.Frame

Reference tiny.http Frame

Defined in tiny.http.

API (9)

Actions

Public operations.

Fields and members

Public fields and members.

No direct callersNo direct callstiny.httpFrame
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Source: lib/http/src/websocket.zig:269

zig
pub const Frame = struct {    fin: bool,    opcode: Opcode,    mask: ?[4]u8,    payload: []const u8,    pub fn parse(data: []u8, maximum_payload_bytes: usize) FrameError!FrameParseResult {        if (data.len < 2) return FrameError.IncompleteFrame;        if ((data[0] & 0x70) != 0) return FrameError.InvalidFrame;        const fin = (data[0] & 0x80) != 0;        const opcode = try Opcode.fromWire(data[0] & 0x0F);        const masked = (data[1] & 0x80) != 0;        const len7 = data[1] & 0x7F;        var header_len: usize = 2;        var payload_len: usize = undefined;        if (len7 < 126) {            payload_len = len7;        } else if (len7 == 126) {            if (data.len < 4) return FrameError.IncompleteFrame;            payload_len = std.mem.readInt(u16, data[2..4], .big);            if (payload_len < 126) return FrameError.InvalidFrame;            header_len = 4;        } else {            if (data.len < 10) return FrameError.IncompleteFrame;            const len64 = std.mem.readInt(u64, data[2..10], .big);            if (len64 < 65536) return FrameError.InvalidFrame;            if (@as(u128, len64) > maximum_protocol_payload_bytes) {                return FrameError.InvalidFrame;            }            if (@as(u128, len64) > @as(u128, std.math.maxInt(usize))) {                return FrameError.PayloadTooLarge;            }            payload_len = @intCast(len64);            header_len = 10;        }        try validateFrameHeader(fin, opcode, payload_len);        if (payload_len > maximum_payload_bytes) return FrameError.PayloadTooLarge;        const mask_key_offset = header_len;        if (masked) {            header_len += 4;        }        const total_len = std.math.add(usize, header_len, payload_len) catch {            return FrameError.PayloadTooLarge;        };        if (data.len < total_len) return FrameError.IncompleteFrame;        const mask: ?[4]u8 = if (masked)            data[mask_key_offset..][0..4].*        else            null;        const payload = data[header_len..total_len];        if (mask) |m| {            maskPayload(payload, payload, m);        }        return .{            .frame = .{                .fin = fin,                .opcode = opcode,                .mask = mask,                .payload = payload,            },            .consumed = total_len,        };    }    pub fn serializedLength(        self: *const Frame,        maximum_payload_bytes: usize,    ) FrameError!usize {        const header_bytes = try self.headerLength(maximum_payload_bytes);        return std.math.add(usize, header_bytes, self.payload.len) catch {            return FrameError.PayloadTooLarge;        };    }    pub fn serializeInto(        self: *const Frame,        output: []u8,        maximum_payload_bytes: usize,    ) FrameError![]u8 {        const total_bytes = try self.serializedLength(maximum_payload_bytes);        if (output.len < total_bytes) return FrameError.OutputTooSmall;        const target = output[0..total_bytes];        const header = try self.writeHeader(target, maximum_payload_bytes);        const payload = target[header.len..];        if (self.mask) |mask| {            maskPayload(self.payload, payload, mask);        } else {            @memcpy(payload, self.payload);        }        return target;    }    pub fn serializeHeaderInto(        self: *const Frame,        output: []u8,        maximum_payload_bytes: usize,    ) FrameError![]u8 {        return try self.writeHeader(            output,            maximum_payload_bytes,        );    }    pub fn parseServer(data: []u8, maximum_payload_bytes: usize) FrameError!FrameParseResult {        if (data.len < 2) return FrameError.IncompleteFrame;        if ((data[1] & 0x80) == 0) return FrameError.MaskRequired;        return parse(data, maximum_payload_bytes);    }    fn headerLength(self: *const Frame, maximum_payload_bytes: usize) FrameError!usize {        const payload_bytes = self.payload.len;        try validateFrameHeader(self.fin, self.opcode, payload_bytes);        if (payload_bytes > maximum_payload_bytes) return FrameError.PayloadTooLarge;        if (@as(u128, payload_bytes) > maximum_protocol_payload_bytes) {            return FrameError.PayloadTooLarge;        }        const length_bytes: usize = if (payload_bytes < 126)            0        else if (payload_bytes <= std.math.maxInt(u16))            2        else            8;        return 2 + length_bytes + @as(usize, if (self.mask == null) 0 else 4);    }    fn writeHeader(        self: *const Frame,        output: []u8,        maximum_payload_bytes: usize,    ) FrameError![]u8 {        const header_bytes = try self.headerLength(maximum_payload_bytes);        if (output.len < header_bytes) return FrameError.OutputTooSmall;        const target = output[0..header_bytes];        target[0] = @as(u8, if (self.fin) 0x80 else 0) | @backingInt(self.opcode);        const mask_bit: u8 = if (self.mask == null) 0 else 0x80;        var index: usize = 1;        if (self.payload.len < 126) {            target[index] = mask_bit | @as(u8, @intCast(self.payload.len));            index += 1;        } else if (self.payload.len <= std.math.maxInt(u16)) {            target[index] = mask_bit | 126;            index += 1;            std.mem.writeInt(u16, target[index..][0..2], @intCast(self.payload.len), .big);            index += 2;        } else {            target[index] = mask_bit | 127;            index += 1;            std.mem.writeInt(u64, target[index..][0..8], @intCast(self.payload.len), .big);            index += 8;        }        if (self.mask) |mask| {            @memcpy(target[index..][0..mask.len], &mask);            index += mask.len;        }        std.debug.assert(index == target.len);        return target;    }};

Source: lib/http/src/root.zig:69

zig
pub const Frame = websocket.Frame;
Called byCallsprivate sourcelib.http.src.properties.websocket.RoundtripPr...propertyprivate sourcelib.http.src.properties.websocketexpectFrameParseErrorFrameparseServerprivate sourcelib.http.src.websocketcheckFragmentedMessageAtLimitprivate sourcelib.http.src.websocketexpectFrameParseError+10 moreOpcodefromWireprivate sourcelib.http.src.websocketmaskPayloadprivate sourcelib.http.src.websocketvalidateFrameHeaderFrameparse
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsprivate sourcelib.http.src.properties.websocket.RoundtripPr...propertyprivate sourcelib.http.src.websocket.WebSocketprocessBufferedFrametest sourcelib.http.src.websocket.test_FrameparseServer: accepts masked framestest sourcelib.http.src.websocket.test_Frame.parseServer...1)FrameparseFrameparseServer
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersprivate sourcelib.http.src.websocket.FramewriteHeaderFrameserializeHeaderInto
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callersFrameserializedLengthprivate sourcelib.http.src.websocket.FramewriteHeaderprivate sourcelib.http.src.websocketmaskPayloadFrameserializeInto
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsFrameserializeIntoprivate sourcelib.http.src.websocket.FrameheaderLengthFrameserializedLength
Static calls · unresolved targets: 0 · external targets: 0.

Complete caller list for Frame.parse

15 direct callers.

Audit

Definitions6
Public names6
Members4
Version26.7.0
Revisiondaab053ee433