authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-20 22:50:30-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2025-10-29 06:20:50-07:00
log0b5179a231c3f639f2fe3f2cafffa8b2cfd02482
tree8830becdca02499e6274c66a6b6bc90ff76c5c2f
parent34891b528e11afe1a1818a18d8ae01035542bb27

std.Io.Threaded: implement netAccept for Windows


3 files changed, 34 insertions(+), 46 deletions(-)

lib/std/Io/Threaded.zig+33-1
...@@ -244,7 +244,7 @@ pub fn io(t: *Threaded) Io {...@@ -244,7 +244,7 @@ pub fn io(t: *Threaded) Io {
244 },244 },
245 .netListenUnix = netListenUnix,245 .netListenUnix = netListenUnix,
246 .netAccept = switch (builtin.os.tag) {246 .netAccept = switch (builtin.os.tag) {
247 .windows => @panic("TODO"),247 .windows => netAcceptWindows,
248 else => netAcceptPosix,248 else => netAcceptPosix,
249 },249 },
250 .netBindIp = switch (builtin.os.tag) {250 .netBindIp = switch (builtin.os.tag) {
...@@ -3288,6 +3288,38 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve...@@ -3288,6 +3288,38 @@ fn netAcceptPosix(userdata: ?*anyopaque, listen_fd: net.Socket.Handle) net.Serve
3288 } };3288 } };
3289}3289}
32903290
3291fn netAcceptWindows(userdata: ?*anyopaque, listen_handle: net.Socket.Handle) net.Server.AcceptError!net.Stream {
3292 if (!have_networking) return error.NetworkDown;
3293 const t: *Threaded = @ptrCast(@alignCast(userdata));
3294 var storage: WsaAddress = undefined;
3295 var addr_len: i32 = @sizeOf(WsaAddress);
3296 while (true) {
3297 try t.checkCancel();
3298 const rc = ws2_32.accept(listen_handle, &storage.any, &addr_len);
3299 if (rc != windows.ws2_32.INVALID_SOCKET) return .{ .socket = .{
3300 .handle = rc,
3301 .address = addressFromWsa(&storage),
3302 } };
3303 switch (windows.ws2_32.WSAGetLastError()) {
3304 .EINTR => continue,
3305 .ECANCELLED, .E_CANCELLED => return error.Canceled,
3306 .NOTINITIALISED => {
3307 try initializeWsa(t);
3308 continue;
3309 },
3310 .ECONNRESET => return error.ConnectionAborted,
3311 .EFAULT => |err| return wsaErrorBug(err),
3312 .ENOTSOCK => |err| return wsaErrorBug(err),
3313 .EINVAL => |err| return wsaErrorBug(err),
3314 .EMFILE => return error.ProcessFdQuotaExceeded,
3315 .ENETDOWN => return error.NetworkDown,
3316 .ENOBUFS => return error.SystemResources,
3317 .EOPNOTSUPP => |err| return wsaErrorBug(err),
3318 else => |err| return windows.unexpectedWSAError(err),
3319 }
3320 }
3321}
3322
3291fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {3323fn netReadPosix(userdata: ?*anyopaque, fd: net.Socket.Handle, data: [][]u8) net.Stream.Reader.Error!usize {
3292 const t: *Threaded = @ptrCast(@alignCast(userdata));3324 const t: *Threaded = @ptrCast(@alignCast(userdata));
32933325
lib/std/os/windows.zig-5
...@@ -1574,11 +1574,6 @@ pub fn GetFileAttributesW(lpFileName: [*:0]const u16) GetFileAttributesError!DWO...@@ -1574,11 +1574,6 @@ pub fn GetFileAttributesW(lpFileName: [*:0]const u16) GetFileAttributesError!DWO
1574 return rc;1574 return rc;
1575}1575}
15761576
1577pub fn accept(s: ws2_32.SOCKET, name: ?*ws2_32.sockaddr, namelen: ?*ws2_32.socklen_t) ws2_32.SOCKET {
1578 assert((name == null) == (namelen == null));
1579 return ws2_32.accept(s, name, @as(?*i32, @ptrCast(namelen)));
1580}
1581
1582pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.socklen_t) i32 {1577pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.socklen_t) i32 {
1583 return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));1578 return ws2_32.getpeername(s, name, @as(*i32, @ptrCast(namelen)));
1584}1579}
lib/std/posix.zig+1-40
...@@ -3471,31 +3471,10 @@ pub fn listen(sock: socket_t, backlog: u31) ListenError!void {...@@ -3471,31 +3471,10 @@ pub fn listen(sock: socket_t, backlog: u31) ListenError!void {
34713471
3472pub const AcceptError = std.Io.net.Server.AcceptError;3472pub const AcceptError = std.Io.net.Server.AcceptError;
34733473
3474/// Accept a connection on a socket.
3475/// If `sockfd` is opened in non blocking mode, the function will
3476/// return error.WouldBlock when EAGAIN is received.
3477pub fn accept(3474pub fn accept(
3478 /// This argument is a socket that has been created with `socket`, bound to a local address
3479 /// with `bind`, and is listening for connections after a `listen`.
3480 sock: socket_t,3475 sock: socket_t,
3481 /// This argument is a pointer to a sockaddr structure. This structure is filled in with the
3482 /// address of the peer socket, as known to the communications layer. The exact format of the
3483 /// address returned addr is determined by the socket's address family (see `socket` and the
3484 /// respective protocol man pages).
3485 addr: ?*sockaddr,3476 addr: ?*sockaddr,
3486 /// This argument is a value-result argument: the caller must initialize it to contain the
3487 /// size (in bytes) of the structure pointed to by addr; on return it will contain the actual size
3488 /// of the peer address.
3489 ///
3490 /// The returned address is truncated if the buffer provided is too small; in this case, `addr_size`
3491 /// will return a value greater than was supplied to the call.
3492 addr_size: ?*socklen_t,3477 addr_size: ?*socklen_t,
3493 /// The following values can be bitwise ORed in flags to obtain different behavior:
3494 /// * `SOCK.NONBLOCK` - Set the `NONBLOCK` file status flag on the open file description (see `open`)
3495 /// referred to by the new file descriptor. Using this flag saves extra calls to `fcntl` to achieve
3496 /// the same result.
3497 /// * `SOCK.CLOEXEC` - Set the close-on-exec (`FD_CLOEXEC`) flag on the new file descriptor. See the
3498 /// description of the `CLOEXEC` flag in `open` for reasons why this may be useful.
3499 flags: u32,3478 flags: u32,
3500) AcceptError!socket_t {3479) AcceptError!socket_t {
3501 const have_accept4 = !(builtin.target.os.tag.isDarwin() or native_os == .windows or native_os == .haiku);3480 const have_accept4 = !(builtin.target.os.tag.isDarwin() or native_os == .windows or native_os == .haiku);
...@@ -3504,29 +3483,11 @@ pub fn accept(...@@ -3504,29 +3483,11 @@ pub fn accept(
3504 const accepted_sock: socket_t = while (true) {3483 const accepted_sock: socket_t = while (true) {
3505 const rc = if (have_accept4)3484 const rc = if (have_accept4)
3506 system.accept4(sock, addr, addr_size, flags)3485 system.accept4(sock, addr, addr_size, flags)
3507 else if (native_os == .windows)
3508 windows.accept(sock, addr, addr_size)
3509 else3486 else
3510 system.accept(sock, addr, addr_size);3487 system.accept(sock, addr, addr_size);
35113488
3512 if (native_os == .windows) {3489 if (native_os == .windows) {
3513 if (rc == windows.ws2_32.INVALID_SOCKET) {3490 @compileError("use std.Io instead");
3514 switch (windows.ws2_32.WSAGetLastError()) {
3515 .NOTINITIALISED => unreachable, // not initialized WSA
3516 .ECONNRESET => return error.ConnectionResetByPeer,
3517 .EFAULT => unreachable,
3518 .ENOTSOCK => return error.FileDescriptorNotASocket,
3519 .EINVAL => return error.SocketNotListening,
3520 .EMFILE => return error.ProcessFdQuotaExceeded,
3521 .ENETDOWN => return error.NetworkDown,
3522 .ENOBUFS => return error.FileDescriptorNotASocket,
3523 .EOPNOTSUPP => return error.OperationNotSupported,
3524 .EWOULDBLOCK => return error.WouldBlock,
3525 else => |err| return windows.unexpectedWSAError(err),
3526 }
3527 } else {
3528 break rc;
3529 }
3530 } else {3491 } else {
3531 switch (errno(rc)) {3492 switch (errno(rc)) {
3532 .SUCCESS => break @intCast(rc),3493 .SUCCESS => break @intCast(rc),