Files
zaprus/src/c_api.zig
Robby Zambito 558f40213b Update to Saprus 0.2.1
Handle management messages instead of letting them bubble up through the
connection to the consumer.
Right now, this just means handling ping messages by sending a pong.

Also updated to follow the new handshake flow.
The sentinel will mirror the ports instead of matching them.

Now filters on the full source and dest ports, which are less likely to
have erroneous matches.
2026-02-01 19:16:22 -05:00

105 lines
3.0 KiB
Zig

// Copyright 2026 Robby Zambito
//
// This file is part of zaprus.
//
// Zaprus is free software: you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the Free Software
// Foundation, either version 3 of the License, or (at your option) any later
// version.
//
// Zaprus is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
// A PARTICULAR PURPOSE. See the GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along with
// Zaprus. If not, see <https://www.gnu.org/licenses/>.
const std = @import("std");
const zaprus = @import("zaprus");
// Opaque types for C API
const ZaprusClient = opaque {};
const ZaprusConnection = opaque {};
const alloc = std.heap.c_allocator;
const io = std.Io.Threaded.global_single_threaded.io();
export fn zaprus_init_client() ?*ZaprusClient {
const client = alloc.create(zaprus.Client) catch return null;
client.* = zaprus.Client.init() catch {
alloc.destroy(client);
return null;
};
return @ptrCast(client);
}
export fn zaprus_deinit_client(client: ?*ZaprusClient) void {
const c: ?*zaprus.Client = @ptrCast(@alignCast(client));
if (c) |zc| {
zc.deinit();
alloc.destroy(zc);
}
}
export fn zaprus_client_send_relay(
client: ?*ZaprusClient,
payload: [*c]const u8,
payload_len: usize,
dest: [*c]const u8,
) c_int {
const c: ?*zaprus.Client = @ptrCast(@alignCast(client));
const zc = c orelse return 1;
zc.sendRelay(io, payload[0..payload_len], dest[0..4].*) catch return 1;
return 0;
}
export fn zaprus_connect(
client: ?*ZaprusClient,
payload: [*c]const u8,
payload_len: usize,
) ?*ZaprusConnection {
const c: ?*zaprus.Client = @ptrCast(@alignCast(client));
const zc = c orelse return null;
const connection = alloc.create(zaprus.Connection) catch return null;
connection.* = zc.connect(io, payload[0..payload_len]) catch {
alloc.destroy(connection);
return null;
};
return @ptrCast(connection);
}
export fn zaprus_deinit_connection(connection: ?*ZaprusConnection) void {
const c: ?*zaprus.Connection = @ptrCast(@alignCast(connection));
if (c) |zc| {
alloc.destroy(zc);
}
}
export fn zaprus_connection_next(
connection: ?*ZaprusConnection,
out: [*c]u8,
capacity: usize,
out_len: *usize,
) c_int {
const c: ?*zaprus.Connection = @ptrCast(@alignCast(connection));
const zc = c orelse return 1;
const result = zc.next(io, out[0..capacity]) catch return 1;
out_len.* = result.len;
return 0;
}
export fn zaprus_connection_send(
connection: ?*ZaprusConnection,
payload: [*c]const u8,
payload_len: usize,
) c_int {
const c: ?*zaprus.Connection = @ptrCast(@alignCast(connection));
const zc = c orelse return 1;
zc.send(io, .{}, payload[0..payload_len]) catch return 1;
return 0;
}