Commit 77f8a9ae22

lithdew <kenta@lithdew.net>
2021-05-09 08:43:56
x/os/socket, std/os/windows: implement loading winsock extensions
Implement loading Winsock extensions. Add missing Winsock extension GUID's. Implement readVectorized() for POSIX sockets and readVectorized() / writeVectorized() for Windows sockets. Inverse how mixins are used to implement platform-independent syscalls for the std.x.os.Socket abstraction. This cleans up the API as suggested by @komuw.
1 parent 3d946ef
lib/std/os/windows/ws2_32.zig
@@ -266,10 +266,54 @@ pub const SENDER_DEFAULT_LATE_JOINER_PERCENTAGE = 0;
 pub const SENDER_MAX_LATE_JOINER_PERCENTAGE = 75;
 pub const BITS_PER_BYTE = 8;
 pub const LOG2_BITS_PER_BYTE = 3;
+
 pub const SOCKET_DEFAULT2_QM_POLICY = GUID.parse("{aec2ef9c-3a4d-4d3e-8842-239942e39a47}");
 pub const REAL_TIME_NOTIFICATION_CAPABILITY = GUID.parse("{6b59819a-5cae-492d-a901-2a3c2c50164f}");
 pub const REAL_TIME_NOTIFICATION_CAPABILITY_EX = GUID.parse("{6843da03-154a-4616-a508-44371295f96b}");
 pub const ASSOCIATE_NAMERES_CONTEXT = GUID.parse("{59a38b67-d4fe-46e1-ba3c-87ea74ca3049}");
+
+pub const WSAID_CONNECTEX = GUID{
+    .Data1 = 0x25a207b9,
+    .Data2 = 0xddf3,
+    .Data3 = 0x4660,
+    .Data4 = [8]u8{ 0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e },
+};
+
+pub const WSAID_ACCEPTEX = GUID{
+    .Data1 = 0xb5367df1,
+    .Data2 = 0xcbac,
+    .Data3 = 0x11cf,
+    .Data4 = [8]u8{ 0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 },
+};
+
+pub const WSAID_GETACCEPTEXSOCKADDRS = GUID{
+    .Data1 = 0xb5367df2,
+    .Data2 = 0xcbac,
+    .Data3 = 0x11cf,
+    .Data4 = [8]u8{ 0x95, 0xca, 0x00, 0x80, 0x5f, 0x48, 0xa1, 0x92 },
+};
+
+pub const WSAID_WSARECVMSG = GUID{
+    .Data1 = 0xf689d7c8,
+    .Data2 = 0x6f1f,
+    .Data3 = 0x436b,
+    .Data4 = [8]u8{ 0x8a, 0x53, 0xe5, 0x4f, 0xe3, 0x51, 0xc3, 0x22 },
+};
+
+pub const WSAID_WSAPOLL = GUID{
+    .Data1 = 0x18C76F85,
+    .Data2 = 0xDC66,
+    .Data3 = 0x4964,
+    .Data4 = [8]u8{ 0x97, 0x2E, 0x23, 0xC2, 0x72, 0x38, 0x31, 0x2B },
+};
+
+pub const WSAID_WSASENDMSG = GUID{
+    .Data1 = 0xa441e712,
+    .Data2 = 0x754f,
+    .Data3 = 0x43ca,
+    .Data4 = [8]u8{ 0x84, 0xa7, 0x0d, 0xee, 0x44, 0xcf, 0x60, 0x6d },
+};
+
 pub const TCP_INITIAL_RTO_DEFAULT_RTT = 0;
 pub const TCP_INITIAL_RTO_DEFAULT_MAX_SYN_RETRANSMISSIONS = 0;
 pub const SOCKET_SETTINGS_GUARANTEE_ENCRYPTION = 1;
@@ -485,6 +529,7 @@ pub const IOC_UNIX = 0;
 pub const IOC_WS2 = 134217728;
 pub const IOC_PROTOCOL = 268435456;
 pub const IOC_VENDOR = 402653184;
+pub const SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_OUT | IOC_IN | IOC_WS2 | 6;
 pub const SIO_BSP_HANDLE = IOC_OUT | IOC_WS2 | 27;
 pub const SIO_BSP_HANDLE_SELECT = IOC_OUT | IOC_WS2 | 28;
 pub const SIO_BSP_HANDLE_POLL = IOC_OUT | IOC_WS2 | 29;
@@ -1115,9 +1160,9 @@ pub const LPFN_GETACCEPTEXSOCKADDRS = fn (
     RemoteSockaddrLength: *i32,
 ) callconv(WINAPI) void;
 
