diff --git a/zig-impl/makefile b/zig-impl/makefile index 6f8bba1..3fd030c 100644 --- a/zig-impl/makefile +++ b/zig-impl/makefile @@ -1,24 +1,24 @@ all: -ZIGBUSEOPTS ?= -OReleaseSmall -ZIGUSROPTS ?= -freference-trace +ZIGMAKEDOC = -femit-docs -fno-emit-bin +ZIGOPTIM ?= Debug +ZIGBUSEOPTS ?= -O$(ZIGOPTIM) -freference-trace +ZIGUSROPTS ?= ZIGC ?= zig ZIGOPTS ?= $(ZIGBUSEOPTS) $(ZIGUSROPTS) -c: src/send-msg.zig +ipcd: src/ipcd.zig $(ZIGC) build-exe $(ZIGOPTS) $^ -s: src/receive-msg.zig - $(ZIGC) build-exe $(ZIGOPTS) $^ - -m: src/main.zig - $(ZIGC) build-exe $(ZIGOPTS) $^ - -t: src/main.zig +test-libipc: src/main.zig $(ZIGC) test $(ZIGOPTS) $^ -d: src/main.zig - $(ZIGC) build-exe $(ZIGOPTS) $^ - -o: $(SRC) +test-ipcd: src/ipcd.zig $(ZIGC) test $(ZIGOPTS) $^ + +doc: src/ipcd.zig + $(ZIGC) build-exe $(ZIGOPTS) $(ZIGMAKEDOC) $^ + + +# You can add your specific instructions there. +-include makefile.user diff --git a/zig-impl/src/connection.zig b/zig-impl/src/connection.zig index 122e399..0344f09 100644 --- a/zig-impl/src/connection.zig +++ b/zig-impl/src/connection.zig @@ -39,7 +39,6 @@ pub const Connection = struct { pub fn deinit(self: *Self) void { if (self.server) |*s| { s.deinit(); } - if (self.client) |*c| { c.deinit(); } } pub fn format(self: Self, comptime _: []const u8, _: fmt.FormatOptions, out_stream: anytype) !void { diff --git a/zig-impl/src/context.zig b/zig-impl/src/context.zig index 4b0fb83..9a4dfe4 100644 --- a/zig-impl/src/context.zig +++ b/zig-impl/src/context.zig @@ -370,7 +370,6 @@ pub const Context = struct { c.stream.close(); } var pollfd = self.pollfd.swapRemove(index); - print("client at index {} removed\n", .{index}); // Remove all its non-sent messages. var i: usize = 0; @@ -380,7 +379,6 @@ pub const Context = struct { if (self.tx.items[i].fd == pollfd.fd) { var m = self.tx.swapRemove(i); - print("Removing message targeted to client {}: {}\n", .{index, m}); m.deinit(); continue; } @@ -475,7 +473,13 @@ test "Context - creation, display and memory check" { var path = fbs.getWritten(); // SERVER SIDE: creating a service. - var server = try c.server_init(path); + var server = c.server_init(path) catch |err| switch(err) { + error.FileNotFound => { + print ("\nError: cannot init server at {s}\n", .{path}); + return err; + }, + else => return err, + }; defer server.deinit(); defer std.fs.cwd().deleteFile(path) catch {}; // Once done, remove file. @@ -549,7 +553,13 @@ const ConnectThenSendMessageThread = struct { var path = fbs.getWritten(); // SERVER SIDE: creating a service. - var server = try c.server_init(path); + var server = c.server_init(path) catch |err| switch(err) { + error.FileNotFound => { + print ("\nError: cannot init server at {s}\n", .{path}); + return err; + }, + else => return err, + }; defer server.deinit(); defer std.fs.cwd().deleteFile(path) catch {}; // Once done, remove file. @@ -561,7 +571,7 @@ const ConnectThenSendMessageThread = struct { defer client.stream.close(); var buf: [1000]u8 = undefined; const n = try client.stream.reader().read(&buf); - var m = try Message.read(buf[0..n], allocator); + var m = try Message.read(8, buf[0..n], allocator); // 8 == random client's fd number defer m.deinit(); try testing.expectEqual(@as(usize, 12), m.payload.len); diff --git a/zig-impl/src/event.zig b/zig-impl/src/event.zig index ba190c3..e043081 100644 --- a/zig-impl/src/event.zig +++ b/zig-impl/src/event.zig @@ -91,7 +91,7 @@ test "Event - creation and display" { var s = "hello!!"; var m = try Message.init(1, Message.Type.DATA, allocator, s); // fd type payload defer m.deinit(); - var e = Event.init(Event.Type.CONNECTION, 5, 8, &m); // type index origin message + var e = Event.init(Event.Type.CONNECTION, 5, 8, m); // type index origin message try print_eq("event.Event.Type.CONNECTION, origin: 8, index 5, message: [fd: 1, message.Message.Type.DATA, payload: [hello!!]]", e); } diff --git a/zig-impl/src/ipcd.zig b/zig-impl/src/ipcd.zig new file mode 100644 index 0000000..18220d3 --- /dev/null +++ b/zig-impl/src/ipcd.zig @@ -0,0 +1,108 @@ +const std = @import("std"); +const hexdump = @import("./hexdump.zig"); +const net = std.net; +const fmt = std.fmt; + +const ipc = @import("./main.zig"); + +const print = std.debug.print; +const testing = std.testing; +const print_eq = @import("./util.zig").print_eq; + +// TODO: file descriptors should have a specific type (but i32 is used in std.net...). + +// TODO: path => std.XXX.YYY, not simple [] const u8 + +// TODO: both Connection and pollfd store file descriptors. +// Connection stores either Stream (server) or Address (client). + +// TODO: API should completely obfuscate the inner structures. +// Only structures in this file should be necessary. + +var should_quit: bool = false; + +fn create_service() !void { + const config = .{.safety = true}; + var gpa = std.heap.GeneralPurposeAllocator(config){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + var ctx = try ipc.Context.init(allocator); + defer ctx.deinit(); // There. Can't leak. Isn't Zig wonderful? + + const path = "/tmp/.TEST_USOCK"; + + // SERVER SIDE: creating a service. + _ = try ctx.server_init(path); + + // TODO: signal handler, to quit when asked + + var some_event: ipc.Event = undefined; + ctx.timer = 2000; // 1 second + while(true) { + some_event = try ctx.wait_event(); + switch (some_event.t) { + .CONNECTION => { + print("New connection: {}!\n", .{some_event}); + }, + .TIMER => { + print("Timer!\n", .{}); + }, + .EXTERNAL => { + print("Message received from a non IPC socket.\n", .{}); + print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{}); + break; + }, + .SWITCH => { + print("Message to send to a corresponding fd.\n", .{}); + print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{}); + break; + }, + .DISCONNECTION => { + print("User disconnected.\n", .{}); + }, + .MESSAGE => { + print("New message. {}\n", .{some_event}); + print("Let's echo, once\n", .{}); + if (some_event.m) |m| { + try ctx.schedule(m); + } + }, + .LOOKUP => { + print("Client asking for a service through ipcd.\n", .{}); + print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{}); + break; + }, + .TX => { + print("Message sent.\n", .{}); + }, + .NOT_SET => { + print("Event type not set. Something is wrong, let's suicide.\n", .{}); + break; + }, + .ERROR => { + print("A problem occured, event: {}, let's suicide\n", .{some_event}); + break; + }, + } + + if (should_quit) { + break; + } + } + + + // Server.accept returns a net.Connection (handle = fd, addr = net.Address). + // var client = try server.accept(); + // var buf: [4096]u8 = undefined; + // const n = try ctx.read_ (client, &buf); + + // print("new client: {}\n", .{client}); + // print("{} bytes: {s}\n", .{n, buf}); + print("End the create_service function\n", .{}); +} + +pub fn main() !u8 { + try create_service(); + return 0; +} diff --git a/zig-impl/src/main.zig b/zig-impl/src/main.zig index d74504c..dd18019 100644 --- a/zig-impl/src/main.zig +++ b/zig-impl/src/main.zig @@ -1,32 +1,13 @@ -const std = @import("std"); -const hexdump = @import("./hexdump.zig"); -const testing = std.testing; -const net = std.net; -const fmt = std.fmt; +pub const CBEvent = @import("./callback.zig").CBEvent; +pub const Connection = @import("./connection.zig").Connection; +pub const Message = @import("./message.zig").Message; +pub const Event = @import("./event.zig").Event; +pub const Switch = @import("./switch.zig").Switch; -// TODO: file descriptors should have a specific type (but i32 is used in std.net...). - -// TODO: path => std.XXX.YYY, not simple [] const u8 - -// TODO: both Connection and pollfd store file descriptors. -// Connection stores either Stream (server) or Address (client). - -// TODO: API should completely obfuscate the inner structures. -// Only structures in this file should be necessary. - -const CBEvent = @import("./callback.zig").CBEvent; -const Connection = @import("./connection.zig").Connection; -const Message = @import("./message.zig").Message; -const Event = @import("./event.zig").Event; -const Switch = @import("./switch.zig").Switch; -const print_eq = @import("./util.zig").print_eq; - -const print = std.debug.print; - -const Messages = @import("./message.zig").Messages; -const Switches = @import("./switch.zig").Switches; -const Connections = @import("./connection.zig").Connections; -const Context = @import("./context.zig").Context; +pub const Messages = @import("./message.zig").Messages; +pub const Switches = @import("./switch.zig").Switches; +pub const Connections = @import("./connection.zig").Connections; +pub const Context = @import("./context.zig").Context; test { _ = @import("./callback.zig"); @@ -38,90 +19,3 @@ test { _ = @import("./util.zig"); } -var should_quit: bool = false; - -fn create_service() !void { - const config = .{.safety = true}; - var gpa = std.heap.GeneralPurposeAllocator(config){}; - defer _ = gpa.deinit(); - const allocator = gpa.allocator(); - - var ctx = try Context.init(allocator); - defer ctx.deinit(); // There. Can't leak. Isn't Zig wonderful? - - const path = "/tmp/.TEST_USOCK"; - - // SERVER SIDE: creating a service. - _ = try ctx.server_init(path); - - // TODO: signal handler, to quit when asked - - var some_event: Event = undefined; - ctx.timer = 2000; // 1 second - while(true) { - some_event = try ctx.wait_event(); - switch (some_event.t) { - .CONNECTION => { - print("New connection: {}!\n", .{some_event}); - }, - .TIMER => { - print("Timer!\n", .{}); - }, - .EXTERNAL => { - print("Message received from a non IPC socket.\n", .{}); - print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{}); - break; - }, - .SWITCH => { - print("Message to send to a corresponding fd.\n", .{}); - print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{}); - break; - }, - .DISCONNECTION => { - print("User disconnected.\n", .{}); - }, - .MESSAGE => { - print("New message. {}\n", .{some_event}); - print("Let's echo, once\n", .{}); - if (some_event.m) |m| { - try ctx.schedule(m); - } - }, - .LOOKUP => { - print("Client asking for a service through ipcd.\n", .{}); - print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{}); - break; - }, - .TX => { - print("Message sent.\n", .{}); - }, - .NOT_SET => { - print("Event type not set. Something is wrong, let's suicide.\n", .{}); - break; - }, - .ERROR => { - print("A problem occured, event: {}, let's suicide\n", .{some_event}); - break; - }, - } - - if (should_quit) { - break; - } - } - - - // Server.accept returns a net.Connection (handle = fd, addr = net.Address). - // var client = try server.accept(); - // var buf: [4096]u8 = undefined; - // const n = try ctx.read_ (client, &buf); - - // print("new client: {}\n", .{client}); - // print("{} bytes: {s}\n", .{n, buf}); - print("End the create_service function\n", .{}); -} - -pub fn main() !u8 { - try create_service(); - return 0; -} diff --git a/zig-impl/src/message.zig b/zig-impl/src/message.zig index ff31bf0..ad444b5 100644 --- a/zig-impl/src/message.zig +++ b/zig-impl/src/message.zig @@ -123,7 +123,8 @@ test "Message - read and write" { var second_allocator = fba.allocator(); // Read the buffer, similar to receiving a message on the network. - var second_message = try Message.read(buffer[0..count], second_allocator); + // (8 == random client's fd number) + var second_message = try Message.read(8, buffer[0..count], second_allocator); // var second_message = try Message.read(fbs.getWritten(), second_allocator); defer second_message.deinit();