Adversarial C2 Protocol Implemented in Zig
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

+319 -515
-238
src/NetWriter.zig
··· 1 - //! Wraps a writer with UDP headers. 2 - //! This is useful for wrapping RawSocket Writer with appropriate headers. 3 - 4 - rand: Random, 5 - wrapped: *Writer, 6 - interface: Writer, 7 - 8 - pub fn init(w: *Writer, buffer: []u8) !NetWriter { 9 - std.debug.assert(buffer.len > @sizeOf(EthernetHeaders) + @sizeOf(IpHeaders) + @sizeOf(UdpHeaders)); 10 - 11 - var prng = Random.DefaultPrng.init(blk: { 12 - var seed: u64 = undefined; 13 - try posix.getrandom(mem.asBytes(&seed)); 14 - break :blk seed; 15 - }); 16 - 17 - return .{ 18 - .rand = prng.random(), 19 - .wrapped = w, 20 - .interface = .{ 21 - .vtable = &.{ 22 - .drain = drain, 23 - // .flush = flush, 24 - }, 25 - .buffer = buffer, 26 - }, 27 - }; 28 - } 29 - 30 - fn drain(io_w: *Writer, data: []const []const u8, splat: usize) Writer.Error!usize { 31 - const w: *NetWriter = @alignCast(@fieldParentPtr("interface", io_w)); 32 - const headers_byte_len = comptime (EthernetHeaders.byte_len + (@bitSizeOf(IpHeaders) / 8) + @sizeOf(UdpHeaders)); 33 - const headers: [headers_byte_len]u8 = blk: { 34 - const ether_headers: EthernetHeaders = .{ 35 - .dest_mac = .{ 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff }, 36 - .src_mac = src_blk: { 37 - var output_bytes: [6]u8 = undefined; 38 - output_bytes[0] = 0xee; 39 - w.rand.bytes(output_bytes[1..]); 40 - break :src_blk output_bytes; 41 - }, 42 - .ether_type = 0x0800, 43 - }; 44 - 45 - const total_len = Writer.countSplat(data, splat) + w.interface.end; 46 - 47 - const ip_headers: IpHeaders = .{ 48 - // length of the packet minus eth header 49 - .total_length = @intCast(headers_byte_len + total_len - EthernetHeaders.byte_len), //@intCast(total_len), 50 - .ttl = 64, 51 - .protocol = 0x11, 52 - .src_ip = .{ 0xff, 0x02, 0x03, 0x04 }, 53 - .dest_ip = .{ 0xff, 0xff, 0xff, 0xff }, 54 - }; 55 - 56 - const udp_headers: UdpHeaders = .{ 57 - .src_port = 0xbbbb, 58 - .dest_port = 8888, 59 - .length = @intCast(total_len + @sizeOf(UdpHeaders)), 60 - }; 61 - 62 - var buf: [headers_byte_len]u8 = undefined; 63 - var buf_w = Writer.fixed(&buf); 64 - 65 - _ = try ether_headers.write(&buf_w); 66 - try ip_headers.write(&buf_w); 67 - try buf_w.writeStruct(udp_headers, .big); 68 - 69 - break :blk buf; 70 - }; 71 - 72 - _ = try w.wrapped.write(&headers); 73 - const total_len = try w.wrapped.writeSplatHeader(w.interface.buffered(), data, splat); 74 - 75 - try w.wrapped.flush(); 76 - return total_len - w.interface.consumeAll(); 77 - } 78 - 79 - const EthernetHeaders = struct { 80 - dest_mac: @Vector(6, u8), 81 - 82 - src_mac: @Vector(6, u8), 83 - 84 - ether_type: u16, 85 - 86 - fn write(hdr: EthernetHeaders, writer: *std.Io.Writer) Writer.Error!usize { 87 - try writer.writeInt(u48, @bitCast(hdr.dest_mac), .big); 88 - try writer.writeInt(u48, @bitCast(hdr.src_mac), .big); 89 - try writer.writeInt(u16, hdr.ether_type, .big); 90 - return byte_len; 91 - } 92 - 93 - const byte_len = blk: { 94 - var res: usize = 0; 95 - res += @bitSizeOf(u48) / 8; 96 - res += @bitSizeOf(u48) / 8; 97 - res += @bitSizeOf(u16) / 8; 98 - break :blk res; 99 - }; 100 - 101 - fn bytes(hdr: EthernetHeaders) [byte_len]u8 { 102 - var res: [byte_len]u8 = undefined; 103 - hdr.write(Writer.fixed(&res)) catch unreachable; 104 - } 105 - }; 106 - 107 - const IpHeaders = extern struct { 108 - dest_ip: @Vector(4, u8) align(1), 109 - src_ip: @Vector(4, u8) align(1), 110 - header_checksum: @Vector(2, u8) align(1) = .{ 0, 0 }, 111 - protocol: u8 align(1) = 0, 112 - ttl: u8 align(1) = 0, 113 - fragment_and_flags: packed struct(u16) { 114 - fragment_offset: u13 = 0, 115 - ethernet_flags: u3 = 0, 116 - } = .{}, 117 - // fragment_offset: u13 = 0, 118 - // ethernet_flags: u3 = 0, 119 - identification: u16 align(1) = 0, 120 - total_length: u16 align(1) = 0x04, 121 - type_of_service: u8 align(1) = 0, 122 - header_and_version: packed struct(u8) { 123 - header_length: u4 = 5, 124 - ip_version: u4 = 4, 125 - } = .{}, 126 - // header_length: u4 = 5, 127 - // ip_version: u4 = 4, 128 - 129 - fn write(hdr: IpHeaders, writer: *std.Io.Writer) Writer.Error!void { 130 - try writer.writeInt(u8, 0x45, .big); // ip version and header length 131 - try writer.writeByte(hdr.type_of_service); 132 - try writer.writeInt(u16, hdr.total_length, .big); 133 - try writer.writeInt(u16, hdr.identification, .big); 134 - try writer.writeInt(u16, 0x00, .big); // ethernet flags and fragment offset 135 - try writer.writeByte(hdr.ttl); 136 - try writer.writeByte(hdr.protocol); 137 - try writer.writeInt(u16, @bitCast(hdr.header_checksum), .big); 138 - try writer.writeInt(u32, @bitCast(hdr.src_ip), .big); 139 - try writer.writeInt(u32, @bitCast(hdr.dest_ip), .big); 140 - } 141 - 142 - fn bytes(hdr: IpHeaders) [@bitSizeOf(IpHeaders) / 8]u8 { 143 - var res: [@bitSizeOf(IpHeaders) / 8]u8 = undefined; 144 - var w = Writer.fixed(&res); 145 - _ = hdr.write(&w) catch unreachable; 146 - return res; 147 - } 148 - }; 149 - 150 - test IpHeaders { 151 - var a: IpHeaders = .{ 152 - .dest_ip = .{ 1, 2, 3, 4 }, 153 - .src_ip = .{ 5, 6, 7, 8 }, 154 - // .header_checksum = .{ 0x1, 0x1 }, 155 - // .protocol = 0, 156 - // .ttl = 0x64, 157 - // .identification = 3, 158 - // .type_of_service = 7, 159 - }; 160 - // a.dest_ip = .{ 1, 2, 3, 4 }; 161 - // a.src_ip = .{ 5, 6, 7, 8 }; 162 - std.debug.print("ip struct: {}\n", .{a}); 163 - std.debug.print("dest ip: {}\n", .{a.dest_ip}); 164 - std.debug.print("src ip: {}\n", .{a.src_ip}); 165 - 166 - std.debug.print("raw b : {x}\n", .{@as([@bitSizeOf(IpHeaders) / 8]u8, @bitCast(a))}); 167 - 168 - std.debug.print("ip bytes: {x}\n", .{a.bytes()}); 169 - var a_struct: [@bitSizeOf(IpHeaders) / 8]u8 = undefined; 170 - var a_struct_w = Writer.fixed(&a_struct); 171 - _ = a_struct_w.writeStruct(a, .big) catch unreachable; 172 - std.debug.print("ip struct: {x}\n", .{a_struct}); 173 - try std.testing.expectEqual(a, a); 174 - } 175 - 176 - const UdpHeaders = packed struct { 177 - checksum: @Vector(2, u8) = .{ 0, 0 }, 178 - length: u16, 179 - dest_port: u16, 180 - src_port: u16, 181 - 182 - fn write(hdr: UdpHeaders, writer: *std.Io.Writer) Writer.Error!void { 183 - try writer.writeStruct(hdr, .big); 184 - } 185 - 186 - fn bytes(hdr: UdpHeaders) [@sizeOf(UdpHeaders)]u8 { 187 - var res: [@sizeOf(UdpHeaders)]u8 = undefined; 188 - var w = Writer.fixed(&res); 189 - _ = hdr.write(&w) catch unreachable; 190 - return res; 191 - } 192 - }; 193 - 194 - test UdpHeaders { 195 - const a: UdpHeaders = .{ 196 - .src_port = 1, 197 - .dest_port = 2, 198 - .length = 3, 199 - .checksum = .{ 0x04, 0x05 }, 200 - }; 201 - var a_struct: [@sizeOf(UdpHeaders)]u8 = undefined; 202 - var a_struct_w = Writer.fixed(&a_struct); 203 - _ = a_struct_w.writeStruct(a, .big) catch unreachable; 204 - try std.testing.expectEqual(a.bytes(), a_struct); 205 - } 206 - 207 - const std = @import("std"); 208 - const Random = std.Random; 209 - const posix = std.posix; 210 - const Writer = std.Io.Writer; 211 - const mem = std.mem; 212 - 213 - const NetWriter = @This(); 214 - 215 - const saprusOptions: std.Io.net.BindOptions = .{ 216 - .mode = .raw, 217 - .protocol = 0, 218 - }; 219 - 220 - fn netSaprusBindIpPosix( 221 - userdata: ?*anyopaque, 222 - address: *const IpAddress, 223 - options: IpAddress.BindOptions, 224 - ) IpAddress.BindError!net.Socket { 225 - if (!have_networking) return error.NetworkDown; 226 - const t: *Threaded = @ptrCast(@alignCast(userdata)); 227 - const family = std.os.linux.PF.PACKET; 228 - const socket_fd = try openSocketPosix(t, family, options); 229 - errdefer posix.close(socket_fd); 230 - var storage: PosixAddress = undefined; 231 - var addr_len = addressToPosix(address, &storage); 232 - try posixBind(t, socket_fd, &storage.any, addr_len); 233 - try posixGetSockName(t, socket_fd, &storage.any, &addr_len); 234 - return .{ 235 - .handle = socket_fd, 236 - .address = addressFromPosix(&storage), 237 - }; 238 - }
-32
src/RawSocketWriter.zig
··· 1 - const std = @import("std"); 2 - const gcat = @import("gatorcat"); 3 - const RawSocketWriter = @This(); 4 - const Writer = std.Io.Writer; 5 - const assert = std.debug.assert; 6 - 7 - interface: Writer, 8 - socket: gcat.nic.RawSocket, 9 - 10 - fn drain(io_w: *std.Io.Writer, data: []const []const u8, splat: usize) Writer.Error!usize { 11 - const w: *RawSocketWriter = @alignCast(@fieldParentPtr("interface", io_w)); 12 - const rem_buf = io_w.unusedCapacitySlice(); 13 - var rem_w = Writer.fixed(rem_buf); 14 - const res = rem_w.writeSplat(data, splat) catch rem_buf.len; 15 - io_w.advance(res); 16 - const buffered = io_w.buffered(); 17 - w.socket.linkLayer().send(buffered) catch return error.WriteFailed; 18 - _ = io_w.consumeAll(); 19 - 20 - return res; 21 - } 22 - 23 - pub fn init(interface_name: [:0]const u8, buffer: []u8) !RawSocketWriter { 24 - std.debug.assert(buffer.len > 0); 25 - return .{ 26 - .interface = .{ 27 - .vtable = &.{ .drain = drain }, 28 - .buffer = buffer, 29 - }, 30 - .socket = try .init(interface_name), 31 - }; 32 - }
+319 -243
src/message.zig
··· 28 28 InvalidMessage, 29 29 }; 30 30 31 - // ZERO COPY STUFF 32 - // &payload could be a void value that is treated as a pointer to a [*]u8 33 - /// All Saprus messages 34 - pub const Message = packed struct { 35 - pub const Relay = packed struct { 36 - dest: @Vector(4, u8), 37 - payload: void, 31 + pub const RelayMessage = struct { 32 + dest: Dest, 33 + payload: []const u8, 38 34 39 - pub fn getPayload(self: *align(1) Relay) []u8 { 40 - const len: *u16 = @ptrFromInt(@intFromPtr(self) - @sizeOf(u16)); 41 - return @as([*]u8, @ptrCast(&self.payload))[0 .. len.* - @bitSizeOf(Relay) / 8]; 42 - } 43 - }; 44 - pub const Connection = packed struct { 45 - src_port: u16, // random number > 1024 46 - dest_port: u16, // random number > 1024 47 - seq_num: u32 = 0, 48 - msg_id: u32 = 0, 49 - reserved: u8 = 0, 50 - options: ConnectionOptions = .{}, 51 - payload: void, 35 + pub const @"type": PacketType = .relay; 36 + pub const Dest = struct { 37 + bytes: [4]u8, 52 38 53 - pub fn getPayload(self: *align(1) Connection) []u8 { 54 - const len: *u16 = @ptrFromInt(@intFromPtr(self) - @sizeOf(u16)); 55 - return @as([*]u8, @ptrCast(&self.payload))[0 .. len.* - @bitSizeOf(Connection) / 8]; 56 - } 57 - 58 - fn nativeFromNetworkEndian(self: *align(1) Connection) void { 59 - self.src_port = bigToNative(@TypeOf(self.src_port), self.src_port); 60 - self.dest_port = bigToNative(@TypeOf(self.dest_port), self.dest_port); 61 - self.seq_num = bigToNative(@TypeOf(self.seq_num), self.seq_num); 62 - self.msg_id = bigToNative(@TypeOf(self.msg_id), self.msg_id); 63 - } 64 - 65 - fn networkFromNativeEndian(self: *align(1) Connection) void { 66 - self.src_port = nativeToBig(@TypeOf(self.src_port), self.src_port); 67 - self.dest_port = nativeToBig(@TypeOf(self.dest_port), self.dest_port); 68 - self.seq_num = nativeToBig(@TypeOf(self.seq_num), self.seq_num); 69 - self.msg_id = nativeToBig(@TypeOf(self.msg_id), self.msg_id); 39 + /// Asserts bytes is less than or equal to 4 bytes 40 + pub fn fromBytes(bytes: []const u8) Dest { 41 + var buf: [4]u8 = @splat(0); 42 + std.debug.assert(bytes.len <= buf.len); 43 + @memcpy(buf[0..bytes.len], bytes); 44 + return .{ .bytes = buf }; 70 45 } 71 46 }; 72 47 73 - const Self = @This(); 74 - const SelfBytes = []align(1) u8; 75 - 76 - type: PacketType, 77 - length: u16, 78 - bytes: void = {}, 79 - 80 - /// Takes a byte slice, and returns a Message struct backed by the slice. 81 - /// This properly initializes the top level headers within the slice. 82 - /// This is used for creating new messages. For reading messages from the network, 83 - /// see: networkBytesAsValue. 84 - pub fn init(@"type": PacketType, bytes: []u8) *align(1) Self { 85 - std.debug.assert(bytes.len >= @sizeOf(Self)); 86 - const res: *align(1) Self = @ptrCast(bytes.ptr); 87 - res.type = @"type"; 88 - res.length = @intCast(bytes.len - @sizeOf(Self)); 89 - return res; 48 + pub fn init(dest: Dest, payload: []const u8) RelayMessage { 49 + return .{ .dest = dest, .payload = payload }; 90 50 } 91 51 92 - /// Compute the number of bytes required to store a given payload size for a given message type. 93 - pub fn calcSize(comptime @"type": PacketType, payload_len: usize) MessageTypeError!u16 { 94 - const header_size = @bitSizeOf(switch (@"type") { 95 - .relay => Relay, 96 - .connection => Connection, 97 - .file_transfer => return MessageTypeError.NotImplementedSaprusType, 98 - else => return MessageTypeError.UnknownSaprusType, 99 - }) / 8; 100 - return @intCast(payload_len + @sizeOf(Self) + header_size); 52 + /// Asserts that buf is large enough to fit the relay message. 53 + pub fn toBytes(self: RelayMessage, buf: []u8) []u8 { 54 + var out: Writer = .fixed(buf); 55 + out.writeInt(u16, @intFromEnum(RelayMessage.type), .big) catch unreachable; 56 + out.writeInt(u16, @intCast(self.payload.len + self.dest.bytes.len), .big) catch unreachable; 57 + out.writeAll(&self.dest.bytes) catch unreachable; 58 + out.writeAll(self.payload) catch unreachable; 59 + return out.buffered(); 101 60 } 102 61 103 - fn getRelay(self: *align(1) Self) *align(1) Relay { 104 - return std.mem.bytesAsValue(Relay, &self.bytes); 105 - } 106 - fn getConnection(self: *align(1) Self) *align(1) Connection { 107 - return std.mem.bytesAsValue(Connection, &self.bytes); 62 + pub fn fromBytes(buf: []const u8) RelayMessage { 63 + var in: Reader = .fixed(buf); 108 64 } 109 65 110 - /// Access the message Saprus payload. 111 - pub fn getSaprusTypePayload(self: *align(1) Self) MessageTypeError!(union(PacketType) { 112 - relay: *align(1) Relay, 113 - file_transfer: void, 114 - connection: *align(1) Connection, 115 - }) { 116 - return switch (self.type) { 117 - .relay => .{ .relay = self.getRelay() }, 118 - .connection => .{ .connection = self.getConnection() }, 119 - .file_transfer => MessageTypeError.NotImplementedSaprusType, 120 - else => MessageTypeError.UnknownSaprusType, 66 + test toBytes { 67 + var buf: [1024]u8 = undefined; 68 + const relay: RelayMessage = .init( 69 + .fromBytes(&.{ 172, 18, 1, 30 }), 70 + // zig fmt: off 71 + &[_]u8{ 72 + 0x72, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x76, 0x65, 73 + 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x64 74 + }, 75 + // zig fmt: on 76 + ); 77 + // zig fmt: off 78 + var expected = [_]u8{ 79 + 0x00, 0x3c, 0x00, 0x17, 0xac, 0x12, 0x01, 0x1e, 0x72, 80 + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x20, 0x65, 0x76, 0x65, 81 + 0x6e, 0x74, 0x20, 0x6c, 0x6f, 0x67, 0x67, 0x65, 0x64 121 82 }; 83 + // zig fmt: on 84 + try std.testing.expectEqualSlices(u8, &expected, relay.toBytes(&buf)); 122 85 } 86 + }; 123 87 124 - /// Convert the message to native endianness from network endianness in-place. 125 - pub fn nativeFromNetworkEndian(self: *align(1) Self) MessageTypeError!void { 126 - self.type = @enumFromInt(bigToNative( 127 - @typeInfo(@TypeOf(self.type)).@"enum".tag_type, 128 - @intFromEnum(self.type), 129 - )); 130 - self.length = bigToNative(@TypeOf(self.length), self.length); 131 - errdefer { 132 - // If the payload specific headers fail, revert the top level header values 133 - self.type = @enumFromInt(nativeToBig( 134 - @typeInfo(@TypeOf(self.type)).@"enum".tag_type, 135 - @intFromEnum(self.type), 136 - )); 137 - self.length = nativeToBig(@TypeOf(self.length), self.length); 138 - } 139 - switch (try self.getSaprusTypePayload()) { 140 - .relay => {}, 141 - .connection => |*con| con.*.nativeFromNetworkEndian(), 142 - // We know other values are unreachable, 143 - // because they would have returned an error from the switch condition. 144 - else => unreachable, 145 - } 146 - } 88 + // pub const ConnectionMessage = struct { 89 + // length: u16, 90 + // src_port: u16, 91 + // dest_port: u16, 92 + // seq_num: u32 = 0, 93 + // msg_id: u32 = 0, 94 + // // _reserved: u8 = 0, 95 + // options: ConnectionOptions = .{}, 96 + // payload: []u8, 147 97 148 - /// Convert the message to network endianness from native endianness in-place. 149 - pub fn networkFromNativeEndian(self: *align(1) Self) MessageTypeError!void { 150 - try switch (try self.getSaprusTypePayload()) { 151 - .relay => {}, 152 - .connection => |*con| con.*.networkFromNativeEndian(), 153 - .file_transfer => MessageTypeError.NotImplementedSaprusType, 154 - else => MessageTypeError.UnknownSaprusType, 155 - }; 156 - self.type = @enumFromInt(nativeToBig( 157 - @typeInfo(@TypeOf(self.type)).@"enum".tag_type, 158 - @intFromEnum(self.type), 159 - )); 160 - self.length = nativeToBig(@TypeOf(self.length), self.length); 161 - } 98 + // pub const type: PacketType = .connection; 162 99 163 - /// Convert network endian bytes to a native endian value in-place. 164 - pub fn networkBytesAsValue(bytes: SelfBytes) MessageParseError!*align(1) Self { 165 - const res = std.mem.bytesAsValue(Self, bytes); 166 - try res.nativeFromNetworkEndian(); 167 - return .bytesAsValue(bytes); 168 - } 100 + // /// Asserts that buf is large enough to fit the connection message. 101 + // fn toBytes(self: ConnectionMessage, buf: []u8) []u8 { 102 + // var out: Writer = .fixed(buf); 103 + // out.writeInt(u16, ConnectionMessage.type, .big) catch unreachable; 104 + // return w.buffered(); 105 + // } 106 + // }; 169 107 170 - /// Create a structured view of the bytes without initializing the length or type, 171 - /// and without converting the endianness. 172 - pub fn bytesAsValue(bytes: SelfBytes) MessageParseError!*align(1) Self { 173 - const res = std.mem.bytesAsValue(Self, bytes); 174 - return switch (res.type) { 175 - .relay, .connection => if (bytes.len == res.length + @sizeOf(Self)) 176 - res 177 - else 178 - MessageParseError.InvalidMessage, 179 - .file_transfer => MessageParseError.NotImplementedSaprusType, 180 - else => MessageParseError.UnknownSaprusType, 181 - }; 182 - } 108 + // // ZERO COPY STUFF 109 + // // &payload could be a void value that is treated as a pointer to a [*]u8 110 + // /// All Saprus messages 111 + // pub const Message = packed struct { 112 + // pub const Relay = packed struct { 113 + // dest: @Vector(4, u8), 114 + // payload: void, 183 115 184 - /// Deprecated. 185 - /// If I need the bytes, I should just pass around the slice that is backing this to begin with. 186 - pub fn asBytes(self: *align(1) Self) SelfBytes { 187 - const size = @sizeOf(Self) + self.length; 188 - return @as([*]align(1) u8, @ptrCast(self))[0..size]; 189 - } 190 - }; 116 + // pub fn getPayload(self: *align(1) Relay) []u8 { 117 + // const len: *u16 = @ptrFromInt(@intFromPtr(self) - @sizeOf(u16)); 118 + // return @as([*]u8, @ptrCast(&self.payload))[0 .. len.* - @bitSizeOf(Relay) / 8]; 119 + // } 120 + // }; 121 + // pub const Connection = packed struct { 122 + // src_port: u16, // random number > 1024 123 + // dest_port: u16, // random number > 1024 124 + // seq_num: u32 = 0, 125 + // msg_id: u32 = 0, 126 + // reserved: u8 = 0, 127 + // options: ConnectionOptions = .{}, 128 + // payload: void, 191 129 192 - test "testing variable length zero copy struct" { 193 - { 194 - // Relay test 195 - const payload = "Hello darkness my old friend"; 196 - var msg_bytes: [try Message.calcSize(.relay, payload.len)]u8 align(@alignOf(Message)) = undefined; 130 + // pub fn getPayload(self: *align(1) Connection) []u8 { 131 + // const len: *u16 = @ptrFromInt(@intFromPtr(self) - @sizeOf(u16)); 132 + // return @as([*]u8, @ptrCast(&self.payload))[0 .. len.* - @bitSizeOf(Connection) / 8]; 133 + // } 197 134 198 - // Create a view of the byte slice as a Message 199 - const msg: *align(1) Message = .init(.relay, &msg_bytes); 135 + // fn nativeFromNetworkEndian(self: *align(1) Connection) void { 136 + // self.src_port = bigToNative(@TypeOf(self.src_port), self.src_port); 137 + // self.dest_port = bigToNative(@TypeOf(self.dest_port), self.dest_port); 138 + // self.seq_num = bigToNative(@TypeOf(self.seq_num), self.seq_num); 139 + // self.msg_id = bigToNative(@TypeOf(self.msg_id), self.msg_id); 140 + // } 200 141 201 - { 202 - // Set the message values 203 - { 204 - // These are both set by the init call. 205 - // msg.type = .relay; 206 - // msg.length = payload_len; 207 - } 208 - const relay = (try msg.getSaprusTypePayload()).relay; 209 - relay.dest = .{ 1, 2, 3, 4 }; 210 - @memcpy(relay.getPayload(), payload); 211 - } 142 + // fn networkFromNativeEndian(self: *align(1) Connection) void { 143 + // self.src_port = nativeToBig(@TypeOf(self.src_port), self.src_port); 144 + // self.dest_port = nativeToBig(@TypeOf(self.dest_port), self.dest_port); 145 + // self.seq_num = nativeToBig(@TypeOf(self.seq_num), self.seq_num); 146 + // self.msg_id = nativeToBig(@TypeOf(self.msg_id), self.msg_id); 147 + // } 148 + // }; 212 149 213 - { 214 - // Print the message as hex using the network byte order 215 - try msg.networkFromNativeEndian(); 216 - // We know the error from nativeFromNetworkEndian is unreachable because 217 - // it would have returned an error from networkFromNativeEndian. 218 - defer msg.nativeFromNetworkEndian() catch unreachable; 219 - std.debug.print("relay network bytes: {x}\n", .{msg_bytes}); 220 - std.debug.print("bytes len: {d}\n", .{msg_bytes.len}); 221 - } 150 + // const Self = @This(); 151 + // const SelfBytes = []align(1) u8; 222 152 223 - if (false) { 224 - // Illegal behavior 225 - std.debug.print("{any}\n", .{(try msg.getSaprusTypePayload()).connection}); 226 - } 153 + // type: PacketType, 154 + // length: u16, 155 + // bytes: void = {}, 227 156 228 - try std.testing.expectEqualDeep(msg, try Message.bytesAsValue(msg.asBytes())); 229 - } 157 + // /// Takes a byte slice, and returns a Message struct backed by the slice. 158 + // /// This properly initializes the top level headers within the slice. 159 + // /// This is used for creating new messages. For reading messages from the network, 160 + // /// see: networkBytesAsValue. 161 + // pub fn init(@"type": PacketType, bytes: []u8) *align(1) Self { 162 + // std.debug.assert(bytes.len >= @sizeOf(Self)); 163 + // const res: *align(1) Self = @ptrCast(bytes.ptr); 164 + // res.type = @"type"; 165 + // res.length = @intCast(bytes.len - @sizeOf(Self)); 166 + // return res; 167 + // } 230 168 231 - { 232 - // Connection test 233 - const payload = "Hello darkness my old friend"; 234 - var msg_bytes: [try Message.calcSize(.connection, payload.len)]u8 align(@alignOf(Message)) = undefined; 169 + // /// Compute the number of bytes required to store a given payload size for a given message type. 170 + // pub fn calcSize(comptime @"type": PacketType, payload_len: usize) MessageTypeError!u16 { 171 + // const header_size = @bitSizeOf(switch (@"type") { 172 + // .relay => Relay, 173 + // .connection => Connection, 174 + // .file_transfer => return MessageTypeError.NotImplementedSaprusType, 175 + // else => return MessageTypeError.UnknownSaprusType, 176 + // }) / 8; 177 + // return @intCast(payload_len + @sizeOf(Self) + header_size); 178 + // } 179 + 180 + // fn getRelay(self: *align(1) Self) *align(1) Relay { 181 + // return std.mem.bytesAsValue(Relay, &self.bytes); 182 + // } 183 + // fn getConnection(self: *align(1) Self) *align(1) Connection { 184 + // return std.mem.bytesAsValue(Connection, &self.bytes); 185 + // } 186 + 187 + // /// Access the message Saprus payload. 188 + // pub fn getSaprusTypePayload(self: *align(1) Self) MessageTypeError!(union(PacketType) { 189 + // relay: *align(1) Relay, 190 + // file_transfer: void, 191 + // connection: *align(1) Connection, 192 + // }) { 193 + // return switch (self.type) { 194 + // .relay => .{ .relay = self.getRelay() }, 195 + // .connection => .{ .connection = self.getConnection() }, 196 + // .file_transfer => MessageTypeError.NotImplementedSaprusType, 197 + // else => MessageTypeError.UnknownSaprusType, 198 + // }; 199 + // } 200 + 201 + // /// Convert the message to native endianness from network endianness in-place. 202 + // pub fn nativeFromNetworkEndian(self: *align(1) Self) MessageTypeError!void { 203 + // self.type = @enumFromInt(bigToNative( 204 + // @typeInfo(@TypeOf(self.type)).@"enum".tag_type, 205 + // @intFromEnum(self.type), 206 + // )); 207 + // self.length = bigToNative(@TypeOf(self.length), self.length); 208 + // errdefer { 209 + // // If the payload specific headers fail, revert the top level header values 210 + // self.type = @enumFromInt(nativeToBig( 211 + // @typeInfo(@TypeOf(self.type)).@"enum".tag_type, 212 + // @intFromEnum(self.type), 213 + // )); 214 + // self.length = nativeToBig(@TypeOf(self.length), self.length); 215 + // } 216 + // switch (try self.getSaprusTypePayload()) { 217 + // .relay => {}, 218 + // .connection => |*con| con.*.nativeFromNetworkEndian(), 219 + // // We know other values are unreachable, 220 + // // because they would have returned an error from the switch condition. 221 + // else => unreachable, 222 + // } 223 + // } 224 + 225 + // /// Convert the message to network endianness from native endianness in-place. 226 + // pub fn networkFromNativeEndian(self: *align(1) Self) MessageTypeError!void { 227 + // try switch (try self.getSaprusTypePayload()) { 228 + // .relay => {}, 229 + // .connection => |*con| con.*.networkFromNativeEndian(), 230 + // .file_transfer => MessageTypeError.NotImplementedSaprusType, 231 + // else => MessageTypeError.UnknownSaprusType, 232 + // }; 233 + // self.type = @enumFromInt(nativeToBig( 234 + // @typeInfo(@TypeOf(self.type)).@"enum".tag_type, 235 + // @intFromEnum(self.type), 236 + // )); 237 + // self.length = nativeToBig(@TypeOf(self.length), self.length); 238 + // } 239 + 240 + // /// Convert network endian bytes to a native endian value in-place. 241 + // pub fn networkBytesAsValue(bytes: SelfBytes) MessageParseError!*align(1) Self { 242 + // const res = std.mem.bytesAsValue(Self, bytes); 243 + // try res.nativeFromNetworkEndian(); 244 + // return .bytesAsValue(bytes); 245 + // } 246 + 247 + // /// Create a structured view of the bytes without initializing the length or type, 248 + // /// and without converting the endianness. 249 + // pub fn bytesAsValue(bytes: SelfBytes) MessageParseError!*align(1) Self { 250 + // const res = std.mem.bytesAsValue(Self, bytes); 251 + // return switch (res.type) { 252 + // .relay, .connection => if (bytes.len == res.length + @sizeOf(Self)) 253 + // res 254 + // else 255 + // MessageParseError.InvalidMessage, 256 + // .file_transfer => MessageParseError.NotImplementedSaprusType, 257 + // else => MessageParseError.UnknownSaprusType, 258 + // }; 259 + // } 260 + 261 + // /// Deprecated. 262 + // /// If I need the bytes, I should just pass around the slice that is backing this to begin with. 263 + // pub fn asBytes(self: *align(1) Self) SelfBytes { 264 + // const size = @sizeOf(Self) + self.length; 265 + // return @as([*]align(1) u8, @ptrCast(self))[0..size]; 266 + // } 267 + // }; 268 + 269 + // test "testing variable length zero copy struct" { 270 + // { 271 + // // Relay test 272 + // const payload = "Hello darkness my old friend"; 273 + // var msg_bytes: [try Message.calcSize(.relay, payload.len)]u8 align(@alignOf(Message)) = undefined; 274 + 275 + // // Create a view of the byte slice as a Message 276 + // const msg: *align(1) Message = .init(.relay, &msg_bytes); 277 + 278 + // { 279 + // // Set the message values 280 + // { 281 + // // These are both set by the init call. 282 + // // msg.type = .relay; 283 + // // msg.length = payload_len; 284 + // } 285 + // const relay = (try msg.getSaprusTypePayload()).relay; 286 + // relay.dest = .{ 1, 2, 3, 4 }; 287 + // @memcpy(relay.getPayload(), payload); 288 + // } 289 + 290 + // { 291 + // // Print the message as hex using the network byte order 292 + // try msg.networkFromNativeEndian(); 293 + // // We know the error from nativeFromNetworkEndian is unreachable because 294 + // // it would have returned an error from networkFromNativeEndian. 295 + // defer msg.nativeFromNetworkEndian() catch unreachable; 296 + // std.debug.print("relay network bytes: {x}\n", .{msg_bytes}); 297 + // std.debug.print("bytes len: {d}\n", .{msg_bytes.len}); 298 + // } 299 + 300 + // if (false) { 301 + // // Illegal behavior 302 + // std.debug.print("{any}\n", .{(try msg.getSaprusTypePayload()).connection}); 303 + // } 235 304 236 - // Create a view of the byte slice as a Message 237 - const msg: *align(1) Message = .init(.connection, &msg_bytes); 305 + // try std.testing.expectEqualDeep(msg, try Message.bytesAsValue(msg.asBytes())); 306 + // } 238 307 239 - { 240 - // Initializing connection header values 241 - const connection = (try msg.getSaprusTypePayload()).connection; 242 - connection.src_port = 1; 243 - connection.dest_port = 2; 244 - connection.seq_num = 3; 245 - connection.msg_id = 4; 246 - connection.reserved = 5; 247 - connection.options = @bitCast(@as(u8, 6)); 248 - @memcpy(connection.getPayload(), payload); 249 - } 308 + // { 309 + // // Connection test 310 + // const payload = "Hello darkness my old friend"; 311 + // var msg_bytes: [try Message.calcSize(.connection, payload.len)]u8 align(@alignOf(Message)) = undefined; 250 312 251 - { 252 - // Print the message as hex using the network byte order 253 - try msg.networkFromNativeEndian(); 254 - // We know the error from nativeFromNetworkEndian is unreachable because 255 - // it would have returned an error from networkFromNativeEndian. 256 - defer msg.nativeFromNetworkEndian() catch unreachable; 257 - std.debug.print("connection network bytes: {x}\n", .{msg_bytes}); 258 - std.debug.print("bytes len: {d}\n", .{msg_bytes.len}); 259 - } 260 - } 261 - } 313 + // // Create a view of the byte slice as a Message 314 + // const msg: *align(1) Message = .init(.connection, &msg_bytes); 315 + 316 + // { 317 + // // Initializing connection header values 318 + // const connection = (try msg.getSaprusTypePayload()).connection; 319 + // connection.src_port = 1; 320 + // connection.dest_port = 2; 321 + // connection.seq_num = 3; 322 + // connection.msg_id = 4; 323 + // connection.reserved = 5; 324 + // connection.options = @bitCast(@as(u8, 6)); 325 + // @memcpy(connection.getPayload(), payload); 326 + // } 327 + 328 + // { 329 + // // Print the message as hex using the network byte order 330 + // try msg.networkFromNativeEndian(); 331 + // // We know the error from nativeFromNetworkEndian is unreachable because 332 + // // it would have returned an error from networkFromNativeEndian. 333 + // defer msg.nativeFromNetworkEndian() catch unreachable; 334 + // std.debug.print("connection network bytes: {x}\n", .{msg_bytes}); 335 + // std.debug.print("bytes len: {d}\n", .{msg_bytes.len}); 336 + // } 337 + // } 338 + // } 262 339 263 340 const std = @import("std"); 264 341 const Allocator = std.mem.Allocator; 342 + const Writer = std.Io.Writer; 265 343 266 - const asBytes = std.mem.asBytes; 267 - const nativeToBig = std.mem.nativeToBig; 268 - const bigToNative = std.mem.bigToNative; 344 + // const asBytes = std.mem.asBytes; 345 + // const nativeToBig = std.mem.nativeToBig; 346 + // const bigToNative = std.mem.bigToNative; 269 347 270 - test "Round trip Relay toBytes and fromBytes" { 271 - if (false) { 272 - const gpa = std.testing.allocator; 273 - const msg = Message{ 274 - .relay = .{ 275 - .header = .{ .dest = .{ 255, 255, 255, 255 } }, 276 - .payload = "Hello darkness my old friend", 277 - }, 278 - }; 348 + // test "Round trip Relay toBytes and fromBytes" { 349 + // if (true) return error.SkipZigTest; 350 + // const gpa = std.testing.allocator; 351 + // const msg = Message{ 352 + // .relay = .{ 353 + // .header = .{ .dest = .{ 255, 255, 255, 255 } }, 354 + // .payload = "Hello darkness my old friend", 355 + // }, 356 + // }; 279 357 280 - const to_bytes = try msg.toBytes(gpa); 281 - defer gpa.free(to_bytes); 358 + // const to_bytes = try msg.toBytes(gpa); 359 + // defer gpa.free(to_bytes); 282 360 283 - const from_bytes = try Message.fromBytes(to_bytes, gpa); 284 - defer from_bytes.deinit(gpa); 361 + // const from_bytes = try Message.fromBytes(to_bytes, gpa); 362 + // defer from_bytes.deinit(gpa); 285 363 286 - try std.testing.expectEqualDeep(msg, from_bytes); 287 - } 288 - return error.SkipZigTest; 289 - } 364 + // try std.testing.expectEqualDeep(msg, from_bytes); 365 + // } 290 366 291 - test "Round trip Connection toBytes and fromBytes" { 292 - if (false) { 293 - const gpa = std.testing.allocator; 294 - const msg = Message{ 295 - .connection = .{ 296 - .header = .{ 297 - .src_port = 0, 298 - .dest_port = 0, 299 - }, 300 - .payload = "Hello darkness my old friend", 301 - }, 302 - }; 367 + // test "Round trip Connection toBytes and fromBytes" { 368 + // if (false) { 369 + // const gpa = std.testing.allocator; 370 + // const msg = Message{ 371 + // .connection = .{ 372 + // .header = .{ 373 + // .src_port = 0, 374 + // .dest_port = 0, 375 + // }, 376 + // .payload = "Hello darkness my old friend", 377 + // }, 378 + // }; 303 379 304 - const to_bytes = try msg.toBytes(gpa); 305 - defer gpa.free(to_bytes); 380 + // const to_bytes = try msg.toBytes(gpa); 381 + // defer gpa.free(to_bytes); 306 382 307 - const from_bytes = try Message.fromBytes(to_bytes, gpa); 308 - defer from_bytes.deinit(gpa); 383 + // const from_bytes = try Message.fromBytes(to_bytes, gpa); 384 + // defer from_bytes.deinit(gpa); 309 385 310 - try std.testing.expectEqualDeep(msg, from_bytes); 311 - } 312 - return error.SkipZigTest; 313 - } 386 + // try std.testing.expectEqualDeep(msg, from_bytes); 387 + // } 388 + // return error.SkipZigTest; 389 + // } 314 390 315 391 test { 316 392 std.testing.refAllDeclsRecursive(@This());
-2
src/root.zig
··· 1 1 pub const Client = @import("Client.zig"); 2 2 pub const Connection = @import("Connection.zig"); 3 - pub const RawSocketWriter = @import("RawSocketWriter.zig"); 4 - // pub const NetWriter = @import("NetWriter.zig"); 5 3 6 4 const msg = @import("message.zig"); 7 5