tiny.reticulum.node.transport.rewrite
Defined in node.transport.
API (5)
Actions
Public operations.
forward: Names a new next hop in a packet already under HEADER_2, as Reticulum@1.5.0 RNS/Transport.py:1935-1940 does.insert: Inserts a packet under HEADER_1 into transport, following Reticulum@1.5.0 RNS/Transport.py:1345-1354, so a node sending its own packet through a neighbor adds the header field that names that neighbor.rehop: Writes a new hop count in and copies the rest through, as Reticulum@1.5.0 RNS/Transport.py:2674-2676 does for a proof it passes on.strip: Strips transport for the last hop, following Reticulum@1.5.0 RNS/Transport.py:1941-1946, so a node one hop from the destination takes the transport header off, because the destination expects the shorter shape.
Types and contracts
Public types and contracts.
Source
Source: lib/reticulum/src/node/transport/rewrite.zig
zig
const std = @import("std");const wire = @import("../../wire/root.zig");pub const Error = error{PacketTooLarge};const transport_header: u8 = 0b0101_0000;const low_flags: u8 = 0b0000_1111;/// Inserts a packet under HEADER_1 into transport, following Reticulum@1.5.0/// RNS/Transport.py:1345-1354, so a node sending its own packet through a/// neighbor adds the header field that names that neighbor. HEADER_1 is the/// 19-byte header shape carried by a packet that names no node it is passing/// through. Writing into the buffer the packet came in is allowed, because/// every byte ends up at or above where it started. A packet that would pass/// the 500-byte maximum returns `error.PacketTooLarge`.pub fn insert(raw: []const u8, next_hop: [16]u8, out: []u8) Error![]u8 { std.debug.assert(raw.len >= wire.header_one_bytes); std.debug.assert(raw.len <= wire.mtu); std.debug.assert(wire.Flags.decode(raw[0]).header == .one); const total = raw.len + wire.truncated_hash_bytes; if (total > wire.mtu) return error.PacketTooLarge; std.debug.assert(out.len >= total); const flags = raw[0]; const hops = raw[1]; std.mem.copyBackwards(u8, out[18..total], raw[2..]); out[0] = transport_header | (flags & low_flags); out[1] = hops; @memcpy(out[2..18], &next_hop); return out[0..total];}/// Names a new next hop in a packet already under HEADER_2, as Reticulum@1.5.0/// RNS/Transport.py:1935-1940 does. A node carrying a packet that still has/// hops to go calls this function to name the next neighbor. The output and/// the input do not overlap.pub fn forward(raw: []const u8, hops: u8, next_hop: [16]u8, out: []u8) []u8 { std.debug.assert(raw.len >= wire.header_two_bytes); std.debug.assert(raw.len <= wire.mtu); std.debug.assert(wire.Flags.decode(raw[0]).header == .two); std.debug.assert(out.len >= raw.len); out[0] = raw[0]; out[1] = hops; @memcpy(out[2..18], &next_hop); @memcpy(out[18..raw.len], raw[18..]); return out[0..raw.len];}/// Strips transport for the last hop, following Reticulum@1.5.0/// RNS/Transport.py:1941-1946, so a node one hop from the destination takes the/// transport header off, because the destination expects the shorter shape. The/// output and the input do not overlap.pub fn strip(raw: []const u8, hops: u8, out: []u8) []u8 { std.debug.assert(raw.len >= wire.header_two_bytes); std.debug.assert(raw.len <= wire.mtu); std.debug.assert(wire.Flags.decode(raw[0]).header == .two); const total = raw.len - wire.truncated_hash_bytes; std.debug.assert(out.len >= total); out[0] = raw[0] & low_flags; out[1] = hops; @memcpy(out[2..total], raw[18..]); return out[0..total];}/// Writes a new hop count in and copies the rest through, as Reticulum@1.5.0/// RNS/Transport.py:2674-2676 does for a proof it passes on. A node passing a/// proof or link traffic on calls this function, because the hop count is the/// only field that may change. The output and the input do not overlap.pub fn rehop(raw: []const u8, hops: u8, out: []u8) []u8 { std.debug.assert(raw.len >= 2); std.debug.assert(raw.len <= wire.mtu); std.debug.assert(out.len >= raw.len); out[0] = raw[0]; out[1] = hops; @memcpy(out[2..raw.len], raw[2..]); return out[0..raw.len];}fn encodeData(payload: []const u8, out: []u8) ![]u8 { return wire.encode(.{ .ifac = 0, .header = .one, .context_flag = 1, .transport = .broadcast, .destination_type = .single, .packet_type = .data, .hops = 5, .transport_id = null, .destination = @splat(0x44), .context = .none, .payload = payload, }, out);}test "Reticulum@1.5.0 RNS/Transport.py:1345-1354 insertion keeps the packet hash" { var raw_storage: [wire.mtu]u8 = undefined; const raw = try encodeData("routed payload", &raw_storage); const hash = try wire.hash.full(raw); var out: [wire.mtu]u8 = undefined; const inserted = try insert(raw, @splat(0xb7), &out); const decoded = try wire.decode(inserted); try std.testing.expectEqual(wire.HeaderType.two, decoded.header); try std.testing.expectEqual(wire.TransportType.transport, decoded.transport); try std.testing.expectEqual(@as(u1, 0), decoded.context_flag); try std.testing.expectEqual(@as(u8, 5), decoded.hops); const next_hop: [16]u8 = @splat(0xb7); try std.testing.expectEqualSlices(u8, &next_hop, &decoded.transport_id.?); try std.testing.expectEqualSlices(u8, "routed payload", decoded.payload); try std.testing.expectEqualSlices(u8, &hash, &try wire.hash.full(inserted)); const in_place = try insert(raw, next_hop, &raw_storage); try std.testing.expectEqualSlices(u8, inserted, in_place);}test "transport insertion admits the MTU and rejects one byte more" { var raw_storage: [wire.mtu]u8 = undefined; const payload: [wire.mtu - wire.header_one_bytes - wire.truncated_hash_bytes + 1]u8 = @splat(0x61); const raw = try encodeData(&payload, &raw_storage); var out: [wire.mtu]u8 = undefined; try std.testing.expectError(error.PacketTooLarge, insert(raw, @splat(0), &out)); const fitting = try insert(raw[0 .. raw.len - 1], @splat(0), &out); try std.testing.expectEqual(@as(usize, wire.mtu), fitting.len);}fn encodeTransported(payload: []const u8, out: []u8) ![]u8 { return wire.encode(.{ .ifac = 0, .header = .two, .context_flag = 1, .transport = .transport, .destination_type = .single, .packet_type = .data, .hops = 1, .transport_id = @splat(0xb7), .destination = @splat(0x44), .context = .none, .payload = payload, }, out);}test "Reticulum@1.5.0 RNS/Transport.py:1935-1946 forwarding and stripping keep the packet hash" { var raw_storage: [wire.mtu]u8 = undefined; const raw = try encodeTransported("relayed payload", &raw_storage); const hash = try wire.hash.full(raw); const next_hop: [16]u8 = @splat(0xc3); var forwarded_storage: [wire.mtu]u8 = undefined; const forwarded_raw = forward(raw, 2, next_hop, &forwarded_storage); const forwarded = try wire.decode(forwarded_raw); try std.testing.expectEqual(wire.HeaderType.two, forwarded.header); try std.testing.expectEqual(@as(u1, 1), forwarded.context_flag); try std.testing.expectEqual(@as(u8, 2), forwarded.hops); try std.testing.expectEqualSlices(u8, &next_hop, &forwarded.transport_id.?); try std.testing.expectEqualSlices(u8, &hash, &try wire.hash.full(forwarded_raw)); var stripped_storage: [wire.mtu]u8 = undefined; const stripped_raw = strip(raw, 2, &stripped_storage); const stripped = try wire.decode(stripped_raw); try std.testing.expectEqual(wire.HeaderType.one, stripped.header); try std.testing.expectEqual(wire.TransportType.broadcast, stripped.transport); try std.testing.expectEqual(@as(u1, 0), stripped.context_flag); try std.testing.expectEqual(@as(u8, 2), stripped.hops); try std.testing.expect(stripped.transport_id == null); try std.testing.expectEqualSlices(u8, "relayed payload", stripped.payload); try std.testing.expectEqualSlices(u8, &hash, &try wire.hash.full(stripped_raw));}test "Reticulum@1.5.0 RNS/Transport.py:2674-2676 proof relay rewrites only the hops byte" { var raw_storage: [wire.mtu]u8 = undefined; const signature: [64]u8 = @splat(0x42); const raw = try wire.encode(.{ .ifac = 0, .header = .one, .context_flag = 0, .transport = .broadcast, .destination_type = .single, .packet_type = .proof, .hops = 0, .transport_id = null, .destination = @splat(0x3d), .context = .none, .payload = &signature, }, &raw_storage); var out: [wire.mtu]u8 = undefined; const relayed = rehop(raw, 4, &out); try std.testing.expectEqual(raw.len, relayed.len); try std.testing.expectEqual(raw[0], relayed[0]); try std.testing.expectEqual(@as(u8, 4), relayed[1]); try std.testing.expectEqualSlices(u8, raw[2..], relayed[2..]);}Source: lib/reticulum/src/node/transport/root.zig:112
zig
pub const rewrite = @import("rewrite.zig");Audit
| Definitions | 6 |
|---|---|
| Public names | 6 |
| Members | 1 |
| Version | 26.7.0 |
| Revision | daab053ee433 |