From: patrick-scho Date: Sun, 9 Feb 2025 21:26:42 +0000 (+0100) Subject: delete epoll.zig and http.zig X-Git-Url: https://gitweb.ps.run/chirp/commitdiff_plain/d8d69c3c3c00a7dec8c2f80aa9b5eac03e122811 delete epoll.zig and http.zig --- diff --git a/src/epoll.zig b/src/epoll.zig deleted file mode 100644 index ed5d352..0000000 --- a/src/epoll.zig +++ /dev/null @@ -1,22 +0,0 @@ -const std = @import("std"); -const http = @import("http.zig"); - -pub fn main() !void { - var server = try http.Server.init("::", 8080); - defer server.deinit(); - - var req_buffer: [4096]u8 = undefined; - var res_head_buffer: [4096]u8 = undefined; - var res_body_buffer: [4096]u8 = undefined; - - while (true) { - server.wait(); - - while (try server.next_request(&req_buffer)) |req| { - var res = http.Response.init(req.fd, &res_head_buffer, &res_body_buffer); - - try res.write("Hallo", .{}); - try res.send(); - } - } -} diff --git a/src/http.zig b/src/http.zig deleted file mode 100644 index db625d6..0000000 --- a/src/http.zig +++ /dev/null @@ -1,344 +0,0 @@ -const std = @import("std"); -const posix = std.posix; -const linux = std.os.linux; - -pub const Server = struct { - // TODO: factor out - const BACKLOG = 2048; - - listener: posix.socket_t, - efd: i32, - ready_list: [BACKLOG]linux.epoll_event = undefined, - - ready_count: usize = 0, - ready_index: usize = 0, - - pub fn init(name: []const u8, port: u16) !Server { - const address = try std.net.Address.resolveIp(name, port); - - const tpe: u32 = posix.SOCK.STREAM | posix.SOCK.NONBLOCK; - const protocol = posix.IPPROTO.TCP; - const listener = try posix.socket(address.any.family, tpe, protocol); - - try posix.setsockopt(listener, posix.SOL.SOCKET, posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1))); - try posix.bind(listener, &address.any, address.getOsSockLen()); - try posix.listen(listener, BACKLOG); - - // epoll_create1 takes flags. We aren't using any in these examples - const efd = try posix.epoll_create1(0); - - var event = linux.epoll_event{ .events = linux.EPOLL.IN, .data = .{ .fd = listener } }; - try posix.epoll_ctl(efd, linux.EPOLL.CTL_ADD, listener, &event); - - return .{ - .listener = listener, - .efd = efd, - }; - } - - pub fn deinit(self: Server) void { - posix.close(self.efd); - posix.close(self.listener); - } - - pub fn wait(self: *Server) void { - if (self.ready_index >= self.ready_count) { - self.ready_index = 0; - self.ready_count = posix.epoll_wait(self.efd, &self.ready_list, -1); - } - } - - pub fn next_request(self: *Server, buf: []u8) !?Request { - while (self.ready_index < self.ready_count) { - const ready = self.ready_list[self.ready_index]; - const ready_socket = ready.data.fd; - self.ready_index += 1; - - if (ready_socket == self.listener) { - const client_socket = try posix.accept(self.listener, null, null, posix.SOCK.NONBLOCK); - errdefer posix.close(client_socket); - var event = linux.epoll_event{ .events = linux.EPOLL.IN, .data = .{ .fd = client_socket } }; - try posix.epoll_ctl(self.efd, linux.EPOLL.CTL_ADD, client_socket, &event); - } else { - var closed = false; - var req = Request{ .fd = ready_socket }; - - const read = posix.read(ready_socket, buf) catch 0; - if (read == 0) { - closed = true; - } else { - if (req.parse(buf[0..read])) - return req; - } - - if (closed or ready.events & linux.EPOLL.RDHUP == linux.EPOLL.RDHUP) { - posix.close(ready_socket); - } - } - } - return null; - } -}; - -// pub const Method = enum { GET, POST }; -pub const Method = std.http.Method; - -// pub const Header = struct { -// const NAME_SIZE = 32; -// const VALUE_SIZE = 128; - -// name: std.BoundedArray(u8, NAME_SIZE), -// value: std.BoundedArray(u8, VALUE_SIZE), -// }; -pub const Header = struct { - const Name = std.BoundedArray(u8, 32); - const Value = std.BoundedArray(u8, 128); - - name: Name = Name.init(0) catch unreachable, - value: Value = Value.init(0) catch unreachable, -}; -pub const Status = std.http.Status; - -pub const Request = struct { - fd: posix.fd_t, - - method: Method = undefined, - target: []const u8 = undefined, - version: ?[]const u8 = null, - head: ?[]const u8 = null, - body: ?[]const u8 = null, - - pub fn parse(self: *Request, buf: []const u8) bool { - var state: u8 = 0; - - var start: u32 = 0; - // var end: u32 = 0; - - var index: u32 = 0; - while (index < buf.len) { - defer index += 1; - - const c = buf[index]; - - switch (state) { - 0 => { - if (c == ' ') { - self.method = @enumFromInt(Method.parse(buf[start..index])); - start = index + 1; - state += 1; - } - }, - 1 => { - if (c == ' ') { - self.target = buf[start..index]; - start = index + 1; - state += 1; - } - }, - 2 => { - if (c == '\r') { - self.version = buf[start..index]; - start = index + 2; - index += 1; - state += 1; - } - }, - 3 => { - if (c == '\r' and (index + 2) < buf.len and buf[index + 2] == '\r') { - self.head = buf[start..index]; - - if (index + 4 < buf.len) { - self.body = buf[index + 4 .. buf.len]; - } - return true; - } - }, - else => {}, - } - } - - return true; - } - - pub fn get_header(self: Request, name: []const u8) ?[]const u8 { - const head = self.head orelse return null; - var start: usize = 0; - var matching: usize = 0; - for (0..head.len) |i| { - const c = head[i]; - - if (matching < name.len) { - if (c == name[matching]) { - if (matching == 0) start = i; - matching += 1; - } else { - matching = 0; - } - } else { - if (c == '\r') { - return head[start..i]; - } - } - } - return null; - } - - pub fn get_cookie(self: Request, name: []const u8) ?[]const u8 { - const cookie = self.get_header("Cookie") orelse return null; - var start: usize = 0; - var matching: usize = 0; - for (0..cookie.len) |i| { - const c = cookie[i]; - - if (matching < name.len) { - if (c == name[matching]) { - if (matching == 0) start = i; - matching += 1; - } else { - matching = 0; - } - } else { - if (c == '=') { - if (std.mem.indexOfScalarPos(u8, cookie, i, ';')) |semi_index| { - return cookie[i + 1 .. semi_index]; - } else { - return cookie[i + 1 .. cookie.len]; - } - } else { - matching = 0; - } - } - } - return null; - } - - pub fn parse1(self: *Request, buf: []const u8) bool { - const method_start: usize = 0; - const method_end = std.mem.indexOfScalar(u8, buf, ' ') orelse return false; - self.method = @enumFromInt(Method.parse(buf[method_start..method_end])); - - const target_start = method_end + 1; - const target_end = std.mem.indexOfScalarPos(u8, buf, target_start, ' ') orelse return false; - self.target = buf[target_start..target_end]; - - const version_start = target_end + 1; - const version_end = std.mem.indexOfPos(u8, buf, version_start, "\r\n") orelse buf.len; - self.version = buf[version_start..version_end]; - - if (version_end + 2 >= buf.len) - return true; - const head_start = version_end + 2; - const head_end = std.mem.indexOfPos(u8, buf, head_start, "\r\n\r\n") orelse buf.len; - self.head = buf[head_start..head_end]; - - if (head_end + 4 >= buf.len) - return true; - const body_start = head_end + 4; - const body_end = buf.len; - self.body = buf[body_start..body_end]; - - return true; - } - - pub fn get_header1(self: Request, name: []const u8) ?[]const u8 { - const head = self.head orelse return null; - const header_start = std.mem.indexOf(u8, head, name) orelse return null; - const header_end = std.mem.indexOfPos(u8, head, header_start, "\r\n") orelse return null; - return head[header_start..header_end]; - } - - pub fn get_cookie1(self: Request, name: []const u8) ?[]const u8 { - const cookie = self.get_header("Cookie") orelse return null; - const name_index = std.mem.indexOf(u8, cookie, name) orelse return null; - const eql_index = std.mem.indexOfScalarPos(u8, cookie, name_index, '=') orelse return null; - if (std.mem.indexOfScalarPos(u8, cookie, eql_index, ';')) |semi_index| { - return cookie[eql_index + 1 .. semi_index]; - } else { - return cookie[eql_index + 1 .. cookie.len]; - } - } - - pub fn get_value(self: Request, name: []const u8) ?[]const u8 { - const body = self.body orelse return null; - const name_index = std.mem.indexOf(u8, body, name) orelse return null; - const eql_index = std.mem.indexOfScalarPos(u8, body, name_index, '=') orelse return null; - if (std.mem.indexOfScalarPos(u8, body, name_index, '&')) |amp_index| { - return body[eql_index + 1 .. amp_index]; - } else { - return body[eql_index + 1 .. body.len]; - } - } -}; - -pub const Response = struct { - const ExtraHeadersMax = 16; - const HeaderList = std.BoundedArray(Header, ExtraHeadersMax); - - fd: posix.fd_t, - stream_head: std.io.FixedBufferStream([]u8), - stream_body: std.io.FixedBufferStream([]u8), - status: Status = .ok, - extra_headers: HeaderList = HeaderList.init(0) catch unreachable, - - pub fn init(fd: posix.fd_t, buf_head: []u8, buf_body: []u8) Response { - return .{ - .fd = fd, - .stream_head = std.io.fixedBufferStream(buf_head), - .stream_body = std.io.fixedBufferStream(buf_body), - }; - } - - pub fn redirect(self: *Response, location: []const u8) !void { - self.status = .see_other; - try self.add_header("Location", .{ "{s}", .{location} }); - } - - pub fn add_header(self: *Response, name: []const u8, value: anytype) !void { - const header = try self.extra_headers.addOne(); - try header.name.writer().writeAll(name); - if (@typeInfo(@TypeOf(value)).Struct.fields.len < 2 or @sizeOf(@TypeOf(value[1])) == 0) { - try header.value.writer().writeAll(value[0]); - } else { - try std.fmt.format(header.value.writer(), value[0], value[1]); - } - } - - pub fn write(self: *Response, comptime fmt: []const u8, args: anytype) !void { - const writer = self.stream_body.writer(); - - if (@sizeOf(@TypeOf(args)) == 0) { - try writer.writeAll(fmt); - } else { - try std.fmt.format(writer, fmt, args); - } - } - - pub fn send(self: *Response) !void { - // write head - const writer = self.stream_head.writer(); - - try std.fmt.format(writer, "HTTP/1.1 {} {?s}\r\n" ++ - "Content-Length: {}\r\n", .{ @intFromEnum(self.status), self.status.phrase(), self.stream_body.pos }); - - for (self.extra_headers.constSlice()) |header| { - try std.fmt.format(writer, "{s}: {s}\r\n", .{ header.name.constSlice(), header.value.constSlice() }); - } - - try std.fmt.format(writer, "\r\n", .{}); - - // write body to head - - try std.fmt.format(writer, "{s}", .{self.stream_body.getWritten()}); - - // send head - - const res = self.stream_head.getWritten(); - var written: usize = 0; - while (written < res.len) { - written += posix.write(self.fd, res[written..res.len]) catch |err| { - std.debug.print("posix.write: {}\n", .{err}); - continue; - }; - } - } -};