summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2025-04-29 08:29:15 -0400
committerRobby Zambito <contact@robbyzambito.me>2025-04-30 13:46:54 -0400
commit5e22c2b2ef325c843e36bfa67db3b5434069d56f (patch)
tree9d9808800555ff4df43df228a785647700f77ce1
parent5530ed3d7706e7bc04823be0b11263c452d9276a (diff)
-rw-r--r--src/message.zig120
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;