mirror of
https://git.robbyzambito.me/zaprus
synced 2026-02-04 08:24:52 +00:00
Compare commits
2 Commits
213a01afc8
...
a81c4b3175
| Author | SHA1 | Date | |
|---|---|---|---|
| a81c4b3175 | |||
| 43f7497424 |
@@ -49,9 +49,45 @@ pub const EthIpUdp = packed struct(u336) { // 42 bytes * 8 bits = 336
|
|||||||
|
|
||||||
pub fn setPayloadLen(self: *@This(), len: usize) void {
|
pub fn setPayloadLen(self: *@This(), len: usize) void {
|
||||||
self.ip.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8) + (@bitSizeOf(@TypeOf(self.ip)) / 8));
|
self.ip.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8) + (@bitSizeOf(@TypeOf(self.ip)) / 8));
|
||||||
|
|
||||||
|
// Zero the checksum field before calculation
|
||||||
|
self.ip.header_checksum = 0;
|
||||||
|
|
||||||
|
// Serialize IP header to big-endian bytes
|
||||||
|
var ip_bytes: [@bitSizeOf(@TypeOf(self.ip)) / 8]u8 = undefined;
|
||||||
|
var w: Writer = .fixed(&ip_bytes);
|
||||||
|
w.writeStruct(self.ip, .big) catch unreachable;
|
||||||
|
|
||||||
|
// Calculate checksum over serialized bytes
|
||||||
|
self.ip.header_checksum = onesComplement16(&ip_bytes);
|
||||||
|
|
||||||
self.udp.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8));
|
self.udp.len = @intCast(len + (@bitSizeOf(@TypeOf(self.udp)) / 8));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn onesComplement16(data: []const u8) u16 {
|
||||||
|
var sum: u32 = 0;
|
||||||
|
|
||||||
|
// Process pairs of bytes as 16-bit words
|
||||||
|
var i: usize = 0;
|
||||||
|
while (i + 1 < data.len) : (i += 2) {
|
||||||
|
const word: u16 = (@as(u16, data[i]) << 8) | data[i + 1];
|
||||||
|
sum += word;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle odd byte if present
|
||||||
|
if (data.len % 2 == 1) {
|
||||||
|
sum += @as(u32, data[data.len - 1]) << 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fold 32-bit sum to 16 bits
|
||||||
|
while (sum >> 16 != 0) {
|
||||||
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return ones' complement
|
||||||
|
return ~@as(u16, @truncate(sum));
|
||||||
|
}
|
||||||
|
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
const Writer = std.Io.Writer;
|
const Writer = std.Io.Writer;
|
||||||
|
|||||||
@@ -1,11 +1,3 @@
|
|||||||
/// Type tag for Message union.
|
|
||||||
/// This is the first value in the actual packet sent over the network.
|
|
||||||
pub const PacketType = enum(u16) {
|
|
||||||
relay = 0x003C,
|
|
||||||
connection = 0x00E9,
|
|
||||||
_,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const MessageTypeError = error{
|
pub const MessageTypeError = error{
|
||||||
NotImplementedSaprusType,
|
NotImplementedSaprusType,
|
||||||
UnknownSaprusType,
|
UnknownSaprusType,
|
||||||
@@ -16,16 +8,18 @@ pub const MessageParseError = MessageTypeError || error{
|
|||||||
|
|
||||||
const message = @This();
|
const message = @This();
|
||||||
|
|
||||||
pub const Message = union(PacketType) {
|
pub const Message = union(enum(u16)) {
|
||||||
relay: Message.Relay,
|
relay: Message.Relay = 0x003C,
|
||||||
connection: Message.Connection,
|
connection: Message.Connection = 0x00E9,
|
||||||
|
_,
|
||||||
|
|
||||||
pub const Relay = message.Relay;
|
pub const Relay = message.Relay;
|
||||||
pub const Connection = message.Connection;
|
pub const Connection = message.Connection;
|
||||||
|
|
||||||
pub fn toBytes(self: message.Message, buf: []u8) []u8 {
|
pub fn toBytes(self: message.Message, buf: []u8) []u8 {
|
||||||
return switch (self) {
|
return switch (self) {
|
||||||
inline else => |m| m.toBytes(buf),
|
inline .relay, .connection => |m| m.toBytes(buf),
|
||||||
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,7 +30,7 @@ pub const relay_dest_len = 4;
|
|||||||
|
|
||||||
pub fn parse(bytes: []const u8) MessageParseError!Message {
|
pub fn parse(bytes: []const u8) MessageParseError!Message {
|
||||||
var in: Reader = .fixed(bytes);
|
var in: Reader = .fixed(bytes);
|
||||||
const @"type" = in.takeEnum(PacketType, .big) catch |err| switch (err) {
|
const @"type" = in.takeEnum(std.meta.Tag(Message), .big) catch |err| switch (err) {
|
||||||
error.InvalidEnumTag => return error.UnknownSaprusType,
|
error.InvalidEnumTag => return error.UnknownSaprusType,
|
||||||
else => return error.InvalidMessage,
|
else => return error.InvalidMessage,
|
||||||
};
|
};
|
||||||
@@ -124,7 +118,7 @@ const Relay = struct {
|
|||||||
/// Asserts that buf is large enough to fit the relay message.
|
/// Asserts that buf is large enough to fit the relay message.
|
||||||
pub fn toBytes(self: Relay, buf: []u8) []u8 {
|
pub fn toBytes(self: Relay, buf: []u8) []u8 {
|
||||||
var out: Writer = .fixed(buf);
|
var out: Writer = .fixed(buf);
|
||||||
out.writeInt(u16, @intFromEnum(PacketType.relay), .big) catch unreachable;
|
out.writeInt(u16, @intFromEnum(Message.relay), .big) catch unreachable;
|
||||||
out.writeInt(u16, @intCast(self.payload.len + 4), .big) catch unreachable; // Length field, but unread. Will switch to checksum
|
out.writeInt(u16, @intCast(self.payload.len + 4), .big) catch unreachable; // Length field, but unread. Will switch to checksum
|
||||||
out.writeAll(&self.dest.bytes) catch unreachable;
|
out.writeAll(&self.dest.bytes) catch unreachable;
|
||||||
out.writeAll(self.payload) catch unreachable;
|
out.writeAll(self.payload) catch unreachable;
|
||||||
@@ -178,7 +172,7 @@ const Connection = struct {
|
|||||||
/// Asserts that buf is large enough to fit the connection message.
|
/// Asserts that buf is large enough to fit the connection message.
|
||||||
pub fn toBytes(self: Connection, buf: []u8) []u8 {
|
pub fn toBytes(self: Connection, buf: []u8) []u8 {
|
||||||
var out: Writer = .fixed(buf);
|
var out: Writer = .fixed(buf);
|
||||||
out.writeInt(u16, @intFromEnum(PacketType.connection), .big) catch unreachable;
|
out.writeInt(u16, @intFromEnum(Message.connection), .big) catch unreachable;
|
||||||
out.writeInt(u16, @intCast(self.payload.len + 14), .big) catch unreachable; // Saprus length field, unread.
|
out.writeInt(u16, @intCast(self.payload.len + 14), .big) catch unreachable; // Saprus length field, unread.
|
||||||
out.writeInt(u16, self.src, .big) catch unreachable;
|
out.writeInt(u16, self.src, .big) catch unreachable;
|
||||||
out.writeInt(u16, self.dest, .big) catch unreachable;
|
out.writeInt(u16, self.dest, .big) catch unreachable;
|
||||||
|
|||||||
Reference in New Issue
Block a user