From aad8491dbd98052e97b395ea572b186482d3b38f Mon Sep 17 00:00:00 2001 From: Kenta Iwasaki Date: Mon, 31 May 2021 19:29:17 +0900 Subject: [PATCH] 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 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