From 3600508fe18ecc61ea889a65127a2641a76c2933 Mon Sep 17 00:00:00 2001 From: lithdew Date: Wed, 12 May 2021 22:43:34 +0900 Subject: 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 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'lib/std/os.zig') diff --git a/lib/std/os.zig b/lib/std/os.zig index 2fe7ba9c5a..4ed0be8f62 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) { -- cgit v1.2.3 From 9ba65592d64f53d886b00402659cfce775ea77d3 Mon Sep 17 00:00:00 2001 From: lithdew Date: Fri, 14 May 2021 15:50:09 +0900 Subject: 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(-) (limited to 'lib/std/os.zig') diff --git a/lib/std/c.zig b/lib/std/c.zig index 2da0fea614..a91fee7274 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 4ed0be8f62..c2c4c16bd7 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 0d6b87c15f..a3a8c8e431 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 b9fc21a40d..70c8b35b5f 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 -- cgit v1.2.3 From aad8491dbd98052e97b395ea572b186482d3b38f Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Mon, 31 May 2021 19:29:17 +0900 Subject: 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(-) (limited to 'lib/std/os.zig') diff --git a/lib/std/os.zig b/lib/std/os.zig index c2c4c16bd7..f411b4fdc1 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 3f8599a08c..3ec373bbbb 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 f8f89bd07a..88199aee7e 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 381ceb7b3a..c3bcafaa65 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 316f6d7993..bd677e22e8 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 c58b7cfa50..c0e22e447f 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 6f596ab3c5..335ea074ec 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 46126b69fd..e0771e7f66 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 7e5f7935a3..f8dadb8a60 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 908593ae90..96908cb714 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 d7c554fb86..52b9109247 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 e40fb994fd..5c67b745f0 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 b82c1469e9..30e5af384f 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 a3d89620b7..168d0f1c48 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 5335ebac22..2ff81fae0d 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 219c32d928..1aa6daa3e6 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 ebaadcbd5d..5deff22317 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 -- cgit v1.2.3