tiny.http.Frame
Defined in tiny.http.
API (9)
Actions
Public operations.
Fields and members
Public fields and members.
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;Complete caller list for Frame.parse
15 direct callers.
lib.http.src.properties.websocket.RoundtripProperty.property[function] — private source atlib/http/src/properties/websocket.zig:125in nearest public ownerlib.http.src.properties.websocketlib.http.src.properties.websocket.expectFrameParseError[function] — private source atlib/http/src/properties/websocket.zig:72in nearest public ownerlib.http.src.properties.websockettiny.http.Frame.parseServer[function] atlib/http/src/websocket.zig:382lib.http.src.websocket.checkFragmentedMessageAtLimit[function] — private source atlib/http/src/websocket.zig:1484in nearest public ownerlib.http.src.websocketlib.http.src.websocket.expectFrameParseError[function] — private source atlib/http/src/websocket.zig:514in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_16-bit_extended_length[function] — test source atlib/http/src/websocket.zig:1207in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_close_frame_with_code_and_reason[function] — test source atlib/http/src/websocket.zig:1309in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_incomplete_frame_header[function] — test source atlib/http/src/websocket.zig:1221in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_incomplete_frame_payload[function] — test source atlib/http/src/websocket.zig:1227in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_masked_frame[function] — test source atlib/http/src/websocket.zig:1195in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_pong_frame[function] — test source atlib/http/src/websocket.zig:1320in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.parse:_simple_text_frame_unmasked[function] — test source atlib/http/src/websocket.zig:1183in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.serialize/parse_round-trip[function] — test source atlib/http/src/websocket.zig:1233in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_Frame.serialize/parse_round-trip_masked[function] — test source atlib/http/src/websocket.zig:1250in nearest public ownerlib.http.src.websocketlib.http.src.websocket.test_WebSocket.receive_closes_invalid_client_frame_as_protocol_error[function] — test source atlib/http/src/websocket.zig:1640in nearest public ownerlib.http.src.websocket
Audit
| Definitions | 6 |
|---|---|
| Public names | 6 |
| Members | 4 |
| Version | 26.7.0 |
| Revision | daab053ee433 |