Refactored (again) the packet module, added the identity and destination modules

This commit is contained in:
Gu://em_ 2026-07-03 21:58:29 +02:00
parent 0eae5818a0
commit 1216dc2282
5 changed files with 178 additions and 100 deletions

View file

@ -49,6 +49,7 @@ pub fn build(b: *std.Build) void {
ctx.addTestModule(root_module);
ctx.addTestFile("src/packet.zig");
ctx.addTestFile("src/identity.zig");
}

View file

@ -5,13 +5,14 @@
//
pub const Type = enum(u2) {
single = 0x00,
group = 0x01,
plain = 0x02,
link = 0x03,
single = 0b0,
group = 0b01,
plain = 0b10,
link = 0b11,
};
pub const ProofStrategy = enum(u2) {
// From the reference implementation, seems weird
pub const ProofStrategy = enum(u8) {
prove_none = 0x21,
prove_app = 0x22,
prove_all = 0x23,
@ -28,13 +29,31 @@ pub const Direction = enum(u2) {
out = 0x12,
};
///////////////// Functions
///////////////// Enums
//
//////// Helper functions
//
const Destination = struct {
name: []const u8,
aspects: [][]const u8,
direction: Direction,
type: Type,
//////// Public functions
//////// Public functions
//
// TODO
pub fn hash(self: *Destination, destination_buffer: [128]u8) !void {
_ = self;
_ = destination_buffer;
}
// TODO
pub fn announce() !void {}
};
///////////////// Helper functions
//
///////////////// Tests

48
src/identity.zig Normal file
View file

@ -0,0 +1,48 @@
///////////////// Imports
//
const CryptoEngine = @import("crypto.zig").Engine;
///////////////// Constants
//
///////////////// Enums
//
///////////////// Structs
//
// TODO
pub fn Identity(comptime crypto_engine: CryptoEngine) type {
_ = crypto_engine;
return struct {
//////// Fields
//
publicKey: []const u8,
privateKey: []const u8,
signature: []const u8,
hash: []const u8,
//////// Functions
//
pub fn generate() !Identity {
return .{
// .privateKey = crypto_engine.ed25519.generateKey(...),
// .signature = crypto_engine.x25519.
};
}
};
}
///////////////// Helper functions
//
///////////////// Tests
//
const std = @import("std");
const expect = std.testing.expect;

View file

@ -1,13 +1,8 @@
///////////////// Module
///////////////// Imports
//
const Self = @This();
header: PacketHeader,
address1: [ADDRESS_SIZE]u8,
address2: [ADDRESS_SIZE]u8,
context: PacketContext,
data: []u8,
const CryptoEngine = @import("crypto.zig").Engine;
const Destination = @import("destination.zig");
///////////////// Constants
@ -37,13 +32,6 @@ pub const PropagationType = enum(u1) {
transport = 1
};
pub const DestinationType = enum(u2) {
single = 0b0,
group = 0b01,
plain = 0b10,
link = 0b11,
};
pub const PacketType = enum(u2) {
data = 0b0,
announce = 0b01,
@ -83,15 +71,89 @@ pub const PacketHeader = packed struct {
header: HeaderType,
context: ContextFlag,
propagation: PropagationType,
destination: DestinationType,
destination: Destination.Type,
packet: PacketType,
hops: u8,
};
///////////////// Functions
///////////////// Structs
//
//////// Helper functions
const Packet = struct {
const Self = @This();
///////////////// Fields
//
header: PacketHeader,
address1: [ADDRESS_SIZE]u8,
address2: [ADDRESS_SIZE]u8,
context: PacketContext,
data: []u8,
///////////////// Public functions
//
pub fn serialize(packet: *const Self, output_buffer: []u8) !usize {
const has_two_addresses = packet.header.header == HeaderType.type2;
const target_size = getPacketSize(packet.data.len, has_two_addresses);
if (output_buffer.len < target_size) {
return error.BufferTooShort;
}
// Write buffer
var offset: usize = 0;
@memcpy(output_buffer[offset .. offset + @sizeOf(PacketHeader)], asBytes(&packet.header));
offset += @sizeOf(PacketHeader);
@memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address1));
offset += ADDRESS_SIZE;
if (has_two_addresses) {
@memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address2));
offset += ADDRESS_SIZE;
}
@memcpy(output_buffer[offset .. offset + @sizeOf(PacketContext)], asBytes(&packet.context));
offset += @sizeOf(PacketContext);
@memcpy(output_buffer[offset .. offset + packet.data.len], packet.data);
offset += packet.data.len;
if (target_size != offset) {
return error.InternalError;
}
return offset;
}
// Reads the message buffer and builds the corresponding packet struct inside dest_packet
pub fn deserialize(packet: *Self, message_buffer: []u8) !void {
var offset: usize = 0;
offset = try copyToPacket(&packet.header, message_buffer, offset, @sizeOf(PacketHeader));
offset = try copyToPacket(&packet.address1, message_buffer, offset, ADDRESS_SIZE);
const has_two_addresses = packet.header.header == HeaderType.type2;
if (has_two_addresses) {
offset = try copyToPacket(&packet.address2, message_buffer, offset, ADDRESS_SIZE);
}
offset = try copyToPacket(&packet.context, message_buffer, offset, @sizeOf(PacketContext));
offset = try copyToPacket(packet.data, message_buffer, offset, message_buffer.len - offset);
}
};
// pub fn Packet(comptime crypto_engine: CryptoEngine) type {
// return struct {};
// }
///////////////// Helper functions
//
// Copies serialized data (as a byte array) into any structure type
@ -116,58 +178,6 @@ fn getPacketSize(data_size: usize, has_two_addresses: bool) usize {
return res;
}
//////// Public functions
//
pub fn serialize(packet: *const Self, output_buffer: []u8) !usize {
const has_two_addresses = packet.header.header == HeaderType.type2;
const target_size = getPacketSize(packet.data.len, has_two_addresses);
if (output_buffer.len < target_size) {
return error.BufferTooShort;
}
// Write buffer
var offset: usize = 0;
@memcpy(output_buffer[offset .. offset + @sizeOf(PacketHeader)], asBytes(&packet.header));
offset += @sizeOf(PacketHeader);
@memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address1));
offset += ADDRESS_SIZE;
if (has_two_addresses) {
@memcpy(output_buffer[offset .. offset + ADDRESS_SIZE], asBytes(&packet.address2));
offset += ADDRESS_SIZE;
}
@memcpy(output_buffer[offset .. offset + @sizeOf(PacketContext)], asBytes(&packet.context));
offset += @sizeOf(PacketContext);
@memcpy(output_buffer[offset .. offset + packet.data.len], packet.data);
offset += packet.data.len;
if (target_size != offset) {
return error.InternalError;
}
return offset;
}
// Reads the message buffer and builds the corresponding packet struct inside dest_packet
pub fn deserialize(packet: *Self, message_buffer: []u8) !void {
var offset: usize = 0;
offset = try copyToPacket(&packet.header, message_buffer, offset, @sizeOf(PacketHeader));
offset = try copyToPacket(&packet.address1, message_buffer, offset, ADDRESS_SIZE);
const has_two_addresses = packet.header.header == HeaderType.type2;
if (has_two_addresses) {
offset = try copyToPacket(&packet.address2, message_buffer, offset, ADDRESS_SIZE);
}
offset = try copyToPacket(&packet.context, message_buffer, offset, @sizeOf(PacketContext));
offset = try copyToPacket(packet.data, message_buffer, offset, message_buffer.len - offset);
}
///////////////// Tests
//
@ -181,8 +191,8 @@ const asBytes = std.mem.asBytes;
//
// Serializes the given packet and makes sure the output is correct
fn testPacketSerialization(packet: *const Self) !void {
const buf_size = comptime @sizeOf(Self) + MAX_DATA_SIZE;
fn testPacketSerialization(packet: *const Packet) !void {
const buf_size = comptime @sizeOf(Packet) + MAX_DATA_SIZE;
var buf: [buf_size]u8 = undefined;
const res: usize = try packet.serialize(&buf);
const has_second_address = packet.header.header == HeaderType.type2;
@ -220,7 +230,7 @@ fn headersEql(h1: *const PacketHeader, h2: *const PacketHeader) bool {
and h1.hops == h2.hops;
}
fn packetsEql(p1: *const Self, p2: *const Self) bool {
fn packetsEql(p1: *const Packet, p2: *const Packet) bool {
return headersEql(&p1.header, &p2.header)
and memeql(u8, &p1.address1, &p2.address1)
and memeql(u8, &p1.address2, &p2.address2)
@ -242,7 +252,7 @@ test "Basic serialization: header type 1, max data size" {
.header = HeaderType.type1,
.context = ContextFlag.set,
.propagation = PropagationType.transport,
.destination = DestinationType.single,
.destination = Destination.Type.single,
.packet = PacketType.announce,
.hops = 0,
};
@ -250,7 +260,7 @@ test "Basic serialization: header type 1, max data size" {
const data_size = MAX_DATA_SIZE;
var data: [data_size]u8 = undefined;
const packet: Self = .{
const packet: Packet = .{
.header = header,
.address1 = undefined,
.address2 = undefined,
@ -258,7 +268,7 @@ test "Basic serialization: header type 1, max data size" {
.data = &data,
};
try packet.testPacketSerialization();
try testPacketSerialization(&packet);
}
test "Basic serialization: header type 2, max data size" {
@ -267,7 +277,7 @@ test "Basic serialization: header type 2, max data size" {
.header = HeaderType.type2,
.context = ContextFlag.set,
.propagation = PropagationType.transport,
.destination = DestinationType.single,
.destination = Destination.Type.single,
.packet = PacketType.announce,
.hops = 0,
};
@ -275,7 +285,7 @@ test "Basic serialization: header type 2, max data size" {
const data_size = MAX_DATA_SIZE;
var data: [data_size]u8 = undefined;
const packet: Self = .{
const packet: Packet = .{
.header = header,
.address1 = undefined,
.address2 = undefined,
@ -283,7 +293,7 @@ test "Basic serialization: header type 2, max data size" {
.data = &data,
};
try packet.testPacketSerialization();
try testPacketSerialization(&packet);
}
test "Basic serialization: header type 1, medium data size" {
@ -292,7 +302,7 @@ test "Basic serialization: header type 1, medium data size" {
.header = HeaderType.type1,
.context = ContextFlag.set,
.propagation = PropagationType.transport,
.destination = DestinationType.single,
.destination = Destination.Type.single,
.packet = PacketType.announce,
.hops = 0,
};
@ -300,7 +310,7 @@ test "Basic serialization: header type 1, medium data size" {
const data_size = MAX_DATA_SIZE / 2 + 3;
var data: [data_size]u8 = undefined;
const packet: Self = .{
const packet: Packet = .{
.header = header,
.address1 = undefined,
.address2 = undefined,
@ -308,7 +318,7 @@ test "Basic serialization: header type 1, medium data size" {
.data = &data,
};
try packet.testPacketSerialization();
try testPacketSerialization(&packet);
}
test "Basic serialization: header type 2, medium data size" {
@ -317,7 +327,7 @@ test "Basic serialization: header type 2, medium data size" {
.header = HeaderType.type2,
.context = ContextFlag.set,
.propagation = PropagationType.transport,
.destination = DestinationType.single,
.destination = Destination.Type.single,
.packet = PacketType.announce,
.hops = 0,
};
@ -325,7 +335,7 @@ test "Basic serialization: header type 2, medium data size" {
const data_size = MAX_DATA_SIZE / 2 + 3;
var data: [data_size]u8 = undefined;
const packet: Self = .{
const packet: Packet = .{
.header = header,
.address1 = undefined,
.address2 = undefined,
@ -333,7 +343,7 @@ test "Basic serialization: header type 2, medium data size" {
.data = &data,
};
try packet.testPacketSerialization();
try testPacketSerialization(&packet);
}
test "Serialize / Deserialize Packet: Header type2, Medium data size" {
@ -342,7 +352,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" {
.header = HeaderType.type2,
.context = ContextFlag.set,
.propagation = PropagationType.transport,
.destination = DestinationType.single,
.destination = Destination.Type.single,
.packet = PacketType.announce,
.hops = 0,
};
@ -350,7 +360,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" {
const data_size = MAX_DATA_SIZE / 2 + 3;
var data: [data_size]u8 = undefined;
const packet: Self = .{
const packet: Packet = .{
.header = header,
.address1 = undefined,
.address2 = undefined,
@ -360,7 +370,7 @@ test "Serialize / Deserialize Packet: Header type2, Medium data size" {
const buf_size = comptime @sizeOf(PacketHeader) + 2*ADDRESS_SIZE + @sizeOf(PacketContext) + data_size;
var buf: [buf_size]u8 = undefined;
var res_packet: Self = undefined;
var res_packet: Packet = undefined;
var res_data: [data_size]u8 = undefined;
res_packet.data = &res_data;
_ = try packet.serialize(&buf);

View file

@ -4,10 +4,10 @@ const crypto = @import("crypto.zig");
// You can pass your own cryptographic functions to take advantage of your
// platform or use the library's software implementations for compatibility
// Use its return value to access the library modules
pub fn RnsZero(comptime cryptoProvider: crypto.PartialEngine) type {
const cryptoEngine = crypto.resolveEngine(cryptoProvider);
_ = cryptoEngine;
pub fn RnsZero(comptime crypto_provider: crypto.PartialEngine) type {
const crypto_engine = crypto.resolveEngine(crypto_provider);
return struct {
pub const packet = @import("packet.zig");
pub const identity = @import("identity.zig").Identity(crypto_engine);
};
}