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