-pub const LFN_WSASENDMSG = fn (
+pub const LPFN_WSASENDMSG = fn (
     s: SOCKET,
-    lpMsg: *WSAMSG_const,
+    lpMsg: *const WSAMSG_const,
     dwFlags: u32,
     lpNumberOfBytesSent: ?*u32,
     lpOverlapped: ?*OVERLAPPED,
@@ -1927,7 +1972,7 @@ pub extern "ws2_32" fn WSAHtons(
 pub extern "ws2_32" fn WSAIoctl(
     s: SOCKET,
     dwIoControlCode: u32,
-    lpvInBuffer: ?*c_void,
+    lpvInBuffer: ?*const c_void,
     cbInBuffer: u32,
     lpvOutbuffer: ?*c_void,
     cbOutbuffer: u32,
@@ -1992,7 +2037,7 @@ pub extern "ws2_32" fn WSASend(
     s: SOCKET,
     lpBuffers: [*]WSABUF,
     dwBufferCount: u32,
-    lpNumberOfBytesSent: ?*U32,
+    lpNumberOfBytesSent: ?*u32,
     dwFlags: u32,
     lpOverlapped: ?*OVERLAPPED,
     lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
@@ -2000,7 +2045,7 @@ pub extern "ws2_32" fn WSASend(
 
 pub extern "ws2_32" fn WSASendMsg(
     s: SOCKET,
-    lpMsg: *WSAMSG_const,
+    lpMsg: *const WSAMSG_const,
     dwFlags: u32,
     lpNumberOfBytesSent: ?*u32,
     lpOverlapped: ?*OVERLAPPED,
lib/std/os/windows.zig
@@ -1749,6 +1749,38 @@ fn MAKELANGID(p: c_ushort, s: c_ushort) callconv(.Inline) LANGID {
     return (s << 10) | p;
 }
 
+/// Loads a Winsock extension function in runtime specified by a GUID.
+pub fn loadWinsockExtensionFunction(comptime T: type, sock: ws2_32.SOCKET, guid: GUID) !T {
+    var function: T = undefined;
+    var num_bytes: DWORD = undefined;
+
+    const rc = ws2_32.WSAIoctl(
+        sock,
+        ws2_32.SIO_GET_EXTENSION_FUNCTION_POINTER,
+        @ptrCast(*const c_void, &guid),
+        @sizeOf(GUID),
+        &function,
+        @sizeOf(T),
+        &num_bytes,
+        null,
+        null,
+    );
+
+    if (rc == ws2_32.SOCKET_ERROR) {
+        return switch (ws2_32.WSAGetLastError()) {
+            .WSAEOPNOTSUPP => error.OperationNotSupported,
+            .WSAENOTSOCK => error.FileDescriptorNotASocket,
+            else => |err| unexpectedWSAError(err),
+        };
+    }
+
+    if (num_bytes != @sizeOf(T)) {
+        return error.ShortRead;
+    }
+
+    return function;
+}
+
 /// Call this when you made a windows DLL call or something that does SetLastError
 /// and you get an unexpected error.
 pub fn unexpectedError(err: Win32Error) std.os.UnexpectedError {
lib/std/x/os/socket.zig
@@ -13,105 +13,111 @@ const mem = std.mem;
 const time = std.time;
 const builtin = std.builtin;
 
-/// Import in a `Socket` abstraction depending on the platform we are compiling against.
-pub usingnamespace switch (builtin.os.tag) {
-    .windows => @import("socket_windows.zig"),
-    else => @import("socket_posix.zig"),
-};
+/// A generic, cross-platform socket abstraction.
+pub const Socket = struct {
+    /// A socket-address pair.
+    pub const Connection = struct {
+        socket: Socket,
+        address: Socket.Address,
 
-/// A common subset of shared structs across cross-platform abstractions over socket syscalls.
-pub fn Mixin(comptime Self: type) type {
-    return struct {
-        /// A socket-address pair.
-        pub const Connection = struct {
-            socket: Self,
-            address: Self.Address,
+        /// Enclose a socket and address into a socket-address pair.
+        pub fn from(socket: Socket, address: Socket.Address) Socket.Connection {
+            return .{ .socket = socket, .address = address };
+        }
+    };
 
-            /// Enclose a socket and address into a socket-address pair.
-            pub fn from(socket: Self, address: Self.Address) Self.Connection {
-                return .{ .socket = socket, .address = address };
-            }
-        };
+    /// A generic socket address abstraction. It is safe to directly access and modify
+    /// the fields of a `Socket.Address`.
+    pub const Address = union(enum) {
+        ipv4: net.IPv4.Address,
+        ipv6: net.IPv6.Address,
 
-        /// A generic socket address abstraction. It is safe to directly access and modify
-        /// the fields of a `Self.Address`.
-        pub const Address = union(enum) {
-            ipv4: net.IPv4.Address,
-            ipv6: net.IPv6.Address,
+        /// Instantiate a new address with a IPv4 host and port.
+        pub fn initIPv4(host: net.IPv4, port: u16) Socket.Address {
+            return .{ .ipv4 = .{ .host = host, .port = port } };
+        }
 
-            /// Instantiate a new address with a IPv4 host and port.
-            pub fn initIPv4(host: net.IPv4, port: u16) Self.Address {
-                return .{ .ipv4 = .{ .host = host, .port = port } };
-            }
+        /// Instantiate a new address with a IPv6 host and port.
+        pub fn initIPv6(host: net.IPv6, port: u16) Socket.Address {
+            return .{ .ipv6 = .{ .host = host, .port = port } };
+        }
 
-            /// Instantiate a new address with a IPv6 host and port.
-            pub fn initIPv6(host: net.IPv6, port: u16) Self.Address {
-                return .{ .ipv6 = .{ .host = host, .port = port } };
-            }
-
-            /// Parses a `sockaddr` into a generic socket address.
-            pub fn fromNative(address: *align(4) const os.sockaddr) Self.Address {
-                switch (address.family) {
-                    os.AF_INET => {
-                        const info = @ptrCast(*const os.sockaddr_in, address);
-                        const host = net.IPv4{ .octets = @bitCast([4]u8, info.addr) };
-                        const port = mem.bigToNative(u16, info.port);
-                        return Self.Address.initIPv4(host, port);
-                    },
-                    os.AF_INET6 => {
-                        const info = @ptrCast(*const os.sockaddr_in6, address);
-                        const host = net.IPv6{ .octets = info.addr, .scope_id = info.scope_id };
-                        const port = mem.bigToNative(u16, info.port);
-                        return Self.Address.initIPv6(host, port);
-                    },
-                    else => unreachable,
-                }
+        /// Parses a `sockaddr` into a generic socket address.
+        pub fn fromNative(address: *align(4) const os.sockaddr) Socket.Address {
+            switch (address.family) {
+                os.AF_INET => {
+                    const info = @ptrCast(*const os.sockaddr_in, address);
+                    const host = net.IPv4{ .octets = @bitCast([4]u8, info.addr) };
+                    const port = mem.bigToNative(u16, info.port);
+                    return Socket.Address.initIPv4(host, port);
+                },
+                os.AF_INET6 => {
+                    const info = @ptrCast(*const os.sockaddr_in6, address);
+                    const host = net.IPv6{ .octets = info.addr, .scope_id = info.scope_id };
+                    const port = mem.bigToNative(u16, info.port);
+                    return Socket.Address.initIPv6(host, port);
+                },
+                else => unreachable,
             }
+        }
 
-            /// Encodes a generic socket address into an extern union that may be reliably
-            /// casted into a `sockaddr` which may be passed into socket syscalls.
-            pub fn toNative(self: Self.Address) extern union {
-                ipv4: os.sockaddr_in,
-                ipv6: os.sockaddr_in6,
-            } {
-                return switch (self) {
-                    .ipv4 => |address| .{
-                        .ipv4 = .{
-                            .addr = @bitCast(u32, address.host.octets),
-                            .port = mem.nativeToBig(u16, address.port),
-                        },
+        /// Encodes a generic socket address into an extern union that may be reliably
+        /// casted into a `sockaddr` which may be passed into socket syscalls.
+        pub fn toNative(self: Socket.Address) extern union {
+            ipv4: os.sockaddr_in,
+            ipv6: os.sockaddr_in6,
+        } {
+            return switch (self) {
+                .ipv4 => |address| .{
+                    .ipv4 = .{
+                        .addr = @bitCast(u32, address.host.octets),
+                        .port = mem.nativeToBig(u16, address.port),
                     },
-                    .ipv6 => |address| .{
-                        .ipv6 = .{
-                            .addr = address.host.octets,
-                            .port = mem.nativeToBig(u16, address.port),
-                            .scope_id = address.host.scope_id,
-                            .flowinfo = 0,
-                        },
+                },
+                .ipv6 => |address| .{
+                    .ipv6 = .{
+                        .addr = address.host.octets,
+                        .port = mem.nativeToBig(u16, address.port),
+                        .scope_id = address.host.scope_id,
+                        .flowinfo = 0,
                     },
-                };
-            }
+                },
+            };
+        }
 
-            /// Returns the number of bytes that make up the `sockaddr` equivalent to the address. 
-            pub fn getNativeSize(self: Self.Address) u32 {
-                return switch (self) {
-                    .ipv4 => @sizeOf(os.sockaddr_in),
-                    .ipv6 => @sizeOf(os.sockaddr_in6),
-                };
-            }
+        /// Returns the number of bytes that make up the `sockaddr` equivalent to the address. 
+        pub fn getNativeSize(self: Socket.Address) u32 {
+            return switch (self) {
+                .ipv4 => @sizeOf(os.sockaddr_in),
+                .ipv6 => @sizeOf(os.sockaddr_in6),
+            };
+        }
 
-            /// Implements the `std.fmt.format` API.
-            pub fn format(
-                self: Self.Address,
-                comptime layout: []const u8,
-                opts: fmt.FormatOptions,
-                writer: anytype,
-            ) !void {
-                switch (self) {
-                    .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
-                    .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
-                }
+        /// Implements the `std.fmt.format` API.
+        pub fn format(
+            self: Socket.Address,
+            comptime layout: []const u8,
+            opts: fmt.FormatOptions,
+            writer: anytype,
+        ) !void {
+            switch (self) {
+                .ipv4 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
+                .ipv6 => |address| try fmt.format(writer, "{}:{}", .{ address.host, address.port }),
             }
-        };
+        }
     };
-}
+
+    /// The underlying handle of a socket.
+    fd: os.socket_t,
+
+    /// Enclose a socket abstraction over an existing socket file descriptor.
+    pub fn from(fd: os.socket_t) Socket {
+        return Socket{ .fd = fd };
+    }
+
+    /// Mix in socket syscalls depending on the platform we are compiling against.
+    pub usingnamespace switch (builtin.os.tag) {
+        .windows => @import("socket_windows.zig"),
+        else => @import("socket_posix.zig"),
+    }.Mixin(Socket);
+};
lib/std/x/os/socket_posix.zig
@@ -10,232 +10,242 @@ const os = std.os;
 const mem = std.mem;
 const time = std.time;
 
-pub const Socket = struct {
-    /// Import in `Socket.Address` and `Socket.Connection`.
-    pub usingnamespace @import("socket.zig").Mixin(Socket);
-
-    /// The underlying handle of a socket.
-    fd: os.socket_t,
-
-    /// Open a new socket.
-    pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket {
-        return Socket{ .fd = try os.socket(domain, socket_type, protocol) };
-    }
-
-    /// Enclose a socket abstraction over an existing socket file descriptor.
-    pub fn from(fd: os.socket_t) Socket {
-        return Socket{ .fd = fd };
-    }
-
-    /// Closes the socket.
-    pub fn deinit(self: Socket) void {
-        os.closeSocket(self.fd);
-    }
-
-    /// Shutdown either the read side, write side, or all side of the socket.
-    pub fn shutdown(self: Socket, how: os.ShutdownHow) !void {
-        return os.shutdown(self.fd, how);
-    }
-
-    /// Binds the socket to an address.
-    pub fn bind(self: Socket, address: Socket.Address) !void {
-        return os.bind(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize());
-    }
-
-    /// Start listening for incoming connections on the socket.
-    pub fn listen(self: Socket, max_backlog_size: u31) !void {
-        return os.listen(self.fd, max_backlog_size);
-    }
-
-    /// Have the socket attempt to the connect to an address.
-    pub fn connect(self: Socket, address: Socket.Address) !void {
-        return os.connect(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize());
-    }
-
-    /// Accept a pending incoming connection queued to the kernel backlog
-    /// of the socket.
-    pub fn accept(self: Socket, flags: u32) !Socket.Connection {
-        var address: os.sockaddr_storage = undefined;
-        var address_len: u32 = @sizeOf(os.sockaddr_storage);
-
-        const socket = Socket{ .fd = try os.accept(self.fd, @ptrCast(*os.sockaddr, &address), &address_len, flags) };
-        const socket_address = Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
-
-        return Socket.Connection.from(socket, socket_address);
-    }
-
-    /// Read data from the socket into the buffer provided with a set of flags
-    /// specified. It returns the number of bytes read into the buffer provided.
-    pub fn read(self: Socket, buf: []u8, flags: u32) !usize {
-        return os.recv(self.fd, buf, flags);
-    }
-
-    /// Write a buffer of data provided to the socket with a set of flags specified.
-    /// It returns the number of bytes that are written to the socket.
-    pub fn write(self: Socket, buf: []const u8, flags: u32) !usize {
-        return os.send(self.fd, buf, flags);
-    }
-
-    /// Writes multiple I/O vectors with a prepended message header to the socket
-    /// with a set of flags specified. It returns the number of bytes that are
-    /// written to the socket.
-    pub fn writeVectorized(self: Socket, msg: os.msghdr_const, flags: u32) !usize {
-        return os.sendmsg(self.fd, msg, flags);
-    }
-
-    /// Read multiple I/O vectors with a prepended message header from the socket
-    /// with a set of flags specified. It returns the number of bytes that were
-    /// read into the buffer provided.
-    pub fn readVectorized(self: Socket, msg: *os.msghdr, flags: u32) !usize {
-        return error.NotImplemented;
-    }
-
-    /// Query the address that the socket is locally bounded to.
-    pub fn getLocalAddress(self: Socket) !Socket.Address {
-        var address: os.sockaddr_storage = undefined;
-        var address_len: u32 = @sizeOf(os.sockaddr_storage);
-        try os.getsockname(self.fd, @ptrCast(*os.sockaddr, &address), &address_len);
-        return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
-    }
-
-    /// Query the address that the socket is connected to.
-    pub fn getRemoteAddress(self: Socket) !Socket.Address {
-        var address: os.sockaddr_storage = undefined;
-        var address_len: u32 = @sizeOf(os.sockaddr_storage);
-        try os.getpeername(self.fd, @ptrCast(*os.sockaddr, &address), &address_len);
-        return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
-    }
-
-    /// Query and return the latest cached error on the socket.
-    pub fn getError(self: Socket) !void {
-        return os.getsockoptError(self.fd);
-    }
-
-    /// Query the read buffer size of the socket.
-    pub fn getReadBufferSize(self: Socket) !u32 {
-        var value: u32 = undefined;
-        var value_len: u32 = @sizeOf(u32);
-
-        const rc = os.system.getsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&value), &value_len);
-        return switch (os.errno(rc)) {
-            0 => value,
-            os.EBADF => error.BadFileDescriptor,
-            os.EFAULT => error.InvalidAddressSpace,
-            os.EINVAL => error.InvalidSocketOption,
-            os.ENOPROTOOPT => error.UnknownSocketOption,
-            os.ENOTSOCK => error.NotASocket,
-            else => |err| os.unexpectedErrno(err),
-        };
-    }
-
-    /// Query the write buffer size of the socket.
-    pub fn getWriteBufferSize(self: Socket) !u32 {
-        var value: u32 = undefined;
-        var value_len: u32 = @sizeOf(u32);
-
-        const rc = os.system.getsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&value), &value_len);
-        return switch (os.errno(rc)) {
-            0 => value,
-            os.EBADF => error.BadFileDescriptor,
-            os.EFAULT => error.InvalidAddressSpace,
-            os.EINVAL => error.InvalidSocketOption,
-            os.ENOPROTOOPT => error.UnknownSocketOption,
-            os.ENOTSOCK => error.NotASocket,
-            else => |err| os.unexpectedErrno(err),
-        };
-    }
-
-    /// Set a socket option.
-    pub fn setOption(self: Socket, level: u32, code: u32, value: []const u8) !void {
-        return os.setsockopt(self.fd, level, code, value);
-    }
-
-    /// Have close() or shutdown() syscalls block until all queued messages in the socket have been successfully
-    /// sent, or if the timeout specified in seconds has been reached. It returns `error.UnsupportedSocketOption`
-    /// if the host does not support the option for a socket to linger around up until a timeout specified in
-    /// seconds.
-    pub fn setLinger(self: Socket, timeout_seconds: ?u16) !void {
-        if (comptime @hasDecl(os, "SO_LINGER")) {
-            const settings = extern struct {
-                l_onoff: c_int,
-                l_linger: c_int,
-            }{
-                .l_onoff = @intCast(c_int, @boolToInt(timeout_seconds != null)),
-                .l_linger = if (timeout_seconds) |seconds| @intCast(c_int, seconds) else 0,
+pub fn Mixin(comptime Socket: type) type {
+    return struct {
+        /// Open a new socket.
+        pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket {
+            return Socket{ .fd = try os.socket(domain, socket_type, protocol) };
+        }
+
+        /// Closes the socket.
+        pub fn deinit(self: Socket) void {
+            os.closeSocket(self.fd);
+        }
+
+        /// Shutdown either the read side, write side, or all side of the socket.
+        pub fn shutdown(self: Socket, how: os.ShutdownHow) !void {
+            return os.shutdown(self.fd, how);
+        }
+
+        /// Binds the socket to an address.
+        pub fn bind(self: Socket, address: Socket.Address) !void {
+            return os.bind(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize());
+        }
+
+        /// Start listening for incoming connections on the socket.
+        pub fn listen(self: Socket, max_backlog_size: u31) !void {
+            return os.listen(self.fd, max_backlog_size);
+        }
+
+        /// Have the socket attempt to the connect to an address.
+        pub fn connect(self: Socket, address: Socket.Address) !void {
+            return os.connect(self.fd, @ptrCast(*const os.sockaddr, &address.toNative()), address.getNativeSize());
+        }
+
+        /// Accept a pending incoming connection queued to the kernel backlog
+        /// of the socket.
+        pub fn accept(self: Socket, flags: u32) !Socket.Connection {
+            var address: os.sockaddr_storage = undefined;
+            var address_len: u32 = @sizeOf(os.sockaddr_storage);
+
+            const socket = Socket{ .fd = try os.accept(self.fd, @ptrCast(*os.sockaddr, &address), &address_len, flags) };
+            const socket_address = Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
+
+            return Socket.Connection.from(socket, socket_address);
+        }
+
+        /// Read data from the socket into the buffer provided with a set of flags
+        /// specified. It returns the number of bytes read into the buffer provided.
+        pub fn read(self: Socket, buf: []u8, flags: u32) !usize {
+            return os.recv(self.fd, buf, flags);
+        }
+
+        /// Write a buffer of data provided to the socket with a set of flags specified.
+        /// It returns the number of bytes that are written to the socket.
+        pub fn write(self: Socket, buf: []const u8, flags: u32) !usize {
+            return os.send(self.fd, buf, flags);
+        }
+
+        /// Writes multiple I/O vectors with a prepended message header to the socket
+        /// with a set of flags specified. It returns the number of bytes that are
+        /// written to the socket.
+        pub fn writeVectorized(self: Socket, msg: os.msghdr_const, flags: u32) !usize {
+            return os.sendmsg(self.fd, msg, flags);
+        }
+
+        /// Read multiple I/O vectors with a prepended message header from the socket
+        /// with a set of flags specified. It returns the number of bytes that were
+        /// read into the buffer provided.
+        pub fn readVectorized(self: Socket, msg: *os.msghdr, flags: u32) !usize {
+            if (comptime @hasDecl(os.system, "recvmsg")) {
+                while (true) {
+                    const rc = os.system.recvmsg(self.fd, msg, flags);
+                    return switch (os.errno(rc)) {
+                        0 => @intCast(usize, rc),
+                        os.EBADF => unreachable, // always a race condition
+                        os.EFAULT => unreachable,
+                        os.EINVAL => unreachable,
+                        os.ENOTCONN => unreachable,
+                        os.ENOTSOCK => unreachable,
+                        os.EINTR => continue,
+                        os.EAGAIN => error.WouldBlock,
+                        os.ENOMEM => error.SystemResources,
+                        os.ECONNREFUSED => error.ConnectionRefused,
+                        os.ECONNRESET => error.ConnectionResetByPeer,
+                        else => |err| os.unexpectedErrno(err),
+                    };
+                }
+            }
+            return error.NotSupported;
+        }
+
+        /// Query the address that the socket is locally bounded to.
+        pub fn getLocalAddress(self: Socket) !Socket.Address {
+            var address: os.sockaddr_storage = undefined;
+            var address_len: u32 = @sizeOf(os.sockaddr_storage);
+            try os.getsockname(self.fd, @ptrCast(*os.sockaddr, &address), &address_len);
+            return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
+        }
+
+        /// Query the address that the socket is connected to.
+        pub fn getRemoteAddress(self: Socket) !Socket.Address {
+            var address: os.sockaddr_storage = undefined;
+            var address_len: u32 = @sizeOf(os.sockaddr_storage);
+            try os.getpeername(self.fd, @ptrCast(*os.sockaddr, &address), &address_len);
+            return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
+        }
+
+        /// Query and return the latest cached error on the socket.
+        pub fn getError(self: Socket) !void {
+            return os.getsockoptError(self.fd);
+        }
+
+        /// Query the read buffer size of the socket.
+        pub fn getReadBufferSize(self: Socket) !u32 {
+            var value: u32 = undefined;
+            var value_len: u32 = @sizeOf(u32);
+
+            const rc = os.system.getsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&value), &value_len);
+            return switch (os.errno(rc)) {
+                0 => value,
+                os.EBADF => error.BadFileDescriptor,
+                os.EFAULT => error.InvalidAddressSpace,
+                os.EINVAL => error.InvalidSocketOption,
+                os.ENOPROTOOPT => error.UnknownSocketOption,
+                os.ENOTSOCK => error.NotASocket,
+                else => |err| os.unexpectedErrno(err),
             };
+        }
+
+        /// Query the write buffer size of the socket.
+        pub fn getWriteBufferSize(self: Socket) !u32 {
+            var value: u32 = undefined;
+            var value_len: u32 = @sizeOf(u32);
+
+            const rc = os.system.getsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&value), &value_len);
+            return switch (os.errno(rc)) {
+                0 => value,
+                os.EBADF => error.BadFileDescriptor,
+                os.EFAULT => error.InvalidAddressSpace,
+                os.EINVAL => error.InvalidSocketOption,
+                os.ENOPROTOOPT => error.UnknownSocketOption,
+                os.ENOTSOCK => error.NotASocket,
+                else => |err| os.unexpectedErrno(err),
+            };
+        }
+
+        /// Set a socket option.
+        pub fn setOption(self: Socket, level: u32, code: u32, value: []const u8) !void {
+            return os.setsockopt(self.fd, level, code, value);
+        }
+
+        /// Have close() or shutdown() syscalls block until all queued messages in the socket have been successfully
+        /// sent, or if the timeout specified in seconds has been reached. It returns `error.UnsupportedSocketOption`
+        /// if the host does not support the option for a socket to linger around up until a timeout specified in
+        /// seconds.
+        pub fn setLinger(self: Socket, timeout_seconds: ?u16) !void {
+            if (comptime @hasDecl(os, "SO_LINGER")) {
+                const settings = extern struct {
+                    l_onoff: c_int,
+                    l_linger: c_int,
+                }{
+                    .l_onoff = @intCast(c_int, @boolToInt(timeout_seconds != null)),
+                    .l_linger = if (timeout_seconds) |seconds| @intCast(c_int, seconds) else 0,
+                };
+
+                return self.setOption(os.SOL_SOCKET, os.SO_LINGER, mem.asBytes(&settings));
+            }
+
+            return error.UnsupportedSocketOption;
+        }
+
+        /// On connection-oriented sockets, have keep-alive messages be sent periodically. The timing in which keep-alive
+        /// messages are sent are dependant on operating system settings. It returns `error.UnsupportedSocketOption` if
+        /// the host does not support periodically sending keep-alive messages on connection-oriented sockets. 
+        pub fn setKeepAlive(self: Socket, enabled: bool) !void {
+            if (comptime @hasDecl(os, "SO_KEEPALIVE")) {
+                return self.setOption(os.SOL_SOCKET, os.SO_KEEPALIVE, mem.asBytes(&@as(u32, @boolToInt(enabled))));
+            }
+            return error.UnsupportedSocketOption;
+        }
+
+        /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if
+        /// the host does not support sockets listening the same address.
+        pub fn setReuseAddress(self: Socket, enabled: bool) !void {
+            if (comptime @hasDecl(os, "SO_REUSEADDR")) {
+                return self.setOption(os.SOL_SOCKET, os.SO_REUSEADDR, mem.asBytes(&@as(u32, @boolToInt(enabled))));
+            }
+            return error.UnsupportedSocketOption;
+        }
 
-            return self.setOption(os.SOL_SOCKET, os.SO_LINGER, mem.asBytes(&settings));
-        }
-
-        return error.UnsupportedSocketOption;
-    }
-
-    /// On connection-oriented sockets, have keep-alive messages be sent periodically. The timing in which keep-alive
-    /// messages are sent are dependant on operating system settings. It returns `error.UnsupportedSocketOption` if
-    /// the host does not support periodically sending keep-alive messages on connection-oriented sockets. 
-    pub fn setKeepAlive(self: Socket, enabled: bool) !void {
-        if (comptime @hasDecl(os, "SO_KEEPALIVE")) {
-            return self.setOption(os.SOL_SOCKET, os.SO_KEEPALIVE, mem.asBytes(&@as(u32, @boolToInt(enabled))));
-        }
-        return error.UnsupportedSocketOption;
-    }
-
-    /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if
-    /// the host does not support sockets listening the same address.
-    pub fn setReuseAddress(self: Socket, enabled: bool) !void {
-        if (comptime @hasDecl(os, "SO_REUSEADDR")) {
-            return self.setOption(os.SOL_SOCKET, os.SO_REUSEADDR, mem.asBytes(&@as(u32, @boolToInt(enabled))));
-        }
-        return error.UnsupportedSocketOption;
-    }
-
-    /// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if
-    /// the host does not supports sockets listening on the same port.
-    pub fn setReusePort(self: Socket, enabled: bool) !void {
-        if (comptime @hasDecl(os, "SO_REUSEPORT")) {
-            return self.setOption(os.SOL_SOCKET, os.SO_REUSEPORT, mem.asBytes(&@as(u32, @boolToInt(enabled))));
-        }
-        return error.UnsupportedSocketOption;
-    }
-
-    /// Set the write buffer size of the socket.
-    pub fn setWriteBufferSize(self: Socket, size: u32) !void {
-        return self.setOption(os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&size));
-    }
-
-    /// Set the read buffer size of the socket.
-    pub fn setReadBufferSize(self: Socket, size: u32) !void {
-        return self.setOption(os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&size));
-    }
-
-    /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
-    /// set on a non-blocking socket.
-    /// 
-    /// Set a timeout on the socket that is to occur if no messages are successfully written
-    /// to its bound destination after a specified number of milliseconds. A subsequent write
-    /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded.
-    pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void {
-        const timeout = os.timeval{
-            .tv_sec = @intCast(i32, milliseconds / time.ms_per_s),
-            .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms),
-        };
-
-        return self.setOption(os.SOL_SOCKET, os.SO_SNDTIMEO, mem.asBytes(&timeout));
-    }
-
-    /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
-    /// set on a non-blocking socket.
-    /// 
-    /// Set a timeout on the socket that is to occur if no messages are successfully read
-    /// from its bound destination after a specified number of milliseconds. A subsequent
-    /// read from the socket will thereafter return `error.WouldBlock` should the timeout be
-    /// exceeded.
-    pub fn setReadTimeout(self: Socket, milliseconds: usize) !void {
-        const timeout = os.timeval{
-            .tv_sec = @intCast(i32, milliseconds / time.ms_per_s),
-            .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms),
-        };
-
-        return self.setOption(os.SOL_SOCKET, os.SO_RCVTIMEO, mem.asBytes(&timeout));
-    }
-};
+        /// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if
+        /// the host does not supports sockets listening on the same port.
+        pub fn setReusePort(self: Socket, enabled: bool) !void {
+            if (comptime @hasDecl(os, "SO_REUSEPORT")) {
+                return self.setOption(os.SOL_SOCKET, os.SO_REUSEPORT, mem.asBytes(&@as(u32, @boolToInt(enabled))));
+            }
+            return error.UnsupportedSocketOption;
+        }
+
+        /// Set the write buffer size of the socket.
+        pub fn setWriteBufferSize(self: Socket, size: u32) !void {
+            return self.setOption(os.SOL_SOCKET, os.SO_SNDBUF, mem.asBytes(&size));
+        }
+
+        /// Set the read buffer size of the socket.
+        pub fn setReadBufferSize(self: Socket, size: u32) !void {
+            return self.setOption(os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&size));
+        }
+
+        /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
+        /// set on a non-blocking socket.
+        /// 
+        /// Set a timeout on the socket that is to occur if no messages are successfully written
+        /// to its bound destination after a specified number of milliseconds. A subsequent write
+        /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded.
+        pub fn setWriteTimeout(self: Socket, milliseconds: usize) !void {
+            const timeout = os.timeval{
+                .tv_sec = @intCast(i32, milliseconds / time.ms_per_s),
+                .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms),
+            };
+
+            return self.setOption(os.SOL_SOCKET, os.SO_SNDTIMEO, mem.asBytes(&timeout));
+        }
+
+        /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
+        /// set on a non-blocking socket.
+        /// 
+        /// Set a timeout on the socket that is to occur if no messages are successfully read
+        /// from its bound destination after a specified number of milliseconds. A subsequent
+        /// read from the socket will thereafter return `error.WouldBlock` should the timeout be
+        /// exceeded.
+        pub fn setReadTimeout(self: Socket, milliseconds: usize) !void {
+            const timeout = os.timeval{
+                .tv_sec = @intCast(i32, milliseconds / time.ms_per_s),
+                .tv_usec = @intCast(i32, (milliseconds % time.ms_per_s) * time.us_per_ms),
+            };
+
+            return self.setOption(os.SOL_SOCKET, os.SO_RCVTIMEO, mem.asBytes(&timeout));
+        }
+    };
+}
lib/std/x/os/socket_windows.zig
@@ -13,386 +13,438 @@ const mem = std.mem;
 const windows = std.os.windows;
 const ws2_32 = windows.ws2_32;
 
