authorgravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2020-09-03 13:23:48+02:00
committergravatar for BarabasGitHub@users.noreply.github.comBas van den Berg <BarabasGitHub@users.noreply.github.com> 2020-09-03 13:23:48+02:00
log0a40a61548ad9f666ed5300a8910f9040cc1390b
tree0e1084929c0bc0b99704113ab706d625ca61b5c8
parentd80554cedf313bc78f0419faf84776bd987263df

os.send(to) and os.recv(from) functions made to work on windows.


3 files changed, 92 insertions(+), 45 deletions(-)

lib/std/os.zig+70-44
...@@ -4630,7 +4630,7 @@ pub const SendError = error{...@@ -4630,7 +4630,7 @@ pub const SendError = error{
4630/// possible to send more data.4630/// possible to send more data.
4631pub fn sendto(4631pub fn sendto(
4632 /// The file descriptor of the sending socket.4632 /// The file descriptor of the sending socket.
4633 sockfd: fd_t,4633 sockfd: socket_t,
4634 /// Message to send.4634 /// Message to send.
4635 buf: []const u8,4635 buf: []const u8,
4636 flags: u32,4636 flags: u32,
...@@ -4639,32 +4639,43 @@ pub fn sendto(...@@ -4639,32 +4639,43 @@ pub fn sendto(
4639) SendError!usize {4639) SendError!usize {
4640 while (true) {4640 while (true) {
4641 const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen);4641 const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen);
4642 switch (errno(rc)) {4642 if (builtin.os.tag == .windows) {
4643 0 => return @intCast(usize, rc),4643 if (rc == windows.ws2_32.SOCKET_ERROR) {
46444644 switch (windows.ws2_32.WSAGetLastError()) {
4645 EACCES => return error.AccessDenied,4645 // TODO: handle errors
4646 EAGAIN => if (std.event.Loop.instance) |loop| {4646 else => |err| return windows.unexpectedWSAError(err),
4647 loop.waitUntilFdWritable(sockfd);4647 }
4648 continue;
4649 } else {4648 } else {
4650 return error.WouldBlock;4649 return @intCast(usize, rc);
4651 },4650 }
4652 EALREADY => return error.FastOpenAlreadyInProgress,4651 } else {
4653 EBADF => unreachable, // always a race condition4652 switch (errno(rc)) {
4654 ECONNRESET => return error.ConnectionResetByPeer,4653 0 => return @intCast(usize, rc),
4655 EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set.4654
4656 EFAULT => unreachable, // An invalid user space address was specified for an argument.4655 EACCES => return error.AccessDenied,
4657 EINTR => continue,4656 EAGAIN => if (std.event.Loop.instance) |loop| {
4658 EINVAL => unreachable, // Invalid argument passed.4657 loop.waitUntilFdWritable(sockfd);
4659 EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified4658 continue;
4660 EMSGSIZE => return error.MessageTooBig,4659 } else {
4661 ENOBUFS => return error.SystemResources,4660 return error.WouldBlock;
4662 ENOMEM => return error.SystemResources,4661 },
4663 ENOTCONN => unreachable, // The socket is not connected, and no target has been given.4662 EALREADY => return error.FastOpenAlreadyInProgress,
4664 ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.4663 EBADF => unreachable, // always a race condition
4665 EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.4664 ECONNRESET => return error.ConnectionResetByPeer,
4666 EPIPE => return error.BrokenPipe,4665 EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set.
4667 else => |err| return unexpectedErrno(err),4666 EFAULT => unreachable, // An invalid user space address was specified for an argument.
4667 EINTR => continue,
4668 EINVAL => unreachable, // Invalid argument passed.
4669 EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified
4670 EMSGSIZE => return error.MessageTooBig,
4671 ENOBUFS => return error.SystemResources,
4672 ENOMEM => return error.SystemResources,
4673 ENOTCONN => unreachable, // The socket is not connected, and no target has been given.
4674 ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
4675 EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
4676 EPIPE => return error.BrokenPipe,
4677 else => |err| return unexpectedErrno(err),
4678 }
4668 }4679 }
4669 }4680 }
4670}4681}
...@@ -4690,7 +4701,7 @@ pub fn sendto(...@@ -4690,7 +4701,7 @@ pub fn sendto(
4690/// possible to send more data.4701/// possible to send more data.
4691pub fn send(4702pub fn send(
4692 /// The file descriptor of the sending socket.4703 /// The file descriptor of the sending socket.
4693 sockfd: fd_t,4704 sockfd: socket_t,
4694 buf: []const u8,4705 buf: []const u8,
4695 flags: u32,4706 flags: u32,
4696) SendError!usize {4707) SendError!usize {
...@@ -5125,8 +5136,12 @@ pub const RecvFromError = error{...@@ -5125,8 +5136,12 @@ pub const RecvFromError = error{
5125 SystemResources,5136 SystemResources,
5126} || UnexpectedError;5137} || UnexpectedError;
51275138
5139pub fn recv(sock: socket_t, buf: []u8, flags: u32) RecvFromError!usize {
5140 return recvfrom(sock, buf, flags, null, null);
5141}
5142
5128pub fn recvfrom(5143pub fn recvfrom(
5129 sockfd: fd_t,5144 sockfd: socket_t,
5130 buf: []u8,5145 buf: []u8,
5131 flags: u32,5146 flags: u32,
5132 src_addr: ?*sockaddr,5147 src_addr: ?*sockaddr,
...@@ -5134,23 +5149,34 @@ pub fn recvfrom(...@@ -5134,23 +5149,34 @@ pub fn recvfrom(
5134) RecvFromError!usize {5149) RecvFromError!usize {
5135 while (true) {5150 while (true) {
5136 const rc = system.recvfrom(sockfd, buf.ptr, buf.len, flags, src_addr, addrlen);5151 const rc = system.recvfrom(sockfd, buf.ptr, buf.len, flags, src_addr, addrlen);
5137 switch (errno(rc)) {5152 if (builtin.os.tag == .windows) {
5138 0 => return @intCast(usize, rc),5153 if (rc == windows.ws2_32.SOCKET_ERROR) {
5139 EBADF => unreachable, // always a race condition5154 switch (windows.ws2_32.WSAGetLastError()) {
5140 EFAULT => unreachable,5155 // TODO: handle errors
5141 EINVAL => unreachable,5156 else => |err| return windows.unexpectedWSAError(err),
5142 ENOTCONN => unreachable,5157 }
5143 ENOTSOCK => unreachable,
5144 EINTR => continue,
5145 EAGAIN => if (std.event.Loop.instance) |loop| {
5146 loop.waitUntilFdReadable(sockfd);
5147 continue;
5148 } else {5158 } else {
5149 return error.WouldBlock;5159 return @intCast(usize, rc);
5150 },5160 }
5151 ENOMEM => return error.SystemResources,5161 } else {
5152 ECONNREFUSED => return error.ConnectionRefused,5162 switch (errno(rc)) {
5153 else => |err| return unexpectedErrno(err),5163 0 => return @intCast(usize, rc),
5164 EBADF => unreachable, // always a race condition
5165 EFAULT => unreachable,
5166 EINVAL => unreachable,
5167 ENOTCONN => unreachable,
5168 ENOTSOCK => unreachable,
5169 EINTR => continue,
5170 EAGAIN => if (std.event.Loop.instance) |loop| {
5171 loop.waitUntilFdReadable(sockfd);
5172 continue;
5173 } else {
5174 return error.WouldBlock;
5175 },
5176 ENOMEM => return error.SystemResources,
5177 ECONNREFUSED => return error.ConnectionRefused,
5178 else => |err| return unexpectedErrno(err),
5179 }
5154 }5180 }
5155 }5181 }
5156}5182}
lib/std/os/windows.zig+21
...@@ -1190,6 +1190,27 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so...@@ -1190,6 +1190,27 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
1190 return rc;1190 return rc;
1191}1191}
11921192
1193pub 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 {
1194 var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) };
1195 var bytes_send: DWORD = undefined;
1196 if (ws2_32.WSASendTo(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_send, flags, to, to_len, null, null) == ws2_32.SOCKET_ERROR) {
1197 return ws2_32.SOCKET_ERROR;
1198 } else {
1199 return @as(i32, @intCast(u31, bytes_send));
1200 }
1201}
1202
1203pub fn recvfrom(s: ws2_32.SOCKET, buf: [*]u8, len: usize, flags: u32, from: ?*ws2_32.sockaddr, from_len: ?*ws2_32.socklen_t) i32 {
1204 var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = buf };
1205 var bytes_received: DWORD = undefined;
1206 var flags_inout = flags;
1207 if (ws2_32.WSARecvFrom(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_received, &flags_inout, from, from_len, null, null) == ws2_32.SOCKET_ERROR) {
1208 return ws2_32.SOCKET_ERROR;
1209 } else {
1210 return @as(i32, @intCast(u31, bytes_received));
1211 }
1212}
1213
1193pub fn WSAIoctl(1214pub fn WSAIoctl(
1194 s: ws2_32.SOCKET,1215 s: ws2_32.SOCKET,
1195 dwIoControlCode: DWORD,1216 dwIoControlCode: DWORD,
lib/std/os/windows/ws2_32.zig+1-1
...@@ -786,7 +786,7 @@ pub extern "ws2_32" fn WSASendTo(...@@ -786,7 +786,7 @@ pub extern "ws2_32" fn WSASendTo(
786 lpNumberOfBytesSent: ?*DWORD,786 lpNumberOfBytesSent: ?*DWORD,
787 dwFlags: DWORD,787 dwFlags: DWORD,
788 lpTo: ?*const sockaddr,788 lpTo: ?*const sockaddr,
789 iTolen: socklen_t,789 iTolen: c_int,
790 lpOverlapped: ?*WSAOVERLAPPED,790 lpOverlapped: ?*WSAOVERLAPPED,
791 lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,791 lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
792) callconv(.Stdcall) c_int;792) callconv(.Stdcall) c_int;