diff options
| author | Robby Zambito <contact@robbyzambito.me> | 2025-04-29 08:29:15 -0400 | 
|---|---|---|
| committer | Robby Zambito <contact@robbyzambito.me> | 2025-04-30 13:46:54 -0400 | 
| commit | 5e22c2b2ef325c843e36bfa67db3b5434069d56f (patch) | |
| tree | 9d9808800555ff4df43df228a785647700f77ce1 /src | |
| parent | 5530ed3d7706e7bc04823be0b11263c452d9276a (diff) | |
Diffstat (limited to 'src')
| -rw-r--r-- | src/message.zig | 120 | 
1 files changed, 85 insertions, 35 deletions
diff --git a/src/message.zig b/src/message.zig index 0b07603..ae3507e 100644 --- a/src/message.zig +++ b/src/message.zig @@ -26,6 +26,7 @@ pub const ConnectionOptions = packed struct(u8) {  pub const Error = error{      NotImplementedSaprusType,      UnknownSaprusType, +    InvalidMessage,  };  // ZERO COPY STUFF @@ -35,19 +36,10 @@ pub const ZeroCopyMessage = packed struct {          dest: @Vector(4, u8),          payload: void, -        pub fn getPayload(self: *align(1) Relay) []u8 { -            // const vself: *void = @ptrCast(self); -            // var parent: *align(1) ZeroCopyMessage = @fieldParentPtr("bytes", vself); -            // if (false) { -            //     parent = @ptrFromInt(@intFromPtr(parent)); -            // } +        const RSelf = *align(1) @This(); + +        pub fn getPayload(self: RSelf) []u8 {              const len: *u16 = @ptrFromInt(@intFromPtr(self) - @sizeOf(u16)); -            // std.debug.print("relay: {*}\n", .{self}); -            // std.debug.print("inPayload: {*}\n", .{parent}); -            // std.debug.print("len: {d}\n", .{len.*}); -            // std.debug.print("len: {d}\n", .{parent.length}); -            // return @as([*]u8, @ptrCast(&self.payload))[0..3]; -            // return @as([*]u8, @ptrCast(&self.payload))[0 .. parent.length - @sizeOf(Relay)];              return @as([*]u8, @ptrCast(&self.payload))[0 .. len.* - @sizeOf(Relay)];          }      }; @@ -60,10 +52,26 @@ pub const ZeroCopyMessage = packed struct {          options: ConnectionOptions = .{},          payload: void, -        pub fn getPayload(self: *align(1) Connection) []u8 { +        const CSelf = *align(1) Connection; + +        pub fn getPayload(self: CSelf) []u8 {              const len: *u16 = @ptrFromInt(@intFromPtr(self) - @sizeOf(u16));              return @as([*]u8, @ptrCast(&self.payload))[0 .. len.* - @sizeOf(Connection)];          } + +        fn nativeFromNetworkEndian(self: CSelf) Error!void { +            self.src_port = bigToNative(@TypeOf(self.src_port), self.src_port); +            self.dest_port = bigToNative(@TypeOf(self.dest_port), self.dest_port); +            self.seq_num = bigToNative(@TypeOf(self.seq_num), self.seq_num); +            self.msg_id = bigToNative(@TypeOf(self.msg_id), self.msg_id); +        } + +        fn networkFromNativeEndian(self: CSelf) Error!void { +            self.src_port = nativeToBig(@TypeOf(self.src_port), self.src_port); +            self.dest_port = nativeToBig(@TypeOf(self.dest_port), self.dest_port); +            self.seq_num = nativeToBig(@TypeOf(self.seq_num), self.seq_num); +            self.msg_id = nativeToBig(@TypeOf(self.msg_id), self.msg_id); +        }      };      const Self = @This(); @@ -72,14 +80,14 @@ pub const ZeroCopyMessage = packed struct {      length: u16,      bytes: void = {}, -    fn getRelay(self: *align(1) Self) *align(1) Relay { +    fn getRelay(self: ZCM) Relay.RSelf {          return std.mem.bytesAsValue(Relay, &self.bytes);      } -    fn getConnection(self: *align(1) Self) *align(1) Connection { +    fn getConnection(self: ZCM) Connection.CSelf {          return std.mem.bytesAsValue(Connection, &self.bytes);      } -    pub fn getSaprusTypePayload(self: *align(1) Self) Error!(union(PacketType) { +    pub fn getSaprusTypePayload(self: ZCM) Error!(union(PacketType) {          relay: *align(1) Relay,          file_transfer: void,          connection: *align(1) Connection, @@ -92,36 +100,77 @@ pub const ZeroCopyMessage = packed struct {          };      } -    pub fn toNativeBytes() void {} -    pub fn toNetworkBytes() void {} +    pub fn nativeFromNetworkEndian(self: ZCM) Error!void { +        self.type = @enumFromInt(bigToNative( +            @typeInfo(@TypeOf(self.type)).@"enum".tag_type, +            @intFromEnum(self.type), +        )); +        self.length = bigToNative(@TypeOf(self.length), self.length); +        try switch (try self.getSaprusTypePayload()) { +            .relay => {}, +            .connection => |*con| con.*.nativeFromNetworkEndian(), +            .file_transfer => Error.NotImplementedSaprusType, +            else => Error.UnknownSaprusType, +        }; +    } + +    pub fn networkFromNativeEndian(self: ZCM) Error!void { +        try switch (try self.getSaprusTypePayload()) { +            .relay => {}, +            .connection => |*con| con.*.networkFromNativeEndian(), +            .file_transfer => Error.NotImplementedSaprusType, +            else => Error.UnknownSaprusType, +        }; +        self.type = @enumFromInt(nativeToBig( +            @typeInfo(@TypeOf(self.type)).@"enum".tag_type, +            @intFromEnum(self.type), +        )); +        self.length = nativeToBig(@TypeOf(self.length), self.length); +    } + +    pub fn fromBytesUnchecked(bytes: []u8) ZCM { +        return @ptrCast(bytes.ptr); +    } + +    pub fn fromBytes(bytes: []u8) !ZCM { +        const res: ZCM = @ptrCast(bytes.ptr); +        return if (bytes.len == res.length + @sizeOf(Self)) res else Error.InvalidMessage; +    }  }; +const ZCM = *align(1) ZeroCopyMessage; +  test "testing variable length zero copy struct" {      const gpa = std.testing.allocator; -    const bytes = try gpa.alloc(u8, @sizeOf(ZeroCopyMessage) + 64); +    const payload_len = 48; +    const bytes = try gpa.alloc(u8, @sizeOf(ZeroCopyMessage) + payload_len);      defer gpa.free(bytes); -    const zcm: *align(1) ZeroCopyMessage = @ptrCast(bytes.ptr); +    // Create a view of the byte slice as a ZeroCopyMessage +    const zcm: ZCM = .fromBytesUnchecked(bytes); + +    { +        // Set the message values +        zcm.type = .relay; +        // zcm.length = payload_len; +        const relay = (try zcm.getSaprusTypePayload()).relay; +        relay.dest = .{ 1, 2, 3, 4 }; +        const payload = relay.getPayload(); +        const p = "Hello darkness my old friend"; +        @memcpy(payload[0..p.len], p); +    } + +    { +        // Print the message as hex using the network +        zcm.networkFromNativeEndian() catch unreachable; +        defer zcm.nativeFromNetworkEndian() catch unreachable; +        std.debug.print("network bytes: {x}\n", .{bytes}); +    } -    zcm.type = .relay; -    zcm.length = 64; -    std.debug.print("pre: {*}\n", .{zcm}); -    // std.debug.print("{any}\n", .{(try zcm.getSaprusTypePayload()).relay}); -    std.debug.print("{x}\n", .{(try zcm.getSaprusTypePayload()).relay.getPayload()}); -    std.debug.print("{d}\n", .{(try zcm.getSaprusTypePayload()).relay.getPayload().len});      if (false) {          // Illegal behavior          std.debug.print("{any}\n", .{(try zcm.getSaprusTypePayload()).connection});      } -    if (false) { -        std.debug.print("{any}\n", .{zcm.getRelay()}); -        std.debug.print("{any}\n", .{zcm.getConnection()}); -        std.debug.print("{x}\n", .{std.mem.asBytes(zcm.getRelay())}); -        std.debug.print("{x}\n", .{std.mem.asBytes(zcm.getConnection())}); -    } -    std.debug.print("{x}\n", .{bytes}); - -    try std.testing.expect(true);  }  /// All Saprus messages @@ -266,6 +315,7 @@ const Allocator = std.mem.Allocator;  const asBytes = std.mem.asBytes;  const nativeToBig = std.mem.nativeToBig; +const bigToNative = std.mem.bigToNative;  test "Round trip Relay toBytes and fromBytes" {      const gpa = std.testing.allocator;  | 
