Skip to documentation
SLOP

tiny.reticulum.node.transport.rewrite

Reference tiny.reticulum node transport rewrite

Defined in node.transport.

API (5)

Actions

Public operations.

Types and contracts

Public types and contracts.

No direct callersNo direct callsnode.transportrewrite
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callsnode.transport.link.relayrequestnode.transport.relayruntest sourcelib.reticulum.src.node.transport.rewrite.test...py:1935-1946 forwarding and stripping...private sourcelib.reticulum.src.properties.transport.Rewrit...propertynode.transport.rewriteforward
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsnode.linkopennode.outboundruntest sourcelib.reticulum.src.node.transport.rewrite.test...py:1345-1354 insertion keeps the pack...test sourcelib.reticulum.src.node.transport.rewritetest: transport insertion admits the ...private sourcelib.reticulum.src.node.transport.testrelayedRequestprivate sourcelib.reticulum.src.properties.transport.Rewrit...propertynode.transport.rewriteinsert
Static calls · unresolved targets: 1 · external targets: 0.
Called byCallsNo direct callsnode.transport.link.relayproofnode.transport.link.relaytrafficnode.transport.relayprooftest sourcelib.reticulum.src.node.transport.rewrite.test...py:2674-2676 proof relay rewrites onl...node.transport.rewriterehop
Static calls · unresolved targets: 0 · external targets: 0.
Called byCallsNo direct callsnode.transport.link.relayrequestnode.transport.relayruntest sourcelib.reticulum.src.node.transport.rewrite.test...py:1935-1946 forwarding and stripping...private sourcelib.reticulum.src.properties.transport.Rewrit...propertynode.transport.rewritestrip
Static calls · unresolved targets: 1 · external targets: 0.

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

Definitions6
Public names6
Members1
Version26.7.0
Revisiondaab053ee433