Commit aad8491dbd

Kenta Iwasaki <kenta@lithdew.net>
2021-05-31 12:29:17
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.
1 parent 6950e4c
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;
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;
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;
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;
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;
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;
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;
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,
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,
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,
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,
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,
 };
 
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,
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,
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 {
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
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()) {