commit ea0f36da8cc34b10866763847ef2ce4b47a70fd8
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date: Wed, 29 Jan 2025 15:22:17 +0100
add initial commit
Diffstat:
3 files changed, 107 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1,3 @@
+zig-out
+.zig-cache
+zls.build.json
diff --git a/build.zig b/build.zig
@@ -0,0 +1,42 @@
+const std = @import("std");
+
+pub fn build(b: *std.Build) !void {
+ const gnunet_prefix = b.option(
+ []const u8,
+ "gnunet-prefix",
+ "Path to GNUnet",
+ ) orelse "/usr/local";
+ // FIXME parse the below with a separator?
+ const additional_include_paths = b.option(
+ []const u8,
+ "additional-include-paths",
+ "Path to additional includes",
+ ) orelse "";
+ const additional_lib_paths = b.option(
+ []const u8,
+ "additional-lib-paths",
+ "Path to additional libs",
+ ) orelse "";
+
+ const exe = b.addExecutable(.{
+ .name = "gnunet-zig-identity",
+ .root_source_file = b.path("src/gnunet.zig"),
+ .target = b.standardTargetOptions(.{}),
+ .optimize = b.standardOptimizeOption(.{}),
+ .strip = true,
+ });
+ // create our general purpose allocator
+ var gpa = std.heap.GeneralPurposeAllocator(.{}){};
+
+ // get an std.mem.Allocator from it
+ const allocator = gpa.allocator();
+ const gnunet_include_path = try std.fmt.allocPrint(allocator, "{s}/include", .{gnunet_prefix});
+ const gnunet_lib_path = try std.fmt.allocPrint(allocator, "{s}/lib", .{gnunet_prefix});
+ exe.addIncludePath(.{ .cwd_relative = gnunet_include_path });
+ exe.addLibraryPath(.{ .cwd_relative = gnunet_lib_path });
+ exe.addIncludePath(.{ .cwd_relative = additional_include_paths });
+ exe.addLibraryPath(.{ .cwd_relative = additional_lib_paths });
+ exe.linkSystemLibrary("gnunetutil");
+ exe.linkSystemLibrary("gnunetidentity");
+ b.installArtifact(exe);
+}
diff --git a/src/gnunet.zig b/src/gnunet.zig
@@ -0,0 +1,62 @@
+// Author: Martin Schanzenbach; License: AGPL3+
+
+const gnunet = @cImport({
+ @cInclude("gnunet/gnunet_util_lib.h");
+ @cInclude("gnunet/gnunet_identity_service.h");
+});
+
+const std = @import("std");
+const print = std.debug.print;
+
+var id_svc: ?*gnunet.GNUNET_IDENTITY_Handle = undefined;
+
+pub fn do_shutdown(cls: ?*anyopaque) callconv(.C) void {
+ _ = cls;
+ gnunet.GNUNET_IDENTITY_disconnect(id_svc);
+}
+
+pub fn id_cb(cls: ?*anyopaque, ego: ?*gnunet.GNUNET_IDENTITY_Ego, ctx: [*c]?*anyopaque, name: [*c]const u8) callconv(.C) void {
+ _ = ctx;
+ _ = cls;
+ if (ego == null and name != null) {
+ // Unreachable only in this demo, I think!
+ unreachable;
+ }
+ if (ego == null) { // last iteration
+ gnunet.GNUNET_SCHEDULER_shutdown();
+ return;
+ }
+ // Remove to see fancy error
+ if (name == null) {
+ return;
+ }
+ var pk: gnunet.GNUNET_CRYPTO_PublicKey = .{};
+ gnunet.GNUNET_IDENTITY_ego_get_public_key(ego, &pk);
+ const pk_str = gnunet.GNUNET_CRYPTO_public_key_to_string(&pk);
+ defer std.c.free(pk_str);
+ std.debug.print("{s} - {s}\n", .{ name, pk_str });
+}
+
+pub fn run(cls: ?*anyopaque, args: [*c]const [*c]u8, cfgfile: [*c]const u8, cfg: ?*const gnunet.GNUNET_CONFIGURATION_Handle) callconv(.C) void {
+ // Explicit discard, C compiler usually only warns, zig errors out!
+ _ = cfgfile;
+ _ = args;
+ _ = cls;
+ // This does a lot of stuff internally, opening UDS, sending/receiving messages etc.
+ id_svc = gnunet.GNUNET_IDENTITY_connect(@constCast(cfg), id_cb, null);
+ _ = gnunet.GNUNET_SCHEDULER_add_shutdown(do_shutdown, null);
+ return;
+}
+
+pub fn main() !u8 {
+ const options: [*c]const gnunet.GNUNET_GETOPT_CommandLineOption = &.{};
+ const argv = std.os.argv;
+ const c_ptr: [*c][*c]u8 = @ptrCast(argv.ptr);
+
+ // Start GNUnet shenanigans (including scheduler)
+ const ret = gnunet.GNUNET_PROGRAM_run(gnunet.GNUNET_OS_project_data_gnunet(), @intCast(std.os.argv.len), c_ptr, "gnunet-zig", "Gnunet zig demo", options, &run, null);
+ if (ret != gnunet.GNUNET_OK)
+ return 1;
+ return 0;
+ //try stdout.writeAll(res);
+}