const std = @import("std"); const Io = std.Io; const WebSocket = std.http.Server.WebSocket; var m = std.atomic.Mutex.unlocked; var clients: std.ArrayList(*WebSocket) = undefined; fn broadcast(sm: WebSocket.SmallMessage) void { if (!m.tryLock()) return; for (clients.items) |c| { c.writeMessage(sm.data, sm.opcode) catch {}; } m.unlock(); } fn handle_websocket(alloc: std.mem.Allocator, websocket: *WebSocket) void { if (!m.tryLock()) return; clients.append(alloc, websocket) catch {}; m.unlock(); const i = clients.items.len; defer _ = clients.swapRemove(i); websocket.writeMessage("welcome", .text) catch return; while (true) { const sm = websocket.readSmallMessage() catch break; broadcast(sm); } } fn handle_request(alloc: std.mem.Allocator, io: Io, stream: Io.net.Stream) void { var recv_buffer: [999]u8 = undefined; var send_buffer: [100]u8 = undefined; defer stream.close(io); var connection_br = stream.reader(io, &recv_buffer); var connection_bw = stream.writer(io, &send_buffer); var server = std.http.Server.init(&connection_br.interface, &connection_bw.interface); while (true) { var req = server.receiveHead() catch break; switch (req.upgradeRequested()) { .websocket => |ws| { var websocket = req.respondWebSocket(.{ .key = ws.? }) catch break; handle_websocket(alloc, &websocket); }, else => { req.respond( \\ \\
hallo
, .{ .status = .ok }) catch break; }, } } // std.debug.print("closing http thread\n", .{}); } pub fn main(init: std.process.Init) !void { // Prints to stderr, unbuffered, ignoring potential errors. std.debug.print("All your {s} are belong to us.\n", .{"codebase"}); // This is appropriate for anything that lives as long as the process. const arena: std.mem.Allocator = init.arena.allocator(); clients = try .initCapacity(arena, 10); // Accessing command line arguments: const args = try init.minimal.args.toSlice(arena); for (args) |arg| { std.log.info("arg: {s}", .{arg}); } // In order to do I/O operations need an `Io` instance. const io = init.io; var port: u16 = 10010; if (init.environ_map.get("PORT")) |s| { if (std.fmt.parseInt(u16, s, 10)) |p| { port = p; } else |e| { std.debug.print("{}\n", .{e}); } } const address = try std.Io.net.IpAddress.parseIp4("0.0.0.0", port); var net_server = try address.listen(io, .{ .reuse_address = true }); while (true) { const stream = try net_server.accept(io); _ = io.async(handle_request, .{ arena, io, stream }); // std.debug.print("created http thread\n", .{}); } }