| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- const std = @import("std");
- const net = std.net;
- const posix = std.posix;
- const fmt = std.fmt;
- const socket = @import("socket.zig");
- const command = @import("command.zig");
- const storage = @import("storage.zig");
- const persistence = @import("persistence.zig");
- const PORT = 8085;
- var should_exit = std.atomic.Value(bool).init(false);
- fn handleSignal(sig: c_int) callconv(.c) void {
- _ = sig;
- should_exit.store(true, .seq_cst);
- }
- pub fn main() !void {
- const empty_mask = std.mem.zeroes(posix.sigset_t);
- const act = posix.Sigaction{
- .handler = .{ .handler = handleSignal },
- .mask = empty_mask,
- .flags = 0,
- };
- _ = posix.sigaction(posix.SIG.TERM, &act, null);
- _ = posix.sigaction(posix.SIG.INT, &act, null);
- const listener = try socket.init(PORT);
- defer posix.close(listener);
- std.debug.print("2025 pizzakv! TCP Listening on port {any}\n<danilo@fragoso.dev>\n---------\n", .{PORT});
- std.debug.print("Commands:\n\nread key\nwrite key|value\ndelete key\nkeys\nreads prefix\nstatus\n", .{});
- std.debug.print("---------\n", .{});
- storage.init();
- try persistence.init();
- while (!should_exit.load(.seq_cst)) {
- var poll_fds = [_]posix.pollfd{
- .{
- .fd = listener,
- .events = posix.POLL.IN,
- .revents = 0,
- },
- };
- const ready = posix.poll(&poll_fds, 1000) catch |err| {
- if (should_exit.load(.seq_cst)) break;
- std.debug.print("poll error: {any}\n", .{err});
- continue;
- };
- if (ready == 0) {
- continue;
- }
- if (should_exit.load(.seq_cst)) break;
- var client_address: net.Address = undefined;
- var client_address_len: posix.socklen_t = @sizeOf(net.Address);
- const conn = posix.accept(listener, &client_address.any, &client_address_len, 0) catch |err| {
- if (should_exit.load(.seq_cst)) break;
- std.debug.print("error accept: {any}\n", .{err});
- continue;
- };
- if (should_exit.load(.seq_cst)) {
- posix.close(conn);
- break;
- }
- posix.setsockopt(conn, posix.IPPROTO.TCP, posix.TCP.NODELAY, &std.mem.toBytes(@as(c_int, 1))) catch {};
- const thread = try std.Thread.spawn(.{}, handleConnection, .{conn});
- thread.detach();
- }
- std.debug.print("\nShutdown signal received...\n", .{});
- persistence.flush() catch |err| {
- std.debug.print("Failed to flush persistence: {any}\n", .{err});
- };
- }
- pub fn handleConnection(conn: posix.socket_t) !void {
- defer posix.close(conn);
- var requestBuffer: [1024 * 1024]u8 = undefined;
- while (true) {
- const n = socket.readUntilCR(conn, &requestBuffer) catch |err| {
- if (err == error.ConnectionClosed) break;
- return err;
- };
- if (n == 0) {
- break;
- }
- const cmdResponse = command.parse(requestBuffer[0..n]) orelse {
- socket.write(conn, "error\r") catch |err| {
- std.debug.print("error writing: {any}", .{err});
- };
- continue;
- };
- const terminator = "\r";
- const iovecs = [_]posix.iovec_const{
- .{ .base = cmdResponse.ptr, .len = cmdResponse.len },
- .{ .base = terminator.ptr, .len = 1 },
- };
- socket.writev(conn, &iovecs) catch |err| {
- std.debug.print("error writing: {any}", .{err});
- };
- }
- }
|