network: Bug fixes

This commit is contained in:
2026-05-23 19:26:16 +02:00
parent 2e543db418
commit f524c94d8e
2 changed files with 59 additions and 25 deletions
+56 -24
View File
@@ -27,13 +27,21 @@ pub const ConnectError = error {
PeerNotListeningOnAddress, PeerNotListeningOnAddress,
} || Allocator.Error; } || Allocator.Error;
pub const SendError = Allocator.Error; pub const SendError = error {
NotConnected,
} || Allocator.Error;
pub const ReadError = error {}; pub const ReadError = error {};
pub const ListenSocket = struct { pub const ListenSocket = struct {
next: ?*ListenSocket, next: ?*ListenSocket,
// A reference to the host is necessary as sockets from
// other hosts need to be able to infer the host by just
// the pointer to a socket.
host: *Host,
address: Address, address: Address,
accept_queue: std.ArrayList(*ConnSocket), accept_queue: std.ArrayList(*ConnSocket),
}; };
@@ -42,11 +50,13 @@ pub const ConnSocket = struct {
next: ?*ConnSocket, next: ?*ConnSocket,
// See comment on ListenSocket
host: *Host,
peer_listen: ?*ListenSocket, peer_listen: ?*ListenSocket,
peer_conn : ?*ConnSocket, peer_conn : ?*ConnSocket,
input_buffer: std.ArrayList(u8), input_buffer: std.ArrayList(u8),
output_buffer: std.ArrayList(u8),
}; };
pub const Host = struct { pub const Host = struct {
@@ -70,21 +80,49 @@ pub const Host = struct {
} }
pub fn deinit(self: *Host) void { pub fn deinit(self: *Host) void {
_ = self;
while (self.conn_list) |s| {
self.closeConnSocket(s);
}
while (self.listen_list) |s| {
self.closeListenSocket(s);
}
} }
fn linkConnSocket(self: *Host, socket: *ConnSocket) void { fn linkConnSocket(self: *Host, socket: *ConnSocket) void {
socket.host = self;
socket.next = self.conn_list; socket.next = self.conn_list;
self.conn_list = socket; self.conn_list = socket;
} }
fn unlinkConnSocket(self: *Host, socket: *ConnSocket) void { fn unlinkConnSocket(self: *Host, socket: *ConnSocket) void {
var cursor = self.conn_list.*; // Note that the list can't be empty or we wouldn't be unlinking var cursor = &self.conn_list;
if (cursor == socket) { while (cursor.*) |item| {
self.conn_list = null; if (item == socket) {
} else { cursor.* = item.next;
while (cursor.next != socket) socket.next = null;
cursor = cursor.next.*; return;
}
cursor = &item.next;
}
}
fn linkListenSocket(self: *Host, socket: *ListenSocket) void {
socket.host = self;
socket.next = self.listen_list;
self.listen_list = socket;
}
fn unlinkListenSocket(self: *Host, socket: *ListenSocket) void {
var cursor = &self.listen_list;
while (cursor.*) |item| {
if (item == socket) {
cursor.* = item.next;
socket.next = null;
return;
}
cursor = &item.next;
} }
} }
@@ -117,9 +155,7 @@ pub const Host = struct {
socket.address = address; socket.address = address;
socket.accept_queue = .empty; socket.accept_queue = .empty;
// Add listen socket to the list self.linkListenSocket(socket);
socket.next = self.listen_list;
self.listen_list = socket;
} }
pub fn accept(self: *Host, socket: *ListenSocket, new_socket: *ConnSocket) AcceptError!void { pub fn accept(self: *Host, socket: *ListenSocket, new_socket: *ConnSocket) AcceptError!void {
@@ -141,7 +177,6 @@ pub const Host = struct {
// Initialize other fields // Initialize other fields
new_socket.peer_listen = null; new_socket.peer_listen = null;
new_socket.input_buffer = .empty; new_socket.input_buffer = .empty;
new_socket.output_buffer = .empty;
} }
fn findListenSocket(self: *Host, address: Address) ?*ListenSocket { fn findListenSocket(self: *Host, address: Address) ?*ListenSocket {
@@ -166,10 +201,11 @@ pub const Host = struct {
new_socket.peer_listen = listen_socket; new_socket.peer_listen = listen_socket;
new_socket.peer_conn = null; new_socket.peer_conn = null;
new_socket.input_buffer = .empty; new_socket.input_buffer = .empty;
new_socket.output_buffer = .empty;
// Add socket to the peer's accept queue // Add socket to the peer's accept queue
try listen_socket.accept_queue.append(self.gpa, new_socket); //
// Note that we're using the peer's allocator and not the local one. Very important!
try listen_socket.accept_queue.append(host.gpa, new_socket);
} }
pub fn closeConnSocket(self: *Host, socket: *ConnSocket) void { pub fn closeConnSocket(self: *Host, socket: *ConnSocket) void {
@@ -189,7 +225,6 @@ pub const Host = struct {
self.unlinkConnSocket(socket); self.unlinkConnSocket(socket);
socket.input_buffer.deinit(self.gpa); socket.input_buffer.deinit(self.gpa);
socket.output_buffer.deinit(self.gpa);
} }
pub fn closeListenSocket(self: *Host, socket: *ListenSocket) void { pub fn closeListenSocket(self: *Host, socket: *ListenSocket) void {
@@ -202,20 +237,17 @@ pub const Host = struct {
socket.accept_queue.deinit(self.gpa); socket.accept_queue.deinit(self.gpa);
} }
pub fn send(self: *Host, socket: *ConnSocket, source: []const u8) usize { pub fn send(_: *Host, socket: *ConnSocket, source: []const u8) usize {
var n: usize = 0; const peer_conn = socket.peer_conn orelse return SendError.NotConnected;
for (source) |c| { try peer_conn.input_buffer.appendSlice(peer_conn.host.gpa, source);
socket.output_buffer.append(self.gpa, c) catch break; return source.len;
n += 1;
}
return n;
} }
pub fn read(_: *Host, socket: *ConnSocket, target: []u8) usize { pub fn read(_: *Host, socket: *ConnSocket, target: []u8) usize {
const num = @min(target.len, socket.input_buffer.items.len); const num = @min(target.len, socket.input_buffer.items.len);
@memcpy(target[0..num], socket.input_buffer.items[0..num]); @memcpy(target[0..num], socket.input_buffer.items[0..num]);
for (0..num) |_| { for (0..num) |_| {
socket.input_buffer.orderedRemove(0); _ = socket.input_buffer.orderedRemove(0);
} }
return num; return num;
} }
+3 -1
View File
@@ -423,7 +423,9 @@ pub fn readSocket(self: *Node, handle: Handle, target: []u8) HandleError!usize {
return self.network_host.read(&desc.conn, target); return self.network_host.read(&desc.conn, target);
} }
pub fn writeSocket(self: *Node, handle: Handle, source: []const u8) HandleError!usize { pub const WriteSocketError = HandleError || Network.SendError;
pub fn writeSocket(self: *Node, handle: Handle, source: []const u8) WriteSocketError!usize {
self.scheduler.sleep(10); self.scheduler.sleep(10);
const desc = try self.handleToDescOfType(handle, .conn); const desc = try self.handleToDescOfType(handle, .conn);
return self.network_host.send(&desc.conn, source); return self.network_host.send(&desc.conn, source);