mirror of
https://git.robbyzambito.me/zaprus/
synced 2026-02-04 11:44:49 +00:00
For some reason I am still getting this: 2025/05/10 16:37:06 Error decoding message: SGVsbG8gZGFya25lc3MgbXkgb2xkIGZyaWVuZA==::53475673624738675a4746796132356c63334d6762586b676232786b49475a79615756755a413d3daaaa
152 lines
4.3 KiB
Zig
152 lines
4.3 KiB
Zig
const base64Enc = std.base64.Base64Encoder.init(std.base64.standard_alphabet_chars, '=');
|
|
const base64Dec = std.base64.Base64Decoder.init(std.base64.standard_alphabet_chars, '=');
|
|
|
|
var rand: ?Random = null;
|
|
|
|
pub fn init() !void {
|
|
var prng = Random.DefaultPrng.init(blk: {
|
|
var seed: u64 = undefined;
|
|
try posix.getrandom(mem.asBytes(&seed));
|
|
break :blk seed;
|
|
});
|
|
rand = prng.random();
|
|
try network.init();
|
|
}
|
|
|
|
pub fn deinit() void {
|
|
network.deinit();
|
|
}
|
|
|
|
fn broadcastSaprusMessage(msg: *SaprusMessage, udp_port: u16) !void {
|
|
if (false) {
|
|
var foo: gcat.nic.RawSocket = try .init("enp7s0"); // /proc/net/dev
|
|
defer foo.deinit();
|
|
}
|
|
const msg_bytes = msg.asBytes();
|
|
try msg.networkFromNativeEndian();
|
|
defer msg.nativeFromNetworkEndian() catch unreachable;
|
|
|
|
var sock = try network.Socket.create(.ipv4, .udp);
|
|
defer sock.close();
|
|
|
|
try sock.setBroadcast(true);
|
|
|
|
// Bind to 0.0.0.0:0
|
|
const bind_addr = network.EndPoint{
|
|
.address = network.Address{ .ipv4 = network.Address.IPv4.any },
|
|
.port = 0,
|
|
};
|
|
|
|
const dest_addr = network.EndPoint{
|
|
.address = network.Address{ .ipv4 = network.Address.IPv4.broadcast },
|
|
.port = udp_port,
|
|
};
|
|
|
|
try sock.bind(bind_addr);
|
|
|
|
_ = try sock.sendTo(dest_addr, msg_bytes);
|
|
}
|
|
|
|
pub fn sendRelay(payload: []const u8, dest: [4]u8, allocator: Allocator) !void {
|
|
const msg_bytes = try allocator.alignedAlloc(
|
|
u8,
|
|
@alignOf(SaprusMessage),
|
|
try SaprusMessage.lengthForPayloadLength(
|
|
.relay,
|
|
base64Enc.calcSize(payload.len),
|
|
),
|
|
);
|
|
defer allocator.free(msg_bytes);
|
|
const msg: *SaprusMessage = .init(.relay, msg_bytes);
|
|
|
|
const relay = (try msg.getSaprusTypePayload()).relay;
|
|
relay.dest = dest;
|
|
_ = base64Enc.encode(relay.getPayload(), payload);
|
|
|
|
try broadcastSaprusMessage(msg, 8888);
|
|
}
|
|
|
|
fn randomPort() u16 {
|
|
var p: u16 = 0;
|
|
if (rand) |r| {
|
|
p = r.intRangeAtMost(u16, 1024, 65000);
|
|
} else unreachable;
|
|
|
|
return p;
|
|
}
|
|
|
|
pub fn sendInitialConnection(payload: []const u8, initial_port: u16, allocator: Allocator) !*SaprusMessage {
|
|
const dest_port = randomPort();
|
|
const msg_bytes = try allocator.alignedAlloc(
|
|
u8,
|
|
@alignOf(SaprusMessage),
|
|
try SaprusMessage.lengthForPayloadLength(
|
|
.connection,
|
|
base64Enc.calcSize(payload.len),
|
|
),
|
|
);
|
|
defer allocator.free(msg_bytes);
|
|
const msg: *SaprusMessage = .init(.connection, msg_bytes);
|
|
|
|
const connection = (try msg.getSaprusTypePayload()).connection;
|
|
connection.src_port = initial_port;
|
|
connection.dest_port = dest_port;
|
|
_ = base64Enc.encode(connection.getPayload(), payload);
|
|
|
|
try broadcastSaprusMessage(msg, 8888);
|
|
|
|
return msg;
|
|
}
|
|
|
|
pub fn connect(payload: []const u8, allocator: Allocator) !?SaprusConnection {
|
|
var initial_port: u16 = 0;
|
|
if (rand) |r| {
|
|
initial_port = r.intRangeAtMost(u16, 1024, 65000);
|
|
} else unreachable;
|
|
|
|
var initial_conn_res: ?*SaprusMessage = null;
|
|
|
|
var sock = try network.Socket.create(.ipv4, .udp);
|
|
defer sock.close();
|
|
|
|
// Bind to 255.255.255.255:8888
|
|
const bind_addr = network.EndPoint{
|
|
.address = network.Address{ .ipv4 = network.Address.IPv4.broadcast },
|
|
.port = 8888,
|
|
};
|
|
|
|
// timeout 1s
|
|
try sock.setReadTimeout(1 * std.time.us_per_s);
|
|
try sock.bind(bind_addr);
|
|
|
|
const msg = try sendInitialConnection(payload, initial_port, allocator);
|
|
|
|
var response_buf: [4096]u8 align(4) = @splat(0);
|
|
_ = try sock.receive(&response_buf); // Ignore message that I sent.
|
|
const len = try sock.receive(&response_buf);
|
|
|
|
std.debug.print("response bytes: {x}\n", .{response_buf[0..len]});
|
|
initial_conn_res = SaprusMessage.init(.connection, response_buf[0..len]);
|
|
|
|
// Complete handshake after awaiting response
|
|
try broadcastSaprusMessage(msg, randomPort());
|
|
|
|
if (false) {
|
|
return initial_conn_res.?;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
const SaprusMessage = @import("message.zig").Message;
|
|
const SaprusConnection = @import("Connection.zig");
|
|
|
|
const std = @import("std");
|
|
const Random = std.Random;
|
|
const posix = std.posix;
|
|
const mem = std.mem;
|
|
|
|
const network = @import("network");
|
|
const gcat = @import("gatorcat");
|
|
|
|
const Allocator = mem.Allocator;
|