diff --git a/.gitignore b/.gitignore index 86d888e..deca2cf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ zig-cache zig-out +.zig-cache docs *.swp diff --git a/README.md b/README.md index f4481e5..b0ccf15 100644 --- a/README.md +++ b/README.md @@ -24,5 +24,6 @@ See the [dedicated repository][examples]. LibIPC reached a stable state and is usable. Performance is fine for most projects, but can be largely improved. +The `poll` syscall is used instead of more recent and *faster* syscalls (`epoll`, `kqueue`, etc.). [examples]: https://git.baguette.netlib.re/Baguette/libipc-examples diff --git a/build.zig b/build.zig index 7d5a3a4..c52268f 100644 --- a/build.zig +++ b/build.zig @@ -1,6 +1,6 @@ const std = @import("std"); -const VERSION = "0.1.2"; +const VERSION = "0.2.0"; // Although this function looks imperative, note that its job is to // declaratively construct a build graph that will be executed by an external diff --git a/ipc.pc b/ipc.pc index efb4bea..84be89e 100644 --- a/ipc.pc +++ b/ipc.pc @@ -3,6 +3,6 @@ libdir=/usr/local/lib Name: LibIPC Description: The simplest Inter Process Communication library -Version: 0.1.2 +Version: 0.2.0 Libs: -L${libdir} -lipc Cflags: -I${includedir} diff --git a/makefile b/makefile index 7db1b37..1572c71 100644 --- a/makefile +++ b/makefile @@ -48,7 +48,7 @@ serve-doc: darkhttpd docs/ --addr $(DOC_HTTPD_ADDR) --port $(DOC_HTTPD_PORT) --log $(DOC_HTTPD_ACCESS_LOGS) PACKAGE ?= libipc -VERSION ?= 0.1.2 +VERSION ?= 0.2.0 PKG = $(PACKAGE)-$(VERSION) dist-dir: [ -d $(PKG) ] || ln -s . $(PKG) diff --git a/src/bindings.zig b/src/bindings.zig index 6e7f924..2b98e43 100644 --- a/src/bindings.zig +++ b/src/bindings.zig @@ -107,7 +107,10 @@ export fn ipc_wait_event(ctx: *Context, t: *u8, index: *usize, originfd: *i32, n var writer = fbs.writer(); _ = writer.write(m.payload) catch return -4; buflen.* = m.payload.len; - m.deinit(); + switch (event.t) { + .SWITCH_RX => {}, + else => m.deinit(), + } } else { buflen.* = 0; } diff --git a/src/context.zig b/src/context.zig index 2210801..5f6c29f 100644 --- a/src/context.zig +++ b/src/context.zig @@ -1,17 +1,11 @@ const std = @import("std"); const testing = std.testing; -// const DEBUG = @import("./hexdump.zig"); const net = std.net; const os = std.os; const fmt = std.fmt; const c = std.c; const posix = std.posix; -// const print = std.debug.print; - -// TODO: to remove once PR https://github.com/ziglang/zig/pull/14639 is accepted. -pub extern "c" fn umask(mode: c.mode_t) c.mode_t; - const log = std.log.scoped(.libipc_context); const receive_fd = @import("./exchange-fd.zig").receive_fd; @@ -35,7 +29,6 @@ pub const PollFD = std.ArrayList(posix.pollfd); pub const IPC_HEADER_SIZE = 4; // Size (4 bytes) then content. pub const IPC_BASE_SIZE = 100000; // 100 KB, plenty enough space for messages pub const IPC_MAX_MESSAGE_SIZE = IPC_BASE_SIZE - IPC_HEADER_SIZE; -pub const IPC_VERSION = 1; // Context of the whole networking state. pub const Context = struct { @@ -66,8 +59,8 @@ pub const Context = struct { }; // Allow mkdir to create a directory with 0o770 permissions. - const previous_mask = umask(0o007); - defer _ = umask(previous_mask); + const previous_mask = c.umask(0o007); + defer _ = c.umask(previous_mask); // Create the run directory, where all UNIX sockets will be. posix.mkdir(rundir, 0o0770) catch |err| switch (err) { @@ -80,7 +73,12 @@ pub const Context = struct { }, }; - return Self{ .rundir = rundir, .connections = Connections.init(allocator), .pollfd = PollFD.init(allocator), .tx = Messages.init(allocator), .switchdb = SwitchDB.init(allocator), .allocator = allocator }; + return Self{ .rundir = rundir + , .connections = Connections.init(allocator) + , .pollfd = PollFD.init(allocator) + , .tx = Messages.init(allocator) + , .switchdb = SwitchDB.init(allocator) + , .allocator = allocator }; } pub fn deinit(self: *Self) void { @@ -264,8 +262,8 @@ pub const Context = struct { // Allow to create a unix socket with the right permissions. // Group should include write permissions. - const previous_mask = umask(0o117); - defer _ = umask(previous_mask); + const previous_mask = c.umask(0o117); + defer _ = c.umask(previous_mask); // Remove the old UNIX socket. posix.unlink(path) catch |err| switch (err) { @@ -297,12 +295,6 @@ pub const Context = struct { _ = try m.write(writer); // returns paylen _ = try stream.write(fbs.getWritten()); - - // var hexbuf: [2000]u8 = undefined; - // var hexfbs = std.io.fixedBufferStream(&hexbuf); - // var hexwriter = hexfbs.writer(); - // try DEBUG.hexdump(hexwriter, "MSG SENT", fbs.getWritten()); - // print("{s}\n", .{hexfbs.getWritten()}); } pub fn schedule(self: *Self, m: Message) !void { diff --git a/src/hexdump.zig b/src/hexdump.zig index 8f21436..f3d970b 100644 --- a/src/hexdump.zig +++ b/src/hexdump.zig @@ -72,6 +72,17 @@ pub fn hexdump(stream: anytype, header: []const u8, buffer: []const u8) std.posi try stream.writeAll("\n"); } +/// Debug function: print some bytes' hexdump on standard output. +pub fn print_hex(title: []const u8, buffer : []const u8) !void +{ + const stdout = std.io.getStdOut().writer(); + var hexbuf: [100_000]u8 = undefined; + var hexfbs = std.io.fixedBufferStream(&hexbuf); + const hexwriter = hexfbs.writer(); + try hexdump(hexwriter, title, buffer); + try stdout.print("{s}\n", .{hexfbs.getWritten()}); +} + const print = std.debug.print; test "36-byte hexdump test" { diff --git a/src/message.zig b/src/message.zig index 1bc5f08..2e18e8b 100644 --- a/src/message.zig +++ b/src/message.zig @@ -5,6 +5,7 @@ const fmt = std.fmt; const print_eq = @import("./util.zig").print_eq; +const payload_header_length = 4; pub const Messages = std.ArrayList(Message); pub const Message = struct { @@ -28,17 +29,17 @@ pub const Message = struct { var reader = fbs.reader(); const msg_len = try reader.readInt(u32, .big); - if (msg_len > buffer.len - 4) { + if (msg_len > buffer.len - payload_header_length) { return error.wrongMessageLength; } - const msg_payload = buffer[4 .. 4 + msg_len]; + const msg_payload = buffer[payload_header_length .. payload_header_length + msg_len]; return try Message.init(fd, allocator, msg_payload); } pub fn write(self: Self, writer: anytype) !usize { try writer.writeInt(u32, @as(u32, @truncate(self.payload.len)), .big); - return 4 + try writer.write(self.payload); + return payload_header_length + try writer.write(self.payload); } pub fn format(self: Self, comptime _: []const u8, _: fmt.FormatOptions, out_stream: anytype) !void { diff --git a/src/switch.zig b/src/switch.zig index 9d13594..6cdf4e0 100644 --- a/src/switch.zig +++ b/src/switch.zig @@ -40,10 +40,12 @@ pub const SwitchDB = struct { const Self = @This(); db: std.AutoArrayHashMap(i32, ManagedConnection), + allocator: std.mem.Allocator, pub fn init(allocator: Allocator) Self { return Self{ .db = std.AutoArrayHashMap(i32, ManagedConnection).init(allocator), + .allocator = allocator, }; } @@ -87,9 +89,10 @@ pub const SwitchDB = struct { }, CBEventType.NO_ERROR => { // TODO: read message - // TODO: better allocator? // TODO: better errors? - const message: Message = Message.read(managedconnection.dest, buffer[0..message_size], std.heap.c_allocator) catch { + const message: Message = Message.read(managedconnection.dest + , buffer[0..message_size] + , self.allocator) catch { return error.generic; }; return message;