| author | |
| committer | |
| log | 1f17221bc4e17bcd7116fe12ab3f939346179799 |
| tree | 6073c4569cb25b6d232bab68971896b16b135844 |
| parent | 294ee1bbc93a00ead5182234f824b0a665c579d9 |
5 files changed, 96 insertions(+), 10 deletions(-)
lib/std/os.zig+74-1| ... | @@ -4840,7 +4840,7 @@ pub const SendError = error{ | ... | @@ -4840,7 +4840,7 @@ pub const SendError = error{ |
| 4840 | NetworkSubsystemFailed, | 4840 | NetworkSubsystemFailed, |
| 4841 | } || UnexpectedError; | 4841 | } || UnexpectedError; |
| 4842 | 4842 | ||
| 4843 | pub const SendToError = SendError || error{ | 4843 | pub const SendMsgError = SendError || error{ |
| 4844 | /// The passed address didn't have the correct address family in its sa_family field. | 4844 | /// The passed address didn't have the correct address family in its sa_family field. |
| 4845 | AddressFamilyNotSupported, | 4845 | AddressFamilyNotSupported, |
| 4846 | 4846 | ||
| ... | @@ -4859,6 +4859,79 @@ pub const SendToError = SendError || error{ | ... | @@ -4859,6 +4859,79 @@ pub const SendToError = SendError || error{ |
| 4859 | AddressNotAvailable, | 4859 | AddressNotAvailable, |
| 4860 | }; | 4860 | }; |
| 4861 | 4861 | ||
| 4862 | pub fn sendmsg( | ||
| 4863 | /// The file descriptor of the sending socket. | ||
| 4864 | sockfd: socket_t, | ||
| 4865 | /// Message header and iovecs | ||
| 4866 | msg: msghdr_const, | ||
| 4867 | flags: u32, | ||
| 4868 | ) SendMsgError!usize { | ||
| 4869 | while (true) { | ||
| 4870 | const rc = system.sendmsg(sockfd, &msg, flags); | ||
| 4871 | if (builtin.os.tag == .windows) { | ||
| 4872 | if (rc == windows.ws2_32.SOCKET_ERROR) { | ||
| 4873 | switch (windows.ws2_32.WSAGetLastError()) { | ||
| 4874 | .WSAEACCES => return error.AccessDenied, | ||
| 4875 | .WSAEADDRNOTAVAIL => return error.AddressNotAvailable, | ||
| 4876 | .WSAECONNRESET => return error.ConnectionResetByPeer, | ||
| 4877 | .WSAEMSGSIZE => return error.MessageTooBig, | ||
| 4878 | .WSAENOBUFS => return error.SystemResources, | ||
| 4879 | .WSAENOTSOCK => return error.FileDescriptorNotASocket, | ||
| 4880 | .WSAEAFNOSUPPORT => return error.AddressFamilyNotSupported, | ||
| 4881 | .WSAEDESTADDRREQ => unreachable, // A destination address is required. | ||
| 4882 | .WSAEFAULT => unreachable, // The lpBuffers, lpTo, lpOverlapped, lpNumberOfBytesSent, or lpCompletionRoutine parameters are not part of the user address space, or the lpTo parameter is too small. | ||
| 4883 | .WSAEHOSTUNREACH => return error.NetworkUnreachable, | ||
| 4884 | // TODO: WSAEINPROGRESS, WSAEINTR | ||
| 4885 | .WSAEINVAL => unreachable, | ||
| 4886 | .WSAENETDOWN => return error.NetworkSubsystemFailed, | ||
| 4887 | .WSAENETRESET => return error.ConnectionResetByPeer, | ||
| 4888 | .WSAENETUNREACH => return error.NetworkUnreachable, | ||
| 4889 | .WSAENOTCONN => return error.SocketNotConnected, | ||
| 4890 | .WSAESHUTDOWN => unreachable, // The socket has been shut down; it is not possible to WSASendTo on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH. | ||
| 4891 | .WSAEWOULDBLOCK => return error.WouldBlock, | ||
| 4892 | .WSANOTINITIALISED => unreachable, // A successful WSAStartup call must occur before using this function. | ||
| 4893 | else => |err| return windows.unexpectedWSAError(err), | ||
| 4894 | } | ||
| 4895 | } else { | ||
| 4896 | return @intCast(usize, rc); | ||
| 4897 | } | ||
| 4898 | } else { | ||
| 4899 | switch (errno(rc)) { | ||
| 4900 | 0 => return @intCast(usize, rc), | ||
| 4901 | |||
| 4902 | EACCES => return error.AccessDenied, | ||
| 4903 | EAGAIN => return error.WouldBlock, | ||
| 4904 | EALREADY => return error.FastOpenAlreadyInProgress, | ||
| 4905 | EBADF => unreachable, // always a race condition | ||
| 4906 | ECONNRESET => return error.ConnectionResetByPeer, | ||
| 4907 | EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set. | ||
| 4908 | EFAULT => unreachable, // An invalid user space address was specified for an argument. | ||
| 4909 | EINTR => continue, | ||
| 4910 | EINVAL => unreachable, // Invalid argument passed. | ||
| 4911 | EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified | ||
| 4912 | EMSGSIZE => return error.MessageTooBig, | ||
| 4913 | ENOBUFS => return error.SystemResources, | ||
| 4914 | ENOMEM => return error.SystemResources, | ||
| 4915 | ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket. | ||
| 4916 | EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type. | ||
| 4917 | EPIPE => return error.BrokenPipe, | ||
| 4918 | EAFNOSUPPORT => return error.AddressFamilyNotSupported, | ||
| 4919 | ELOOP => return error.SymLinkLoop, | ||
| 4920 | ENAMETOOLONG => return error.NameTooLong, | ||
| 4921 | ENOENT => return error.FileNotFound, | ||
| 4922 | ENOTDIR => return error.NotDir, | ||
| 4923 | EHOSTUNREACH => return error.NetworkUnreachable, | ||
| 4924 | ENETUNREACH => return error.NetworkUnreachable, | ||
| 4925 | ENOTCONN => return error.SocketNotConnected, | ||
| 4926 | ENETDOWN => return error.NetworkSubsystemFailed, | ||
| 4927 | else => |err| return unexpectedErrno(err), | ||
| 4928 | } | ||
| 4929 | } | ||
| 4930 | } | ||
| 4931 | } | ||
| 4932 | |||
| 4933 | pub const SendToError = SendMsgError; | ||
| 4934 | |||
| 4862 | /// Transmit a message to another socket. | 4935 | /// Transmit a message to another socket. |
| 4863 | /// | 4936 | /// |
| 4864 | /// The `sendto` call may be used only when the socket is in a connected state (so that the intended | 4937 | /// The `sendto` call may be used only when the socket is in a connected state (so that the intended |
lib/std/os/bits/linux/arm64.zig+4-4| ... | @@ -400,10 +400,10 @@ pub const msghdr = extern struct { | ... | @@ -400,10 +400,10 @@ pub const msghdr = extern struct { |
| 400 | msg_namelen: socklen_t, | 400 | msg_namelen: socklen_t, |
| 401 | msg_iov: [*]iovec, | 401 | msg_iov: [*]iovec, |
| 402 | msg_iovlen: i32, | 402 | msg_iovlen: i32, |
| 403 | __pad1: i32, | 403 | __pad1: i32 = 0, |
| 404 | msg_control: ?*c_void, | 404 | msg_control: ?*c_void, |
| 405 | msg_controllen: socklen_t, | 405 | msg_controllen: socklen_t, |
| 406 | __pad2: socklen_t, | 406 | __pad2: socklen_t = 0, |
| 407 | msg_flags: i32, | 407 | msg_flags: i32, |
| 408 | }; | 408 | }; |
| 409 | 409 | ||
| ... | @@ -412,10 +412,10 @@ pub const msghdr_const = extern struct { | ... | @@ -412,10 +412,10 @@ pub const msghdr_const = extern struct { |
| 412 | msg_namelen: socklen_t, | 412 | msg_namelen: socklen_t, |
| 413 | msg_iov: [*]iovec_const, | 413 | msg_iov: [*]iovec_const, |
| 414 | msg_iovlen: i32, | 414 | msg_iovlen: i32, |
| 415 | __pad1: i32, | 415 | __pad1: i32 = 0, |
| 416 | msg_control: ?*c_void, | 416 | msg_control: ?*c_void, |
| 417 | msg_controllen: socklen_t, | 417 | msg_controllen: socklen_t, |
| 418 | __pad2: socklen_t, | 418 | __pad2: socklen_t = 0, |
| 419 | msg_flags: i32, | 419 | msg_flags: i32, |
| 420 | }; | 420 | }; |
| 421 | 421 |
lib/std/os/bits/linux/x86_64.zig+4-4| ... | @@ -495,10 +495,10 @@ pub const msghdr = extern struct { | ... | @@ -495,10 +495,10 @@ pub const msghdr = extern struct { |
| 495 | msg_namelen: socklen_t, | 495 | msg_namelen: socklen_t, |
| 496 | msg_iov: [*]iovec, | 496 | msg_iov: [*]iovec, |
| 497 | msg_iovlen: i32, | 497 | msg_iovlen: i32, |
| 498 | __pad1: i32, | 498 | __pad1: i32 = 0, |
| 499 | msg_control: ?*c_void, | 499 | msg_control: ?*c_void, |
| 500 | msg_controllen: socklen_t, | 500 | msg_controllen: socklen_t, |
| 501 | __pad2: socklen_t, | 501 | __pad2: socklen_t = 0, |
| 502 | msg_flags: i32, | 502 | msg_flags: i32, |
| 503 | }; | 503 | }; |
| 504 | 504 | ||
| ... | @@ -507,10 +507,10 @@ pub const msghdr_const = extern struct { | ... | @@ -507,10 +507,10 @@ pub const msghdr_const = extern struct { |
| 507 | msg_namelen: socklen_t, | 507 | msg_namelen: socklen_t, |
| 508 | msg_iov: [*]iovec_const, | 508 | msg_iov: [*]iovec_const, |
| 509 | msg_iovlen: i32, | 509 | msg_iovlen: i32, |
| 510 | __pad1: i32, | 510 | __pad1: i32 = 0, |
| 511 | msg_control: ?*c_void, | 511 | msg_control: ?*c_void, |
| 512 | msg_controllen: socklen_t, | 512 | msg_controllen: socklen_t, |
| 513 | __pad2: socklen_t, | 513 | __pad2: socklen_t = 0, |
| 514 | msg_flags: i32, | 514 | msg_flags: i32, |
| 515 | }; | 515 | }; |
| 516 | 516 |
lib/std/os/linux.zig+1-1| ... | @@ -977,7 +977,7 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal | ... | @@ -977,7 +977,7 @@ pub fn getsockopt(fd: i32, level: u32, optname: u32, noalias optval: [*]u8, noal |
| 977 | return syscall5(.getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); | 977 | return syscall5(.getsockopt, @bitCast(usize, @as(isize, fd)), level, optname, @ptrToInt(optval), @ptrToInt(optlen)); |
| 978 | } | 978 | } |
| 979 | 979 | ||
| 980 | pub fn sendmsg(fd: i32, msg: *msghdr_const, flags: u32) usize { | 980 | pub fn sendmsg(fd: i32, msg: *const msghdr_const, flags: u32) usize { |
| 981 | if (builtin.arch == .i386) { | 981 | if (builtin.arch == .i386) { |
| 982 | return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags }); | 982 | return socketcall(SC_sendmsg, &[3]usize{ @bitCast(usize, @as(isize, fd)), @ptrToInt(msg), flags }); |
| 983 | } | 983 | } |
lib/std/os/windows.zig+13| ... | @@ -1291,6 +1291,19 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so | ... | @@ -1291,6 +1291,19 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so |
| 1291 | return ws2_32.getsockname(s, name, @ptrCast(*i32, namelen)); | 1291 | return ws2_32.getsockname(s, name, @ptrCast(*i32, namelen)); |
| 1292 | } | 1292 | } |
| 1293 | 1293 | ||
| 1294 | pub fn sendmsg( | ||
| 1295 | s: ws2_32.SOCKET, | ||
| 1296 | msg: *const ws2_32.WSAMSG, | ||
| 1297 | flags: u32, | ||
| 1298 | ) i32 { | ||
| 1299 | var bytes_send: DWORD = undefined; | ||
| 1300 | if (ws2_32.WSASendMsg(s, msg, flags, &bytes_send, null, null) == ws2_32.SOCKET_ERROR) { | ||
| 1301 | return ws2_32.SOCKET_ERROR; | ||
| 1302 | } else { | ||
| 1303 | return @as(i32, @intCast(u31, bytes_send)); | ||
| 1304 | } | ||
| 1305 | } | ||
| 1306 | |||
| 1294 | pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 { | 1307 | pub fn sendto(s: ws2_32.SOCKET, buf: [*]const u8, len: usize, flags: u32, to: ?*const ws2_32.sockaddr, to_len: ws2_32.socklen_t) i32 { |
| 1295 | var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) }; | 1308 | var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) }; |
| 1296 | var bytes_send: DWORD = undefined; | 1309 | var bytes_send: DWORD = undefined; |