Rewrite request reading
This commit is contained in:
parent
c1599c755d
commit
0e67ffd8c4
44
src/header.zig
Normal file
44
src/header.zig
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
const mem = std.mem;
|
||||||
|
|
||||||
|
const RequestHeader = struct {
|
||||||
|
content_length: usize,
|
||||||
|
|
||||||
|
/// null implies "application/vscode-jsonrpc; charset=utf-8"
|
||||||
|
content_type: ?[]const u8,
|
||||||
|
|
||||||
|
pub fn deinit(self: @This(), allocator: *mem.Allocator) void {
|
||||||
|
if (self.content_type) |ct| allocator.free(ct);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn readRequestHeader(allocator: *mem.Allocator, instream: var) !RequestHeader {
|
||||||
|
var r = RequestHeader{
|
||||||
|
.content_length = undefined,
|
||||||
|
.content_type = null,
|
||||||
|
};
|
||||||
|
errdefer r.deinit(allocator);
|
||||||
|
|
||||||
|
var has_content_length = false;
|
||||||
|
while (true) {
|
||||||
|
const header = try instream.readUntilDelimiterAlloc(allocator, '\n', 0x100);
|
||||||
|
defer allocator.free(header);
|
||||||
|
if (header.len == 0 or header[header.len - 1] != '\r') return error.MissingCarriageReturn;
|
||||||
|
if (header.len == 1) break;
|
||||||
|
|
||||||
|
const header_name = header[0..mem.indexOf(u8, header, ": ") orelse return error.MissingColon];
|
||||||
|
const header_value = header[header_name.len + 2..header.len-1];
|
||||||
|
if (mem.eql(u8, header_name, "Content-Length")) {
|
||||||
|
if (header_value.len == 0) return error.MissingHeaderValue;
|
||||||
|
r.content_length = std.fmt.parseInt(usize, header_value, 10) catch return error.InvalidContentLength;
|
||||||
|
has_content_length = true;
|
||||||
|
} else if (mem.eql(u8, header_name, "Content-Type")) {
|
||||||
|
r.content_type = try mem.dupe(allocator, u8, header_value);
|
||||||
|
} else {
|
||||||
|
return error.UnknownHeader;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!has_content_length) return error.MissingContentLength;
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
75
src/main.zig
75
src/main.zig
@ -4,6 +4,7 @@ const build_options = @import("build_options");
|
|||||||
const Config = @import("config.zig");
|
const Config = @import("config.zig");
|
||||||
const DocumentStore = @import("document_store.zig");
|
const DocumentStore = @import("document_store.zig");
|
||||||
const DebugAllocator = @import("debug_allocator.zig");
|
const DebugAllocator = @import("debug_allocator.zig");
|
||||||
|
const readRequestHeader = @import("header.zig").readRequestHeader;
|
||||||
const data = @import("data/" ++ build_options.data_version ++ ".zig");
|
const data = @import("data/" ++ build_options.data_version ++ ".zig");
|
||||||
const types = @import("types.zig");
|
const types = @import("types.zig");
|
||||||
const analysis = @import("analysis.zig");
|
const analysis = @import("analysis.zig");
|
||||||
@ -649,74 +650,18 @@ pub fn main() anyerror!void {
|
|||||||
var json_parser = std.json.Parser.init(allocator, false);
|
var json_parser = std.json.Parser.init(allocator, false);
|
||||||
defer json_parser.deinit();
|
defer json_parser.deinit();
|
||||||
|
|
||||||
var offset: usize = 0;
|
while (true) {
|
||||||
var bytes_read: usize = 0;
|
const headers = readRequestHeader(allocator, stdin) catch |err| {
|
||||||
|
try log("{}; exiting!", .{@errorName(err)});
|
||||||
var index: usize = 0;
|
|
||||||
var content_len: usize = 0;
|
|
||||||
|
|
||||||
stdin_poll: while (true) {
|
|
||||||
if (offset >= 16 and std.mem.startsWith(u8, buffer.items, "Content-Length: ")) {
|
|
||||||
index = 16;
|
|
||||||
while (index <= offset + 10) : (index += 1) {
|
|
||||||
const c = buffer.items[index];
|
|
||||||
if (c >= '0' and c <= '9') {
|
|
||||||
content_len = content_len * 10 + (c - '0');
|
|
||||||
} else if (c == '\r' and buffer.items[index + 1] == '\n') {
|
|
||||||
index += 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buffer.items[index] == '\r') {
|
|
||||||
index += 2;
|
|
||||||
if (buffer.items.len < index + content_len) {
|
|
||||||
try buffer.resize(index + content_len);
|
|
||||||
}
|
|
||||||
|
|
||||||
body_poll: while (offset < content_len + index) {
|
|
||||||
bytes_read = try stdin.readAll(buffer.items[offset .. index + content_len]);
|
|
||||||
if (bytes_read == 0) {
|
|
||||||
try log("0 bytes read; exiting!", .{});
|
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
|
defer headers.deinit(allocator);
|
||||||
offset += bytes_read;
|
const buf = try allocator.alloc(u8, headers.content_length);
|
||||||
}
|
defer allocator.free(buf);
|
||||||
|
try stdin.readNoEof(buf);
|
||||||
try processJsonRpc(&json_parser, buffer.items[index .. index + content_len], config);
|
try processJsonRpc(&json_parser, buf, config);
|
||||||
json_parser.reset();
|
json_parser.reset();
|
||||||
|
|
||||||
offset = 0;
|
|
||||||
content_len = 0;
|
|
||||||
} else {
|
|
||||||
try log("\\r not found", .{});
|
|
||||||
}
|
|
||||||
} else if (offset >= 16) {
|
|
||||||
try log("Offset is greater than 16!", .{});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset < 16) {
|
|
||||||
bytes_read = try stdin.readAll(buffer.items[offset..25]);
|
|
||||||
} else {
|
|
||||||
if (offset == buffer.items.len) {
|
|
||||||
try buffer.resize(buffer.items.len * 2);
|
|
||||||
}
|
|
||||||
if (index + content_len > buffer.items.len) {
|
|
||||||
bytes_read = try stdin.readAll(buffer.items[offset..buffer.items.len]);
|
|
||||||
} else {
|
|
||||||
bytes_read = try stdin.readAll(buffer.items[offset .. index + content_len]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytes_read == 0) {
|
|
||||||
try log("0 bytes read; exiting!", .{});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += bytes_read;
|
|
||||||
|
|
||||||
if (debug_alloc) |dbg| {
|
if (debug_alloc) |dbg| {
|
||||||
try log("{}", .{dbg.info});
|
try log("{}", .{dbg.info});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user