9 Commits

Author SHA1 Message Date
87c9d921d4 startiing to clean up c api 2025-04-30 17:04:32 -04:00
f212454dfb Big changes to the C api implementations
Should map directly to the zig struct instead of mallocing
2025-04-27 18:03:06 -04:00
983544facf Add C to Zig converter
Further simplify struct
2025-04-27 18:03:06 -04:00
67818ed9d6 Make C struct match the binary API more closely
Also make the internal conversion function return errors properly
2025-04-27 18:03:06 -04:00
d459dd60ef Convert from Zig struct to C struct 2025-04-27 18:03:06 -04:00
ce21b94a43 use InstallHeader function to install the header 2025-04-27 18:03:06 -04:00
c0e466b28a successfully build c interface 2025-04-27 18:03:06 -04:00
ee6062334b Initial C api 2025-04-27 18:03:06 -04:00
683a2015b0 Use FAIL as the default dest if unable to parse 2025-04-27 18:03:06 -04:00
4 changed files with 9 additions and 128 deletions

View File

@@ -11,41 +11,5 @@ int zaprus_send_relay(const char* payload, size_t len, char dest[4]);
int zaprus_send_initial_connection(const char* payload, size_t len, uint16_t initial_port); int zaprus_send_initial_connection(const char* payload, size_t len, uint16_t initial_port);
struct SaprusMessage* zaprus_connect(const char* payload, size_t len); void* zaprus_connect(const char* payload, size_t len);
// message
#define SAPRUS_RELAY_MESSAGE_TYPE 0x003C
#define SAPRUS_FILE_TRANSFER_MESSAGE_TYPE 0x8888
#define SAPRUS_CONNECTION_MESSAGE_TYPE 0x00E9
struct SaprusMessage {
uint16_t packet_type;
uint16_t payload_len;
union {
struct {
struct {
char dest[4];
};
} relay;
struct {
struct {
uint16_t src_port;
uint16_t dest_port;
uint32_t seq_num;
uint32_t msg_id;
char _reserved;
char options;
};
} connection;
} headers;
char *payload;
};
// ptr should be freed by the caller.
int zaprus_message_to_bytes(struct SaprusMessage msg, char** ptr, size_t* len);
// Return value should be destroyed with zaprus_message_deinit.
struct SaprusMessage* zaprus_message_from_bytes(const char* bytes, size_t len);
void zaprus_message_deinit(struct SaprusMessage* msg);

View File

