5
5
const std = @import ("std" );
6
6
const httpz = @import ("httpz.zig" );
7
7
8
+ const posix = std .posix ;
8
9
const Allocator = std .mem .Allocator ;
9
10
10
11
const Conn = @import ("worker.zig" ).HTTPConn ;
@@ -26,7 +27,7 @@ pub fn reset() void {
26
27
27
28
pub fn getRandom () std.Random.DefaultPrng {
28
29
var seed : u64 = undefined ;
29
- std . posix .getrandom (std .mem .asBytes (& seed )) catch unreachable ;
30
+ posix .getrandom (std .mem .asBytes (& seed )) catch unreachable ;
30
31
return std .Random .DefaultPrng .init (seed );
31
32
}
32
33
@@ -49,25 +50,34 @@ pub const Context = struct {
49
50
_random : ? std.Random.DefaultPrng = null ,
50
51
51
52
pub fn allocInit (ctx_allocator : Allocator , config_ : httpz.Config ) Context {
52
- var pair : [2 ]c_int = undefined ;
53
- const rc = std .c .socketpair (std .posix .AF .LOCAL , std .posix .SOCK .STREAM , 0 , & pair );
54
- if (rc != 0 ) {
55
- @panic ("socketpair fail" );
53
+ var pair : [2 ]posix.socket_t = undefined ;
54
+ if (@import ("builtin" ).os .tag == .windows ) {
55
+ // create the socket pair manually on Windows because `socketpair` does not exist on Windows
56
+ // use INET instead of LOCAL because LOCAL is an alias for UNIX, which does not exist on Windows
57
+ setupFakeSocketPair (& pair [0 ], & pair [1 ]) catch | err | {
58
+ std .debug .print ("Failed to setup local client<->server: {}" , .{err });
59
+ @panic (@errorName (err ));
60
+ };
61
+ } else {
62
+ const rc = std .c .socketpair (posix .AF .LOCAL , posix .SOCK .STREAM , 0 , & pair );
63
+ if (rc != 0 ) {
64
+ @panic ("socketpair fail" );
65
+ }
56
66
}
57
67
58
68
{
59
- const timeout = std .mem .toBytes (std. posix.timeval {
69
+ const timeout = std .mem .toBytes (posix.timeval {
60
70
.sec = 0 ,
61
71
.usec = 20_000 ,
62
72
});
63
- std . posix .setsockopt (pair [0 ], std . posix .SOL .SOCKET , std . posix .SO .RCVTIMEO , & timeout ) catch unreachable ;
64
- std . posix .setsockopt (pair [0 ], std . posix .SOL .SOCKET , std . posix .SO .SNDTIMEO , & timeout ) catch unreachable ;
65
- std . posix .setsockopt (pair [1 ], std . posix .SOL .SOCKET , std . posix .SO .RCVTIMEO , & timeout ) catch unreachable ;
66
- std . posix .setsockopt (pair [1 ], std . posix .SOL .SOCKET , std . posix .SO .SNDTIMEO , & timeout ) catch unreachable ;
73
+ posix .setsockopt (pair [0 ], posix .SOL .SOCKET , posix .SO .RCVTIMEO , & timeout ) catch unreachable ;
74
+ posix .setsockopt (pair [0 ], posix .SOL .SOCKET , posix .SO .SNDTIMEO , & timeout ) catch unreachable ;
75
+ posix .setsockopt (pair [1 ], posix .SOL .SOCKET , posix .SO .RCVTIMEO , & timeout ) catch unreachable ;
76
+ posix .setsockopt (pair [1 ], posix .SOL .SOCKET , posix .SO .SNDTIMEO , & timeout ) catch unreachable ;
67
77
68
78
// for request.fuzz, which does up to an 8K write. Not sure why this has
69
79
// to be so much more but on linux, even a 10K SNDBUF results in WOULD_BLOCK.
70
- std . posix .setsockopt (pair [1 ], std . posix .SOL .SOCKET , std . posix .SO .SNDBUF , & std .mem .toBytes (@as (c_int , 20_000 ))) catch unreachable ;
80
+ posix .setsockopt (pair [1 ], posix .SOL .SOCKET , posix .SO .SNDBUF , & std .mem .toBytes (@as (c_int , 20_000 ))) catch unreachable ;
71
81
}
72
82
73
83
const server = std.net.Stream { .handle = pair [0 ] };
@@ -141,6 +151,29 @@ pub const Context = struct {
141
151
ctx_allocator .destroy (self .arena );
142
152
}
143
153
154
+ fn setupFakeSocketPair (server : * posix.socket_t , client : * posix.socket_t ) ! void {
155
+ const listener = posix .socket (posix .AF .INET , posix .SOCK .STREAM , 0 ) catch unreachable ;
156
+ defer posix .close (listener );
157
+
158
+ var address = try std .net .Address .parseIp ("127.0.0.1" , 0 );
159
+ try posix .setsockopt (listener , posix .SOL .SOCKET , posix .SO .REUSEADDR , & std .mem .toBytes (@as (c_int , 1 )));
160
+ try posix .bind (listener , & address .any , address .getOsSockLen ());
161
+ try posix .listen (listener , 0 );
162
+
163
+ var len : posix.socklen_t = @sizeOf (std .net .Address );
164
+ try posix .getsockname (listener , & address .any , & len );
165
+
166
+ var thread = try std .Thread .spawn (.{}, struct {
167
+ fn accept (l : posix.socket_t , server_side : * posix.socket_t ) ! void {
168
+ server_side .* = try posix .accept (l , null , null , 0 );
169
+ }
170
+ }.accept , .{ listener , server });
171
+
172
+ client .* = posix .socket (posix .AF .INET , posix .SOCK .STREAM , 0 ) catch unreachable ;
173
+ try posix .connect (client .* , & address .any , address .getOsSockLen ());
174
+ thread .join ();
175
+ }
176
+
144
177
// force the server side socket to be closed, which helps our reading-test
145
178
// know that there's no more data.
146
179
pub fn close (self : * Context ) void {
@@ -187,7 +220,7 @@ pub const Context = struct {
187
220
// should have no extra data
188
221
// let's check, with a shor timeout, which could let things slip, but
189
222
// else we slow down fuzz tests too much
190
- std . posix .setsockopt (self .client .handle , std . posix .SOL .SOCKET , std . posix .SO .RCVTIMEO , & std .mem .toBytes (std. posix.timeval {
223
+ posix .setsockopt (self .client .handle , posix .SOL .SOCKET , posix .SO .RCVTIMEO , & std .mem .toBytes (posix.timeval {
191
224
.sec = 0 ,
192
225
.usec = 1_000 ,
193
226
})) catch unreachable ;
@@ -200,7 +233,7 @@ pub const Context = struct {
200
233
};
201
234
try expectEqual (0 , n );
202
235
203
- std . posix .setsockopt (self .client .handle , std . posix .SOL .SOCKET , std . posix .SO .RCVTIMEO , & std .mem .toBytes (std. posix.timeval {
236
+ posix .setsockopt (self .client .handle , posix .SOL .SOCKET , posix .SO .RCVTIMEO , & std .mem .toBytes (posix.timeval {
204
237
.sec = 0 ,
205
238
.usec = 20_000 ,
206
239
})) catch unreachable ;
@@ -209,7 +242,7 @@ pub const Context = struct {
209
242
fn random (self : * Context ) std.Random {
210
243
if (self ._random == null ) {
211
244
var seed : u64 = undefined ;
212
- std . posix .getrandom (std .mem .asBytes (& seed )) catch unreachable ;
245
+ posix .getrandom (std .mem .asBytes (& seed )) catch unreachable ;
213
246
self ._random = std .Random .DefaultPrng .init (seed );
214
247
}
215
248
return self ._random .? .random ();
0 commit comments