This is from the live coding stream: https://youtu.be/aDd0BexKWps
This version of zig should be good: 0.5.0+913f7d04
This is from the live coding stream: https://youtu.be/aDd0BexKWps
This version of zig should be good: 0.5.0+913f7d04
const std = @import("std"); | |
const net = std.net; | |
const fs = std.fs; | |
const os = std.os; | |
pub const io_mode = .evented; | |
pub fn main() anyerror!void { | |
const allocator = std.heap.direct_allocator; | |
const req_listen_addr = net.IpAddress.parse("127.0.0.1", 0) catch unreachable; | |
var server = net.TcpServer.init(net.TcpServer.Options{}); | |
defer server.deinit(); | |
try server.listen(req_listen_addr); | |
std.debug.warn("listening at {}\n", server.listen_address); | |
var room = Room{ | |
.clients = std.AutoHashMap(*Client, void).init(allocator), | |
.lock = std.Mutex.init(), // TODO fix std.event.Lock and use that instead. | |
}; | |
while (true) { | |
const client_file = try server.accept(); | |
const client = try allocator.create(Client); | |
client.* = Client{ | |
.file = client_file, | |
.handle_frame = async client.handle(&room), | |
}; | |
var held_lock = room.lock.acquire(); | |
defer held_lock.release(); | |
try room.clients.putNoClobber(client, {}); | |
} | |
} | |
const Client = struct { | |
file: fs.File, | |
handle_frame: @Frame(handle), | |
fn handle(self: *Client, room: *Room) !void { | |
try self.file.write("server: welcome to teh chat server\n"); | |
while (true) { | |
var buf: [100]u8 = undefined; | |
const amt = try self.file.read(&buf); | |
const msg = buf[0..amt]; | |
try room.broadcast(msg, self); | |
} | |
} | |
}; | |
const Room = struct { | |
clients: std.AutoHashMap(*Client, void), | |
lock: std.Mutex, | |
fn broadcast(room: *Room, msg: []const u8, sender: *Client) !void { | |
var held_lock = room.lock.acquire(); | |
defer held_lock.release(); | |
var it = room.clients.iterator(); | |
while (it.next()) |entry| { | |
const client = entry.key; | |
if (client == sender) continue; | |
// TODO make this not give SIGPIPE. | |
// Also, `try` here is no good because it should still write to the other clients! | |
try client.file.write(msg); | |
} | |
} | |
}; |