From b39603522f3bc131902de8e97059b65521214b16 Mon Sep 17 00:00:00 2001 From: Robby Zambito Date: Tue, 14 Oct 2025 16:55:14 -0400 Subject: --- src/NetWriter.zig | 142 ++++++++++++++++++++++++++++++------------------------ src/message.zig | 4 +- src/root.zig | 5 +- 3 files changed, 86 insertions(+), 65 deletions(-) diff --git a/src/NetWriter.zig b/src/NetWriter.zig index 055d991..9f06823 100644 --- a/src/NetWriter.zig +++ b/src/NetWriter.zig @@ -29,7 +29,7 @@ pub fn init(w: *Writer, buffer: []u8) !NetWriter { fn drain(io_w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize { const w: *NetWriter = @alignCast(@fieldParentPtr("interface", io_w)); - const headers_byte_len = comptime (EthernetHeaders.byte_len + IpHeaders.byte_len + UdpHeaders.byte_len); + const headers_byte_len = comptime (EthernetHeaders.byte_len + (@bitSizeOf(IpHeaders) / 8) + @sizeOf(UdpHeaders)); const headers: [headers_byte_len]u8 = blk: { const ether_headers: EthernetHeaders = .{ .dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff }, @@ -56,15 +56,15 @@ fn drain(io_w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usi const udp_headers: UdpHeaders = .{ .src_port = 0xbbbb, .dest_port = 8888, - .length = @intCast(total_len + UdpHeaders.byte_len), + .length = @intCast(total_len + @sizeOf(UdpHeaders)), }; var buf: [headers_byte_len]u8 = undefined; var buf_w = Writer.fixed(&buf); _ = try ether_headers.write(&buf_w); - _ = try ip_headers.write(&buf_w); - _ = try udp_headers.write(&buf_w); + try ip_headers.write(&buf_w); + try buf_w.writeStruct(udp_headers, .big); break :blk buf; }; @@ -104,24 +104,29 @@ const EthernetHeaders = struct { } }; -const IpHeaders = struct { - // ip_version: u4, - // header_length: u4 = 0, - type_of_service: u8 = 0, - total_length: u16 = 0x04, - - identification: u16 = 0, - // ethernet_flags: u3 = 0, +const IpHeaders = extern struct { + dest_ip: @Vector(4, u8) align(1), + src_ip: @Vector(4, u8) align(1), + header_checksum: @Vector(2, u8) align(1) = .{ 0, 0 }, + protocol: u8 align(1) = 0, + ttl: u8 align(1) = 0, + fragment_and_flags: packed struct(u16) { + fragment_offset: u13 = 0, + ethernet_flags: u3 = 0, + } = .{}, // fragment_offset: u13 = 0, - ttl: u8 = 0, - protocol: u8 = 0, - - header_checksum: @Vector(2, u8) = .{ 0, 0 }, - src_ip: @Vector(4, u8), - - dest_ip: @Vector(4, u8), - - fn write(hdr: @This(), writer: *std.Io.Writer) Writer.Error!usize { + // ethernet_flags: u3 = 0, + identification: u16 align(1) = 0, + total_length: u16 align(1) = 0x04, + type_of_service: u8 align(1) = 0, + header_and_version: packed struct(u8) { + header_length: u4 = 5, + ip_version: u4 = 4, + } = .{}, + // header_length: u4 = 5, + // ip_version: u4 = 4, + + fn write(hdr: IpHeaders, writer: *std.Io.Writer) Writer.Error!void { try writer.writeInt(u8, 0x45, .big); // ip version and header length try writer.writeByte(hdr.type_of_service); try writer.writeInt(u16, hdr.total_length, .big); @@ -132,60 +137,73 @@ const IpHeaders = struct { try writer.writeInt(u16, @bitCast(hdr.header_checksum), .big); try writer.writeInt(u32, @bitCast(hdr.src_ip), .big); try writer.writeInt(u32, @bitCast(hdr.dest_ip), .big); - return byte_len; } - const byte_len = blk: { - var res: usize = 0; - res += @sizeOf(u8); - res += @sizeOf(u8); - res += @sizeOf(u16); - res += @sizeOf(u16); - res += @sizeOf(u16); - res += @sizeOf(u8); - res += @sizeOf(u8); - res += @sizeOf(u16); - res += @sizeOf(u32); - res += @sizeOf(u32); - break :blk res; - }; - - fn bytes(hdr: IpHeaders) [byte_len]u8 { - var res: [byte_len]u8 = undefined; - hdr.write(Writer.fixed(&res)) catch unreachable; + fn bytes(hdr: IpHeaders) [@bitSizeOf(IpHeaders) / 8]u8 { + var res: [@bitSizeOf(IpHeaders) / 8]u8 = undefined; + var w = Writer.fixed(&res); + _ = hdr.write(&w) catch unreachable; + return res; } }; -const UdpHeaders = packed struct { - src_port: u16, +test IpHeaders { + var a: IpHeaders = .{ + .dest_ip = .{ 1, 2, 3, 4 }, + .src_ip = .{ 5, 6, 7, 8 }, + // .header_checksum = .{ 0x1, 0x1 }, + // .protocol = 0, + // .ttl = 0x64, + // .identification = 3, + // .type_of_service = 7, + }; + // a.dest_ip = .{ 1, 2, 3, 4 }; + // a.src_ip = .{ 5, 6, 7, 8 }; + std.debug.print("ip struct: {}\n", .{a}); + std.debug.print("dest ip: {}\n", .{a.dest_ip}); + std.debug.print("src ip: {}\n", .{a.src_ip}); + + std.debug.print("raw b : {x}\n", .{@as([@bitSizeOf(IpHeaders) / 8]u8, @bitCast(a))}); + + std.debug.print("ip bytes: {x}\n", .{a.bytes()}); + var a_struct: [@bitSizeOf(IpHeaders) / 8]u8 = undefined; + var a_struct_w = Writer.fixed(&a_struct); + _ = a_struct_w.writeStruct(a, .big) catch unreachable; + std.debug.print("ip struct: {x}\n", .{a_struct}); + try std.testing.expectEqual(a, a); +} - dest_port: u16, - length: u16, +const UdpHeaders = packed struct { checksum: @Vector(2, u8) = .{ 0, 0 }, + length: u16, + dest_port: u16, + src_port: u16, - fn write(hdr: @This(), writer: *std.Io.Writer) Writer.Error!usize { - try writer.writeInt(u16, hdr.src_port, .big); - try writer.writeInt(u16, hdr.dest_port, .big); - try writer.writeInt(u16, hdr.length, .big); - try writer.writeInt(u16, @bitCast(hdr.checksum), .big); - return byte_len; + fn write(hdr: UdpHeaders, writer: *std.Io.Writer) Writer.Error!void { + try writer.writeStruct(hdr, .big); } - const byte_len = blk: { - var res: usize = 0; - res += @sizeOf(u16); - res += @sizeOf(u16); - res += @sizeOf(u16); - res += @sizeOf(u16); - break :blk res; - }; - - fn bytes(hdr: UdpHeaders) [byte_len]u8 { - var res: [byte_len]u8 = undefined; - hdr.write(Writer.fixed(&res)) catch unreachable; + fn bytes(hdr: UdpHeaders) [@sizeOf(UdpHeaders)]u8 { + var res: [@sizeOf(UdpHeaders)]u8 = undefined; + var w = Writer.fixed(&res); + _ = hdr.write(&w) catch unreachable; + return res; } }; +test UdpHeaders { + const a: UdpHeaders = .{ + .src_port = 1, + .dest_port = 2, + .length = 3, + .checksum = .{ 0x04, 0x05 }, + }; + var a_struct: [@sizeOf(UdpHeaders)]u8 = undefined; + var a_struct_w = Writer.fixed(&a_struct); + _ = a_struct_w.writeStruct(a, .big) catch unreachable; + try std.testing.expectEqual(a.bytes(), a_struct); +} + const std = @import("std"); const Random = std.Random; const posix = std.posix; diff --git a/src/message.zig b/src/message.zig index d5d4262..eb15557 100644 --- a/src/message.zig +++ b/src/message.zig @@ -196,7 +196,7 @@ test "testing variable length zero copy struct" { var msg_bytes: [try Message.calcSize(.relay, payload.len)]u8 align(@alignOf(Message)) = undefined; // Create a view of the byte slice as a Message - const msg: *Message = .init(.relay, &msg_bytes); + const msg: *align(1) Message = .init(.relay, &msg_bytes); { // Set the message values @@ -234,7 +234,7 @@ test "testing variable length zero copy struct" { var msg_bytes: [try Message.calcSize(.connection, payload.len)]u8 align(@alignOf(Message)) = undefined; // Create a view of the byte slice as a Message - const msg: *Message = .init(.connection, &msg_bytes); + const msg: *align(1) Message = .init(.connection, &msg_bytes); { // Initializing connection header values diff --git a/src/root.zig b/src/root.zig index bcf9415..2005490 100644 --- a/src/root.zig +++ b/src/root.zig @@ -6,8 +6,11 @@ pub const NetWriter = @import("NetWriter.zig"); const msg = @import("message.zig"); pub const PacketType = msg.PacketType; -pub const foo = msg.foo; pub const ConnectionOptions = msg.ConnectionOptions; pub const MessageTypeError = msg.MessageTypeError; pub const MessageParseError = msg.MessageParseError; pub const Message = msg.Message; + +test { + @import("std").testing.refAllDecls(@This()); +} -- cgit