Commit 0a40a61548

Bas van den Berg <BarabasGitHub@users.noreply.github.com>
2020-09-03 13:23:48
os.send(to) and os.recv(from) functions made to work on windows.
1 parent d80554c
Changed files (3)
lib
lib/std/os/windows/ws2_32.zig
@@ -786,7 +786,7 @@ pub extern "ws2_32" fn WSASendTo(
     lpNumberOfBytesSent: ?*DWORD,
     dwFlags: DWORD,
     lpTo: ?*const sockaddr,
-    iTolen: socklen_t,
+    iTolen: c_int,
     lpOverlapped: ?*WSAOVERLAPPED,
     lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
 ) callconv(.Stdcall) c_int;
lib/std/os/windows.zig
@@ -1190,6 +1190,27 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
     return rc;
 }
 
+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 {
+    var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = @intToPtr([*]u8, @ptrToInt(buf)) };
+    var bytes_send: DWORD = undefined;
+    if (ws2_32.WSASendTo(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_send, flags, to, to_len, null, null) == ws2_32.SOCKET_ERROR) {
+        return ws2_32.SOCKET_ERROR;
+    } else {
+        return @as(i32, @intCast(u31, bytes_send));
+    }
+}
+
+pub fn recvfrom(s: ws2_32.SOCKET, buf: [*]u8, len: usize, flags: u32, from: ?*ws2_32.sockaddr, from_len: ?*ws2_32.socklen_t) i32 {
+    var buffer = ws2_32.WSABUF{ .len = @truncate(u31, len), .buf = buf };
+    var bytes_received: DWORD = undefined;
+    var flags_inout = flags;
+    if (ws2_32.WSARecvFrom(s, @ptrCast([*]ws2_32.WSABUF, &buffer), 1, &bytes_received, &flags_inout, from, from_len, null, null) == ws2_32.SOCKET_ERROR) {
+        return ws2_32.SOCKET_ERROR;
+    } else {
+        return @as(i32, @intCast(u31, bytes_received));
+    }
+}
+
 pub fn WSAIoctl(
     s: ws2_32.SOCKET,
     dwIoControlCode: DWORD,
lib/std/os.zig
@@ -4630,7 +4630,7 @@ pub const SendError = error{
 /// possible to send more data.
 pub fn sendto(
     /// The file descriptor of the sending socket.
-    sockfd: fd_t,
+    sockfd: socket_t,
     /// Message to send.
     buf: []const u8,
     flags: u32,
@@ -4639,32 +4639,43 @@ pub fn sendto(
 ) SendError!usize {
     while (true) {
         const rc = system.sendto(sockfd, buf.ptr, buf.len, flags, dest_addr, addrlen);
-        switch (errno(rc)) {
-            0 => return @intCast(usize, rc),
-
-            EACCES => return error.AccessDenied,
-            EAGAIN => if (std.event.Loop.instance) |loop| {
-                loop.waitUntilFdWritable(sockfd);
-                continue;
+        if (builtin.os.tag == .windows) {
+            if (rc == windows.ws2_32.SOCKET_ERROR) {
+                switch (windows.ws2_32.WSAGetLastError()) {
+                    // TODO: handle errors
+                    else => |err| return windows.unexpectedWSAError(err),
+                }
             } else {
-                return error.WouldBlock;
-            },
-            EALREADY => return error.FastOpenAlreadyInProgress,
-            EBADF => unreachable, // always a race condition
-            ECONNRESET => return error.ConnectionResetByPeer,
-            EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set.
-            EFAULT => unreachable, // An invalid user space address was specified for an argument.
-            EINTR => continue,
-            EINVAL => unreachable, // Invalid argument passed.
-            EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified
-            EMSGSIZE => return error.MessageTooBig,
-            ENOBUFS => return error.SystemResources,
-            ENOMEM => return error.SystemResources,
-            ENOTCONN => unreachable, // The socket is not connected, and no target has been given.
-            ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
-            EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
-            EPIPE => return error.BrokenPipe,
-            else => |err| return unexpectedErrno(err),
+                return @intCast(usize, rc);
+            }
+        } else {
+            switch (errno(rc)) {
+                0 => return @intCast(usize, rc),
+
+                EACCES => return error.AccessDenied,
+                EAGAIN => if (std.event.Loop.instance) |loop| {
+                    loop.waitUntilFdWritable(sockfd);
+                    continue;
+                } else {
+                    return error.WouldBlock;
+                },
+                EALREADY => return error.FastOpenAlreadyInProgress,
+                EBADF => unreachable, // always a race condition
+                ECONNRESET => return error.ConnectionResetByPeer,
+                EDESTADDRREQ => unreachable, // The socket is not connection-mode, and no peer address is set.
+                EFAULT => unreachable, // An invalid user space address was specified for an argument.
+                EINTR => continue,
+                EINVAL => unreachable, // Invalid argument passed.
+                EISCONN => unreachable, // connection-mode socket was connected already but a recipient was specified
+                EMSGSIZE => return error.MessageTooBig,
+                ENOBUFS => return error.SystemResources,
+                ENOMEM => return error.SystemResources,
+                ENOTCONN => unreachable, // The socket is not connected, and no target has been given.
+                ENOTSOCK => unreachable, // The file descriptor sockfd does not refer to a socket.
+                EOPNOTSUPP => unreachable, // Some bit in the flags argument is inappropriate for the socket type.
+                EPIPE => return error.BrokenPipe,
+                else => |err| return unexpectedErrno(err),
+            }
         }
     }
 }
@@ -4690,7 +4701,7 @@ pub fn sendto(
 /// possible to send more data.
 pub fn send(
     /// The file descriptor of the sending socket.
-    sockfd: fd_t,
+    sockfd: socket_t,
     buf: []const u8,
     flags: u32,
 ) SendError!usize {
@@ -5125,8 +5136,12 @@ pub const RecvFromError = error{
     SystemResources,
 } || UnexpectedError;
 
+pub fn recv(sock: socket_t, buf: []u8, flags: u32) RecvFromError!usize {
+    return recvfrom(sock, buf, flags, null, null);
+}
+
 pub fn recvfrom(
-    sockfd: fd_t,
+    sockfd: socket_t,
     buf: []u8,
     flags: u32,
     src_addr: ?*sockaddr,
@@ -5134,23 +5149,34 @@ pub fn recvfrom(
 ) RecvFromError!usize {
     while (true) {
         const rc = system.recvfrom(sockfd, buf.ptr, buf.len, flags, src_addr, addrlen);
-        switch (errno(rc)) {
-            0 => return @intCast(usize, rc),
-            EBADF => unreachable, // always a race condition
-            EFAULT => unreachable,
-            EINVAL => unreachable,
-            ENOTCONN => unreachable,
-            ENOTSOCK => unreachable,
-            EINTR => continue,
-            EAGAIN => if (std.event.Loop.instance) |loop| {
-                loop.waitUntilFdReadable(sockfd);
-                continue;
+        if (builtin.os.tag == .windows) {
+            if (rc == windows.ws2_32.SOCKET_ERROR) {
+                switch (windows.ws2_32.WSAGetLastError()) {
+                    // TODO: handle errors
+                    else => |err| return windows.unexpectedWSAError(err),
+                }
             } else {
-                return error.WouldBlock;
-            },
-            ENOMEM => return error.SystemResources,
-            ECONNREFUSED => return error.ConnectionRefused,
-            else => |err| return unexpectedErrno(err),
+                return @intCast(usize, rc);
+            }
+        } else {
+            switch (errno(rc)) {
+                0 => return @intCast(usize, rc),
+                EBADF => unreachable, // always a race condition
+                EFAULT => unreachable,
+                EINVAL => unreachable,
+                ENOTCONN => unreachable,
+                ENOTSOCK => unreachable,
+                EINTR => continue,
+                EAGAIN => if (std.event.Loop.instance) |loop| {
+                    loop.waitUntilFdReadable(sockfd);
+                    continue;
+                } else {
+                    return error.WouldBlock;
+                },
+                ENOMEM => return error.SystemResources,
+                ECONNREFUSED => return error.ConnectionRefused,
+                else => |err| return unexpectedErrno(err),
+            }
         }
     }
 }