From 3600508fe18ecc61ea889a65127a2641a76c2933 Mon Sep 17 00:00:00 2001 From: lithdew Date: Wed, 12 May 2021 22:43:34 +0900 Subject: [PATCH 01/11] x/io, x/os: async i/o reactor, cross-platform socket syscalls and bits Cross-platform versions of msghdr, sendmsg, recvmsg, linger, and iovec were provided based on findings from glibc, musl, and Microsoft's documentation. Implemented initial Reactor interface for epoll (linux) which wraps around I/O reactor subsystems such as epoll, kqueue, select, etc. across different platforms. The Reactor interface allows for driving async I/O in Zig applications. A test was added for the Reactor interface to drive a TCP client/listener socket pair. A greatest-common-subset of possible socket initialization flags (close socket on exec syscalls, initialize socket to be non-blocking) were implemented. A test was added for using sendmsg/recvmsg syscalls across different platforms for a TCP client/listener socket pair. --- lib/std/os.zig | 2 +- lib/std/os/bits/dragonfly.zig | 9 -- lib/std/os/bits/freebsd.zig | 46 ------- lib/std/os/bits/haiku.zig | 46 ------- lib/std/os/bits/linux.zig | 4 +- lib/std/os/bits/linux/arm-eabi.zig | 20 --- lib/std/os/bits/linux/arm64.zig | 24 ---- lib/std/os/bits/linux/i386.zig | 20 --- lib/std/os/bits/linux/powerpc.zig | 20 --- lib/std/os/bits/linux/powerpc64.zig | 20 --- lib/std/os/bits/linux/sparc64.zig | 20 --- lib/std/os/bits/linux/x86_64.zig | 24 ---- lib/std/os/bits/netbsd.zig | 46 ------- lib/std/os/bits/openbsd.zig | 46 ------- lib/std/os/windows/ws2_32.zig | 30 +--- lib/std/x.zig | 1 + lib/std/x/net/tcp.zig | 74 +++++++--- lib/std/x/os/io.zig | 205 ++++++++++++++++++++++++++++ lib/std/x/os/socket.zig | 199 +++++++++++++++++++++++++++ lib/std/x/os/socket_posix.zig | 77 ++++++----- lib/std/x/os/socket_windows.zig | 66 +++++---- 21 files changed, 548 insertions(+), 451 deletions(-) create mode 100644 lib/std/x/os/io.zig diff --git a/lib/std/os.zig b/lib/std/os.zig index 2fe7ba9c5a91a04b6893da80181bb7f0c4dd4a19..4ed0be8f62c9ae501d89e695e7ebfea24c8f382b 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -4994,7 +4994,7 @@ pub fn sendmsg( /// The file descriptor of the sending socket. sockfd: socket_t, /// Message header and iovecs - msg: msghdr_const, + msg: std.x.os.Socket.Message, flags: u32, ) SendMsgError!usize { while (true) { diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index 7686fec96e8369456fb656fd91549fb8d1c03179..f8f89bd07aa0f14fe82691a2160b572e194edaad 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -768,15 +768,6 @@ pub const dl_phdr_info = extern struct { dlpi_phdr: [*]std.elf.Phdr, dlpi_phnum: u16, }; -pub const msghdr = extern struct { - msg_name: ?*c_void, - msg_namelen: socklen_t, - msg_iov: [*c]iovec, - msg_iovlen: c_int, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: c_int, -}; pub const cmsghdr = extern struct { cmsg_len: socklen_t, cmsg_level: c_int, diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index a679b0fe702422d940b4eb63d68623e14841a96c..cd32972b89164c0994b204397f2787cddad049d0 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -82,52 +82,6 @@ pub const Flock = extern struct { __unused: [4]u8, }; -pub const msghdr = extern struct { - /// optional address - msg_name: ?*sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec, - - /// # elements in msg_iov - msg_iovlen: i32, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - /// optional address - msg_name: ?*const sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec_const, - - /// # elements in msg_iov - msg_iovlen: i32, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: i32, -}; - pub const libc_stat = extern struct { dev: dev_t, ino: ino_t, diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig index c9a420e95718f0e8d2b6427cd54ccbe2c8480216..b229a4744d8a498cfb4f747fe4dcf2a116d53b55 100644 --- a/lib/std/os/bits/haiku.zig +++ b/lib/std/os/bits/haiku.zig @@ -73,52 +73,6 @@ pub const Flock = extern struct { __unused: [4]u8, }; -pub const msghdr = extern struct { - /// optional address - msg_name: ?*sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec, - - /// # elements in msg_iov - msg_iovlen: i32, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - /// optional address - msg_name: ?*const sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec_const, - - /// # elements in msg_iov - msg_iovlen: i32, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: i32, -}; - pub const off_t = i64; pub const ino_t = u64; diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 72ea62c32c53f8d6e1cf227ae29b73b78436e725..5ecdcf24a34a32063ef9a67a7aaf0280c26ef2f4 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -1180,12 +1180,12 @@ pub const sockaddr_un = extern struct { }; pub const mmsghdr = extern struct { - msg_hdr: msghdr, + msg_hdr: std.x.os.Socket.Message, msg_len: u32, }; pub const mmsghdr_const = extern struct { - msg_hdr: msghdr_const, + msg_hdr: std.x.os.Socket.Message, msg_len: u32, }; diff --git a/lib/std/os/bits/linux/arm-eabi.zig b/lib/std/os/bits/linux/arm-eabi.zig index 335ea074ec2ccb075c299485202a6e8048d3a1b3..6f596ab3c5eebf0b66c17e2c0c19dab76f6d27fc 100644 --- a/lib/std/os/bits/linux/arm-eabi.zig +++ b/lib/std/os/bits/linux/arm-eabi.zig @@ -526,26 +526,6 @@ pub const Flock = extern struct { __unused: [4]u8, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: i32, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: i32, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: i32, -}; - pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/arm64.zig b/lib/std/os/bits/linux/arm64.zig index e0771e7f662e4f0619b9042958edd3035a0c044a..46126b69fd02e21492c6eec91c122a5d127f4bf1 100644 --- a/lib/std/os/bits/linux/arm64.zig +++ b/lib/std/os/bits/linux/arm64.zig @@ -395,30 +395,6 @@ pub const Flock = extern struct { __unused: [4]u8, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: i32, - __pad1: i32 = 0, - msg_control: ?*c_void, - msg_controllen: socklen_t, - __pad2: socklen_t = 0, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: i32, - __pad1: i32 = 0, - msg_control: ?*c_void, - msg_controllen: socklen_t, - __pad2: socklen_t = 0, - msg_flags: i32, -}; - pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/i386.zig b/lib/std/os/bits/linux/i386.zig index f8dadb8a6026c5895041b93a5ce594dfd369b667..7e5f7935a30dc9a9718a0ddbc5c6ad2bc1fbaa8a 100644 --- a/lib/std/os/bits/linux/i386.zig +++ b/lib/std/os/bits/linux/i386.zig @@ -523,26 +523,6 @@ pub const Flock = extern struct { l_pid: pid_t, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: i32, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: i32, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: i32, -}; - pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/powerpc.zig b/lib/std/os/bits/linux/powerpc.zig index 96908cb7141ef4b585aa3efc8062cd79cbb8a728..908593ae908ea04c16c3ea9301a11600d07cf013 100644 --- a/lib/std/os/bits/linux/powerpc.zig +++ b/lib/std/os/bits/linux/powerpc.zig @@ -515,26 +515,6 @@ pub const Flock = extern struct { l_pid: pid_t, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: usize, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: usize, - msg_control: ?*c_void, - msg_controllen: socklen_t, - msg_flags: i32, -}; - pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/powerpc64.zig b/lib/std/os/bits/linux/powerpc64.zig index 52b9109247f1ee66120018d0c68f4fa289c807bc..d7c554fb867343307a478cc3511ab054cac8f75b 100644 --- a/lib/std/os/bits/linux/powerpc64.zig +++ b/lib/std/os/bits/linux/powerpc64.zig @@ -491,26 +491,6 @@ pub const Flock = extern struct { __unused: [4]u8, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: usize, - msg_control: ?*c_void, - msg_controllen: usize, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: usize, - msg_control: ?*c_void, - msg_controllen: usize, - msg_flags: i32, -}; - pub const blksize_t = i64; pub const nlink_t = u64; pub const time_t = i64; diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index 5c67b745f003c6989da85b932695b75cc4c4dcba..e40fb994fd118dc573d700e737af5d669b47ba90 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -465,26 +465,6 @@ pub const Flock = extern struct { l_pid: pid_t, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: u64, - msg_control: ?*c_void, - msg_controllen: u64, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: u64, - msg_control: ?*c_void, - msg_controllen: u64, - msg_flags: i32, -}; - pub const off_t = i64; pub const ino_t = u64; pub const mode_t = u32; diff --git a/lib/std/os/bits/linux/x86_64.zig b/lib/std/os/bits/linux/x86_64.zig index 30e5af384f9c6a96a353df448e5740589b59501c..b82c1469e9012668ca2c9e09596d99693cd8e426 100644 --- a/lib/std/os/bits/linux/x86_64.zig +++ b/lib/std/os/bits/linux/x86_64.zig @@ -489,30 +489,6 @@ pub const Flock = extern struct { l_pid: pid_t, }; -pub const msghdr = extern struct { - msg_name: ?*sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec, - msg_iovlen: i32, - __pad1: i32 = 0, - msg_control: ?*c_void, - msg_controllen: socklen_t, - __pad2: socklen_t = 0, - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - msg_name: ?*const sockaddr, - msg_namelen: socklen_t, - msg_iov: [*]iovec_const, - msg_iovlen: i32, - __pad1: i32 = 0, - msg_control: ?*c_void, - msg_controllen: socklen_t, - __pad2: socklen_t = 0, - msg_flags: i32, -}; - pub const off_t = i64; pub const ino_t = u64; pub const dev_t = u64; diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index 221baad8643e15583ffe5a84d989826a0d6f6577..0a3ea0d8077662d912466a1a207ef407bc23c076 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -108,52 +108,6 @@ pub const EAI = enum(c_int) { pub const EAI_MAX = 15; -pub const msghdr = extern struct { - /// optional address - msg_name: ?*sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec, - - /// # elements in msg_iov - msg_iovlen: i32, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: i32, -}; - -pub const msghdr_const = extern struct { - /// optional address - msg_name: ?*const sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec_const, - - /// # elements in msg_iov - msg_iovlen: i32, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: i32, -}; - pub const libc_stat = extern struct { dev: dev_t, mode: mode_t, diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig index 8d42300817981059196254c371feae9f7e59aee9..44fe9cc5f2d683386b2a96b24202807b23b6d916 100644 --- a/lib/std/os/bits/openbsd.zig +++ b/lib/std/os/bits/openbsd.zig @@ -124,52 +124,6 @@ pub const EAI = enum(c_int) { pub const EAI_MAX = 15; -pub const msghdr = extern struct { - /// optional address - msg_name: ?*sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec, - - /// # elements in msg_iov - msg_iovlen: c_uint, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: c_int, -}; - -pub const msghdr_const = extern struct { - /// optional address - msg_name: ?*const sockaddr, - - /// size of address - msg_namelen: socklen_t, - - /// scatter/gather array - msg_iov: [*]iovec_const, - - /// # elements in msg_iov - msg_iovlen: c_uint, - - /// ancillary data - msg_control: ?*c_void, - - /// ancillary data buffer len - msg_controllen: socklen_t, - - /// flags on received message - msg_flags: c_int, -}; - pub const libc_stat = extern struct { mode: mode_t, dev: dev_t, diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index 15aa0d487ff2a3e5ee4200a0caaacd79ca4f44de..39f68bb234f53e3779a1a80379cc5050b007b370 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -3,6 +3,7 @@ // This file is part of [zig](https://ziglang.org/), which is MIT licensed. // The MIT license requires this copyright notice to be included in all copies // and substantial portions of the software. +const std = @import("../../std.zig"); usingnamespace @import("bits.zig"); pub const SOCKET = *opaque {}; @@ -1093,27 +1094,6 @@ pub const WSABUF = extern struct { buf: [*]u8, }; -pub const msghdr = WSAMSG; -pub const msghdr_const = WSAMSG_const; - -pub const WSAMSG_const = extern struct { - name: *const sockaddr, - namelen: INT, - lpBuffers: [*]WSABUF, - dwBufferCount: DWORD, - Control: WSABUF, - dwFlags: DWORD, -}; - -pub const WSAMSG = extern struct { - name: *sockaddr, - namelen: INT, - lpBuffers: [*]WSABUF, - dwBufferCount: DWORD, - Control: WSABUF, - dwFlags: DWORD, -}; - pub const WSAPOLLFD = pollfd; pub const pollfd = extern struct { @@ -1163,7 +1143,7 @@ pub const LPFN_GETACCEPTEXSOCKADDRS = fn ( pub const LPFN_WSASENDMSG = fn ( s: SOCKET, - lpMsg: *const WSAMSG_const, + lpMsg: *const std.x.os.Socket.Message, dwFlags: u32, lpNumberOfBytesSent: ?*u32, lpOverlapped: ?*OVERLAPPED, @@ -1172,7 +1152,7 @@ pub const LPFN_WSASENDMSG = fn ( pub const LPFN_WSARECVMSG = fn ( s: SOCKET, - lpMsg: *WSAMSG, + lpMsg: *std.x.os.Socket.Message, lpdwNumberOfBytesRecv: ?*u32, lpOverlapped: ?*OVERLAPPED, lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE, @@ -2046,7 +2026,7 @@ pub extern "ws2_32" fn WSASend( pub extern "ws2_32" fn WSASendMsg( s: SOCKET, - lpMsg: *const WSAMSG_const, + lpMsg: *const std.x.os.Socket.Message, dwFlags: u32, lpNumberOfBytesSent: ?*u32, lpOverlapped: ?*OVERLAPPED, @@ -2055,7 +2035,7 @@ pub extern "ws2_32" fn WSASendMsg( pub extern "ws2_32" fn WSARecvMsg( s: SOCKET, - lpMsg: *WSAMSG, + lpMsg: *std.x.os.Socket.Message, lpdwNumberOfBytesRecv: ?*u32, lpOverlapped: ?*OVERLAPPED, lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE, diff --git a/lib/std/x.zig b/lib/std/x.zig index 022261bf3b400acc6ea9059439e9ceedb59c27b5..3ac8b10f4a04a4baa7c6cca9559ba9afd6f7ee62 100644 --- a/lib/std/x.zig +++ b/lib/std/x.zig @@ -8,6 +8,7 @@ const std = @import("std.zig"); pub const os = struct { pub const Socket = @import("x/os/socket.zig").Socket; + pub usingnamespace @import("x/os/io.zig"); pub usingnamespace @import("x/os/net.zig"); }; diff --git a/lib/std/x/net/tcp.zig b/lib/std/x/net/tcp.zig index f0e341234a575346097964d0f7bc189822d21efd..abf1191dfd98c0b5697535a3b208418c3ec35763 100644 --- a/lib/std/x/net/tcp.zig +++ b/lib/std/x/net/tcp.zig @@ -18,6 +18,7 @@ const testing = std.testing; const IPv4 = std.x.os.IPv4; const IPv6 = std.x.os.IPv6; const Socket = std.x.os.Socket; +const Buffer = std.x.os.Buffer; /// A generic TCP socket abstraction. const tcp = @This(); @@ -82,12 +83,13 @@ pub const Client = struct { }; /// Opens a new client. - pub fn init(domain: tcp.Domain, flags: u32) !Client { + pub fn init(domain: tcp.Domain, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Client { return Client{ .socket = try Socket.init( @enumToInt(domain), - os.SOCK_STREAM | flags, + os.SOCK_STREAM, os.IPPROTO_TCP, + flags, ), }; } @@ -143,14 +145,14 @@ pub const Client = struct { /// Writes multiple I/O vectors with a prepended message header to the socket /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. - pub fn writeVectorized(self: Client, msg: os.msghdr_const, flags: u32) !usize { + pub fn writeVectorized(self: Client, msg: Socket.Message, flags: u32) !usize { return self.socket.writeVectorized(msg, flags); } /// Read multiple I/O vectors with a prepended message header from the socket /// with a set of flags specified. It returns the number of bytes that were /// read into the buffer provided. - pub fn readVectorized(self: Client, msg: *os.msghdr, flags: u32) !usize { + pub fn readVectorized(self: Client, msg: *Socket.Message, flags: u32) !usize { return self.socket.readVectorized(msg, flags); } @@ -244,12 +246,13 @@ pub const Listener = struct { socket: Socket, /// Opens a new listener. - pub fn init(domain: tcp.Domain, flags: u32) !Listener { + pub fn init(domain: tcp.Domain, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Listener { return Listener{ .socket = try Socket.init( @enumToInt(domain), - os.SOCK_STREAM | flags, + os.SOCK_STREAM, os.IPPROTO_TCP, + flags, ), }; } @@ -278,7 +281,7 @@ pub const Listener = struct { /// Accept a pending incoming connection queued to the kernel backlog /// of the listener's socket. - pub fn accept(self: Listener, flags: u32) !tcp.Connection { + pub fn accept(self: Listener, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !tcp.Connection { return tcp.Connection.from(try self.socket.accept(flags)); } @@ -324,7 +327,7 @@ pub const Listener = struct { test "tcp: create client/listener pair" { if (builtin.os.tag == .wasi) return error.SkipZigTest; - const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); + const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); @@ -336,19 +339,19 @@ test "tcp: create client/listener pair" { .ipv6 => |*ipv6| ipv6.host = IPv6.localhost, } - const client = try tcp.Client.init(.ip, os.SOCK_CLOEXEC); + const client = try tcp.Client.init(.ip, .{ .close_on_exec = true }); defer client.deinit(); try client.connect(binded_address); - const conn = try listener.accept(os.SOCK_CLOEXEC); + const conn = try listener.accept(.{ .close_on_exec = true }); defer conn.deinit(); } -test "tcp/client: set read timeout of 1 millisecond on blocking client" { +test "tcp/client: 1ms read timeout" { if (builtin.os.tag == .wasi) return error.SkipZigTest; - const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); + const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); @@ -360,23 +363,62 @@ test "tcp/client: set read timeout of 1 millisecond on blocking client" { .ipv6 => |*ipv6| ipv6.host = IPv6.localhost, } - const client = try tcp.Client.init(.ip, os.SOCK_CLOEXEC); + const client = try tcp.Client.init(.ip, .{ .close_on_exec = true }); defer client.deinit(); try client.connect(binded_address); try client.setReadTimeout(1); - const conn = try listener.accept(os.SOCK_CLOEXEC); + const conn = try listener.accept(.{ .close_on_exec = true }); defer conn.deinit(); var buf: [1]u8 = undefined; try testing.expectError(error.WouldBlock, client.reader(0).read(&buf)); } +test "tcp/client: read and write multiple vectors" { + if (builtin.os.tag == .wasi) return error.SkipZigTest; + + const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); + defer listener.deinit(); + + try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); + try listener.listen(128); + + var binded_address = try listener.getLocalAddress(); + switch (binded_address) { + .ipv4 => |*ipv4| ipv4.host = IPv4.localhost, + .ipv6 => |*ipv6| ipv6.host = IPv6.localhost, + } + + const client = try tcp.Client.init(.ip, .{ .close_on_exec = true }); + defer client.deinit(); + + try client.connect(binded_address); + + const conn = try listener.accept(.{ .close_on_exec = true }); + defer conn.deinit(); + + const message = "hello world"; + _ = try conn.client.writeVectorized(Socket.Message.fromBuffers(&[_]Buffer{ + Buffer.from(message[0 .. message.len / 2]), + Buffer.from(message[message.len / 2 ..]), + }), 0); + + var buf: [message.len]u8 = undefined; + var msg = Socket.Message.fromBuffers(&[_]Buffer{ + Buffer.from(buf[0 .. message.len / 2]), + Buffer.from(buf[message.len / 2 ..]), + }); + _ = try client.readVectorized(&msg, 0); + + try testing.expectEqualStrings(message, &buf); +} + test "tcp/listener: bind to unspecified ipv4 address" { if (builtin.os.tag == .wasi) return error.SkipZigTest; - const listener = try tcp.Listener.init(.ip, os.SOCK_CLOEXEC); + const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); @@ -389,7 +431,7 @@ test "tcp/listener: bind to unspecified ipv4 address" { test "tcp/listener: bind to unspecified ipv6 address" { if (builtin.os.tag == .wasi) return error.SkipZigTest; - const listener = try tcp.Listener.init(.ipv6, os.SOCK_CLOEXEC); + const listener = try tcp.Listener.init(.ipv6, .{ .close_on_exec = true }); defer listener.deinit(); try listener.bind(ip.Address.initIPv6(IPv6.unspecified, 0)); diff --git a/lib/std/x/os/io.zig b/lib/std/x/os/io.zig new file mode 100644 index 0000000000000000000000000000000000000000..597f7d268cebe20792f72f0626154db93fea418e --- /dev/null +++ b/lib/std/x/os/io.zig @@ -0,0 +1,205 @@ +const std = @import("../../std.zig"); + +const os = std.os; +const mem = std.mem; +const builtin = std.builtin; +const testing = std.testing; + +/// POSIX `iovec`, or Windows `WSABUF`. The difference between the two are the ordering +/// of fields, alongside the length being represented as either a ULONG or a size_t. +pub const Buffer = if (builtin.os.tag == .windows) + extern struct { + len: c_ulong, + ptr: usize, + + pub fn from(slice: []const u8) Buffer { + return .{ .len = @intCast(c_ulong, slice.len), .ptr = @ptrToInt(slice.ptr) }; + } + + pub fn into(self: Buffer) []const u8 { + return @intToPtr([*]const u8, self.ptr)[0..self.len]; + } + + pub fn intoMutable(self: Buffer) []u8 { + return @intToPtr([*]u8, self.ptr)[0..self.len]; + } + } +else + extern struct { + ptr: usize, + len: usize, + + pub fn from(slice: []const u8) Buffer { + return .{ .ptr = @ptrToInt(slice.ptr), .len = slice.len }; + } + + pub fn into(self: Buffer) []const u8 { + return @intToPtr([*]const u8, self.ptr)[0..self.len]; + } + + pub fn intoMutable(self: Buffer) []u8 { + return @intToptr([*]u8, self.ptr)[0..self.len]; + } + }; + +pub const Reactor = struct { + pub const InitFlags = enum { + close_on_exec, + }; + + pub const Event = struct { + data: usize, + is_error: bool, + is_hup: bool, + is_readable: bool, + is_writable: bool, + }; + + pub const Interest = struct { + hup: bool = false, + oneshot: bool = false, + readable: bool = false, + writable: bool = false, + }; + + fd: os.fd_t, + + pub fn init(flags: std.enums.EnumFieldStruct(Reactor.InitFlags, bool, false)) !Reactor { + var raw_flags: u32 = 0; + const set = std.EnumSet(Reactor.InitFlags).init(flags); + if (set.contains(.close_on_exec)) raw_flags |= os.EPOLL_CLOEXEC; + return Reactor{ .fd = try os.epoll_create1(raw_flags) }; + } + + pub fn deinit(self: Reactor) void { + os.close(self.fd); + } + + pub fn update(self: Reactor, fd: os.fd_t, identifier: usize, interest: Reactor.Interest) !void { + var flags: u32 = 0; + flags |= if (interest.oneshot) os.EPOLLONESHOT else os.EPOLLET; + if (interest.hup) flags |= os.EPOLLRDHUP; + if (interest.readable) flags |= os.EPOLLIN; + if (interest.writable) flags |= os.EPOLLOUT; + + const event = &os.epoll_event{ + .events = flags, + .data = .{ .ptr = identifier }, + }; + + os.epoll_ctl(self.fd, os.EPOLL_CTL_MOD, fd, event) catch |err| switch (err) { + error.FileDescriptorNotRegistered => try os.epoll_ctl(self.fd, os.EPOLL_CTL_ADD, fd, event), + else => return err, + }; + } + + pub fn poll(self: Reactor, comptime max_num_events: comptime_int, closure: anytype, timeout_milliseconds: ?u64) !void { + var events: [max_num_events]os.epoll_event = undefined; + + const num_events = os.epoll_wait(self.fd, &events, if (timeout_milliseconds) |ms| @intCast(i32, ms) else -1); + for (events[0..num_events]) |ev| { + const is_error = ev.events & os.EPOLLERR != 0; + const is_hup = ev.events & (os.EPOLLHUP | os.EPOLLRDHUP) != 0; + const is_readable = ev.events & os.EPOLLIN != 0; + const is_writable = ev.events & os.EPOLLOUT != 0; + + try closure.call(Reactor.Event{ + .data = ev.data.ptr, + .is_error = is_error, + .is_hup = is_hup, + .is_readable = is_readable, + .is_writable = is_writable, + }); + } + } +}; + +test "reactor/linux: drive async tcp client/listener pair" { + if (builtin.os.tag != .linux) return error.SkipZigTest; + + const ip = std.x.net.ip; + const tcp = std.x.net.tcp; + + const IPv4 = std.x.os.IPv4; + const IPv6 = std.x.os.IPv6; + const Socket = std.x.os.Socket; + + const reactor = try Reactor.init(.{ .close_on_exec = true }); + defer reactor.deinit(); + + const listener = try tcp.Listener.init(.ip, .{ + .close_on_exec = true, + .nonblocking = true, + }); + defer listener.deinit(); + + try reactor.update(listener.socket.fd, 0, .{ .readable = true }); + try reactor.poll(1, struct { + fn call(event: Reactor.Event) !void { + try testing.expectEqual(Reactor.Event{ + .data = 0, + .is_error = false, + .is_hup = true, + .is_readable = false, + .is_writable = false, + }, event); + } + }, null); + + try listener.bind(ip.Address.initIPv4(IPv4.unspecified, 0)); + try listener.listen(128); + + var binded_address = try listener.getLocalAddress(); + switch (binded_address) { + .ipv4 => |*ipv4| ipv4.host = IPv4.localhost, + .ipv6 => |*ipv6| ipv6.host = IPv6.localhost, + } + + const client = try tcp.Client.init(.ip, .{ + .close_on_exec = true, + .nonblocking = true, + }); + defer client.deinit(); + + try reactor.update(client.socket.fd, 1, .{ .readable = true, .writable = true }); + try reactor.poll(1, struct { + fn call(event: Reactor.Event) !void { + try testing.expectEqual(Reactor.Event{ + .data = 1, + .is_error = false, + .is_hup = true, + .is_readable = false, + .is_writable = true, + }, event); + } + }, null); + + client.connect(binded_address) catch |err| switch (err) { + error.WouldBlock => {}, + else => return err, + }; + + try reactor.poll(1, struct { + fn call(event: Reactor.Event) !void { + try testing.expectEqual(Reactor.Event{ + .data = 1, + .is_error = false, + .is_hup = false, + .is_readable = false, + .is_writable = true, + }, event); + } + }, null); + + try reactor.poll(1, struct { + fn call(event: Reactor.Event) !void { + try testing.expectEqual(Reactor.Event{ + .data = 0, + .is_error = false, + .is_hup = false, + .is_readable = true, + .is_writable = false, + }, event); + } + }, null); +} diff --git a/lib/std/x/os/socket.zig b/lib/std/x/os/socket.zig index 963a1adca6ed386972cc791727ba1f5dfb66c864..05bd0499d1384758fb730ca0cb26e3467c310ac3 100644 --- a/lib/std/x/os/socket.zig +++ b/lib/std/x/os/socket.zig @@ -11,8 +11,13 @@ const os = std.os; const fmt = std.fmt; const mem = std.mem; const time = std.time; +const meta = std.meta; const builtin = std.builtin; +const Buffer = std.x.os.Buffer; + +const assert = std.debug.assert; + /// A generic, cross-platform socket abstraction. pub const Socket = struct { /// A socket-address pair. @@ -29,6 +34,32 @@ pub const Socket = struct { /// A generic socket address abstraction. It is safe to directly access and modify /// the fields of a `Socket.Address`. pub const Address = union(enum) { + pub const Native = struct { + pub const requires_prepended_length = builtin.os.getVersionRange() == .semver; + pub const Length = if (requires_prepended_length) u8 else [0]u8; + + pub const Family = if (requires_prepended_length) u8 else c_ushort; + + /// POSIX `sockaddr_storage`. The expected size and alignment is specified in IETF RFC 2553. + pub const Storage = extern struct { + pub const expected_size = 128; + pub const expected_alignment = 8; + + pub const padding_size = expected_size - + mem.alignForward(@sizeOf(Address.Native.Length), expected_alignment) - + mem.alignForward(@sizeOf(Address.Native.Family), expected_alignment); + + len: Address.Native.Length align(expected_alignment) = undefined, + family: Address.Native.Family align(expected_alignment) = undefined, + padding: [padding_size]u8 align(expected_alignment) = undefined, + + comptime { + assert(@sizeOf(Storage) == Storage.expected_size); + assert(@alignOf(Storage) == Storage.expected_alignment); + } + }; + }; + ipv4: net.IPv4.Address, ipv6: net.IPv6.Address, @@ -107,6 +138,174 @@ pub const Socket = struct { } }; + /// POSIX `msghdr`. Denotes a destination address, set of buffers, control data, and flags. Ported + /// directly from musl. + pub const Message = if (builtin.os.isAtLeast(.windows, .vista) != null and builtin.os.isAtLeast(.windows, .vista).?) + extern struct { + name: usize = @ptrToInt(@as(?[*]u8, null)), + name_len: c_int = 0, + + buffers: usize = undefined, + buffers_len: c_ulong = undefined, + + control: Buffer = .{ + .ptr = @ptrToInt(@as(?[*]u8, null)), + .len = 0, + }, + flags: c_ulong = 0, + + pub usingnamespace MessageMixin(Message); + } + else if (builtin.os.tag == .windows) + extern struct { + name: usize = @ptrToInt(@as(?[*]u8, null)), + name_len: c_int = 0, + + buffers: usize = undefined, + buffers_len: u32 = undefined, + + control: Buffer = .{ + .ptr = @ptrToInt(@as(?[*]u8, null)), + .len = 0, + }, + flags: u32 = 0, + + pub usingnamespace MessageMixin(Message); + } + else if (@sizeOf(usize) > 4 and builtin.endian == .Big) + extern struct { + name: usize = @ptrToInt(@as(?[*]u8, null)), + name_len: c_uint = 0, + + buffers: usize = undefined, + _pad_1: c_int = 0, + buffers_len: c_int = undefined, + + control: usize = @ptrToInt(@as(?[*]u8, null)), + _pad_2: c_int = 0, + control_len: c_uint = 0, + + flags: c_int = 0, + + pub usingnamespace MessageMixin(Message); + } + else if (@sizeOf(usize) > 4 and builtin.endian == .Little) + extern struct { + name: usize = @ptrToInt(@as(?[*]u8, null)), + name_len: c_uint = 0, + + buffers: usize = undefined, + buffers_len: c_int = undefined, + _pad_1: c_int = 0, + + control: usize = @ptrToInt(@as(?[*]u8, null)), + control_len: c_uint = 0, + _pad_2: c_int = 0, + + flags: c_int = 0, + + pub usingnamespace MessageMixin(Message); + } + else + extern struct { + name: usize = @ptrToInt(@as(?[*]u8, null)), + name_len: c_uint = 0, + + buffers: usize = undefined, + buffers_len: c_int, + + control: usize = null, + control_len: c_uint = 0, + + flags: c_int = 0, + + pub usingnamespace MessageMixin(Message); + }; + + fn MessageMixin(comptime Self: type) type { + return struct { + pub fn fromBuffers(buffers: []const Buffer) Self { + var self: Self = .{}; + self.setBuffers(buffers); + return self; + } + + pub fn setName(self: *Self, name: []const u8) void { + self.name = @ptrToInt(name.ptr); + self.name_len = @intCast(meta.fieldInfo(Self, .name_len).field_type, name.len); + } + + pub fn setBuffers(self: *Self, buffers: []const Buffer) void { + self.buffers = @ptrToInt(buffers.ptr); + self.buffers_len = @intCast(meta.fieldInfo(Self, .buffers_len).field_type, buffers.len); + } + + pub fn setControl(self: *Self, control: []const u8) void { + if (builtin.os.tag == .windows) { + self.control = Buffer.from(control); + } else { + self.control = @ptrToInt(control.ptr); + self.control_len = @intCast(meta.fieldInfo(Self, .control_len).field_type, control.len); + } + } + + pub fn setFlags(self: *Self, flags: u32) void { + self.flags = @intCast(meta.fieldInfo(Self, .flags).field_type, flags); + } + + pub fn getName(self: Self) []const u8 { + return @intToPtr([*]const u8, self.name)[0..@intCast(usize, self.name_len)]; + } + + pub fn getBuffers(self: Self) []const Buffer { + return @intToPtr([*]const Buffer, self.buffers)[0..@intCast(usize, self.buffers_len)]; + } + + pub fn getControl(self: Self) []const u8 { + if (builtin.os.tag == .windows) { + return self.control.into(); + } else { + return @intToPtr([*]const u8, self.control)[0..@intCast(usize, self.control_len)]; + } + } + + pub fn getFlags(self: Self) u32 { + return @intCast(u32, self.flags); + } + }; + } + + /// POSIX `linger`, denoting the linger settings of a socket. + /// + /// Microsoft's documentation and glibc denote the fields to be unsigned + /// short's on Windows, whereas glibc and musl denote the fields to be + /// int's on every other platform. + pub const Linger = extern struct { + pub const Field = switch (builtin.os.tag) { + .windows => c_ushort, + else => c_int, + }; + + enabled: Field, + timeout_seconds: Field, + + pub fn init(timeout_seconds: ?u16) Socket.Linger { + return .{ + .enabled = @intCast(Socket.Linger.Field, @boolToInt(timeout_seconds != null)), + .timeout_seconds = if (timeout_seconds) |seconds| @intCast(Socket.Linger.Field, seconds) else 0, + }; + } + }; + + /// Possible set of flags to initialize a socket with. + pub const InitFlags = enum { + // Initialize a socket to be non-blocking. + nonblocking, + + // Have a socket close itself on exec syscalls. + close_on_exec, + }; + /// The underlying handle of a socket. fd: os.socket_t, diff --git a/lib/std/x/os/socket_posix.zig b/lib/std/x/os/socket_posix.zig index 1e54c5c7a2fa6e3f49fa87cd5248804597a4cf08..b9fc21a40d8b8e7edd67f66a2d23972ccd661f91 100644 --- a/lib/std/x/os/socket_posix.zig +++ b/lib/std/x/os/socket_posix.zig @@ -13,8 +13,12 @@ const time = std.time; pub fn Mixin(comptime Socket: type) type { return struct { /// Open a new socket. - pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket { - return Socket{ .fd = try os.socket(domain, socket_type, protocol) }; + pub fn init(domain: u32, socket_type: u32, protocol: u32, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Socket { + var raw_flags: u32 = socket_type; + const set = std.EnumSet(Socket.InitFlags).init(flags); + if (set.contains(.close_on_exec)) raw_flags |= os.SOCK_CLOEXEC; + if (set.contains(.nonblocking)) raw_flags |= os.SOCK_NONBLOCK; + return Socket{ .fd = try os.socket(domain, raw_flags, protocol) }; } /// Closes the socket. @@ -44,11 +48,16 @@ pub fn Mixin(comptime Socket: type) type { /// Accept a pending incoming connection queued to the kernel backlog /// of the socket. - pub fn accept(self: Socket, flags: u32) !Socket.Connection { - var address: os.sockaddr_storage = undefined; - var address_len: u32 = @sizeOf(os.sockaddr_storage); + pub fn accept(self: Socket, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Socket.Connection { + var address: Socket.Address.Native.Storage = undefined; + var address_len: u32 = @sizeOf(Socket.Address.Native.Storage); - const socket = Socket{ .fd = try os.accept(self.fd, @ptrCast(*os.sockaddr, &address), &address_len, flags) }; + var raw_flags: u32 = 0; + const set = std.EnumSet(Socket.InitFlags).init(flags); + if (set.contains(.close_on_exec)) raw_flags |= os.SOCK_CLOEXEC; + if (set.contains(.nonblocking)) raw_flags |= os.SOCK_NONBLOCK; + + const socket = Socket{ .fd = try os.accept(self.fd, @ptrCast(*os.sockaddr, &address), &address_len, raw_flags) }; const socket_address = Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address)); return Socket.Connection.from(socket, socket_address); @@ -69,48 +78,45 @@ pub fn Mixin(comptime Socket: type) type { /// Writes multiple I/O vectors with a prepended message header to the socket /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. - pub fn writeVectorized(self: Socket, msg: os.msghdr_const, flags: u32) !usize { + pub fn writeVectorized(self: Socket, msg: Socket.Message, flags: u32) !usize { return os.sendmsg(self.fd, msg, flags); } /// Read multiple I/O vectors with a prepended message header from the socket /// with a set of flags specified. It returns the number of bytes that were /// read into the buffer provided. - pub fn readVectorized(self: Socket, msg: *os.msghdr, flags: u32) !usize { - if (comptime @hasDecl(os.system, "recvmsg")) { - while (true) { - const rc = os.system.recvmsg(self.fd, msg, flags); - return switch (os.errno(rc)) { - 0 => @intCast(usize, rc), - os.EBADF => unreachable, // always a race condition - os.EFAULT => unreachable, - os.EINVAL => unreachable, - os.ENOTCONN => unreachable, - os.ENOTSOCK => unreachable, - os.EINTR => continue, - os.EAGAIN => error.WouldBlock, - os.ENOMEM => error.SystemResources, - os.ECONNREFUSED => error.ConnectionRefused, - os.ECONNRESET => error.ConnectionResetByPeer, - else => |err| os.unexpectedErrno(err), - }; - } + pub fn readVectorized(self: Socket, msg: *Socket.Message, flags: u32) !usize { + while (true) { + const rc = os.system.recvmsg(self.fd, msg, flags); + return switch (os.errno(rc)) { + 0 => @intCast(usize, rc), + os.EBADF => unreachable, // always a race condition + os.EFAULT => unreachable, + os.EINVAL => unreachable, + os.ENOTCONN => unreachable, + os.ENOTSOCK => unreachable, + os.EINTR => continue, + os.EAGAIN => error.WouldBlock, + os.ENOMEM => error.SystemResources, + os.ECONNREFUSED => error.ConnectionRefused, + os.ECONNRESET => error.ConnectionResetByPeer, + else => |err| os.unexpectedErrno(err), + }; } - return error.NotSupported; } /// Query the address that the socket is locally bounded to. pub fn getLocalAddress(self: Socket) !Socket.Address { - var address: os.sockaddr_storage = undefined; - var address_len: u32 = @sizeOf(os.sockaddr_storage); + var address: Socket.Address.Native.Storage = undefined; + var address_len: u32 = @sizeOf(Socket.Address.Native.Storage); try os.getsockname(self.fd, @ptrCast(*os.sockaddr, &address), &address_len); return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address)); } /// Query the address that the socket is connected to. pub fn getRemoteAddress(self: Socket) !Socket.Address { - var address: os.sockaddr_storage = undefined; - var address_len: u32 = @sizeOf(os.sockaddr_storage); + var address: Socket.Address.Native.Storage = undefined; + var address_len: u32 = @sizeOf(Socket.Address.Native.Storage); try os.getpeername(self.fd, @ptrCast(*os.sockaddr, &address), &address_len); return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address)); } @@ -165,14 +171,7 @@ pub fn Mixin(comptime Socket: type) type { /// seconds. pub fn setLinger(self: Socket, timeout_seconds: ?u16) !void { if (comptime @hasDecl(os, "SO_LINGER")) { - const settings = extern struct { - l_onoff: c_int, - l_linger: c_int, - }{ - .l_onoff = @intCast(c_int, @boolToInt(timeout_seconds != null)), - .l_linger = if (timeout_seconds) |seconds| @intCast(c_int, seconds) else 0, - }; - + const settings = Socket.Linger.init(timeout_seconds); return self.setOption(os.SOL_SOCKET, os.SO_LINGER, mem.asBytes(&settings)); } diff --git a/lib/std/x/os/socket_windows.zig b/lib/std/x/os/socket_windows.zig index 6dd1f9a6a9d588b9e21df451c2ebeae50c3a70d9..ed1db4f62ff1fb50940c19d788fd9e56b4a571fd 100644 --- a/lib/std/x/os/socket_windows.zig +++ b/lib/std/x/os/socket_windows.zig @@ -16,27 +16,24 @@ const ws2_32 = windows.ws2_32; pub fn Mixin(comptime Socket: type) type { return struct { /// Open a new socket. - pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket { - var filtered_socket_type = socket_type & ~@as(u32, os.SOCK_CLOEXEC); - - var filtered_flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED; - if (socket_type & os.SOCK_CLOEXEC != 0) { - filtered_flags |= ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; - } + pub fn init(domain: u32, socket_type: u32, protocol: u32, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Socket { + var raw_flags: u32 = 0; + const set = std.EnumSet(Socket.InitFlags).init(flags); + if (set.contains(.close_on_exec)) raw_flags |= ws2_32.WSA_FLAG_NO_HANDLE_INHERIT; const fd = ws2_32.WSASocketW( @intCast(i32, domain), - @intCast(i32, filtered_socket_type), + @intCast(i32, socket_type), @intCast(i32, protocol), null, 0, - filtered_flags, + raw_flags, ); if (fd == ws2_32.INVALID_SOCKET) { return switch (ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => { _ = try windows.WSAStartup(2, 2); - return Socket.init(domain, socket_type, protocol); + return Socket.init(domain, socket_type, protocol, flags); }, .WSAEAFNOSUPPORT => error.AddressFamilyNotSupported, .WSAEMFILE => error.ProcessFdQuotaExceeded, @@ -46,6 +43,14 @@ pub fn Mixin(comptime Socket: type) type { }; } + if (set.contains(.nonblocking)) { + var enabled: c_ulong = 1; + const rc = ws2_32.ioctlsocket(fd, ws2_32.FIONBIO, &enabled); + if (rc == ws2_32.SOCKET_ERROR) { + return windows.unexpectedWSAError(ws2_32.WSAGetLastError()); + } + } + return Socket{ .fd = fd }; } @@ -138,12 +143,12 @@ pub fn Mixin(comptime Socket: type) type { /// Accept a pending incoming connection queued to the kernel backlog /// of the socket. - pub fn accept(self: Socket, flags: u32) !Socket.Connection { - var address: ws2_32.sockaddr_storage = undefined; - var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage); + pub fn accept(self: Socket, flags: std.enums.EnumFieldStruct(Socket.InitFlags, bool, false)) !Socket.Connection { + var address: Socket.Address.Native.Storage = undefined; + var address_len: c_int = @sizeOf(Socket.Address.Native.Storage); - const rc = ws2_32.accept(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len); - if (rc == ws2_32.INVALID_SOCKET) { + const fd = ws2_32.accept(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len); + if (fd == ws2_32.INVALID_SOCKET) { return switch (ws2_32.WSAGetLastError()) { .WSANOTINITIALISED => unreachable, .WSAECONNRESET => error.ConnectionResetByPeer, @@ -158,9 +163,20 @@ pub fn Mixin(comptime Socket: type) type { }; } - const socket = Socket.from(rc); + const socket = Socket.from(fd); + errdefer socket.deinit(); + const socket_address = Socket.Address.fromNative(@ptrCast(*ws2_32.sockaddr, &address)); + const set = std.EnumSet(Socket.InitFlags).init(flags); + if (set.contains(.nonblocking)) { + var enabled: c_ulong = 1; + const rc = ws2_32.ioctlsocket(fd, ws2_32.FIONBIO, &enabled); + if (rc == ws2_32.SOCKET_ERROR) { + return windows.unexpectedWSAError(ws2_32.WSAGetLastError()); + } + } + return Socket.Connection.from(socket, socket_address); } @@ -238,7 +254,7 @@ pub fn Mixin(comptime Socket: type) type { /// Writes multiple I/O vectors with a prepended message header to the socket /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. - pub fn writeVectorized(self: Socket, msg: ws2_32.msghdr_const, flags: u32) !usize { + pub fn writeVectorized(self: Socket, msg: Socket.Message, flags: u32) !usize { const call = try windows.loadWinsockExtensionFunction(ws2_32.LPFN_WSASENDMSG, self.fd, ws2_32.WSAID_WSASENDMSG); var num_bytes: u32 = undefined; @@ -275,7 +291,7 @@ pub fn Mixin(comptime Socket: type) type { /// Read multiple I/O vectors with a prepended message header from the socket /// with a set of flags specified. It returns the number of bytes that were /// read into the buffer provided. - pub fn readVectorized(self: Socket, msg: *ws2_32.msghdr, flags: u32) !usize { + pub fn readVectorized(self: Socket, msg: *Socket.Message, flags: u32) !usize { const call = try windows.loadWinsockExtensionFunction(ws2_32.LPFN_WSARECVMSG, self.fd, ws2_32.WSAID_WSARECVMSG); var num_bytes: u32 = undefined; @@ -311,8 +327,8 @@ pub fn Mixin(comptime Socket: type) type { /// Query the address that the socket is locally bounded to. pub fn getLocalAddress(self: Socket) !Socket.Address { - var address: ws2_32.sockaddr_storage = undefined; - var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage); + var address: Socket.Address.Native.Storage = undefined; + var address_len: c_int = @sizeOf(Socket.Address.Native.Storage); const rc = ws2_32.getsockname(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len); if (rc == ws2_32.SOCKET_ERROR) { @@ -331,8 +347,8 @@ pub fn Mixin(comptime Socket: type) type { /// Query the address that the socket is connected to. pub fn getRemoteAddress(self: Socket) !Socket.Address { - var address: ws2_32.sockaddr_storage = undefined; - var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage); + var address: Socket.Address.Native.Storage = undefined; + var address_len: c_int = @sizeOf(Socket.Address.Native.Storage); const rc = ws2_32.getpeername(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len); if (rc == ws2_32.SOCKET_ERROR) { @@ -384,11 +400,7 @@ pub fn Mixin(comptime Socket: type) type { /// if the host does not support the option for a socket to linger around up until a timeout specified in /// seconds. pub fn setLinger(self: Socket, timeout_seconds: ?u16) !void { - const settings = ws2_32.linger{ - .l_onoff = @as(u16, @boolToInt(timeout_seconds != null)), - .l_linger = if (timeout_seconds) |seconds| seconds else 0, - }; - + const settings = Socket.Linger.init(timeout_seconds); return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_LINGER, mem.asBytes(&settings)); } -- 2.54.0 From d41575737e50757abe6998c123c3e3dd8a64365f Mon Sep 17 00:00:00 2001 From: lithdew Date: Fri, 14 May 2021 13:29:40 +0900 Subject: [PATCH 02/11] std/c: add recvmsg, sendmsg --- lib/std/c.zig | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index 1d60af67471f146d307176dd81f28138c903824e..a91fee7274dca60a653013c743543c9dddf3b5bb 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -166,9 +166,10 @@ pub extern "c" fn sendto( dest_addr: ?*const sockaddr, addrlen: socklen_t, ) isize; +pub extern "c" fn sendmsg(sockfd: fd_t, msg: *const std.x.os.Socket.Message, flags: c_int) isize; -pub extern fn recv(sockfd: fd_t, arg1: ?*c_void, arg2: usize, arg3: c_int) isize; -pub extern fn recvfrom( +pub extern "c" fn recv(sockfd: fd_t, arg1: ?*c_void, arg2: usize, arg3: c_int) isize; +pub extern "c" fn recvfrom( sockfd: fd_t, noalias buf: *c_void, len: usize, @@ -176,6 +177,7 @@ pub extern fn recvfrom( noalias src_addr: ?*sockaddr, noalias addrlen: ?*socklen_t, ) isize; +pub extern "c" fn recvmsg(sockfd: fd_t, msg: *std.x.os.Socket.Message, flags: c_int) isize; pub usingnamespace switch (builtin.os.tag) { .netbsd => struct { -- 2.54.0 From 494665e40866639878aac62848bf6e8ce9a730a8 Mon Sep 17 00:00:00 2001 From: lithdew Date: Fri, 14 May 2021 13:54:17 +0900 Subject: [PATCH 03/11] std/c: have sendmsg, recvmsg flags be u32 --- lib/std/c.zig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index a91fee7274dca60a653013c743543c9dddf3b5bb..2da0fea614cfa489a5ebefed4351ba3c8a8511d1 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -166,7 +166,7 @@ pub extern "c" fn sendto( dest_addr: ?*const sockaddr, addrlen: socklen_t, ) isize; -pub extern "c" fn sendmsg(sockfd: fd_t, msg: *const std.x.os.Socket.Message, flags: c_int) isize; +pub extern "c" fn sendmsg(sockfd: fd_t, msg: *const std.x.os.Socket.Message, flags: u32) isize; pub extern "c" fn recv(sockfd: fd_t, arg1: ?*c_void, arg2: usize, arg3: c_int) isize; pub extern "c" fn recvfrom( @@ -177,7 +177,7 @@ pub extern "c" fn recvfrom( noalias src_addr: ?*sockaddr, noalias addrlen: ?*socklen_t, ) isize; -pub extern "c" fn recvmsg(sockfd: fd_t, msg: *std.x.os.Socket.Message, flags: c_int) isize; +pub extern "c" fn recvmsg(sockfd: fd_t, msg: *std.x.os.Socket.Message, flags: u32) isize; pub usingnamespace switch (builtin.os.tag) { .netbsd => struct { -- 2.54.0 From 12650bcda4584828799d837388a7b728f7f650ec Mon Sep 17 00:00:00 2001 From: lithdew Date: Fri, 14 May 2021 15:42:22 +0900 Subject: [PATCH 04/11] x/os, x/tcp: fix Socket.Message init values and tcp test buf len --- lib/std/x/net/tcp.zig | 4 ++-- lib/std/x/os/socket.zig | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/x/net/tcp.zig b/lib/std/x/net/tcp.zig index abf1191dfd98c0b5697535a3b208418c3ec35763..05b0f50c10f87eac13baa3656ee4b28a5e22f6bc 100644 --- a/lib/std/x/net/tcp.zig +++ b/lib/std/x/net/tcp.zig @@ -405,14 +405,14 @@ test "tcp/client: read and write multiple vectors" { Buffer.from(message[message.len / 2 ..]), }), 0); - var buf: [message.len]u8 = undefined; + var buf: [message.len + 1]u8 = undefined; var msg = Socket.Message.fromBuffers(&[_]Buffer{ Buffer.from(buf[0 .. message.len / 2]), Buffer.from(buf[message.len / 2 ..]), }); _ = try client.readVectorized(&msg, 0); - try testing.expectEqualStrings(message, &buf); + try testing.expectEqualStrings(message, buf[0..message.len]); } test "tcp/listener: bind to unspecified ipv4 address" { diff --git a/lib/std/x/os/socket.zig b/lib/std/x/os/socket.zig index 05bd0499d1384758fb730ca0cb26e3467c310ac3..1825d9f00cb5518c4c689453e1cf5d87b40ecbd2 100644 --- a/lib/std/x/os/socket.zig +++ b/lib/std/x/os/socket.zig @@ -212,9 +212,9 @@ pub const Socket = struct { name_len: c_uint = 0, buffers: usize = undefined, - buffers_len: c_int, + buffers_len: c_int = undefined, - control: usize = null, + control: usize = @ptrToInt(@as(?[*]u8, null)), control_len: c_uint = 0, flags: c_int = 0, -- 2.54.0 From 9ba65592d64f53d886b00402659cfce775ea77d3 Mon Sep 17 00:00:00 2001 From: lithdew Date: Fri, 14 May 2021 15:50:09 +0900 Subject: [PATCH 05/11] os: have sendmsg, recvmsg flags be c_int --- lib/std/c.zig | 4 ++-- lib/std/os.zig | 2 +- lib/std/os/linux.zig | 4 ++-- lib/std/x/os/socket_posix.zig | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/std/c.zig b/lib/std/c.zig index 2da0fea614cfa489a5ebefed4351ba3c8a8511d1..a91fee7274dca60a653013c743543c9dddf3b5bb 100644 --- a/lib/std/c.zig +++ b/lib/std/c.zig @@ -166,7 +166,7 @@ pub extern "c" fn sendto( dest_addr: ?*const sockaddr, addrlen: socklen_t, ) isize; -pub extern "c" fn sendmsg(sockfd: fd_t, msg: *const std.x.os.Socket.Message, flags: u32) isize; +pub extern "c" fn sendmsg(sockfd: fd_t, msg: *const std.x.os.Socket.Message, flags: c_int) isize; pub extern "c" fn recv(sockfd: fd_t, arg1: ?*c_void, arg2: usize, arg3: c_int) isize; pub extern "c" fn recvfrom( @@ -177,7 +177,7 @@ pub extern "c" fn recvfrom( noalias src_addr: ?*sockaddr, noalias addrlen: ?*socklen_t, ) isize; -pub extern "c" fn recvmsg(sockfd: fd_t, msg: *std.x.os.Socket.Message, flags: u32) isize; +pub extern "c" fn recvmsg(sockfd: fd_t, msg: *std.x.os.Socket.Message, flags: c_int) isize; pub usingnamespace switch (builtin.os.tag) { .netbsd => struct { diff --git a/lib/std/os.zig b/lib/std/os.zig index 4ed0be8f62c9ae501d89e695e7ebfea24c8f382b..c2c4c16bd72f9238f605657e7f8f2894bd46ede6 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -4998,7 +4998,7 @@ pub fn sendmsg( flags: u32, ) SendMsgError!usize { while (true) { - const rc = system.sendmsg(sockfd, &msg, flags); + const rc = system.sendmsg(sockfd, &msg, @intCast(c_int, flags)); if (builtin.os.tag == .windows) { if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index 0d6b87c15ffa22a351a4456c3648e65a52d86ea7..a3a8c8e431c5a6819b4a12a2633132ba7c66fb7c 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1004,7 +1004,7 @@ pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize { if (native_arch == .i386) { return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags }); } - return syscall3(.sendmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags); + return syscall3(.sendmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), @bitCast(usize, @as(isize, flags))); } pub fn sendmmsg(fd: i32, msgvec: [*]mmsghdr_const, vlen: u32, flags: u32) usize { @@ -1058,7 +1058,7 @@ pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { if (native_arch == .i386) { return socketcall(SC_recvmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags }); } - return syscall3(.recvmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags); + return syscall3(.recvmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), @bitCast(usize, @as(isize, flags))); } pub fn recvfrom(fd: i32, noalias buf: [*]u8, len: usize, flags: u32, noalias addr: ?*sockaddr, noalias alen: ?*socklen_t) usize { diff --git a/lib/std/x/os/socket_posix.zig b/lib/std/x/os/socket_posix.zig index b9fc21a40d8b8e7edd67f66a2d23972ccd661f91..70c8b35b5f73095db839405db38228bf5dbffd95 100644 --- a/lib/std/x/os/socket_posix.zig +++ b/lib/std/x/os/socket_posix.zig @@ -87,7 +87,7 @@ pub fn Mixin(comptime Socket: type) type { /// read into the buffer provided. pub fn readVectorized(self: Socket, msg: *Socket.Message, flags: u32) !usize { while (true) { - const rc = os.system.recvmsg(self.fd, msg, flags); + const rc = os.system.recvmsg(self.fd, msg, @intCast(c_int, flags)); return switch (os.errno(rc)) { 0 => @intCast(usize, rc), os.EBADF => unreachable, // always a race condition -- 2.54.0 From 7b6ec3e3548dadc597b6aa396d70ba4c6595da26 Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Tue, 18 May 2021 17:23:59 +0900 Subject: [PATCH 06/11] x/os: {read, write}Vectorized() -> {read, write}Message() --- lib/std/json.zig | 5 +---- lib/std/x/net/tcp.zig | 12 ++++++------ lib/std/x/os/socket_posix.zig | 4 ++-- lib/std/x/os/socket_windows.zig | 4 ++-- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/lib/std/json.zig b/lib/std/json.zig index 9fb77d501f5930da76b8f15ee49b0b7ca3c4a92d..ed90efb791a97dc9aff2dd989e73802d721bcce1 100644 --- a/lib/std/json.zig +++ b/lib/std/json.zig @@ -2111,10 +2111,7 @@ test "parse into struct with duplicate field" { const ballast = try testing.allocator.alloc(u64, 1); defer testing.allocator.free(ballast); - const options_first = ParseOptions{ - .allocator = testing.allocator, - .duplicate_field_behavior = .UseFirst, - }; + const options_first = ParseOptions{ .allocator = testing.allocator, .duplicate_field_behavior = .UseFirst }; const options_last = ParseOptions{ .allocator = testing.allocator, diff --git a/lib/std/x/net/tcp.zig b/lib/std/x/net/tcp.zig index 05b0f50c10f87eac13baa3656ee4b28a5e22f6bc..8740c17e61b2da1a157b495ea365a86c0c0132e7 100644 --- a/lib/std/x/net/tcp.zig +++ b/lib/std/x/net/tcp.zig @@ -145,15 +145,15 @@ pub const Client = struct { /// Writes multiple I/O vectors with a prepended message header to the socket /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. - pub fn writeVectorized(self: Client, msg: Socket.Message, flags: u32) !usize { - return self.socket.writeVectorized(msg, flags); + pub fn writeMessage(self: Client, msg: Socket.Message, flags: u32) !usize { + return self.socket.writeMessage(msg, flags); } /// Read multiple I/O vectors with a prepended message header from the socket /// with a set of flags specified. It returns the number of bytes that were /// read into the buffer provided. - pub fn readVectorized(self: Client, msg: *Socket.Message, flags: u32) !usize { - return self.socket.readVectorized(msg, flags); + pub fn readMessage(self: Client, msg: *Socket.Message, flags: u32) !usize { + return self.socket.readMessage(msg, flags); } /// Query and return the latest cached error on the client's underlying socket. @@ -400,7 +400,7 @@ test "tcp/client: read and write multiple vectors" { defer conn.deinit(); const message = "hello world"; - _ = try conn.client.writeVectorized(Socket.Message.fromBuffers(&[_]Buffer{ + _ = try conn.client.writeMessage(Socket.Message.fromBuffers(&[_]Buffer{ Buffer.from(message[0 .. message.len / 2]), Buffer.from(message[message.len / 2 ..]), }), 0); @@ -410,7 +410,7 @@ test "tcp/client: read and write multiple vectors" { Buffer.from(buf[0 .. message.len / 2]), Buffer.from(buf[message.len / 2 ..]), }); - _ = try client.readVectorized(&msg, 0); + _ = try client.readMessage(&msg, 0); try testing.expectEqualStrings(message, buf[0..message.len]); } diff --git a/lib/std/x/os/socket_posix.zig b/lib/std/x/os/socket_posix.zig index 70c8b35b5f73095db839405db38228bf5dbffd95..ebaadcbd5d154c5fb81f76d9df79b6c3d9930781 100644 --- a/lib/std/x/os/socket_posix.zig +++ b/lib/std/x/os/socket_posix.zig @@ -78,14 +78,14 @@ pub fn Mixin(comptime Socket: type) type { /// Writes multiple I/O vectors with a prepended message header to the socket /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. - pub fn writeVectorized(self: Socket, msg: Socket.Message, flags: u32) !usize { + pub fn writeMessage(self: Socket, msg: Socket.Message, flags: u32) !usize { return os.sendmsg(self.fd, msg, flags); } /// Read multiple I/O vectors with a prepended message header from the socket /// with a set of flags specified. It returns the number of bytes that were /// read into the buffer provided. - pub fn readVectorized(self: Socket, msg: *Socket.Message, flags: u32) !usize { + pub fn readMessage(self: Socket, msg: *Socket.Message, flags: u32) !usize { while (true) { const rc = os.system.recvmsg(self.fd, msg, @intCast(c_int, flags)); return switch (os.errno(rc)) { diff --git a/lib/std/x/os/socket_windows.zig b/lib/std/x/os/socket_windows.zig index ed1db4f62ff1fb50940c19d788fd9e56b4a571fd..d479d8619ad3fa911ad72704ea23ef92e84e09b6 100644 --- a/lib/std/x/os/socket_windows.zig +++ b/lib/std/x/os/socket_windows.zig @@ -254,7 +254,7 @@ pub fn Mixin(comptime Socket: type) type { /// Writes multiple I/O vectors with a prepended message header to the socket /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. - pub fn writeVectorized(self: Socket, msg: Socket.Message, flags: u32) !usize { + pub fn writeMessage(self: Socket, msg: Socket.Message, flags: u32) !usize { const call = try windows.loadWinsockExtensionFunction(ws2_32.LPFN_WSASENDMSG, self.fd, ws2_32.WSAID_WSASENDMSG); var num_bytes: u32 = undefined; @@ -291,7 +291,7 @@ pub fn Mixin(comptime Socket: type) type { /// Read multiple I/O vectors with a prepended message header from the socket /// with a set of flags specified. It returns the number of bytes that were /// read into the buffer provided. - pub fn readVectorized(self: Socket, msg: *Socket.Message, flags: u32) !usize { + pub fn readMessage(self: Socket, msg: *Socket.Message, flags: u32) !usize { const call = try windows.loadWinsockExtensionFunction(ws2_32.LPFN_WSARECVMSG, self.fd, ws2_32.WSAID_WSARECVMSG); var num_bytes: u32 = undefined; -- 2.54.0 From 21ec0158a1b76cb52014b5dc79fb35ba3449d226 Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Tue, 18 May 2021 17:28:06 +0900 Subject: [PATCH 07/11] os: `sockaddr_storage` -> `std.x.os.Socket.Address.Native.Storage` --- lib/std/os/bits/darwin.zig | 7 ------- lib/std/os/bits/freebsd.zig | 8 -------- lib/std/os/bits/haiku.zig | 8 -------- lib/std/os/bits/linux.zig | 7 ------- lib/std/os/bits/netbsd.zig | 8 -------- lib/std/os/bits/openbsd.zig | 8 -------- lib/std/os/windows/ws2_32.zig | 7 ------- 7 files changed, 53 deletions(-) diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index 0c2d8dc01ee0eb56c16071730b733e4e44d3febb..3f8599a08cb96bdbb70e5722718d937600c414f3 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -23,13 +23,6 @@ pub const sockaddr = extern struct { family: sa_family_t, data: [14]u8, }; -pub const sockaddr_storage = extern struct { - len: u8, - family: sa_family_t, - __pad1: [5]u8, - __align: i64, - __pad2: [112]u8, -}; pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index cd32972b89164c0994b204397f2787cddad049d0..381ceb7b3a56ca4ccefa2ac97350b4ac853cf8d3 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -160,14 +160,6 @@ pub const sockaddr = extern struct { data: [14]u8, }; -pub const sockaddr_storage = extern struct { - len: u8, - family: sa_family_t, - __pad1: [5]u8, - __align: i64, - __pad2: [112]u8, -}; - pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig index b229a4744d8a498cfb4f747fe4dcf2a116d53b55..316f6d799314b8024cf784ac4979ce7f2f8a7a95 100644 --- a/lib/std/os/bits/haiku.zig +++ b/lib/std/os/bits/haiku.zig @@ -193,14 +193,6 @@ pub const sockaddr = extern struct { data: [14]u8, }; -pub const sockaddr_storage = extern struct { - len: u8, - family: sa_family_t, - __pad1: [5]u8, - __align: i64, - __pad2: [112]u8, -}; - pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index 5ecdcf24a34a32063ef9a67a7aaf0280c26ef2f4..c58b7cfa5076ea0368bf98b77b14df2fd5730a2c 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -1149,13 +1149,6 @@ pub const sockaddr = extern struct { data: [14]u8, }; -pub const sockaddr_storage = extern struct { - family: sa_family_t, - __pad1: [6]u8, - __align: i64, - __pad2: [112]u8, -}; - /// IPv4 socket address pub const sockaddr_in = extern struct { family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index 0a3ea0d8077662d912466a1a207ef407bc23c076..a3d89620b7cd177c8243791674c3de75b8d9de1a 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -180,14 +180,6 @@ pub const sockaddr = extern struct { data: [14]u8, }; -pub const sockaddr_storage = extern struct { - len: u8, - family: sa_family_t, - __pad1: [5]u8, - __align: i64, - __pad2: [112]u8, -}; - pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig index 44fe9cc5f2d683386b2a96b24202807b23b6d916..5335ebac22844736cc9c66893a9c73c9b5438c80 100644 --- a/lib/std/os/bits/openbsd.zig +++ b/lib/std/os/bits/openbsd.zig @@ -200,14 +200,6 @@ pub const sockaddr = extern struct { data: [14]u8, }; -pub const sockaddr_storage = extern struct { - len: u8, - family: sa_family_t, - __pad1: [5]u8, - __align: i64, - __pad2: [112]u8, -}; - pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index 39f68bb234f53e3779a1a80379cc5050b007b370..219c32d92808ada5f1a7c4e089267a9a2cb00ae9 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -1059,13 +1059,6 @@ pub const sockaddr = extern struct { data: [14]u8, }; -pub const sockaddr_storage = extern struct { - family: ADDRESS_FAMILY, - __pad1: [6]u8, - __align: i64, - __pad2: [112]u8, -}; - /// IPv4 socket address pub const sockaddr_in = extern struct { family: ADDRESS_FAMILY = AF_INET, -- 2.54.0 From 278e5d398ea137a4c81bd00b1f40e50a16755684 Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Wed, 19 May 2021 14:30:04 +0900 Subject: [PATCH 08/11] x: replace std.builtin with std.Target.current --- lib/std/os/linux.zig | 8 ++++---- lib/std/x/net/tcp.zig | 12 ++++++------ lib/std/x/os/io.zig | 8 ++++---- lib/std/x/os/net.zig | 4 ++-- lib/std/x/os/socket.zig | 21 +++++++++++---------- 5 files changed, 27 insertions(+), 26 deletions(-) diff --git a/lib/std/os/linux.zig b/lib/std/os/linux.zig index a3a8c8e431c5a6819b4a12a2633132ba7c66fb7c..9e7b38fe9061d7b9a2cfd557e8992adc51445575 100644 --- a/lib/std/os/linux.zig +++ b/lib/std/os/linux.zig @@ -1000,9 +1000,9 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal return syscall5(.getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); } -pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize { +pub fn sendmsg(fd: i32, msg: *const std.x.os.Socket.Message, flags: c_int) usize { if (native_arch == .i386) { - return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags }); + return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), @bitCast(usize, @as(isize, flags)) }); } return syscall3(.sendmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), @bitCast(usize, @as(isize, flags))); } @@ -1054,9 +1054,9 @@ pub fn connect(fd: i32, addr: *const c_void, len: socklen_t) usize { return syscall3(.connect, @bitCast(usize, @as(isize, fd)), @ptrToInt(addr), len); } -pub fn recvmsg(fd: i32, msg: *msghdr, flags: u32) usize { +pub fn recvmsg(fd: i32, msg: *std.x.os.Socket.Message, flags: c_int) usize { if (native_arch == .i386) { - return socketcall(SC_recvmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags }); + return socketcall(SC_recvmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), @bitCast(usize, @as(isize, flags)) }); } return syscall3(.recvmsg, @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), @bitCast(usize, @as(isize, flags))); } diff --git a/lib/std/x/net/tcp.zig b/lib/std/x/net/tcp.zig index 8740c17e61b2da1a157b495ea365a86c0c0132e7..25efbae67310989284f480dc4ca1ec3248f5085a 100644 --- a/lib/std/x/net/tcp.zig +++ b/lib/std/x/net/tcp.zig @@ -12,8 +12,8 @@ const ip = std.x.net.ip; const fmt = std.fmt; const mem = std.mem; -const builtin = std.builtin; const testing = std.testing; +const native_os = std.Target.current.os; const IPv4 = std.x.os.IPv4; const IPv6 = std.x.os.IPv6; @@ -325,7 +325,7 @@ pub const Listener = struct { }; test "tcp: create client/listener pair" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; + if (native_os.tag == .wasi) return error.SkipZigTest; const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); @@ -349,7 +349,7 @@ test "tcp: create client/listener pair" { } test "tcp/client: 1ms read timeout" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; + if (native_os.tag == .wasi) return error.SkipZigTest; const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); @@ -377,7 +377,7 @@ test "tcp/client: 1ms read timeout" { } test "tcp/client: read and write multiple vectors" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; + if (native_os.tag == .wasi) return error.SkipZigTest; const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); @@ -416,7 +416,7 @@ test "tcp/client: read and write multiple vectors" { } test "tcp/listener: bind to unspecified ipv4 address" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; + if (native_os.tag == .wasi) return error.SkipZigTest; const listener = try tcp.Listener.init(.ip, .{ .close_on_exec = true }); defer listener.deinit(); @@ -429,7 +429,7 @@ test "tcp/listener: bind to unspecified ipv4 address" { } test "tcp/listener: bind to unspecified ipv6 address" { - if (builtin.os.tag == .wasi) return error.SkipZigTest; + if (native_os.tag == .wasi) return error.SkipZigTest; const listener = try tcp.Listener.init(.ipv6, .{ .close_on_exec = true }); defer listener.deinit(); diff --git a/lib/std/x/os/io.zig b/lib/std/x/os/io.zig index 597f7d268cebe20792f72f0626154db93fea418e..1c0e0e913064db71dd6eb3105bd25acf99dad130 100644 --- a/lib/std/x/os/io.zig +++ b/lib/std/x/os/io.zig @@ -2,12 +2,12 @@ const std = @import("../../std.zig"); const os = std.os; const mem = std.mem; -const builtin = std.builtin; const testing = std.testing; +const native_os = std.Target.current.os; /// POSIX `iovec`, or Windows `WSABUF`. The difference between the two are the ordering /// of fields, alongside the length being represented as either a ULONG or a size_t. -pub const Buffer = if (builtin.os.tag == .windows) +pub const Buffer = if (native_os.tag == .windows) extern struct { len: c_ulong, ptr: usize, @@ -38,7 +38,7 @@ else } pub fn intoMutable(self: Buffer) []u8 { - return @intToptr([*]u8, self.ptr)[0..self.len]; + return @intToPtr([*]u8, self.ptr)[0..self.len]; } }; @@ -115,7 +115,7 @@ pub const Reactor = struct { }; test "reactor/linux: drive async tcp client/listener pair" { - if (builtin.os.tag != .linux) return error.SkipZigTest; + if (native_os.tag != .linux) return error.SkipZigTest; const ip = std.x.net.ip; const tcp = std.x.net.tcp; diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig index f2f49ea62f4b5f930f0a5f6a44fa41c2857c0329..3d32019bb288b67731113f3a6a60836519f37089 100644 --- a/lib/std/x/os/net.zig +++ b/lib/std/x/os/net.zig @@ -10,8 +10,8 @@ const os = std.os; const fmt = std.fmt; const mem = std.mem; const math = std.math; -const builtin = std.builtin; const testing = std.testing; +const native_os = std.Target.current.os; /// Resolves a network interface name into a scope/zone ID. It returns /// an error if either resolution fails, or if the interface name is @@ -20,7 +20,7 @@ pub fn resolveScopeID(name: []const u8) !u32 { if (comptime @hasDecl(os, "IFNAMESIZE")) { if (name.len >= os.IFNAMESIZE - 1) return error.NameTooLong; - if (comptime builtin.os.tag == .windows) { + if (comptime native_os.tag == .windows) { var interface_name: [os.IFNAMESIZE]u8 = undefined; mem.copy(u8, &interface_name, name); interface_name[name.len] = 0; diff --git a/lib/std/x/os/socket.zig b/lib/std/x/os/socket.zig index 1825d9f00cb5518c4c689453e1cf5d87b40ecbd2..61e47939f8de3bacd964560a85706570f2342d78 100644 --- a/lib/std/x/os/socket.zig +++ b/lib/std/x/os/socket.zig @@ -12,7 +12,8 @@ const fmt = std.fmt; const mem = std.mem; const time = std.time; const meta = std.meta; -const builtin = std.builtin; +const native_os = std.Target.current.os; +const native_endian = std.Target.current.cpu.arch.endian(); const Buffer = std.x.os.Buffer; @@ -35,7 +36,7 @@ pub const Socket = struct { /// the fields of a `Socket.Address`. pub const Address = union(enum) { pub const Native = struct { - pub const requires_prepended_length = builtin.os.getVersionRange() == .semver; + pub const requires_prepended_length = native_os.getVersionRange() == .semver; pub const Length = if (requires_prepended_length) u8 else [0]u8; pub const Family = if (requires_prepended_length) u8 else c_ushort; @@ -140,7 +141,7 @@ pub const Socket = struct { /// POSIX `msghdr`. Denotes a destination address, set of buffers, control data, and flags. Ported /// directly from musl. - pub const Message = if (builtin.os.isAtLeast(.windows, .vista) != null and builtin.os.isAtLeast(.windows, .vista).?) + pub const Message = if (native_os.isAtLeast(.windows, .vista) != null and native_os.isAtLeast(.windows, .vista).?) extern struct { name: usize = @ptrToInt(@as(?[*]u8, null)), name_len: c_int = 0, @@ -156,7 +157,7 @@ pub const Socket = struct { pub usingnamespace MessageMixin(Message); } - else if (builtin.os.tag == .windows) + else if (native_os.tag == .windows) extern struct { name: usize = @ptrToInt(@as(?[*]u8, null)), name_len: c_int = 0, @@ -172,7 +173,7 @@ pub const Socket = struct { pub usingnamespace MessageMixin(Message); } - else if (@sizeOf(usize) > 4 and builtin.endian == .Big) + else if (@sizeOf(usize) > 4 and native_endian == .Big) extern struct { name: usize = @ptrToInt(@as(?[*]u8, null)), name_len: c_uint = 0, @@ -189,7 +190,7 @@ pub const Socket = struct { pub usingnamespace MessageMixin(Message); } - else if (@sizeOf(usize) > 4 and builtin.endian == .Little) + else if (@sizeOf(usize) > 4 and native_endian == .Little) extern struct { name: usize = @ptrToInt(@as(?[*]u8, null)), name_len: c_uint = 0, @@ -241,7 +242,7 @@ pub const Socket = struct { } pub fn setControl(self: *Self, control: []const u8) void { - if (builtin.os.tag == .windows) { + if (native_os.tag == .windows) { self.control = Buffer.from(control); } else { self.control = @ptrToInt(control.ptr); @@ -262,7 +263,7 @@ pub const Socket = struct { } pub fn getControl(self: Self) []const u8 { - if (builtin.os.tag == .windows) { + if (native_os.tag == .windows) { return self.control.into(); } else { return @intToPtr([*]const u8, self.control)[0..@intCast(usize, self.control_len)]; @@ -281,7 +282,7 @@ pub const Socket = struct { /// short's on Windows, whereas glibc and musl denote the fields to be /// int's on every other platform. pub const Linger = extern struct { - pub const Field = switch (builtin.os.tag) { + pub const Field = switch (native_os.tag) { .windows => c_ushort, else => c_int, }; @@ -315,7 +316,7 @@ pub const Socket = struct { } /// Mix in socket syscalls depending on the platform we are compiling against. - pub usingnamespace switch (builtin.os.tag) { + pub usingnamespace switch (native_os.tag) { .windows => @import("socket_windows.zig"), else => @import("socket_posix.zig"), }.Mixin(Socket); -- 2.54.0 From 6950e4c2943d7eee1868aff1bf9e24f6bb310f60 Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Mon, 31 May 2021 15:57:48 +0900 Subject: [PATCH 09/11] x/os/net: remove unnecessary comptime prefix in resolveScopeID() --- lib/std/mem.zig | 2 +- lib/std/os/windows.zig | 2 +- lib/std/x/os/net.zig | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/std/mem.zig b/lib/std/mem.zig index f365ffe2e43d52a0afd17c0715ddf030ebc50f94..4cf879cf054b7c70feb55891f2fd64f05eda226a 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -2201,7 +2201,7 @@ pub fn collapseRepeatsLen(comptime T: type, slice: []T, elem: T) usize { /// Collapse consecutive duplicate elements into one entry. pub fn collapseRepeats(comptime T: type, slice: []T, elem: T) []T { - return slice[0 .. collapseRepeatsLen(T, slice, elem)]; + return slice[0..collapseRepeatsLen(T, slice, elem)]; } fn testCollapseRepeats(str: []const u8, elem: u8, expected: []const u8) !void { diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig index 4bdbe64fbfef0f6028a15cdca4b5f1df1cc97200..8e8351e4464d287cbede765c77081ca5ff604315 100644 --- a/lib/std/os/windows.zig +++ b/lib/std/os/windows.zig @@ -1844,7 +1844,7 @@ pub fn sliceToPrefixedFileW(s: []const u8) !PathSpace { } fn getFullPathNameW(path: [*:0]const u16, out: []u16) !usize { - const result= kernel32.GetFullPathNameW(path, @intCast(u32, out.len), std.meta.assumeSentinel(out.ptr, 0), null); + const result = kernel32.GetFullPathNameW(path, @intCast(u32, out.len), std.meta.assumeSentinel(out.ptr, 0), null); if (result == 0) { switch (kernel32.GetLastError()) { else => |err| return unexpectedError(err), diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig index 3d32019bb288b67731113f3a6a60836519f37089..bbb2c105a77b8fd4fce7a6ee963336855a94fd1f 100644 --- a/lib/std/x/os/net.zig +++ b/lib/std/x/os/net.zig @@ -17,10 +17,10 @@ const native_os = std.Target.current.os; /// an error if either resolution fails, or if the interface name is /// too long. pub fn resolveScopeID(name: []const u8) !u32 { - if (comptime @hasDecl(os, "IFNAMESIZE")) { + if (@hasDecl(os, "IFNAMESIZE")) { if (name.len >= os.IFNAMESIZE - 1) return error.NameTooLong; - if (comptime native_os.tag == .windows) { + if (native_os.tag == .windows) { var interface_name: [os.IFNAMESIZE]u8 = undefined; mem.copy(u8, &interface_name, name); interface_name[name.len] = 0; -- 2.54.0 From aad8491dbd98052e97b395ea572b186482d3b38f Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Mon, 31 May 2021 19:29:17 +0900 Subject: [PATCH 10/11] os: make msghdr, msghdr_const, and sockaddr_storage backwards-compatible `msghdr` and `msghdr_const` definitions have been added back the way they were in std.os. std.os.sendmsg has also been modified to accept a msghdr_const again to ensure backwards-compatibility with this PR. Underneath the hood, std.os.sendmsg will @ptrCast the provided msghdr_const into a std.x.os.Socket.Message. `sockaddr_storage` definitions have been added back the way they were in std.os, except that it now simply aliases std.x.os.Socket.Address.Native.Storage as all of std.x.os.Socket.Address.Native.Storage's fields are equivalent to the fields that were previously defined for std.x.os.bits.sockaddr_storage. std.x.os.Socket.sendMessage now no longer is a stub that aliases std.os.sendmsg, but instead calls and handles errors from std.os.system.sendmsg directly. Addresses feedback to urge backwards compatibility from @andrewrk. --- lib/std/os.zig | 4 +-- lib/std/os/bits/darwin.zig | 1 + lib/std/os/bits/dragonfly.zig | 11 +++++++ lib/std/os/bits/freebsd.zig | 48 +++++++++++++++++++++++++++++ lib/std/os/bits/haiku.zig | 48 +++++++++++++++++++++++++++++ lib/std/os/bits/linux.zig | 6 ++-- lib/std/os/bits/linux/arm-eabi.zig | 20 ++++++++++++ lib/std/os/bits/linux/arm64.zig | 24 +++++++++++++++ lib/std/os/bits/linux/i386.zig | 20 ++++++++++++ lib/std/os/bits/linux/powerpc.zig | 20 ++++++++++++ lib/std/os/bits/linux/powerpc64.zig | 20 ++++++++++++ lib/std/os/bits/linux/sparc64.zig | 20 ++++++++++++ lib/std/os/bits/linux/x86_64.zig | 24 +++++++++++++++ lib/std/os/bits/netbsd.zig | 48 +++++++++++++++++++++++++++++ lib/std/os/bits/openbsd.zig | 48 +++++++++++++++++++++++++++++ lib/std/os/windows/ws2_32.zig | 23 ++++++++++++++ lib/std/x/os/socket_posix.zig | 33 +++++++++++++++++++- 17 files changed, 413 insertions(+), 5 deletions(-) diff --git a/lib/std/os.zig b/lib/std/os.zig index c2c4c16bd72f9238f605657e7f8f2894bd46ede6..f411b4fdc194a469a05743a16944dd2593c270f9 100644 --- a/lib/std/os.zig +++ b/lib/std/os.zig @@ -4994,11 +4994,11 @@ pub fn sendmsg( /// The file descriptor of the sending socket. sockfd: socket_t, /// Message header and iovecs - msg: std.x.os.Socket.Message, + msg: msghdr_const, flags: u32, ) SendMsgError!usize { while (true) { - const rc = system.sendmsg(sockfd, &msg, @intCast(c_int, flags)); + const rc = system.sendmsg(sockfd, @ptrCast(*const std.x.os.Socket.Message, &msg), @intCast(c_int, flags)); if (builtin.os.tag == .windows) { if (rc == windows.ws2_32.SOCKET_ERROR) { switch (windows.ws2_32.WSAGetLastError()) { diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig index 3f8599a08cb96bdbb70e5722718d937600c414f3..3ec373bbbb34a19731fed7ae8d42c223e3a8b8aa 100644 --- a/lib/std/os/bits/darwin.zig +++ b/lib/std/os/bits/darwin.zig @@ -23,6 +23,7 @@ pub const sockaddr = extern struct { family: sa_family_t, data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index f8f89bd07aa0f14fe82691a2160b572e194edaad..88199aee7e4e29c4fc642d7d0a28c33dab800075 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -396,6 +396,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + pub const Kevent = extern struct { ident: usize, filter: c_short, @@ -773,6 +775,15 @@ pub const cmsghdr = extern struct { cmsg_level: c_int, cmsg_type: c_int, }; +pub const msghdr = extern struct { + msg_name: ?*c_void, + msg_namelen: socklen_t, + msg_iov: [*c]iovec, + msg_iovlen: c_int, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: c_int, +}; pub const cmsgcred = extern struct { cmcred_pid: pid_t, cmcred_uid: uid_t, diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig index 381ceb7b3a56ca4ccefa2ac97350b4ac853cf8d3..c3bcafaa65e75371fd47fe362c56375a8a1e0125 100644 --- a/lib/std/os/bits/freebsd.zig +++ b/lib/std/os/bits/freebsd.zig @@ -82,6 +82,52 @@ pub const Flock = extern struct { __unused: [4]u8, }; +pub const msghdr = extern struct { + /// optional address + msg_name: ?*sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec, + + /// # elements in msg_iov + msg_iovlen: i32, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + /// optional address + msg_name: ?*const sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec_const, + + /// # elements in msg_iov + msg_iovlen: i32, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: i32, +}; + pub const libc_stat = extern struct { dev: dev_t, ino: ino_t, @@ -160,6 +206,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig index 316f6d799314b8024cf784ac4979ce7f2f8a7a95..bd677e22e81518a69c618352fda25e339e609c40 100644 --- a/lib/std/os/bits/haiku.zig +++ b/lib/std/os/bits/haiku.zig @@ -73,6 +73,52 @@ pub const Flock = extern struct { __unused: [4]u8, }; +pub const msghdr = extern struct { + /// optional address + msg_name: ?*sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec, + + /// # elements in msg_iov + msg_iovlen: i32, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + /// optional address + msg_name: ?*const sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec_const, + + /// # elements in msg_iov + msg_iovlen: i32, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: i32, +}; + pub const off_t = i64; pub const ino_t = u64; @@ -193,6 +239,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig index c58b7cfa5076ea0368bf98b77b14df2fd5730a2c..c0e22e447f26bc4e0d9509410367d052ee6c380d 100644 --- a/lib/std/os/bits/linux.zig +++ b/lib/std/os/bits/linux.zig @@ -1149,6 +1149,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + /// IPv4 socket address pub const sockaddr_in = extern struct { family: sa_family_t = AF_INET, @@ -1173,12 +1175,12 @@ pub const sockaddr_un = extern struct { }; pub const mmsghdr = extern struct { - msg_hdr: std.x.os.Socket.Message, + msg_hdr: msghdr, msg_len: u32, }; pub const mmsghdr_const = extern struct { - msg_hdr: std.x.os.Socket.Message, + msg_hdr: msghdr_const, msg_len: u32, }; diff --git a/lib/std/os/bits/linux/arm-eabi.zig b/lib/std/os/bits/linux/arm-eabi.zig index 6f596ab3c5eebf0b66c17e2c0c19dab76f6d27fc..335ea074ec2ccb075c299485202a6e8048d3a1b3 100644 --- a/lib/std/os/bits/linux/arm-eabi.zig +++ b/lib/std/os/bits/linux/arm-eabi.zig @@ -526,6 +526,26 @@ pub const Flock = extern struct { __unused: [4]u8, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: i32, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: i32, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/arm64.zig b/lib/std/os/bits/linux/arm64.zig index 46126b69fd02e21492c6eec91c122a5d127f4bf1..e0771e7f662e4f0619b9042958edd3035a0c044a 100644 --- a/lib/std/os/bits/linux/arm64.zig +++ b/lib/std/os/bits/linux/arm64.zig @@ -395,6 +395,30 @@ pub const Flock = extern struct { __unused: [4]u8, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: i32, + __pad1: i32 = 0, + msg_control: ?*c_void, + msg_controllen: socklen_t, + __pad2: socklen_t = 0, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: i32, + __pad1: i32 = 0, + msg_control: ?*c_void, + msg_controllen: socklen_t, + __pad2: socklen_t = 0, + msg_flags: i32, +}; + pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/i386.zig b/lib/std/os/bits/linux/i386.zig index 7e5f7935a30dc9a9718a0ddbc5c6ad2bc1fbaa8a..f8dadb8a6026c5895041b93a5ce594dfd369b667 100644 --- a/lib/std/os/bits/linux/i386.zig +++ b/lib/std/os/bits/linux/i386.zig @@ -523,6 +523,26 @@ pub const Flock = extern struct { l_pid: pid_t, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: i32, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: i32, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/powerpc.zig b/lib/std/os/bits/linux/powerpc.zig index 908593ae908ea04c16c3ea9301a11600d07cf013..96908cb7141ef4b585aa3efc8062cd79cbb8a728 100644 --- a/lib/std/os/bits/linux/powerpc.zig +++ b/lib/std/os/bits/linux/powerpc.zig @@ -515,6 +515,26 @@ pub const Flock = extern struct { l_pid: pid_t, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: usize, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: usize, + msg_control: ?*c_void, + msg_controllen: socklen_t, + msg_flags: i32, +}; + pub const blksize_t = i32; pub const nlink_t = u32; pub const time_t = isize; diff --git a/lib/std/os/bits/linux/powerpc64.zig b/lib/std/os/bits/linux/powerpc64.zig index d7c554fb867343307a478cc3511ab054cac8f75b..52b9109247f1ee66120018d0c68f4fa289c807bc 100644 --- a/lib/std/os/bits/linux/powerpc64.zig +++ b/lib/std/os/bits/linux/powerpc64.zig @@ -491,6 +491,26 @@ pub const Flock = extern struct { __unused: [4]u8, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: usize, + msg_control: ?*c_void, + msg_controllen: usize, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: usize, + msg_control: ?*c_void, + msg_controllen: usize, + msg_flags: i32, +}; + pub const blksize_t = i64; pub const nlink_t = u64; pub const time_t = i64; diff --git a/lib/std/os/bits/linux/sparc64.zig b/lib/std/os/bits/linux/sparc64.zig index e40fb994fd118dc573d700e737af5d669b47ba90..5c67b745f003c6989da85b932695b75cc4c4dcba 100644 --- a/lib/std/os/bits/linux/sparc64.zig +++ b/lib/std/os/bits/linux/sparc64.zig @@ -465,6 +465,26 @@ pub const Flock = extern struct { l_pid: pid_t, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: u64, + msg_control: ?*c_void, + msg_controllen: u64, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: u64, + msg_control: ?*c_void, + msg_controllen: u64, + msg_flags: i32, +}; + pub const off_t = i64; pub const ino_t = u64; pub const mode_t = u32; diff --git a/lib/std/os/bits/linux/x86_64.zig b/lib/std/os/bits/linux/x86_64.zig index b82c1469e9012668ca2c9e09596d99693cd8e426..30e5af384f9c6a96a353df448e5740589b59501c 100644 --- a/lib/std/os/bits/linux/x86_64.zig +++ b/lib/std/os/bits/linux/x86_64.zig @@ -489,6 +489,30 @@ pub const Flock = extern struct { l_pid: pid_t, }; +pub const msghdr = extern struct { + msg_name: ?*sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec, + msg_iovlen: i32, + __pad1: i32 = 0, + msg_control: ?*c_void, + msg_controllen: socklen_t, + __pad2: socklen_t = 0, + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + msg_name: ?*const sockaddr, + msg_namelen: socklen_t, + msg_iov: [*]iovec_const, + msg_iovlen: i32, + __pad1: i32 = 0, + msg_control: ?*c_void, + msg_controllen: socklen_t, + __pad2: socklen_t = 0, + msg_flags: i32, +}; + pub const off_t = i64; pub const ino_t = u64; pub const dev_t = u64; diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig index a3d89620b7cd177c8243791674c3de75b8d9de1a..168d0f1c48f78f2374e8b40e753d6e86e1ffc8ba 100644 --- a/lib/std/os/bits/netbsd.zig +++ b/lib/std/os/bits/netbsd.zig @@ -108,6 +108,52 @@ pub const EAI = enum(c_int) { pub const EAI_MAX = 15; +pub const msghdr = extern struct { + /// optional address + msg_name: ?*sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec, + + /// # elements in msg_iov + msg_iovlen: i32, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: i32, +}; + +pub const msghdr_const = extern struct { + /// optional address + msg_name: ?*const sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec_const, + + /// # elements in msg_iov + msg_iovlen: i32, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: i32, +}; + pub const libc_stat = extern struct { dev: dev_t, mode: mode_t, @@ -180,6 +226,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig index 5335ebac22844736cc9c66893a9c73c9b5438c80..2ff81fae0d0f4b5f6a6b128729d6d91de4bfb4ba 100644 --- a/lib/std/os/bits/openbsd.zig +++ b/lib/std/os/bits/openbsd.zig @@ -124,6 +124,52 @@ pub const EAI = enum(c_int) { pub const EAI_MAX = 15; +pub const msghdr = extern struct { + /// optional address + msg_name: ?*sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec, + + /// # elements in msg_iov + msg_iovlen: c_uint, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: c_int, +}; + +pub const msghdr_const = extern struct { + /// optional address + msg_name: ?*const sockaddr, + + /// size of address + msg_namelen: socklen_t, + + /// scatter/gather array + msg_iov: [*]iovec_const, + + /// # elements in msg_iov + msg_iovlen: c_uint, + + /// ancillary data + msg_control: ?*c_void, + + /// ancillary data buffer len + msg_controllen: socklen_t, + + /// flags on received message + msg_flags: c_int, +}; + pub const libc_stat = extern struct { mode: mode_t, dev: dev_t, @@ -200,6 +246,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig index 219c32d92808ada5f1a7c4e089267a9a2cb00ae9..1aa6daa3e6c60c8c79dd8c70c15a9645f6f6f512 100644 --- a/lib/std/os/windows/ws2_32.zig +++ b/lib/std/os/windows/ws2_32.zig @@ -1059,6 +1059,8 @@ pub const sockaddr = extern struct { data: [14]u8, }; +pub const sockaddr_storage = std.x.os.Socket.Address.Native.Storage; + /// IPv4 socket address pub const sockaddr_in = extern struct { family: ADDRESS_FAMILY = AF_INET, @@ -1087,6 +1089,27 @@ pub const WSABUF = extern struct { buf: [*]u8, }; +pub const msghdr = WSAMSG; +pub const msghdr_const = WSAMSG_const; + +pub const WSAMSG_const = extern struct { + name: *const sockaddr, + namelen: INT, + lpBuffers: [*]WSABUF, + dwBufferCount: DWORD, + Control: WSABUF, + dwFlags: DWORD, +}; + +pub const WSAMSG = extern struct { + name: *sockaddr, + namelen: INT, + lpBuffers: [*]WSABUF, + dwBufferCount: DWORD, + Control: WSABUF, + dwFlags: DWORD, +}; + pub const WSAPOLLFD = pollfd; pub const pollfd = extern struct { diff --git a/lib/std/x/os/socket_posix.zig b/lib/std/x/os/socket_posix.zig index ebaadcbd5d154c5fb81f76d9df79b6c3d9930781..5deff2231720d8cfa0b8b3146f9f4746a56bb32c 100644 --- a/lib/std/x/os/socket_posix.zig +++ b/lib/std/x/os/socket_posix.zig @@ -79,7 +79,38 @@ pub fn Mixin(comptime Socket: type) type { /// with a set of flags specified. It returns the number of bytes that are /// written to the socket. pub fn writeMessage(self: Socket, msg: Socket.Message, flags: u32) !usize { - return os.sendmsg(self.fd, msg, flags); + while (true) { + const rc = os.system.sendmsg(self.fd, &msg, @intCast(c_int, flags)); + return switch (os.errno(rc)) { + 0 => return @intCast(usize, rc), + os.EACCES => error.AccessDenied, + os.EAGAIN => error.WouldBlock, + os.EALREADY => error.FastOpenAlreadyInProgress, + os.EBADF => unreachable, // always a race condition + os.ECONNRESET => error.ConnectionResetByPeer, + os.EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. + os.EFAULT => unreachable, // An invalid user space address was specified for an argument. + os.EINTR => continue, + os.EINVAL => unreachable, // Invalid argument passed. + os.EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified + os.EMSGSIZE => error.MessageTooBig, + os.ENOBUFS => error.SystemResources, + os.ENOMEM => error.SystemResources, + os.ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. + os.EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. + os.EPIPE => error.BrokenPipe, + os.EAFNOSUPPORT => error.AddressFamilyNotSupported, + os.ELOOP => error.SymLinkLoop, + os.ENAMETOOLONG => error.NameTooLong, + os.ENOENT => error.FileNotFound, + os.ENOTDIR => error.NotDir, + os.EHOSTUNREACH => error.NetworkUnreachable, + os.ENETUNREACH => error.NetworkUnreachable, + os.ENOTCONN => error.SocketNotConnected, + os.ENETDOWN => error.NetworkSubsystemFailed, + else => |err| os.unexpectedErrno(err), + }; + } } /// Read multiple I/O vectors with a prepended message header from the socket -- 2.54.0 From 4909aa1da43d227ad85b2fe03a58ef1a8c12b769 Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Tue, 1 Jun 2021 18:35:13 +0900 Subject: [PATCH 11/11] os/bits: remove duplicate `sockaddr_storage` for dragonfly --- lib/std/atomic.zig | 6 ++--- lib/std/atomic/Atomic.zig | 44 +++++++++++++++++------------------ lib/std/mem.zig | 4 ++-- lib/std/os/bits/dragonfly.zig | 8 ------- lib/std/target.zig | 3 +-- 5 files changed, 28 insertions(+), 37 deletions(-) diff --git a/lib/std/atomic.zig b/lib/std/atomic.zig index 224b57d1d2053e8c967fb58401a643fa8e1d4fbe..1944e5346b5462fcc4de3e139a0f37fc6fb4cb99 100644 --- a/lib/std/atomic.zig +++ b/lib/std/atomic.zig @@ -19,7 +19,7 @@ test "std.atomic" { _ = @import("atomic/Atomic.zig"); } -pub fn fence(comptime ordering: Ordering) callconv(.Inline) void { +pub inline fn fence(comptime ordering: Ordering) void { switch (ordering) { .Acquire, .Release, .AcqRel, .SeqCst => { @fence(ordering); @@ -30,7 +30,7 @@ pub fn fence(comptime ordering: Ordering) callconv(.Inline) void { } } -pub fn compilerFence(comptime ordering: Ordering) callconv(.Inline) void { +pub inline fn compilerFence(comptime ordering: Ordering) void { switch (ordering) { .Acquire, .Release, .AcqRel, .SeqCst => asm volatile ("" ::: "memory"), else => @compileLog(ordering, " only applies to a given memory location"), @@ -45,7 +45,7 @@ test "fence/compilerFence" { } /// Signals to the processor that the caller is inside a busy-wait spin-loop. -pub fn spinLoopHint() callconv(.Inline) void { +pub inline fn spinLoopHint() void { const hint_instruction = switch (target.cpu.arch) { // No-op instruction that can hint to save (or share with a hardware-thread) pipelining/power resources // https://software.intel.com/content/www/us/en/develop/articles/benefitting-power-and-performance-sleep-loops.html diff --git a/lib/std/atomic/Atomic.zig b/lib/std/atomic/Atomic.zig index 5c3b865a6a65f347245dbd43f5d4288bc11e54b9..d137bc7552713d6853939d6cbb84c148c1668680 100644 --- a/lib/std/atomic/Atomic.zig +++ b/lib/std/atomic/Atomic.zig @@ -48,38 +48,38 @@ pub fn Atomic(comptime T: type) type { }; } - pub fn swap(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn swap(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Xchg, value, ordering); } - pub fn compareAndSwap( + pub inline fn compareAndSwap( self: *Self, compare: T, exchange: T, comptime success: Ordering, comptime failure: Ordering, - ) callconv(.Inline) ?T { + ) ?T { return self.cmpxchg(true, compare, exchange, success, failure); } - pub fn tryCompareAndSwap( + pub inline fn tryCompareAndSwap( self: *Self, compare: T, exchange: T, comptime success: Ordering, comptime failure: Ordering, - ) callconv(.Inline) ?T { + ) ?T { return self.cmpxchg(false, compare, exchange, success, failure); } - fn cmpxchg( + inline fn cmpxchg( self: *Self, comptime is_strong: bool, compare: T, exchange: T, comptime success: Ordering, comptime failure: Ordering, - ) callconv(.Inline) ?T { + ) ?T { if (success == .Unordered or failure == .Unordered) { @compileError(@tagName(Ordering.Unordered) ++ " is only allowed on atomic loads and stores"); } @@ -103,12 +103,12 @@ pub fn Atomic(comptime T: type) type { }; } - fn rmw( + inline fn rmw( self: *Self, comptime op: std.builtin.AtomicRmwOp, value: T, comptime ordering: Ordering, - ) callconv(.Inline) T { + ) T { return @atomicRmw(T, &self.value, op, value, ordering); } @@ -117,37 +117,37 @@ pub fn Atomic(comptime T: type) type { } pub usingnamespace exportWhen(std.meta.trait.isNumber(T), struct { - pub fn fetchAdd(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchAdd(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Add, value, ordering); } - pub fn fetchSub(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchSub(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Sub, value, ordering); } - pub fn fetchMin(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchMin(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Min, value, ordering); } - pub fn fetchMax(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchMax(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Max, value, ordering); } }); pub usingnamespace exportWhen(std.meta.trait.isIntegral(T), struct { - pub fn fetchAnd(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchAnd(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.And, value, ordering); } - pub fn fetchNand(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchNand(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Nand, value, ordering); } - pub fn fetchOr(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchOr(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Or, value, ordering); } - pub fn fetchXor(self: *Self, value: T, comptime ordering: Ordering) callconv(.Inline) T { + pub inline fn fetchXor(self: *Self, value: T, comptime ordering: Ordering) T { return self.rmw(.Xor, value, ordering); } @@ -158,24 +158,24 @@ pub fn Atomic(comptime T: type) type { Toggle, }; - pub fn bitSet(self: *Self, bit: Bit, comptime ordering: Ordering) callconv(.Inline) u1 { + pub inline fn bitSet(self: *Self, bit: Bit, comptime ordering: Ordering) u1 { return bitRmw(self, .Set, bit, ordering); } - pub fn bitReset(self: *Self, bit: Bit, comptime ordering: Ordering) callconv(.Inline) u1 { + pub inline fn bitReset(self: *Self, bit: Bit, comptime ordering: Ordering) u1 { return bitRmw(self, .Reset, bit, ordering); } - pub fn bitToggle(self: *Self, bit: Bit, comptime ordering: Ordering) callconv(.Inline) u1 { + pub inline fn bitToggle(self: *Self, bit: Bit, comptime ordering: Ordering) u1 { return bitRmw(self, .Toggle, bit, ordering); } - fn bitRmw( + inline fn bitRmw( self: *Self, comptime op: BitRmwOp, bit: Bit, comptime ordering: Ordering, - ) callconv(.Inline) u1 { + ) u1 { // x86 supports dedicated bitwise instructions if (comptime target.cpu.arch.isX86() and @sizeOf(T) >= 2 and @sizeOf(T) <= 8) { const instruction = switch (op) { diff --git a/lib/std/mem.zig b/lib/std/mem.zig index 4cf879cf054b7c70feb55891f2fd64f05eda226a..fd9af71e4bc69a809d67865ab1a747db54bfc0dd 100644 --- a/lib/std/mem.zig +++ b/lib/std/mem.zig @@ -1171,7 +1171,7 @@ test "mem.indexOf" { test "mem.indexOf multibyte" { { // make haystack and needle long enough to trigger boyer-moore-horspool algorithm - const haystack = [1]u16{0} ** 100 ++ [_]u16 { 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff }; + const haystack = [1]u16{0} ** 100 ++ [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff }; const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee }; try testing.expectEqual(indexOfPos(u16, &haystack, 0, &needle), 100); @@ -1184,7 +1184,7 @@ test "mem.indexOf multibyte" { { // make haystack and needle long enough to trigger boyer-moore-horspool algorithm - const haystack = [_]u16 { 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ [1]u16{0} ** 100; + const haystack = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee, 0x00ff } ++ [1]u16{0} ** 100; const needle = [_]u16{ 0xbbaa, 0xccbb, 0xddcc, 0xeedd, 0xffee }; try testing.expectEqual(lastIndexOf(u16, &haystack, &needle), 0); diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig index 88199aee7e4e29c4fc642d7d0a28c33dab800075..5c3ad305da073a8d654a4c7d13e5683fe3af0157 100644 --- a/lib/std/os/bits/dragonfly.zig +++ b/lib/std/os/bits/dragonfly.zig @@ -696,14 +696,6 @@ pub const in_port_t = u16; pub const sa_family_t = u8; pub const socklen_t = u32; -pub const sockaddr_storage = extern struct { - ss_len: u8, - ss_family: sa_family_t, - __ss_pad1: [5]u8, - __ss_align: i64, - __ss_pad2: [112]u8, -}; - pub const sockaddr_in = extern struct { len: u8 = @sizeOf(sockaddr_in), family: sa_family_t = AF_INET, diff --git a/lib/std/target.zig b/lib/std/target.zig index 692d29b1c7e63d532d7d9e32f10640e67676a6d6..9a2be37ee8c66bb02a85af41547575c3bce9e007 100644 --- a/lib/std/target.zig +++ b/lib/std/target.zig @@ -500,8 +500,7 @@ pub const Target = struct { .haiku, .windows, => return .gnu, - .uefi, - => return .msvc, + .uefi => return .msvc, .linux, .wasi, .emscripten, -- 2.54.0