╭─────────────╮ │scroll to top│ ╰─────────────╯ ╭ serve.zig ────────────────────────────────────────────────────╮ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰───────────────────────────────────────────────────────────────╯
╭────╮ ╭ clone ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╮ │http│ ssh │ │ ╰────╯ ╰ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ╯
70 // load or generate the SSH host key 71 const host_key = try serve_ssh_protocol.HostKey.loadOrGenerate(io, allocator, data_dir_path); 72 73 // disk-backed store for web login sessions 74 const session_store = try web.SessionStore.init(io, data_dir); 75 defer session_store.deinit(); 76 77 // create wui listener 78 79 const wui_listen_address = try parseListenAddress(options.wui_listen); 80 const wui_address = try std.Io.net.IpAddress.parseIp4(wui_listen_address.host, wui_listen_address.port); 81 var wui_server = try wui_address.listen(io, .{ .reuse_address = true }); 82 defer wui_server.deinit(io); 83 84 // start task group 85 86 var tasks: std.Io.Group = .init; 87 defer tasks.cancel(io); 88 89 // run listeners 90 91 try err.print("serving HTTP on {s}, repo root {s}\n", .{ options.http_listen, repo_root_path }); 92 try err.flush(); 93 94 serve_http.runListener(repo_kind, any_repo_opts, io, allocator, repo_root_path, admin_repo_path, &http_server, &tasks, err); 95 96 try err.print("serving SSH on {s}\n", .{options.ssh_listen}); 97 try err.flush(); 98 99 const ssh_session_handler = serve_ssh.SessionHandler{ 100 .admin_repo_path = admin_repo_path, 101 .repo_root_path = repo_root_path, 102 .wui_port = wui_listen_address.port, 103 .err = err, 104 }; 105 serve_ssh.runListener(io, allocator, &host_key, &ssh_session_handler, &ssh_server, &tasks, err); 106 107 try err.print("serving web UI on http://{s}/\n", .{options.wui_listen}); 108 try err.flush(); 109 110 web.run(io, allocator, &wui_server, &tasks, admin_repo_path, session_store, err); 111 112 if (@TypeOf(runnable) != void) { 113 try runnable.run(); 114 } else { 115 try tasks.await(io); 116 } 117 } 118 119 fn parseListenAddress(value: []const u8) !ListenAddress { 120 const colon = std.mem.lastIndexOfScalar(u8, value, ':') orelse return error.InvalidListenAddress; 121 if (colon == 0 or colon + 1 >= value.len) return error.InvalidListenAddress; 122 const port = try std.fmt.parseInt(u16, value[colon + 1 ..], 10); 123 return .{ .host = value[0..colon], .port = port }; 124 } 125