Skip to content

Commit e828712

Browse files
committed
Ability to start/stop CDP server.
Exists for cleaning up after tests.
1 parent 42e5f49 commit e828712

File tree

2 files changed

+81
-73
lines changed

2 files changed

+81
-73
lines changed

src/main.zig

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,9 @@ const builtin = @import("builtin");
2121
const Allocator = std.mem.Allocator;
2222

2323
const log = @import("log.zig");
24-
const server = @import("server.zig");
2524
const App = @import("app.zig").App;
2625
const Http = @import("http/Http.zig");
27-
const Platform = @import("runtime/js.zig").Platform;
26+
const Server = @import("server.zig").Server;
2827
const Browser = @import("browser/browser.zig").Browser;
2928

3029
const build_config = @import("build_config");
@@ -100,7 +99,11 @@ fn run(alloc: Allocator) !void {
10099
};
101100

102101
const timeout = std.time.ns_per_s * @as(u64, opts.timeout);
103-
server.run(app, address, timeout) catch |err| {
102+
var server = try Server.init(app, address, timeout);
103+
defer server.deinit();
104+
105+
// address is only passed again so we can print it nicely.
106+
server.run(address) catch |err| {
104107
log.fatal(.app, "server run error", .{ .err = err });
105108
return err;
106109
};
@@ -679,6 +682,7 @@ test {
679682
std.testing.refAllDecls(@This());
680683
}
681684

685+
var test_cdp_server: ?Server = null;
682686
test "tests:beforeAll" {
683687
log.opts.level = .err;
684688
log.opts.format = .logfmt;
@@ -704,6 +708,9 @@ test "tests:beforeAll" {
704708
}
705709

706710
test "tests:afterAll" {
711+
if (test_cdp_server) |*server| {
712+
server.deinit();
713+
}
707714
testing.shutdown();
708715
}
709716

@@ -758,9 +765,10 @@ fn serveHTTP(wg: *std.Thread.WaitGroup) !void {
758765

759766
fn serveCDP(wg: *std.Thread.WaitGroup) !void {
760767
const address = try std.net.Address.parseIp("127.0.0.1", 9583);
768+
test_cdp_server = try Server.init(testing.test_app, address, std.time.ns_per_s * 2);
761769

762770
wg.finish();
763-
server.run(testing.test_app, address, std.time.ns_per_s * 2) catch |err| {
771+
test_cdp_server.?.run(address) catch |err| {
764772
std.debug.print("CDP server error: {}", .{err});
765773
return err;
766774
};

src/server.zig

Lines changed: 69 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const MAX_HTTP_REQUEST_SIZE = 4096;
4646
// +140 for the max control packet that might be interleaved in a message
4747
const MAX_MESSAGE_SIZE = 512 * 1024 + 14;
4848

49-
const Server = struct {
49+
pub const Server = struct {
5050
app: *App,
5151
loop: *Loop,
5252
allocator: Allocator,
@@ -62,8 +62,74 @@ const Server = struct {
6262
// The response to send on a GET /json/version request
6363
json_version_response: []const u8,
6464

65-
fn deinit(self: *Server) void {
66-
_ = self;
65+
pub fn init(
66+
app: *App,
67+
address: net.Address,
68+
timeout: u64,
69+
) !Server {
70+
// create socket
71+
const flags = posix.SOCK.STREAM | posix.SOCK.CLOEXEC | posix.SOCK.NONBLOCK;
72+
const listener = try posix.socket(address.any.family, flags, posix.IPPROTO.TCP);
73+
errdefer posix.close(listener);
74+
75+
try posix.setsockopt(listener, posix.SOL.SOCKET, posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1)));
76+
// TODO: Broken on darwin
77+
// https://github.com/ziglang/zig/issues/17260 (fixed in Zig 0.14)
78+
// if (@hasDecl(os.TCP, "NODELAY")) {
79+
// try os.setsockopt(socket.sockfd.?, os.IPPROTO.TCP, os.TCP.NODELAY, &std.mem.toBytes(@as(c_int, 1)));
80+
// }
81+
try posix.setsockopt(listener, posix.IPPROTO.TCP, 1, &std.mem.toBytes(@as(c_int, 1)));
82+
83+
// bind & listen
84+
try posix.bind(listener, &address.any, address.getOsSockLen());
85+
try posix.listen(listener, 1);
86+
87+
const allocator = app.allocator;
88+
const json_version_response = try buildJSONVersionResponse(allocator, address);
89+
errdefer allocator.free(json_version_response);
90+
91+
return .{
92+
.app = app,
93+
.loop = app.loop,
94+
.timeout = timeout,
95+
.listener = listener,
96+
.allocator = allocator,
97+
.accept_completion = undefined,
98+
.json_version_response = json_version_response,
99+
};
100+
}
101+
102+
pub fn deinit(self: *Server) void {
103+
posix.close(self.listener);
104+
self.allocator.free(self.json_version_response);
105+
}
106+
107+
pub fn run(self: *Server, address: net.Address) !void {
108+
// accept an connection
109+
self.queueAccept();
110+
log.info(.app, "server running", .{ .address = address });
111+
112+
// infinite loop on I/O events, either:
113+
// - cmd from incoming connection on server socket
114+
// - JS callbacks events from scripts
115+
while (true) {
116+
// @newhttp. This is a hack. We used to just have 1 loop, so we could
117+
// sleep it it "forever" and any activity (message to this server,
118+
// JS callback, http data) would wake it up.
119+
// Now we have 2 loops. If we block on one, the other won't get woken
120+
// up. We don't block "forever" but even 10ms adds a bunch of latency
121+
// since this is called in a loop.
122+
// Hopefully this is temporary and we can remove the io loop and then
123+
// only have 1 loop. But, until then, we need to check both loops and
124+
// pay some blocking penalty.
125+
if (self.client) |client| {
126+
if (client.cdp) |*cdp| {
127+
cdp.pageWait();
128+
}
129+
}
130+
131+
try self.loop.io.run_for_ns(10 * std.time.ns_per_ms);
132+
}
67133
}
68134

69135
fn queueAccept(self: *Server) void {
@@ -1008,72 +1074,6 @@ fn websocketHeader(buf: []u8, op_code: OpCode, payload_len: usize) []const u8 {
10081074
return buf[0..10];
10091075
}
10101076

1011-
pub fn run(
1012-
app: *App,
1013-
address: net.Address,
1014-
timeout: u64,
1015-
) !void {
1016-
// create socket
1017-
const flags = posix.SOCK.STREAM | posix.SOCK.CLOEXEC | posix.SOCK.NONBLOCK;
1018-
const listener = try posix.socket(address.any.family, flags, posix.IPPROTO.TCP);
1019-
defer posix.close(listener);
1020-
1021-
try posix.setsockopt(listener, posix.SOL.SOCKET, posix.SO.REUSEADDR, &std.mem.toBytes(@as(c_int, 1)));
1022-
// TODO: Broken on darwin
1023-
// https://github.com/ziglang/zig/issues/17260 (fixed in Zig 0.14)
1024-
// if (@hasDecl(os.TCP, "NODELAY")) {
1025-
// try os.setsockopt(socket.sockfd.?, os.IPPROTO.TCP, os.TCP.NODELAY, &std.mem.toBytes(@as(c_int, 1)));
1026-
// }
1027-
try posix.setsockopt(listener, posix.IPPROTO.TCP, 1, &std.mem.toBytes(@as(c_int, 1)));
1028-
1029-
// bind & listen
1030-
try posix.bind(listener, &address.any, address.getOsSockLen());
1031-
try posix.listen(listener, 1);
1032-
1033-
var loop = app.loop;
1034-
const allocator = app.allocator;
1035-
const json_version_response = try buildJSONVersionResponse(allocator, address);
1036-
defer allocator.free(json_version_response);
1037-
1038-
var server = Server{
1039-
.app = app,
1040-
.loop = loop,
1041-
.timeout = timeout,
1042-
.listener = listener,
1043-
.allocator = allocator,
1044-
.accept_completion = undefined,
1045-
.json_version_response = json_version_response,
1046-
};
1047-
defer server.deinit();
1048-
1049-
// accept an connection
1050-
server.queueAccept();
1051-
log.info(.app, "server running", .{ .address = address });
1052-
1053-
// infinite loop on I/O events, either:
1054-
// - cmd from incoming connection on server socket
1055-
// - JS callbacks events from scripts
1056-
// var http_client = app.http_client;
1057-
while (true) {
1058-
// @newhttp. This is a hack. We used to just have 1 loop, so we could
1059-
// sleep it it "forever" and any activity (message to this server,
1060-
// JS callback, http data) would wake it up.
1061-
// Now we have 2 loops. If we block on one, the other won't get woken
1062-
// up. We don't block "forever" but even 10ms adds a bunch of latency
1063-
// since this is called in a loop.
1064-
// Hopefully this is temporary and we can remove the io loop and then
1065-
// only have 1 loop. But, until then, we need to check both loops and
1066-
// pay some blocking penalty.
1067-
if (server.client) |client| {
1068-
if (client.cdp) |*cdp| {
1069-
cdp.pageWait();
1070-
}
1071-
}
1072-
1073-
try loop.io.run_for_ns(10 * std.time.ns_per_ms);
1074-
}
1075-
}
1076-
10771077
// Utils
10781078
// --------
10791079

0 commit comments

Comments
 (0)