-pub const Socket = struct {
-    /// Import in `Socket.Address` and `Socket.Connection`.
-    pub usingnamespace @import("socket.zig").Mixin(Socket);
+pub fn Mixin(comptime Socket: type) type {
+    return struct {
+        /// Open a new socket.
+        pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket {
+            var filtered_socket_type = socket_type & ~@as(u32, os.SOCK_CLOEXEC);
+
+            var filtered_flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED;
+            if (socket_type & os.SOCK_CLOEXEC != 0) {
+                filtered_flags |= ws2_32.WSA_FLAG_NO_HANDLE_INHERIT;
+            }
+
+            const fd = ws2_32.WSASocketW(
+                @intCast(i32, domain),
+                @intCast(i32, filtered_socket_type),
+                @intCast(i32, protocol),
+                null,
+                0,
+                filtered_flags,
+            );
+            if (fd == ws2_32.INVALID_SOCKET) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSANOTINITIALISED => {
+                        _ = try windows.WSAStartup(2, 2);
+                        return Socket.init(domain, socket_type, protocol);
+                    },
+                    .WSAEAFNOSUPPORT => error.AddressFamilyNotSupported,
+                    .WSAEMFILE => error.ProcessFdQuotaExceeded,
+                    .WSAENOBUFS => error.SystemResources,
+                    .WSAEPROTONOSUPPORT => error.ProtocolNotSupported,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return Socket{ .fd = fd };
+        }
 
-    /// The underlying handle of a socket.
-    fd: os.socket_t,
+        /// Closes the socket.
+        pub fn deinit(self: Socket) void {
+            _ = ws2_32.closesocket(self.fd);
+        }
 
-    /// Open a new socket.
-    pub fn init(domain: u32, socket_type: u32, protocol: u32) !Socket {
-        var filtered_socket_type = socket_type & ~@as(u32, os.SOCK_CLOEXEC);
+        /// Shutdown either the read side, write side, or all side of the socket.
+        pub fn shutdown(self: Socket, how: os.ShutdownHow) !void {
+            const rc = ws2_32.shutdown(self.fd, switch (how) {
+                .recv => ws2_32.SD_RECEIVE,
+                .send => ws2_32.SD_SEND,
+                .both => ws2_32.SD_BOTH,
+            });
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAECONNABORTED => return error.ConnectionAborted,
+                    .WSAECONNRESET => return error.ConnectionResetByPeer,
+                    .WSAEINPROGRESS => return error.BlockingOperationInProgress,
+                    .WSAEINVAL => unreachable,
+                    .WSAENETDOWN => return error.NetworkSubsystemFailed,
+                    .WSAENOTCONN => return error.SocketNotConnected,
+                    .WSAENOTSOCK => unreachable,
+                    .WSANOTINITIALISED => unreachable,
+                    else => |err| return windows.unexpectedWSAError(err),
+                };
+            }
+        }
 
-        var filtered_flags: u32 = ws2_32.WSA_FLAG_OVERLAPPED;
-        if (socket_type & os.SOCK_CLOEXEC != 0) {
-            filtered_flags |= ws2_32.WSA_FLAG_NO_HANDLE_INHERIT;
+        /// Binds the socket to an address.
+        pub fn bind(self: Socket, address: Socket.Address) !void {
+            const rc = ws2_32.bind(self.fd, @ptrCast(*const ws2_32.sockaddr, &address.toNative()), @intCast(c_int, address.getNativeSize()));
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAEACCES => error.AccessDenied,
+                    .WSAEADDRINUSE => error.AddressInUse,
+                    .WSAEADDRNOTAVAIL => error.AddressNotAvailable,
+                    .WSAEFAULT => error.BadAddress,
+                    .WSAEINPROGRESS => error.WouldBlock,
+                    .WSAEINVAL => error.AlreadyBound,
+                    .WSAENOBUFS => error.NoEphemeralPortsAvailable,
+                    .WSAENOTSOCK => error.NotASocket,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
         }
 
-        const fd = ws2_32.WSASocketW(
-            @intCast(i32, domain),
-            @intCast(i32, filtered_socket_type),
-            @intCast(i32, protocol),
-            null,
-            0,
-            filtered_flags,
-        );
-        if (fd == ws2_32.INVALID_SOCKET) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSANOTINITIALISED => {
-                    _ = try windows.WSAStartup(2, 2);
-                    return Socket.init(domain, socket_type, protocol);
-                },
-                .WSAEAFNOSUPPORT => error.AddressFamilyNotSupported,
-                .WSAEMFILE => error.ProcessFdQuotaExceeded,
-                .WSAENOBUFS => error.SystemResources,
-                .WSAEPROTONOSUPPORT => error.ProtocolNotSupported,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+        /// Start listening for incoming connections on the socket.
+        pub fn listen(self: Socket, max_backlog_size: u31) !void {
+            const rc = ws2_32.listen(self.fd, max_backlog_size);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAEADDRINUSE => error.AddressInUse,
+                    .WSAEISCONN => error.AlreadyConnected,
+                    .WSAEINVAL => error.SocketNotBound,
+                    .WSAEMFILE, .WSAENOBUFS => error.SystemResources,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEOPNOTSUPP => error.OperationNotSupported,
+                    .WSAEINPROGRESS => error.WouldBlock,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
         }
 
-        return Socket{ .fd = fd };
-    }
-
-    /// Enclose a socket abstraction over an existing socket file descriptor.
-    pub fn from(fd: os.socket_t) Socket {
-        return Socket{ .fd = fd };
-    }
-
-    /// Closes the socket.
-    pub fn deinit(self: Socket) void {
-        _ = ws2_32.closesocket(self.fd);
-    }
-
-    /// Shutdown either the read side, write side, or all side of the socket.
-    pub fn shutdown(self: Socket, how: os.ShutdownHow) !void {
-        const rc = ws2_32.shutdown(self.fd, switch (how) {
-            .recv => ws2_32.SD_RECEIVE,
-            .send => ws2_32.SD_SEND,
-            .both => ws2_32.SD_BOTH,
-        });
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSAECONNABORTED => return error.ConnectionAborted,
-                .WSAECONNRESET => return error.ConnectionResetByPeer,
-                .WSAEINPROGRESS => return error.BlockingOperationInProgress,
-                .WSAEINVAL => unreachable,
-                .WSAENETDOWN => return error.NetworkSubsystemFailed,
-                .WSAENOTCONN => return error.SocketNotConnected,
-                .WSAENOTSOCK => unreachable,
-                .WSANOTINITIALISED => unreachable,
-                else => |err| return windows.unexpectedWSAError(err),
-            };
+        /// Have the socket attempt to the connect to an address.
+        pub fn connect(self: Socket, address: Socket.Address) !void {
+            const rc = ws2_32.connect(self.fd, @ptrCast(*const ws2_32.sockaddr, &address.toNative()), @intCast(c_int, address.getNativeSize()));
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAEADDRINUSE => error.AddressInUse,
+                    .WSAEADDRNOTAVAIL => error.AddressNotAvailable,
+                    .WSAECONNREFUSED => error.ConnectionRefused,
+                    .WSAETIMEDOUT => error.ConnectionTimedOut,
+                    .WSAEFAULT => error.BadAddress,
+                    .WSAEINVAL => error.ListeningSocket,
+                    .WSAEISCONN => error.AlreadyConnected,
+                    .WSAENOTSOCK => error.NotASocket,
+                    .WSAEACCES => error.BroadcastNotEnabled,
+                    .WSAENOBUFS => error.SystemResources,
+                    .WSAEAFNOSUPPORT => error.AddressFamilyNotSupported,
+                    .WSAEINPROGRESS, .WSAEWOULDBLOCK => error.WouldBlock,
+                    .WSAEHOSTUNREACH, .WSAENETUNREACH => error.NetworkUnreachable,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
         }
-    }
-
-    /// Binds the socket to an address.
-    pub fn bind(self: Socket, address: Socket.Address) !void {
-        const rc = ws2_32.bind(self.fd, @ptrCast(*const ws2_32.sockaddr, &address.toNative()), @intCast(c_int, address.getNativeSize()));
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAEACCES => error.AccessDenied,
-                .WSAEADDRINUSE => error.AddressInUse,
-                .WSAEADDRNOTAVAIL => error.AddressNotAvailable,
-                .WSAEFAULT => error.BadAddress,
-                .WSAEINPROGRESS => error.WouldBlock,
-                .WSAEINVAL => error.AlreadyBound,
-                .WSAENOBUFS => error.NoEphemeralPortsAvailable,
-                .WSAENOTSOCK => error.NotASocket,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+
+        /// Accept a pending incoming connection queued to the kernel backlog
+        /// of the socket.
+        pub fn accept(self: Socket, flags: u32) !Socket.Connection {
+            var address: ws2_32.sockaddr_storage = undefined;
+            var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage);
+
+            const rc = ws2_32.accept(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len);
+            if (rc == ws2_32.INVALID_SOCKET) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSANOTINITIALISED => unreachable,
+                    .WSAECONNRESET => error.ConnectionResetByPeer,
+                    .WSAEFAULT => unreachable,
+                    .WSAEINVAL => error.SocketNotListening,
+                    .WSAEMFILE => error.ProcessFdQuotaExceeded,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENOBUFS => error.FileDescriptorNotASocket,
+                    .WSAEOPNOTSUPP => error.OperationNotSupported,
+                    .WSAEWOULDBLOCK => error.WouldBlock,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            const socket = Socket.from(rc);
+            const socket_address = Socket.Address.fromNative(@ptrCast(*ws2_32.sockaddr, &address));
+
+            return Socket.Connection.from(socket, socket_address);
         }
-    }
-
-    /// Start listening for incoming connections on the socket.
-    pub fn listen(self: Socket, max_backlog_size: u31) !void {
-        const rc = ws2_32.listen(self.fd, max_backlog_size);
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAEADDRINUSE => error.AddressInUse,
-                .WSAEISCONN => error.AlreadyConnected,
-                .WSAEINVAL => error.SocketNotBound,
-                .WSAEMFILE, .WSAENOBUFS => error.SystemResources,
-                .WSAENOTSOCK => error.FileDescriptorNotASocket,
-                .WSAEOPNOTSUPP => error.OperationNotSupported,
-                .WSAEINPROGRESS => error.WouldBlock,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+
+        /// Read data from the socket into the buffer provided with a set of flags
+        /// specified. It returns the number of bytes read into the buffer provided.
+        pub fn read(self: Socket, buf: []u8, flags: u32) !usize {
+            var bufs = &[_]ws2_32.WSABUF{.{ .len = @intCast(u32, buf.len), .buf = buf.ptr }};
+            var num_bytes: u32 = undefined;
+            var flags_ = flags;
+
+            const rc = ws2_32.WSARecv(self.fd, bufs, 1, &num_bytes, &flags_, null, null);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAECONNABORTED => error.ConnectionAborted,
+                    .WSAECONNRESET => error.ConnectionResetByPeer,
+                    .WSAEDISCON => error.ConnectionClosedByPeer,
+                    .WSAEFAULT => error.BadBuffer,
+                    .WSAEINPROGRESS,
+                    .WSAEWOULDBLOCK,
+                    .WSA_IO_PENDING,
+                    .WSAETIMEDOUT,
+                    => error.WouldBlock,
+                    .WSAEINTR => error.Cancelled,
+                    .WSAEINVAL => error.SocketNotBound,
+                    .WSAEMSGSIZE => error.MessageTooLarge,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENETRESET => error.NetworkReset,
+                    .WSAENOTCONN => error.SocketNotConnected,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEOPNOTSUPP => error.OperationNotSupported,
+                    .WSAESHUTDOWN => error.AlreadyShutdown,
+                    .WSA_OPERATION_ABORTED => error.OperationAborted,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return @intCast(usize, num_bytes);
         }
-    }
-
-    /// Have the socket attempt to the connect to an address.
-    pub fn connect(self: Socket, address: Socket.Address) !void {
-        const rc = ws2_32.connect(self.fd, @ptrCast(*const ws2_32.sockaddr, &address.toNative()), @intCast(c_int, address.getNativeSize()));
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSAEADDRINUSE => error.AddressInUse,
-                .WSAEADDRNOTAVAIL => error.AddressNotAvailable,
-                .WSAECONNREFUSED => error.ConnectionRefused,
-                .WSAETIMEDOUT => error.ConnectionTimedOut,
-                .WSAEFAULT => error.BadAddress,
-                .WSAEINVAL => error.ListeningSocket,
-                .WSAEISCONN => error.AlreadyConnected,
-                .WSAENOTSOCK => error.NotASocket,
-                .WSAEACCES => error.BroadcastNotEnabled,
-                .WSAENOBUFS => error.SystemResources,
-                .WSAEAFNOSUPPORT => error.AddressFamilyNotSupported,
-                .WSAEINPROGRESS, .WSAEWOULDBLOCK => error.WouldBlock,
-                .WSAEHOSTUNREACH, .WSAENETUNREACH => error.NetworkUnreachable,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+
+        /// Write a buffer of data provided to the socket with a set of flags specified.
+        /// It returns the number of bytes that are written to the socket.
+        pub fn write(self: Socket, buf: []const u8, flags: u32) !usize {
+            var bufs = &[_]ws2_32.WSABUF{.{ .len = @intCast(u32, buf.len), .buf = @intToPtr([*]u8, @ptrToInt(buf.ptr)) }};
+            var num_bytes: u32 = undefined;
+
+            const rc = ws2_32.WSASend(self.fd, bufs, 1, &num_bytes, flags, null, null);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAECONNABORTED => error.ConnectionAborted,
+                    .WSAECONNRESET => error.ConnectionResetByPeer,
+                    .WSAEFAULT => error.BadBuffer,
+                    .WSAEINPROGRESS,
+                    .WSAEWOULDBLOCK,
+                    .WSA_IO_PENDING,
+                    .WSAETIMEDOUT,
+                    => error.WouldBlock,
+                    .WSAEINTR => error.Cancelled,
+                    .WSAEINVAL => error.SocketNotBound,
+                    .WSAEMSGSIZE => error.MessageTooLarge,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENETRESET => error.NetworkReset,
+                    .WSAENOBUFS => error.BufferDeadlock,
+                    .WSAENOTCONN => error.SocketNotConnected,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEOPNOTSUPP => error.OperationNotSupported,
+                    .WSAESHUTDOWN => error.AlreadyShutdown,
+                    .WSA_OPERATION_ABORTED => error.OperationAborted,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return @intCast(usize, num_bytes);
         }
-    }
-
-    /// Accept a pending incoming connection queued to the kernel backlog
-    /// of the socket.
-    pub fn accept(self: Socket, flags: u32) !Socket.Connection {
-        var address: ws2_32.sockaddr_storage = undefined;
-        var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage);
-
-        const rc = ws2_32.accept(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len);
-        if (rc == ws2_32.INVALID_SOCKET) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSANOTINITIALISED => unreachable,
-                .WSAECONNRESET => error.ConnectionResetByPeer,
-                .WSAEFAULT => unreachable,
-                .WSAEINVAL => error.SocketNotListening,
-                .WSAEMFILE => error.ProcessFdQuotaExceeded,
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAENOBUFS => error.FileDescriptorNotASocket,
-                .WSAEOPNOTSUPP => error.OperationNotSupported,
-                .WSAEWOULDBLOCK => error.WouldBlock,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+
+        /// Writes multiple I/O vectors with a prepended message header to the socket
+        /// with a set of flags specified. It returns the number of bytes that are
+        /// written to the socket.
+        pub fn writeVectorized(self: Socket, msg: ws2_32.msghdr_const, flags: u32) !usize {
+            const call = try windows.loadWinsockExtensionFunction(ws2_32.LPFN_WSASENDMSG, self.fd, ws2_32.WSAID_WSASENDMSG);
+
+            var num_bytes: u32 = undefined;
+
+            const rc = call(self.fd, &msg, flags, &num_bytes, null, null);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAECONNABORTED => error.ConnectionAborted,
+                    .WSAECONNRESET => error.ConnectionResetByPeer,
+                    .WSAEFAULT => error.BadBuffer,
+                    .WSAEINPROGRESS,
+                    .WSAEWOULDBLOCK,
+                    .WSA_IO_PENDING,
+                    .WSAETIMEDOUT,
+                    => error.WouldBlock,
+                    .WSAEINTR => error.Cancelled,
+                    .WSAEINVAL => error.SocketNotBound,
+                    .WSAEMSGSIZE => error.MessageTooLarge,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENETRESET => error.NetworkReset,
+                    .WSAENOBUFS => error.BufferDeadlock,
+                    .WSAENOTCONN => error.SocketNotConnected,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEOPNOTSUPP => error.OperationNotSupported,
+                    .WSAESHUTDOWN => error.AlreadyShutdown,
+                    .WSA_OPERATION_ABORTED => error.OperationAborted,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return @intCast(usize, num_bytes);
         }
 
