╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ serve.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
182 fn runWebListener( 183 io: std.Io, 184 allocator: std.mem.Allocator, 185 net_server: *std.Io.net.Server, 186 tasks: *std.Io.Group, 187 host: web.Host, 188 err: *std.Io.Writer, 189 ) void { 190 const Context = struct { 191 io: std.Io, 192 allocator: std.mem.Allocator, 193 host: web.Host, 194 err: *std.Io.Writer, 195 }; 196 197 const handle = struct { 198 fn h(ctx: Context, stream: std.Io.net.Stream) void { 199 defer stream.close(ctx.io); 200 web.handleConnection(ctx.io, ctx.allocator, stream, ctx.host, ctx.err) catch |request_err| { 201 serve_common.logError(ctx.io, ctx.err, "web ui request failed: {s}\n", .{@errorName(request_err)}); 202 }; 203 } 204 }.h; 205 206 serve_common.runListener(io, net_server, tasks, err, "web ui", Context{ 207 .io = io, 208 .allocator = allocator, 209 .host = host, 210 .err = err, 211 }, handle); 212 } 213 214 // what a listener does with a port that is already taken 215 const PortPolicy = enum { 216 exact, 217 // leave it to whoever holds it and take an OS-assigned port instead 218 fallback, 219 }; 220 221 fn listen(io: std.Io, listen_address: ListenAddress, policy: PortPolicy) !std.Io.net.Server { 222 const address = try std.Io.net.IpAddress.parseIp4(listen_address.host, listen_address.port); 223 return switch (policy) { 224 .exact => try address.listen(io, .{}), 225 .fallback => address.listen(io, .{}) catch |listen_err| switch (listen_err) { 226 error.AddressInUse => blk: { 227 const any_port = try std.Io.net.IpAddress.parseIp4(listen_address.host, 0); 228 break :blk try any_port.listen(io, .{}); 229 }, 230 else => |e| return e, 231 }, 232 }; 233 } 234 235 fn parseListenAddress(value: []const u8) !ListenAddress { 236 const colon = std.mem.lastIndexOfScalar(u8, value, ':') orelse return error.InvalidListenAddress; 237 if (colon == 0 or colon + 1 >= value.len) return error.InvalidListenAddress; 238 const port = try std.fmt.parseInt(u16, value[colon + 1 ..], 10); 239 return .{ .host = value[0..colon], .port = port }; 240 } 241