implemented http-header-server

CrepeGoat
Jul 9, 2023, 7:52 AM
VSQAPX26BUP7PWVBLLZCTYMBFBMBTNXCU5DXUPULWTEFFKTJ26RQC

Dependencies

  • [2] KXKRFDS5 WIP: implemented echo TCP server

Change contents

  • edit in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 7
    [2.171]
    [2.171]
    const ServerError = os.SocketError || os.BindError || os.ListenError || os.AcceptError || os.RecvFromError || SendHttpResponseError;
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 22
    [2.482][2.482:543]()
    std.debug.print("closed socket {any}\n", .{sockfd});
    [2.482]
    [2.543]
    std.debug.print("closed socket {d}\n", .{sockfd});
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 24
    [2.549][2.549:606]()
    std.debug.print("opened socket {any}\n", .{sockfd});
    [2.549]
    [2.606]
    std.debug.print("opened socket {d}\n", .{sockfd});
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 37
    [2.961][2.961:1018]()
    "listening at @{any}.{any}.{any}.{any}:{any}\n",
    [2.961]
    [2.1018]
    "listening at @{d}.{d}.{d}.{d}:{d}\n",
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 46
    [2.1265][2.1265:1351]()
    std.debug.print("connection to socket {any} closed\n", .{sockfd_accept});
    [2.1265]
    [2.1351]
    std.debug.print("connection to socket {d} closed\n", .{sockfd_accept});
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 48
    [2.1361][2.1361:1445]()
    std.debug.print("accepted connection to socket {any}\n", .{sockfd_accept});
    [2.1361]
    [2.1445]
    std.debug.print("accepted connection to socket {d}\n", .{sockfd_accept});
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 52
    [2.1533][2.1533:1796]()
    while (true) {
    const msg_len = try std.os.recv(sockfd_accept, &buffer, 0);
    if (msg_len == 0) break;
    const socket_msg = buffer[0..msg_len];
    std.debug.print(" Received message:\n {s}\n", .{socket_msg});
    [2.1533]
    [2.1796]
    const msg_len = try std.os.recv(sockfd_accept, &buffer, 0);
    if (msg_len == 0) break;
    const socket_msg = buffer[0..msg_len];
    std.debug.print(" Received message:\n{s}\n", .{socket_msg});
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 57
    [2.1797][2.1797:1908]()
    // Echo received message.
    _ = try std.os.send(sockfd_accept, socket_msg, 0);
    }
    [2.1797]
    [2.1908]
    // Send response.
    _ = try sendHttpResponse(BUFFER_SIZE, sockfd_accept, socket_msg);
  • replacement in src/computer-networks/introduction-to-network-programming/http-header-server.zig at line 62
    [2.1917][2.1917:2041]()
    const ServerError = os.SocketError || os.BindError || os.ListenError || os.AcceptError || os.RecvFromError || os.SendError;
    [2.1917]
    const SendHttpResponseError = os.SendError || HttpHeadersIterator.NextError || error{
    Overflow,
    NoStartLine,
    BadStartLine,
    };
    fn sendHttpResponse(
    comptime BUFFER_SIZE: usize,
    sockfd: os.socket_t,
    request: []const u8,
    ) SendHttpResponseError!void {
    const start_line = request[0 .. std.mem.indexOf(u8, request, "\r\n") orelse request.len];
    if (request.len == 0) return SendHttpResponseError.NoStartLine;
    // TODO don't assume start line is OK!
    // Make the writer object.
    var send_writer = OsSendWriter{ .sockfd = sockfd };
    var buf_send_writer = std.io.BufferedWriter(
    BUFFER_SIZE,
    OsSendWriter.Writer,
    ){ .unbuffered_writer = send_writer.writer() };
    var writer = buf_send_writer.writer();
    var json_writer = std.json.writeStream(writer, 3);
    _ = try writer.write("HTTP/1.1 200 OK\r\n\r\n");
    var headers_iter = HttpHeadersIterator.init(request[start_line.len + 2 ..]);
    // Build the JSON blob.
    try json_writer.beginObject();
    while (try headers_iter.next()) |header| {
    try json_writer.objectField(header[0]);
    try json_writer.emitString(header[1]);
    }
    try json_writer.endObject();
    // Flush the buffer.
    try buf_send_writer.flush();
    }
    const OsSendWriter = struct {
    sockfd: os.socket_t,
    const Self = @This();
    const WriteError = os.SendError;
    pub fn write(self: *Self, str: []const u8) WriteError!usize {
    return os.send(self.sockfd, str, 0);
    }
    pub const Writer = std.io.Writer(*Self, WriteError, write);
    pub fn writer(self: *Self) Writer {
    return .{ .context = self };
    }
    };
    const HttpHeadersIterator = struct {
    lines_iter: std.mem.SplitIterator(u8),
    const Self = @This();
    pub fn init(request: []const u8) Self {
    return .{ .lines_iter = .{ .buffer = request, .delimiter = "\r\n", .index = 0 } };
    }
    const NextError = error{NoDivider};
    pub fn next(self: *Self) !?struct { []const u8, []const u8 } {
    const DIVIDER: []const u8 = ": ";
    const line = self.lines_iter.next() orelse return null;
    if (line.len == 0) return null;
    const div_pos = std.mem.indexOf(u8, line, DIVIDER) orelse return NextError.NoDivider;
    const result = .{
    line[0..div_pos],
    line[div_pos + DIVIDER.len ..],
    };
    return result;
    }
    };