-        const socket = Socket.from(rc);
-        const socket_address = Socket.Address.fromNative(@ptrCast(*ws2_32.sockaddr, &address));
-
-        return Socket.Connection.from(socket, socket_address);
-    }
-
-    /// Read data from the socket into the buffer provided with a set of flags
-    /// specified. It returns the number of bytes read into the buffer provided.
-    pub fn read(self: Socket, buf: []u8, flags: u32) !usize {
-        var bufs = &[_]ws2_32.WSABUF{.{ .len = @intCast(u32, buf.len), .buf = buf.ptr }};
-        var flags_ = flags;
-
-        const rc = ws2_32.WSARecv(self.fd, bufs, 1, null, &flags_, null, null);
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSAECONNABORTED => error.ConnectionAborted,
-                .WSAECONNRESET => error.ConnectionResetByPeer,
-                .WSAEDISCON => error.ConnectionClosedByPeer,
-                .WSAEFAULT => error.BadBuffer,
-                .WSAEINPROGRESS,
-                .WSAEWOULDBLOCK,
-                .WSA_IO_PENDING,
-                .WSAETIMEDOUT,
-                => error.WouldBlock,
-                .WSAEINTR => error.Cancelled,
-                .WSAEINVAL => error.SocketNotBound,
-                .WSAEMSGSIZE => error.MessageTooLarge,
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAENETRESET => error.NetworkReset,
-                .WSAENOTCONN => error.SocketNotConnected,
-                .WSAENOTSOCK => error.FileDescriptorNotASocket,
-                .WSAEOPNOTSUPP => error.OperationNotSupported,
-                .WSAESHUTDOWN => error.AlreadyShutdown,
-                .WSA_OPERATION_ABORTED => error.OperationAborted,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+        /// Read multiple I/O vectors with a prepended message header from the socket
+        /// with a set of flags specified. It returns the number of bytes that were
+        /// read into the buffer provided.
+        pub fn readVectorized(self: Socket, msg: *ws2_32.msghdr, flags: u32) !usize {
+            const call = try windows.loadWinsockExtensionFunction(ws2_32.LPFN_WSARECVMSG, self.fd, ws2_32.WSAID_WSARECVMSG);
+
+            var num_bytes: u32 = undefined;
+
+            const rc = call(self.fd, msg, &num_bytes, null, null);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSAECONNABORTED => error.ConnectionAborted,
+                    .WSAECONNRESET => error.ConnectionResetByPeer,
+                    .WSAEDISCON => error.ConnectionClosedByPeer,
+                    .WSAEFAULT => error.BadBuffer,
+                    .WSAEINPROGRESS,
+                    .WSAEWOULDBLOCK,
+                    .WSA_IO_PENDING,
+                    .WSAETIMEDOUT,
+                    => error.WouldBlock,
+                    .WSAEINTR => error.Cancelled,
+                    .WSAEINVAL => error.SocketNotBound,
+                    .WSAEMSGSIZE => error.MessageTooLarge,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENETRESET => error.NetworkReset,
+                    .WSAENOTCONN => error.SocketNotConnected,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEOPNOTSUPP => error.OperationNotSupported,
+                    .WSAESHUTDOWN => error.AlreadyShutdown,
+                    .WSA_OPERATION_ABORTED => error.OperationAborted,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return @intCast(usize, num_bytes);
         }
 
-        return @intCast(usize, rc);
-    }
-
-    /// Write a buffer of data provided to the socket with a set of flags specified.
-    /// It returns the number of bytes that are written to the socket.
-    pub fn write(self: Socket, buf: []const u8, flags: u32) !usize {
-        var bufs = &[_]ws2_32.WSABUF{.{ .len = @intCast(u32, buf.len), .buf = buf.ptr }};
-        var flags_ = flags;
-
-        const rc = ws2_32.WSASend(self.fd, bufs, 1, null, &flags_, null, null);
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSAECONNABORTED => error.ConnectionAborted,
-                .WSAECONNRESET => error.ConnectionResetByPeer,
-                .WSAEFAULT => error.BadBuffer,
-                .WSAEINPROGRESS,
-                .WSAEWOULDBLOCK,
-                .WSA_IO_PENDING,
-                .WSAETIMEDOUT,
-                => error.WouldBlock,
-                .WSAEINTR => error.Cancelled,
-                .WSAEINVAL => error.SocketNotBound,
-                .WSAEMSGSIZE => error.MessageTooLarge,
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAENETRESET => error.NetworkReset,
-                .WSAENOBUFS => error.BufferDeadlock,
-                .WSAENOTCONN => error.SocketNotConnected,
-                .WSAENOTSOCK => error.FileDescriptorNotASocket,
-                .WSAEOPNOTSUPP => error.OperationNotSupported,
-                .WSAESHUTDOWN => error.AlreadyShutdown,
-                .WSA_OPERATION_ABORTED => error.OperationAborted,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+        /// Query the address that the socket is locally bounded to.
+        pub fn getLocalAddress(self: Socket) !Socket.Address {
+            var address: ws2_32.sockaddr_storage = undefined;
+            var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage);
+
+            const rc = ws2_32.getsockname(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSANOTINITIALISED => unreachable,
+                    .WSAEFAULT => unreachable,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEINVAL => error.SocketNotBound,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return Socket.Address.fromNative(@ptrCast(*ws2_32.sockaddr, &address));
         }
 
-        return @intCast(usize, rc);
-    }
-
-    /// Writes multiple I/O vectors with a prepended message header to the socket
-    /// with a set of flags specified. It returns the number of bytes that are
-    /// written to the socket.
-    pub fn writeVectorized(self: Socket, msg: os.msghdr_const, flags: u32) !usize {
-        return error.NotImplemented;
-    }
-
-    /// Read multiple I/O vectors with a prepended message header from the socket
-    /// with a set of flags specified. It returns the number of bytes that were
-    /// read into the buffer provided.
-    pub fn readVectorized(self: Socket, msg: *os.msghdr, flags: u32) !usize {
-        return error.NotImplemented;
-    }
-
-    /// Query the address that the socket is locally bounded to.
-    pub fn getLocalAddress(self: Socket) !Socket.Address {
-        var address: ws2_32.sockaddr_storage = undefined;
-        var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage);
-
-        const rc = ws2_32.getsockname(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len);
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSANOTINITIALISED => unreachable,
-                .WSAEFAULT => unreachable,
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAENOTSOCK => error.FileDescriptorNotASocket,
-                .WSAEINVAL => error.SocketNotBound,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+        /// Query the address that the socket is connected to.
+        pub fn getRemoteAddress(self: Socket) !Socket.Address {
+            var address: ws2_32.sockaddr_storage = undefined;
+            var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage);
+
+            const rc = ws2_32.getpeername(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len);
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSANOTINITIALISED => unreachable,
+                    .WSAEFAULT => unreachable,
+                    .WSAENETDOWN => error.NetworkSubsystemFailed,
+                    .WSAENOTSOCK => error.FileDescriptorNotASocket,
+                    .WSAEINVAL => error.SocketNotBound,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+
+            return Socket.Address.fromNative(@ptrCast(*ws2_32.sockaddr, &address));
         }
 
