A websocket implementation for zig
0

Configure Feed

Select the types of activity you want to include in your feed.

Pass configured port to underlying socketpair.

Make testing.ensureMessage public.

https://github.com/karlseguin/websocket.zig/issues/71

Karl Seguin (Jul 26, 2025, 2:14 PM +0800) 069cc04c fd689480

+23 -18
+10 -10
src/client/client.zig
··· 578 578 test "Client: handshake" { 579 579 { 580 580 // empty response 581 - var pair = t.SocketPair.init(); 581 + var pair = t.SocketPair.init(.{}); 582 582 defer pair.deinit(); 583 583 try pair.client.writeAll("\r\n\r\n"); 584 584 ··· 589 589 590 590 { 591 591 // invalid websocket response 592 - var pair = t.SocketPair.init(); 592 + var pair = t.SocketPair.init(.{}); 593 593 defer pair.deinit(); 594 594 try pair.client.writeAll("HTTP/1.1 200 OK\r\n\r\n"); 595 595 ··· 600 600 601 601 { 602 602 // missing upgrade header 603 - var pair = t.SocketPair.init(); 603 + var pair = t.SocketPair.init(.{}); 604 604 defer pair.deinit(); 605 605 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\n\r\n"); 606 606 ··· 611 611 612 612 { 613 613 // wrong upgrade header 614 - var pair = t.SocketPair.init(); 614 + var pair = t.SocketPair.init(.{}); 615 615 defer pair.deinit(); 616 616 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nUpgrade: nope\r\n\r\n"); 617 617 ··· 622 622 623 623 { 624 624 // missing connection header 625 - var pair = t.SocketPair.init(); 625 + var pair = t.SocketPair.init(.{}); 626 626 defer pair.deinit(); 627 627 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nUpgrade: websocket\r\n\r\n"); 628 628 ··· 633 633 634 634 { 635 635 // wrong connection header 636 - var pair = t.SocketPair.init(); 636 + var pair = t.SocketPair.init(.{}); 637 637 defer pair.deinit(); 638 638 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nupgrade: WebSocket\r\nConnection: something\r\n\r\n"); 639 639 ··· 644 644 645 645 { 646 646 // missing Sec-Websocket-Accept header 647 - var pair = t.SocketPair.init(); 647 + var pair = t.SocketPair.init(.{}); 648 648 defer pair.deinit(); 649 649 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nUpgrade: websocket\r\nConnection: upgrade\r\n\r\n"); 650 650 ··· 655 655 656 656 { 657 657 // wrong Sec-Websocket-Accept header 658 - var pair = t.SocketPair.init(); 658 + var pair = t.SocketPair.init(.{}); 659 659 defer pair.deinit(); 660 660 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nupgrade: WebSocket\r\nConnection: UPGRADE\r\nSec-Websocket-Accept: hack\r\n\r\n"); 661 661 ··· 666 666 667 667 { 668 668 // ok for successful 669 - var pair = t.SocketPair.init(); 669 + var pair = t.SocketPair.init(.{}); 670 670 defer pair.deinit(); 671 671 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nupgrade: WebSocket\r\nConnection: UPGRADE\r\nSec-Websocket-Accept: C/0nmHhBztSRGR1CwL6Tf4ZjwpY=\r\n\r\n"); 672 672 ··· 678 678 679 679 { 680 680 // ok for successful, with overread 681 - var pair = t.SocketPair.init(); 681 + var pair = t.SocketPair.init(.{}); 682 682 defer pair.deinit(); 683 683 try pair.client.writeAll("HTTP/1.1 101 Switching Protocol\r\nupgrade: WebSocket\r\nConnection: UPGRADE\r\nSec-Websocket-Accept: C/0nmHhBztSRGR1CwL6Tf4ZjwpY=\r\n\r\nSome Random Data Which is Part Of the Next Message"); 684 684
+3 -3
src/proto.zig
··· 620 620 test "Reader: read too large" { 621 621 defer t.reset(); 622 622 623 - var pair = t.SocketPair.init(); 623 + var pair = t.SocketPair.init(.{}); 624 624 defer pair.deinit(); 625 625 pair.textFrame(true, "hello world"); 626 626 pair.sendBuf(); ··· 633 633 test "Reader: read too large over multiple fragments" { 634 634 defer t.reset(); 635 635 636 - var pair = t.SocketPair.init(); 636 + var pair = t.SocketPair.init(.{}); 637 637 defer pair.deinit(); 638 638 pair.textFrame(false, "hello world"); 639 639 pair.cont(false, " !!!_!!! "); ··· 648 648 test "Reader: exact read into static with no overflow" { 649 649 defer t.reset(); 650 650 651 - var pair = t.SocketPair.init(); 651 + var pair = t.SocketPair.init(.{}); 652 652 defer pair.deinit(); 653 653 pair.textFrame(true, "hello!"); 654 654 pair.sendBuf();
+6 -2
src/t.zig
··· 148 148 client: std.net.Stream, 149 149 server: std.net.Stream, 150 150 151 - pub fn init() SocketPair { 152 - var address = std.net.Address.parseIp("127.0.0.1", 0) catch unreachable; 151 + const Opts = struct { 152 + port: ?u16 = null, 153 + }; 154 + 155 + pub fn init(opts: Opts) SocketPair { 156 + var address = std.net.Address.parseIp("127.0.0.1", opts.port orelse 0) catch unreachable; 153 157 var address_len = address.getOsSockLen(); 154 158 155 159 const listener = posix.socket(address.any.family, posix.SOCK.STREAM | posix.SOCK.CLOEXEC, posix.IPPROTO.TCP) catch unreachable;
+4 -3
src/testing.zig
··· 26 26 arena.* = std.heap.ArenaAllocator.init(t.allocator); 27 27 errdefer arena.deinit(); 28 28 29 - const pair = t.SocketPair.init(); 29 + const port = opts.port orelse 0; 30 + const pair = t.SocketPair.init(.{.port = port}); 30 31 const timeout = std.mem.toBytes(std.posix.timeval{ 31 32 .sec = 0, 32 33 .usec = 50_000, ··· 52 53 ._closed = false, 53 54 .started = 0, 54 55 .stream = pair.server, 55 - .address = std.net.Address.parseIp("127.0.0.1", opts.port orelse 0) catch unreachable, 56 + .address = std.net.Address.parseIp("127.0.0.1", port) catch unreachable, 56 57 }, 57 58 .reader = reader, 58 59 .received = std.ArrayList(ws.Message).init(aa), ··· 97 98 98 99 // we have a 50ms timeout on this socket. It's all localhost. We expect 99 100 // to be able to read messages in that time. 100 - fn ensureMessage(self: *Testing) !void { 101 + pub fn ensureMessage(self: *Testing) !void { 101 102 if (self.received_index < self.received.items.len) { 102 103 return; 103 104 }