@@ -76,7 +76,7 @@ pub fn sendInitialConnection(payload: []const u8, initial_port: u16, allocator:
return msg; return msg;
} }
pub fn connect(payload: []const u8, allocator: Allocator) !?SaprusMessage { pub fn connect(payload: []const u8, allocator: Allocator) !SaprusMessage {
var initial_port: u16 = 0; var initial_port: u16 = 0;
if (rand) |r| { if (rand) |r| {
initial_port = r.intRangeAtMost(u16, 1024, 65000); initial_port = r.intRangeAtMost(u16, 1024, 65000);
@@ -109,7 +109,7 @@ pub fn connect(payload: []const u8, allocator: Allocator) !?SaprusMessage {
// Complete handshake after awaiting response // Complete handshake after awaiting response
try broadcastSaprusMessage(msg, randomPort(), allocator); try broadcastSaprusMessage(msg, randomPort(), allocator);
return initial_conn_res; return initial_conn_res.?;
} }
const SaprusMessage = @import("message.zig").Message; const SaprusMessage = @import("message.zig").Message;

View File

@@ -1,54 +1,3 @@
const c = @cImport({
@cInclude("zaprus.h");
});
fn zigToCMessage(msg: ?*zaprus.Message) !?*c.SaprusMessage {
if (msg) |m| {
var res = c.SaprusMessage{
.packet_type = @intFromEnum(m.*),
};
switch (m.*) {
.relay => |r| {
res.headers.relay = .{
.unnamed_0 = .{
.dest = r.header.dest,
},
};
res.payload_len = @intCast(r.payload.len);
res.payload = (try allocator.alloc(u8, r.payload.len)).ptr;
},
.connection => |con| {
res.headers.connection = .{
.unnamed_0 = .{
.src_port = con.header.src_port,
.dest_port = con.header.dest_port,
.seq_num = con.header.seq_num,
.msg_id = con.header.msg_id,
._reserved = con.header.reserved,
.options = @bitCast(con.header.options),
},
};
res.payload_len = @intCast(con.payload.len);
res.payload = (try allocator.alloc(u8, con.payload.len)).ptr;
},
.file_transfer => return zaprus.Error.NotImplementedSaprusType,
else => return zaprus.Error.UnknownSaprusType,
}
return &res;
} else return null;
}
fn cToZigMessage(msg: ?*c.SaprusMessage) ?*zaprus.Message {
_ = msg;
return @constCast(&zaprus.Message{
.relay = .{
.header = .{ .dest = @splat(0) },
.payload = &.{0},
},
});
}
// client // client
export fn zaprus_init() c_int { export fn zaprus_init() c_int {
SaprusClient.init() catch return 1; SaprusClient.init() catch return 1;
@@ -65,48 +14,16 @@ export fn zaprus_send_relay(payload: [*]const u8, len: usize, dest: [*]u8) c_int
return 0; return 0;
} }
export fn zaprus_send_initial_connection(payload: [*]const u8, len: usize, initial_port: u16) c_int { export fn zaprus_connect(payload: [*]const u8, len: usize, output: *SaprusConnection) c_int {
_ = SaprusClient.sendInitialConnection(payload[0..len], initial_port, allocator) catch return 1; output.* = (SaprusClient.connect(payload[0..len], allocator) catch return 1).?;
return 0; return 0;
} }
export fn zaprus_connect(payload: [*]const u8, len: usize) ?*c.SaprusMessage {
if (SaprusClient.connect(payload[0..len], allocator)) |msg| {
return zigToCMessage(@constCast(&(msg.?))) catch null;
} else |_| {
return null;
}
}
// message
/// ptr should be freed by the caller.
export fn zaprus_message_to_bytes(msg: c.SaprusMessage, ptr: *[*]u8, len: *usize) c_int {
if (cToZigMessage(@constCast(&msg))) |m| {
const bytes = m.toBytes(allocator) catch return 1;
ptr.* = bytes.ptr;
len.* = bytes.len;
return 0;
} else return 1;
}
/// Return value should be destroyed with zaprus_message_deinit.
export fn zaprus_message_from_bytes(bytes: [*]const u8, len: usize) ?*c.SaprusMessage {
if (zaprus.Message.fromBytes(bytes[0..len], allocator)) |msg| {
return zigToCMessage(@constCast(&msg)) catch null;
} else |_| return null;
}
export fn zaprus_message_deinit(msg: *c.SaprusMessage) void {
// noop
_ = msg;
// msg.*.deinit(allocator);
}
const std = @import("std"); const std = @import("std");
const zaprus = @import("./root.zig"); const zaprus = @import("./root.zig");
const SaprusClient = zaprus.Client; const SaprusClient = zaprus.Client;
const SaprusConnection = zaprus.Connection;
const allocator = std.heap.c_allocator; const allocator = std.heap.c_allocator;

View File

@@ -75,7 +75,7 @@ pub fn main() !void {
return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{}); return clap.help(std.io.getStdErr().writer(), clap.Help, &params, .{});
} }
fn parseDest(in: ?[]const u8) ![4]u8 { fn parseDest(in: ?[]const u8) [4]u8 {
if (in) |dest| { if (in) |dest| {
if (dest.len <= 4) { if (dest.len <= 4) {
var res: [4]u8 = @splat(0); var res: [4]u8 = @splat(0);
@@ -83,10 +83,10 @@ fn parseDest(in: ?[]const u8) ![4]u8 {
return res; return res;
} }
const addr = try std.net.Ip4Address.parse(dest, 0); const addr = std.net.Ip4Address.parse(dest, 0) catch return "FAIL".*;
return @bitCast(addr.sa.addr); return @bitCast(addr.sa.addr);
} }
return .{ 70, 70, 70, 70 }; return "zap".*;
} }
const builtin = @import("builtin"); const builtin = @import("builtin");