-        return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
-    }
-
-    /// Query the address that the socket is connected to.
-    pub fn getRemoteAddress(self: Socket) !Socket.Address {
-        var address: ws2_32.sockaddr_storage = undefined;
-        var address_len: c_int = @sizeOf(ws2_32.sockaddr_storage);
-
-        const rc = ws2_32.getpeername(self.fd, @ptrCast(*ws2_32.sockaddr, &address), &address_len);
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSANOTINITIALISED => unreachable,
-                .WSAEFAULT => unreachable,
-                .WSAENETDOWN => error.NetworkSubsystemFailed,
-                .WSAENOTSOCK => error.FileDescriptorNotASocket,
-                .WSAEINVAL => error.SocketNotBound,
-                else => |err| windows.unexpectedWSAError(err),
-            };
+        /// Query and return the latest cached error on the socket.
+        pub fn getError(self: Socket) !void {
+            return {};
+        }
+
+        /// Query the read buffer size of the socket.
+        pub fn getReadBufferSize(self: Socket) !u32 {
+            return 0;
         }
 
-        return Socket.Address.fromNative(@ptrCast(*os.sockaddr, &address));
-    }
-
-    /// Query and return the latest cached error on the socket.
-    pub fn getError(self: Socket) !void {
-        return {};
-    }
-
-    /// Query the read buffer size of the socket.
-    pub fn getReadBufferSize(self: Socket) !u32 {
-        return 0;
-    }
-
-    /// Query the write buffer size of the socket.
-    pub fn getWriteBufferSize(self: Socket) !u32 {
-        return 0;
-    }
-
-    /// Set a socket option.
-    pub fn setOption(self: Socket, level: u32, code: u32, value: []const u8) !void {
-        const rc = ws2_32.setsockopt(self.fd, @intCast(i32, level), @intCast(i32, code), value.ptr, @intCast(i32, value.len));
-        if (rc == ws2_32.SOCKET_ERROR) {
-            return switch (ws2_32.WSAGetLastError()) {
-                .WSANOTINITIALISED => unreachable,
-                .WSAENETDOWN => return error.NetworkSubsystemFailed,
-                .WSAEFAULT => unreachable,
-                .WSAENOTSOCK => return error.FileDescriptorNotASocket,
-                .WSAEINVAL => return error.SocketNotBound,
-                .WSAENOTCONN => return error.SocketNotConnected,
-                .WSAESHUTDOWN => return error.AlreadyShutdown,
-                else => |err| windows.unexpectedWSAError(err),
+        /// Query the write buffer size of the socket.
+        pub fn getWriteBufferSize(self: Socket) !u32 {
+            return 0;
+        }
+
+        /// Set a socket option.
+        pub fn setOption(self: Socket, level: u32, code: u32, value: []const u8) !void {
+            const rc = ws2_32.setsockopt(self.fd, @intCast(i32, level), @intCast(i32, code), value.ptr, @intCast(i32, value.len));
+            if (rc == ws2_32.SOCKET_ERROR) {
+                return switch (ws2_32.WSAGetLastError()) {
+                    .WSANOTINITIALISED => unreachable,
+                    .WSAENETDOWN => return error.NetworkSubsystemFailed,
+                    .WSAEFAULT => unreachable,
+                    .WSAENOTSOCK => return error.FileDescriptorNotASocket,
+                    .WSAEINVAL => return error.SocketNotBound,
+                    .WSAENOTCONN => return error.SocketNotConnected,
+                    .WSAESHUTDOWN => return error.AlreadyShutdown,
+                    else => |err| windows.unexpectedWSAError(err),
+                };
+            }
+        }
+
+        /// Have close() or shutdown() syscalls block until all queued messages in the socket have been successfully
+        /// sent, or if the timeout specified in seconds has been reached. It returns `error.UnsupportedSocketOption`
+        /// if the host does not support the option for a socket to linger around up until a timeout specified in
+        /// seconds.
+        pub fn setLinger(self: Socket, timeout_seconds: ?u16) !void {
+            const settings = ws2_32.linger{
+                .l_onoff = @as(u16, @boolToInt(timeout_seconds != null)),
+                .l_linger = if (timeout_seconds) |seconds| seconds else 0,
             };
+
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_LINGER, mem.asBytes(&settings));
+        }
+
+        /// On connection-oriented sockets, have keep-alive messages be sent periodically. The timing in which keep-alive
+        /// messages are sent are dependant on operating system settings. It returns `error.UnsupportedSocketOption` if
+        /// the host does not support periodically sending keep-alive messages on connection-oriented sockets. 
+        pub fn setKeepAlive(self: Socket, enabled: bool) !void {
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_KEEPALIVE, mem.asBytes(&@as(u32, @boolToInt(enabled))));
+        }
+
+        /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if
+        /// the host does not support sockets listening the same address.
+        pub fn setReuseAddress(self: Socket, enabled: bool) !void {
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_REUSEADDR, mem.asBytes(&@as(u32, @boolToInt(enabled))));
+        }
+
+        /// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if
+        /// the host does not supports sockets listening on the same port.
+        ///
+        /// TODO: verify if this truly mimicks SO_REUSEPORT behavior, or if SO_REUSE_UNICASTPORT provides the correct behavior
+        pub fn setReusePort(self: Socket, enabled: bool) !void {
+            try self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_BROADCAST, mem.asBytes(&@as(u32, @boolToInt(enabled))));
+            try self.setReuseAddress(enabled);
+        }
+
+        /// Set the write buffer size of the socket.
+        pub fn setWriteBufferSize(self: Socket, size: u32) !void {
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_SNDBUF, mem.asBytes(&size));
+        }
+
+        /// Set the read buffer size of the socket.
+        pub fn setReadBufferSize(self: Socket, size: u32) !void {
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_RCVBUF, mem.asBytes(&size));
+        }
+
+        /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
+        /// set on a non-blocking socket.
+        /// 
+        /// Set a timeout on the socket that is to occur if no messages are successfully written
+        /// to its bound destination after a specified number of milliseconds. A subsequent write
+        /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded.
+        pub fn setWriteTimeout(self: Socket, milliseconds: u32) !void {
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_SNDTIMEO, mem.asBytes(&milliseconds));
+        }
+
+        /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
+        /// set on a non-blocking socket.
+        /// 
+        /// Set a timeout on the socket that is to occur if no messages are successfully read
+        /// from its bound destination after a specified number of milliseconds. A subsequent
+        /// read from the socket will thereafter return `error.WouldBlock` should the timeout be
+        /// exceeded.
+        pub fn setReadTimeout(self: Socket, milliseconds: u32) !void {
+            return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_RCVTIMEO, mem.asBytes(&milliseconds));
         }
