summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobby Zambito <contact@robbyzambito.me>2025-04-23 07:26:39 -0400
committerRobby Zambito <contact@robbyzambito.me>2025-04-23 07:26:41 -0400
commit89bfbe485454ee87712364fab05024cec305aad4 (patch)
treed8c063d2e6c697108ede31a64199bc14151aa8ce
parentfe26cb002db4b7bd9a53265690aba19a54ebe50f (diff)
successfully build c interface
-rw-r--r--build.zig4
-rw-r--r--include/zaprus.h38
-rw-r--r--src/c_api.zig65
3 files changed, 85 insertions, 22 deletions
diff --git a/build.zig b/build.zig
index 6f7f1e4..1708ce0 100644
--- a/build.zig
+++ b/build.zig
@@ -43,6 +43,8 @@ pub fn build(b: *std.Build) void {
.name = "zaprus",
.root_module = lib_mod,
});
+ static_lib.addIncludePath(.{ .cwd_relative = "include" });
+ static_lib.linkLibC();
b.installArtifact(static_lib);
@@ -51,6 +53,8 @@ pub fn build(b: *std.Build) void {
.name = "zaprus",
.root_module = lib_mod,
});
+ dynamic_lib.addIncludePath(.{ .cwd_relative = "include" });
+ dynamic_lib.linkLibC();
b.installArtifact(dynamic_lib);
diff --git a/include/zaprus.h b/include/zaprus.h
index 31fe97c..b442753 100644
--- a/include/zaprus.h
+++ b/include/zaprus.h
@@ -1,24 +1,50 @@
// client
+#include<stdint.h>
+#include<stdlib.h>
+
int zaprus_init(void);
int zaprus_deinit(void);
-int zaprus_send_relay(const char* payload, usize len, char[4] dest);
+int zaprus_send_relay(const char* payload, size_t len, char dest[4]);
-int zaprus_send_initial_connection(const char* payload, usize 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, usize len);
+struct SaprusMessage* 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;
+ union {
+ struct {
+ struct {
+ char dest[4];
+ };
+ char *payload;
+ } relay;
+ struct {
+ struct {
+ uint16_t src_port;
+ uint16_t dest_port;
+ uint32_t seq_num;
+ uint32_t msg_id;
+ char _reserved;
+ char options;
+ };
+ char *payload;
+ } connection;
+ };
};
// ptr should be freed by the caller.
-int zaprus_message_to_bytes(struct SaprusMessage msg, char** ptr, usize* len);
+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, usize len);
+struct SaprusMessage* zaprus_message_from_bytes(const char* bytes, size_t len);
void zaprus_message_deinit(struct SaprusMessage* msg);
diff --git a/src/c_api.zig b/src/c_api.zig
index bb233e0..481dc78 100644
--- a/src/c_api.zig
+++ b/src/c_api.zig
@@ -1,5 +1,28 @@
-// client
+const c = @cImport({
+ @cInclude("zaprus.h");
+});
+
+fn zigToCMessage(msg: ?*zaprus.Message) ?*c.SaprusMessage {
+ if (msg) |m| {
+ return switch (m.*) {
+ .relay => |_| @constCast(&c.SaprusMessage{}),
+ .connection => |_| @constCast(&c.SaprusMessage{}),
+ else => |_| null,
+ };
+ } else return null;
+}
+fn cToZigMessage(msg: ?*c.SaprusMessage) ?*zaprus.Message {
+ _ = msg;
+ return @constCast(&zaprus.Message{
+ .relay = .{
+ .header = .{ .dest = @splat(0) },
+ .payload = &.{0},
+ },
+ });
+}
+
+// client
export fn zaprus_init() c_int {
SaprusClient.init() catch return 1;
return 0;
@@ -10,44 +33,54 @@ export fn zaprus_deinit() c_int {
return 0;
}
-export fn zaprus_send_relay(payload: [*]const u8, len: usize, dest: [4]u8) c_int {
- SaprusClient.sendRelay(payload[0..len], dest, allocator) catch return 1;
+export fn zaprus_send_relay(payload: [*]const u8, len: usize, dest: [*]u8) c_int {
+ SaprusClient.sendRelay(payload[0..len], dest[0..4].*, allocator) catch return 1;
return 0;
}
export fn zaprus_send_initial_connection(payload: [*]const u8, len: usize, initial_port: u16) c_int {
- SaprusClient.sendInitialConnection(payload[0..len], initial_port, allocator) catch return 1;
+ _ = SaprusClient.sendInitialConnection(payload[0..len], initial_port, allocator) catch return 1;
return 0;
}
-export fn zaprus_connect(payload: [*]const u8, len: usize) ?*SaprusMessage {
- return SaprusClient.connect(payload[0..len], allocator) catch null;
+export fn zaprus_connect(payload: [*]const u8, len: usize) ?*c.SaprusMessage {
+ if (SaprusClient.connect(payload[0..len], allocator)) |msg| {
+ return zigToCMessage(@constCast(&(msg.?)));
+ } else |_| {
+ return null;
+ }
}
// message
/// ptr should be freed by the caller.
-export fn zaprus_message_to_bytes(msg: SaprusMessage, ptr: *[*]u8, len: *usize) c_int {
- const bytes = msg.toBytes(allocator) catch return 1;
- ptr.* = bytes[0..].*;
- len.* = bytes.len;
- return 0;
+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) ?*SaprusMessage {
- return SaprusMessage.fromBytes(bytes[0..len], allocator) catch null;
+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));
+ } else |_| return null;
}
-export fn zaprus_message_deinit(msg: *SaprusMessage) void {
- msg.deinit(allocator);
+export fn zaprus_message_deinit(msg: *c.SaprusMessage) void {
+ // noop
+ _ = msg;
+ // msg.*.deinit(allocator);
}
const std = @import("std");
const zaprus = @import("./root.zig");
const SaprusClient = zaprus.Client;
-const SaprusMessage = zaprus.Message;
+// const SaprusMessage = zaprus.Message;
const allocator = std.heap.c_allocator;