gnunet-zig

GNUnet Bindings for Zig
Log | Files | Refs | README

commit ea0f36da8cc34b10866763847ef2ce4b47a70fd8
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Wed, 29 Jan 2025 15:22:17 +0100

add initial commit

Diffstat:
A.gitignore | 3+++
Abuild.zig | 42++++++++++++++++++++++++++++++++++++++++++
Asrc/gnunet.zig | 62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
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); +}