-    }
-
-    /// Have close() or shutdown() syscalls block until all queued messages in the socket have been successfully
-    /// sent, or if the timeout specified in seconds has been reached. It returns `error.UnsupportedSocketOption`
-    /// if the host does not support the option for a socket to linger around up until a timeout specified in
-    /// seconds.
-    pub fn setLinger(self: Socket, timeout_seconds: ?u16) !void {
-        const settings = ws2_32.linger{
-            .l_onoff = @as(u16, @boolToInt(timeout_seconds != null)),
-            .l_linger = if (timeout_seconds) |seconds| seconds else 0,
-        };
-
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_LINGER, mem.asBytes(&settings));
-    }
-
-    /// On connection-oriented sockets, have keep-alive messages be sent periodically. The timing in which keep-alive
-    /// messages are sent are dependant on operating system settings. It returns `error.UnsupportedSocketOption` if
-    /// the host does not support periodically sending keep-alive messages on connection-oriented sockets. 
-    pub fn setKeepAlive(self: Socket, enabled: bool) !void {
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_KEEPALIVE, mem.asBytes(&@as(u32, @boolToInt(enabled))));
-    }
-
-    /// Allow multiple sockets on the same host to listen on the same address. It returns `error.UnsupportedSocketOption` if
-    /// the host does not support sockets listening the same address.
-    pub fn setReuseAddress(self: Socket, enabled: bool) !void {
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_REUSEADDR, mem.asBytes(&@as(u32, @boolToInt(enabled))));
-    }
-
-    /// Allow multiple sockets on the same host to listen on the same port. It returns `error.UnsupportedSocketOption` if
-    /// the host does not supports sockets listening on the same port.
-    ///
-    /// TODO: verify if this truly mimicks SO_REUSEPORT behavior, or if SO_REUSE_UNICASTPORT provides the correct behavior
-    pub fn setReusePort(self: Socket, enabled: bool) !void {
-        try self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_BROADCAST, mem.asBytes(&@as(u32, @boolToInt(enabled))));
-        try self.setReuseAddress(enabled);
-    }
-
-    /// Set the write buffer size of the socket.
-    pub fn setWriteBufferSize(self: Socket, size: u32) !void {
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_SNDBUF, mem.asBytes(&size));
-    }
-
-    /// Set the read buffer size of the socket.
-    pub fn setReadBufferSize(self: Socket, size: u32) !void {
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_RCVBUF, mem.asBytes(&size));
-    }
-
-    /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
-    /// set on a non-blocking socket.
-    /// 
-    /// Set a timeout on the socket that is to occur if no messages are successfully written
-    /// to its bound destination after a specified number of milliseconds. A subsequent write
-    /// to the socket will thereafter return `error.WouldBlock` should the timeout be exceeded.
-    pub fn setWriteTimeout(self: Socket, milliseconds: u32) !void {
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_SNDTIMEO, mem.asBytes(&milliseconds));
-    }
-
-    /// WARNING: Timeouts only affect blocking sockets. It is undefined behavior if a timeout is
-    /// set on a non-blocking socket.
-    /// 
-    /// Set a timeout on the socket that is to occur if no messages are successfully read
-    /// from its bound destination after a specified number of milliseconds. A subsequent
-    /// read from the socket will thereafter return `error.WouldBlock` should the timeout be
-    /// exceeded.
-    pub fn setReadTimeout(self: Socket, milliseconds: u32) !void {
-        return self.setOption(ws2_32.SOL_SOCKET, ws2_32.SO_RCVTIMEO, mem.asBytes(&milliseconds));
-    }
-};
+    };
+}