Archived
3
0
This repository has been archived on 2024-06-18. You can view files and clone it, but cannot push or open issues or pull requests.
libipc-old/zig-impl/src/ipcd.zig

200 lines
7.0 KiB
Zig
Raw Normal View History

2022-12-27 22:39:23 +01:00
const std = @import("std");
const hexdump = @import("./hexdump.zig");
const net = std.net;
const fmt = std.fmt;
2022-12-29 12:16:12 +01:00
const os = std.os;
2022-12-27 22:39:23 +01:00
const ipc = @import("./main.zig");
2023-01-03 10:56:01 +01:00
const Message = ipc.Message;
// Import send_fd this way in order to produce docs for exchange-fd functions.
const exchange_fd = @import("./exchange-fd.zig");
const send_fd = exchange_fd.send_fd;
2022-12-27 22:39:23 +01:00
2022-12-29 12:16:12 +01:00
const builtin = @import("builtin");
const native_os = builtin.target.os.tag;
2022-12-27 22:39:23 +01:00
const print = std.debug.print;
const testing = std.testing;
const print_eq = @import("./util.zig").print_eq;
2022-12-29 10:12:40 +01:00
// TODO: standard library is unecessary complex regarding networking.
// Should libipc drop it and use plain old file descriptors instead?
2022-12-27 22:39:23 +01:00
// 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.
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?
// SERVER SIDE: creating a service.
2023-01-03 18:18:16 +01:00
_ = try ctx.server_init("ipcd");
2022-12-27 22:39:23 +01:00
2022-12-29 12:16:12 +01:00
// signal handler, to quit when asked
const S = struct {
var should_quit: bool = false;
fn handler(sig: i32, info: *const os.siginfo_t, _: ?*const anyopaque) callconv(.C) void {
print ("A signal has been received: {}\n", .{sig});
// Check that we received the correct signal.
switch (native_os) {
.netbsd => {
if (sig != os.SIG.HUP or sig != info.info.signo)
return;
},
else => {
if (sig != os.SIG.HUP and sig != info.signo)
return;
},
}
should_quit = true;
}
};
var sa = os.Sigaction{
.handler = .{ .sigaction = &S.handler },
.mask = os.empty_sigset, // Do not mask any signal.
.flags = os.SA.SIGINFO,
};
// Quit on SIGHUP (kill -1).
try os.sigaction(os.SIG.HUP, &sa, null);
2022-12-27 22:39:23 +01:00
var some_event: ipc.Event = undefined;
2022-12-29 12:16:12 +01:00
ctx.timer = 10000; // 10 seconds
var count: u32 = 0;
2022-12-29 12:16:12 +01:00
while(! S.should_quit) {
2022-12-27 22:39:23 +01:00
some_event = try ctx.wait_event();
switch (some_event.t) {
.TIMER => {
print("\rTimer! ({})", .{count});
count += 1;
2022-12-27 22:39:23 +01:00
},
2022-12-29 10:12:40 +01:00
.CONNECTION => {
print("New connection: {} so far!\n", .{ctx.pollfd.items.len});
},
.DISCONNECTION => {
print("User {} disconnected, {} remainaing.\n"
, .{some_event.origin, ctx.pollfd.items.len});
},
2022-12-27 22:39:23 +01:00
.EXTERNAL => {
print("Message received from a non IPC socket.\n", .{});
print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{});
break;
},
2022-12-29 10:12:40 +01:00
2022-12-27 22:39:23 +01:00
.SWITCH => {
print("Message to send to a corresponding fd.\n", .{});
print("NOT IMPLEMENTED, YET. It's a suicide, then.\n", .{});
break;
},
2022-12-29 10:12:40 +01:00
2022-12-27 22:39:23 +01:00
.MESSAGE => {
if (some_event.m) |m| {
2022-12-29 10:12:40 +01:00
print("New message: {}\n", .{m});
print("Let's echo it...\n", .{});
2022-12-27 22:39:23 +01:00
try ctx.schedule(m);
}
2022-12-29 10:12:40 +01:00
else {
print("Error while receiving new message.\n", .{});
print("Ignoring...\n", .{});
}
2022-12-27 22:39:23 +01:00
},
2022-12-29 10:12:40 +01:00
2022-12-27 22:39:23 +01:00
.LOOKUP => {
print("Client asking for a service through ipcd.\n", .{});
2023-01-03 10:56:01 +01:00
if (some_event.m) |m| {
print("Message: {}\n", .{m});
2023-01-03 10:56:01 +01:00
// 1. split message
print("payload is: {s}\n", .{m.payload});
var iterator = std.mem.split(u8, m.payload, ";");
var service_to_contact = iterator.first();
print("service to contact: {s}\n", .{service_to_contact});
var final_destination: ?[]const u8 = null;
2023-01-03 10:56:01 +01:00
// 2. find relevant part of the message
while (iterator.next()) |next| {
print("next part: {s}\n", .{next});
var iterator2 = std.mem.split(u8, next, " ");
var sname = iterator2.first();
var target = iterator2.next();
if (target) |t| {
print ("sname: {s} - target: {s}\n", .{sname, t});
if (std.mem.eql(u8, service_to_contact, sname)) {
final_destination = t;
}
}
else {
print("ERROR: no target in: {s}\n", .{next});
}
}
// 3. connect whether asked to and send a message
// TODO: currently only switching with other UNIX sockets ^^'.
// Should include TCP connections in a near future.
if (final_destination) |dest| {
print("service IPCd should contact for the client: {s}, via {s}\n"
, .{service_to_contact, dest});
var newfd = try ctx.connect_service (dest);
send_fd (some_event.origin, "ok", newfd);
print("fd sent\n" , .{});
try ctx.close_fd (some_event.origin);
print("FD 1 removed\n" , .{});
try ctx.close_fd (newfd);
print("FDs removed\n" , .{});
}
m.deinit();
2023-01-03 10:56:01 +01:00
}
else {
// There is a problem: ipcd was contacted without providing
// a message, meaning there is nothing to do. This should be
// explicitely warned about.
2023-01-03 18:18:16 +01:00
var response = try Message.init(some_event.origin
2023-01-03 10:56:01 +01:00
, Message.Type.ERROR
, allocator
, "lookup message without data");
2023-01-03 18:18:16 +01:00
try ctx.write(response);
response.deinit();
2023-01-03 10:56:01 +01:00
}
2022-12-27 22:39:23 +01:00
},
2022-12-29 10:12:40 +01:00
2022-12-27 22:39:23 +01:00
.TX => {
print("Message sent.\n", .{});
},
2022-12-29 10:12:40 +01:00
2022-12-27 22:39:23 +01:00
.NOT_SET => {
print("Event type not set. Something is wrong, let's suicide.\n", .{});
break;
},
2022-12-29 10:12:40 +01:00
2022-12-27 22:39:23 +01:00
.ERROR => {
print("A problem occured, event: {}, let's suicide\n", .{some_event});
break;
},
}
}
2022-12-29 12:16:12 +01:00
print("Goodbye\n", .{});
2022-12-27 22:39:23 +01:00
}
pub fn main() !u8 {
try create_service();
return 0;
}