aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/std/c.zig1
-rw-r--r--lib/std/os.zig37
-rw-r--r--lib/std/os/bits/darwin.zig7
-rw-r--r--lib/std/os/bits/dragonfly.zig10
-rw-r--r--lib/std/os/bits/freebsd.zig8
-rw-r--r--lib/std/os/bits/haiku.zig8
-rw-r--r--lib/std/os/bits/linux.zig7
-rw-r--r--lib/std/os/bits/netbsd.zig8
-rw-r--r--lib/std/os/bits/openbsd.zig8
-rw-r--r--lib/std/os/bits/windows.zig2
-rw-r--r--lib/std/os/windows.zig95
-rw-r--r--lib/std/os/windows/bits.zig15
-rw-r--r--lib/std/os/windows/kernel32.zig18
-rw-r--r--lib/std/os/windows/ws2_32.zig1914
-rw-r--r--lib/std/x.zig2
-rw-r--r--lib/std/x/net/tcp.zig116
-rw-r--r--lib/std/x/os/Socket.zig295
-rw-r--r--lib/std/x/os/net.zig9
-rw-r--r--lib/std/x/os/socket.zig123
-rw-r--r--lib/std/x/os/socket_posix.zig251
-rw-r--r--lib/std/x/os/socket_windows.zig448
21 files changed, 2797 insertions, 585 deletions
diff --git a/lib/std/c.zig b/lib/std/c.zig
index f66376f812..58ebaaa804 100644
--- a/lib/std/c.zig
+++ b/lib/std/c.zig
@@ -151,6 +151,7 @@ pub extern "c" fn bind(socket: fd_t, address: ?*const sockaddr, address_len: soc
pub extern "c" fn socketpair(domain: c_uint, sock_type: c_uint, protocol: c_uint, sv: *[2]fd_t) c_int;
pub extern "c" fn listen(sockfd: fd_t, backlog: c_uint) c_int;
pub extern "c" fn getsockname(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
+pub extern "c" fn getpeername(sockfd: fd_t, noalias addr: *sockaddr, noalias addrlen: *socklen_t) c_int;
pub extern "c" fn connect(sockfd: fd_t, sock_addr: *const sockaddr, addrlen: socklen_t) c_int;
pub extern "c" fn accept(sockfd: fd_t, noalias addr: ?*sockaddr, noalias addrlen: ?*socklen_t) c_int;
pub extern "c" fn accept4(sockfd: fd_t, noalias addr: ?*sockaddr, noalias addrlen: ?*socklen_t, flags: c_uint) c_int;
diff --git a/lib/std/os.zig b/lib/std/os.zig
index 4cdecf5231..8bfebb362c 100644
--- a/lib/std/os.zig
+++ b/lib/std/os.zig
@@ -2758,9 +2758,9 @@ pub const ShutdownHow = enum { recv, send, both };
pub fn shutdown(sock: socket_t, how: ShutdownHow) ShutdownError!void {
if (builtin.os.tag == .windows) {
const result = windows.ws2_32.shutdown(sock, switch (how) {
- .recv => windows.SD_RECEIVE,
- .send => windows.SD_SEND,
- .both => windows.SD_BOTH,
+ .recv => windows.ws2_32.SD_RECEIVE,
+ .send => windows.ws2_32.SD_SEND,
+ .both => windows.ws2_32.SD_BOTH,
});
if (0 != result) switch (windows.ws2_32.WSAGetLastError()) {
.WSAECONNABORTED => return error.ConnectionAborted,
@@ -3217,6 +3217,35 @@ pub fn getsockname(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSock
}
}
+pub fn getpeername(sock: socket_t, addr: *sockaddr, addrlen: *socklen_t) GetSockNameError!void {
+ if (builtin.os.tag == .windows) {
+ const rc = windows.getpeername(sock, addr, addrlen);
+ if (rc == windows.ws2_32.SOCKET_ERROR) {
+ switch (windows.ws2_32.WSAGetLastError()) {
+ .WSANOTINITIALISED => unreachable,
+ .WSAENETDOWN => return error.NetworkSubsystemFailed,
+ .WSAEFAULT => unreachable, // addr or addrlen have invalid pointers or addrlen points to an incorrect value
+ .WSAENOTSOCK => return error.FileDescriptorNotASocket,
+ .WSAEINVAL => return error.SocketNotBound,
+ else => |err| return windows.unexpectedWSAError(err),
+ }
+ }
+ return;
+ } else {
+ const rc = system.getpeername(sock, addr, addrlen);
+ switch (errno(rc)) {
+ 0 => return,
+ else => |err| return unexpectedErrno(err),
+
+ EBADF => unreachable, // always a race condition
+ EFAULT => unreachable,
+ EINVAL => unreachable, // invalid parameters
+ ENOTSOCK => return error.FileDescriptorNotASocket,
+ ENOBUFS => return error.SystemResources,
+ }
+ }
+}
+
pub const ConnectError = error{
/// For UNIX domain sockets, which are identified by pathname: Write permission is denied on the socket
/// file, or search permission is denied for one of the directories in the path prefix.
@@ -5722,7 +5751,7 @@ pub const SetSockOptError = error{
/// Set a socket's options.
pub fn setsockopt(fd: socket_t, level: u32, optname: u32, opt: []const u8) SetSockOptError!void {
if (builtin.os.tag == .windows) {
- const rc = windows.ws2_32.setsockopt(fd, level, optname, opt.ptr, @intCast(socklen_t, opt.len));
+ const rc = windows.ws2_32.setsockopt(fd, @intCast(i32, level), @intCast(i32, optname), opt.ptr, @intCast(i32, opt.len));
if (rc == windows.ws2_32.SOCKET_ERROR) {
switch (windows.ws2_32.WSAGetLastError()) {
.WSANOTINITIALISED => unreachable,
diff --git a/lib/std/os/bits/darwin.zig b/lib/std/os/bits/darwin.zig
index e8a477c5d6..e3e09bfb5b 100644
--- a/lib/std/os/bits/darwin.zig
+++ b/lib/std/os/bits/darwin.zig
@@ -23,6 +23,13 @@ pub const sockaddr = extern struct {
family: sa_family_t,
data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ len: u8,
+ family: sa_family_t,
+ __pad1: [5]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
pub const sockaddr_in = extern struct {
len: u8 = @sizeOf(sockaddr_in),
family: sa_family_t = AF_INET,
diff --git a/lib/std/os/bits/dragonfly.zig b/lib/std/os/bits/dragonfly.zig
index 3df6eb43de..e0cfa387bd 100644
--- a/lib/std/os/bits/dragonfly.zig
+++ b/lib/std/os/bits/dragonfly.zig
@@ -380,6 +380,14 @@ pub const sockaddr = extern struct {
sa_data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ len: u8,
+ family: sa_family_t,
+ __pad1: [5]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
pub const Kevent = extern struct {
ident: usize,
filter: c_short,
@@ -640,7 +648,7 @@ pub const socklen_t = c_uint;
pub const sockaddr_storage = extern struct {
ss_len: u8,
ss_family: sa_family_t,
- __ss_pad1: [6]u8,
+ __ss_pad1: [5]u8,
__ss_align: i64,
__ss_pad2: [112]u8,
};
diff --git a/lib/std/os/bits/freebsd.zig b/lib/std/os/bits/freebsd.zig
index 8529c5e3db..1a8f29e793 100644
--- a/lib/std/os/bits/freebsd.zig
+++ b/lib/std/os/bits/freebsd.zig
@@ -206,6 +206,14 @@ pub const sockaddr = extern struct {
data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ len: u8,
+ family: sa_family_t,
+ __pad1: [5]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
pub const sockaddr_in = extern struct {
len: u8 = @sizeOf(sockaddr_in),
family: sa_family_t = AF_INET,
diff --git a/lib/std/os/bits/haiku.zig b/lib/std/os/bits/haiku.zig
index 25a881ba56..8d170baebd 100644
--- a/lib/std/os/bits/haiku.zig
+++ b/lib/std/os/bits/haiku.zig
@@ -239,6 +239,14 @@ pub const sockaddr = extern struct {
data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ len: u8,
+ family: sa_family_t,
+ __pad1: [5]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
pub const sockaddr_in = extern struct {
len: u8 = @sizeOf(sockaddr_in),
family: sa_family_t = AF_INET,
diff --git a/lib/std/os/bits/linux.zig b/lib/std/os/bits/linux.zig
index 61a432673a..048a7b3552 100644
--- a/lib/std/os/bits/linux.zig
+++ b/lib/std/os/bits/linux.zig
@@ -1149,6 +1149,13 @@ pub const sockaddr = extern struct {
data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ family: sa_family_t,
+ __pad1: [6]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
/// IPv4 socket address
pub const sockaddr_in = extern struct {
family: sa_family_t = AF_INET,
diff --git a/lib/std/os/bits/netbsd.zig b/lib/std/os/bits/netbsd.zig
index dfb6c3bdf9..e205f6042c 100644
--- a/lib/std/os/bits/netbsd.zig
+++ b/lib/std/os/bits/netbsd.zig
@@ -226,6 +226,14 @@ pub const sockaddr = extern struct {
data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ len: u8,
+ family: sa_family_t,
+ __pad1: [5]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
pub const sockaddr_in = extern struct {
len: u8 = @sizeOf(sockaddr_in),
family: sa_family_t = AF_INET,
diff --git a/lib/std/os/bits/openbsd.zig b/lib/std/os/bits/openbsd.zig
index 1aa5ce1c9c..4104041891 100644
--- a/lib/std/os/bits/openbsd.zig
+++ b/lib/std/os/bits/openbsd.zig
@@ -246,6 +246,14 @@ pub const sockaddr = extern struct {
data: [14]u8,
};
+pub const sockaddr_storage = extern struct {
+ len: u8,
+ family: sa_family_t,
+ __pad1: [5]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
pub const sockaddr_in = extern struct {
len: u8 = @sizeOf(sockaddr_in),
family: sa_family_t = AF_INET,
diff --git a/lib/std/os/bits/windows.zig b/lib/std/os/bits/windows.zig
index 00ca2a1532..c5b101296b 100644
--- a/lib/std/os/bits/windows.zig
+++ b/lib/std/os/bits/windows.zig
@@ -321,3 +321,5 @@ pub const O_NOATIME = 0o1000000;
pub const O_PATH = 0o10000000;
pub const O_TMPFILE = 0o20200000;
pub const O_NDELAY = O_NONBLOCK;
+
+pub const IFNAMESIZE = 30;
diff --git a/lib/std/os/windows.zig b/lib/std/os/windows.zig
index 86d1012319..12238ba776 100644
--- a/lib/std/os/windows.zig
+++ b/lib/std/os/windows.zig
@@ -389,6 +389,43 @@ pub fn GetQueuedCompletionStatus(
return GetQueuedCompletionStatusResult.Normal;
}
+pub const GetQueuedCompletionStatusError = error{
+ Aborted,
+ Cancelled,
+ EOF,
+ Timeout,
+} || std.os.UnexpectedError;
+
+pub fn GetQueuedCompletionStatusEx(
+ completion_port: HANDLE,
+ completion_port_entries: []OVERLAPPED_ENTRY,
+ timeout_ms: ?DWORD,
+ alertable: bool,
+) GetQueuedCompletionStatusError!u32 {
+ var num_entries_removed: u32 = 0;
+
+ const success = kernel32.GetQueuedCompletionStatusEx(
+ completion_port,
+ completion_port_entries.ptr,
+ @intCast(ULONG, completion_port_entries.len),
+ &num_entries_removed,
+ timeout_ms orelse INFINITE,
+ @boolToInt(alertable),
+ );
+
+ if (success == FALSE) {
+ return switch (kernel32.GetLastError()) {
+ .ABANDONED_WAIT_0 => error.Aborted,
+ .OPERATION_ABORTED => error.Cancelled,
+ .HANDLE_EOF => error.EOF,
+ .IMEOUT => error.Timeout,
+ else => |err| unexpectedError(err),
+ };
+ }
+
+ return num_entries_removed;
+}
+
pub fn CloseHandle(hObject: HANDLE) void {
assert(ntdll.NtClose(hObject) == .SUCCESS);
}
@@ -1291,6 +1328,10 @@ pub fn getsockname(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.so
return ws2_32.getsockname(s, name, @ptrCast(*i32, namelen));
}
+pub fn getpeername(s: ws2_32.SOCKET, name: *ws2_32.sockaddr, namelen: *ws2_32.socklen_t) i32 {
+ return ws2_32.getpeername(s, name, @ptrCast(*i32, namelen));
+}
+
pub fn sendmsg(
s: ws2_32.SOCKET,
msg: *const ws2_32.WSAMSG,
@@ -1404,6 +1445,28 @@ pub fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) SetCon
}
}
+pub fn SetConsoleCtrlHandler(handler_routine: ?HANDLER_ROUTINE, add: bool) !void {
+ const success = kernel32.SetConsoleCtrlHandler(
+ handler_routine,
+ if (add) TRUE else FALSE,
+ );
+
+ if (success == FALSE) {
+ return switch (kernel32.GetLastError()) {
+ else => |err| unexpectedError(err),
+ };
+ }
+}
+
+pub fn SetFileCompletionNotificationModes(handle: HANDLE, flags: UCHAR) !void {
+ const success = kernel32.SetFileCompletionNotificationModes(handle, flags);
+ if (success == FALSE) {
+ return switch (kernel32.GetLastError()) {
+ else => |err| unexpectedError(err),
+ };
+ }
+}
+
pub const GetEnvironmentStringsError = error{OutOfMemory};
pub fn GetEnvironmentStringsW() GetEnvironmentStringsError![*:0]u16 {
@@ -1686,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 {
diff --git a/lib/std/os/windows/bits.zig b/lib/std/os/windows/bits.zig
index cbeb0b483d..1e08dbbf5c 100644
--- a/lib/std/os/windows/bits.zig
+++ b/lib/std/os/windows/bits.zig
@@ -1619,10 +1619,6 @@ pub const MOUNTMGR_MOUNT_POINTS = extern struct {
};
pub const IOCTL_MOUNTMGR_QUERY_POINTS: ULONG = 0x6d0008;
-pub const SD_RECEIVE = 0;
-pub const SD_SEND = 1;
-pub const SD_BOTH = 2;
-
pub const OBJECT_INFORMATION_CLASS = extern enum {
ObjectBasicInformation = 0,
ObjectNameInformation = 1,
@@ -1642,3 +1638,14 @@ pub const SRWLOCK = usize;
pub const SRWLOCK_INIT: SRWLOCK = 0;
pub const CONDITION_VARIABLE = usize;
pub const CONDITION_VARIABLE_INIT: CONDITION_VARIABLE = 0;
+
+pub const FILE_SKIP_COMPLETION_PORT_ON_SUCCESS = 0x1;
+pub const FILE_SKIP_SET_EVENT_ON_HANDLE = 0x2;
+
+pub const CTRL_C_EVENT: DWORD = 0;
+pub const CTRL_BREAK_EVENT: DWORD = 1;
+pub const CTRL_CLOSE_EVENT: DWORD = 2;
+pub const CTRL_LOGOFF_EVENT: DWORD = 5;
+pub const CTRL_SHUTDOWN_EVENT: DWORD = 6;
+
+pub const HANDLER_ROUTINE = fn (dwCtrlType: DWORD) callconv(.C) BOOL;
diff --git a/lib/std/os/windows/kernel32.zig b/lib/std/os/windows/kernel32.zig
index 734059a08a..e117f362eb 100644
--- a/lib/std/os/windows/kernel32.zig
+++ b/lib/std/os/windows/kernel32.zig
@@ -140,6 +140,14 @@ pub extern "kernel32" fn GetOverlappedResult(hFile: HANDLE, lpOverlapped: *OVERL
pub extern "kernel32" fn GetProcessHeap() callconv(WINAPI) ?HANDLE;
pub extern "kernel32" fn GetQueuedCompletionStatus(CompletionPort: HANDLE, lpNumberOfBytesTransferred: LPDWORD, lpCompletionKey: *ULONG_PTR, lpOverlapped: *?*OVERLAPPED, dwMilliseconds: DWORD) callconv(WINAPI) BOOL;
+pub extern "kernel32" fn GetQueuedCompletionStatusEx(
+ CompletionPort: HANDLE,
+ lpCompletionPortEntries: [*]OVERLAPPED_ENTRY,
+ ulCount: ULONG,
+ ulNumEntriesRemoved: *ULONG,
+ dwMilliseconds: DWORD,
+ fAlertable: BOOL,
+) callconv(WINAPI) BOOL;
pub extern "kernel32" fn GetSystemInfo(lpSystemInfo: *SYSTEM_INFO) callconv(WINAPI) void;
pub extern "kernel32" fn GetSystemTimeAsFileTime(*FILETIME) callconv(WINAPI) void;
@@ -197,6 +205,16 @@ pub extern "kernel32" fn RemoveDirectoryW(lpPathName: [*:0]const u16) callconv(W
pub extern "kernel32" fn SetConsoleTextAttribute(hConsoleOutput: HANDLE, wAttributes: WORD) callconv(WINAPI) BOOL;
+pub extern "kernel32" fn SetConsoleCtrlHandler(
+ HandlerRoutine: ?HANDLER_ROUTINE,
+ Add: BOOL,
+) callconv(WINAPI) BOOL;
+
+pub extern "kernel32" fn SetFileCompletionNotificationModes(
+ FileHandle: HANDLE,
+ Flags: UCHAR,
+) callconv(WINAPI) BOOL;
+
pub extern "kernel32" fn SetFilePointerEx(
in_fFile: HANDLE,
in_liDistanceToMove: LARGE_INTEGER,
diff --git a/lib/std/os/windows/ws2_32.zig b/lib/std/os/windows/ws2_32.zig
index 1dd2ce738b..1fa5110b52 100644
--- a/lib/std/os/windows/ws2_32.zig
+++ b/lib/std/os/windows/ws2_32.zig
@@ -7,10 +7,929 @@ usingnamespace @import("bits.zig");
pub const SOCKET = *opaque {};
pub const INVALID_SOCKET = @intToPtr(SOCKET, ~@as(usize, 0));
-pub const SOCKET_ERROR = -1;
+pub const GROUP = u32;
+pub const ADDRESS_FAMILY = u16;
+pub const WSAEVENT = HANDLE;
+
+// Microsoft use the signed c_int for this, but it should never be negative
+pub const socklen_t = u32;
+
+pub const LM_HB_Extension = 128;
+pub const LM_HB1_PnP = 1;
+pub const LM_HB1_PDA_Palmtop = 2;
+pub const LM_HB1_Computer = 4;
+pub const LM_HB1_Printer = 8;
+pub const LM_HB1_Modem = 16;
+pub const LM_HB1_Fax = 32;
+pub const LM_HB1_LANAccess = 64;
+pub const LM_HB2_Telephony = 1;
+pub const LM_HB2_FileServer = 2;
+pub const ATMPROTO_AALUSER = 0;
+pub const ATMPROTO_AAL1 = 1;
+pub const ATMPROTO_AAL2 = 2;
+pub const ATMPROTO_AAL34 = 3;
+pub const ATMPROTO_AAL5 = 5;
+pub const SAP_FIELD_ABSENT = 4294967294;
+pub const SAP_FIELD_ANY = 4294967295;
+pub const SAP_FIELD_ANY_AESA_SEL = 4294967290;
+pub const SAP_FIELD_ANY_AESA_REST = 4294967291;
+pub const ATM_E164 = 1;
+pub const ATM_NSAP = 2;
+pub const ATM_AESA = 2;
+pub const ATM_ADDR_SIZE = 20;
+pub const BLLI_L2_ISO_1745 = 1;
+pub const BLLI_L2_Q921 = 2;
+pub const BLLI_L2_X25L = 6;
+pub const BLLI_L2_X25M = 7;
+pub const BLLI_L2_ELAPB = 8;
+pub const BLLI_L2_HDLC_ARM = 9;
+pub const BLLI_L2_HDLC_NRM = 10;
+pub const BLLI_L2_HDLC_ABM = 11;
+pub const BLLI_L2_LLC = 12;
+pub const BLLI_L2_X75 = 13;
+pub const BLLI_L2_Q922 = 14;
+pub const BLLI_L2_USER_SPECIFIED = 16;
+pub const BLLI_L2_ISO_7776 = 17;
+pub const BLLI_L3_X25 = 6;
+pub const BLLI_L3_ISO_8208 = 7;
+pub const BLLI_L3_X223 = 8;
+pub const BLLI_L3_SIO_8473 = 9;
+pub const BLLI_L3_T70 = 10;
+pub const BLLI_L3_ISO_TR9577 = 11;
+pub const BLLI_L3_USER_SPECIFIED = 16;
+pub const BLLI_L3_IPI_SNAP = 128;
+pub const BLLI_L3_IPI_IP = 204;
+pub const BHLI_ISO = 0;
+pub const BHLI_UserSpecific = 1;
+pub const BHLI_HighLayerProfile = 2;
+pub const BHLI_VendorSpecificAppId = 3;
+pub const AAL5_MODE_MESSAGE = 1;
+pub const AAL5_MODE_STREAMING = 2;
+pub const AAL5_SSCS_NULL = 0;
+pub const AAL5_SSCS_SSCOP_ASSURED = 1;
+pub const AAL5_SSCS_SSCOP_NON_ASSURED = 2;
+pub const AAL5_SSCS_FRAME_RELAY = 4;
+pub const BCOB_A = 1;
+pub const BCOB_C = 3;
+pub const BCOB_X = 16;
+pub const TT_NOIND = 0;
+pub const TT_CBR = 4;
+pub const TT_VBR = 8;
+pub const TR_NOIND = 0;
+pub const TR_END_TO_END = 1;
+pub const TR_NO_END_TO_END = 2;
+pub const CLIP_NOT = 0;
+pub const CLIP_SUS = 32;
+pub const UP_P2P = 0;
+pub const UP_P2MP = 1;
+pub const BLLI_L2_MODE_NORMAL = 64;
+pub const BLLI_L2_MODE_EXT = 128;
+pub const BLLI_L3_MODE_NORMAL = 64;
+pub const BLLI_L3_MODE_EXT = 128;
+pub const BLLI_L3_PACKET_16 = 4;
+pub const BLLI_L3_PACKET_32 = 5;
+pub const BLLI_L3_PACKET_64 = 6;
+pub const BLLI_L3_PACKET_128 = 7;
+pub const BLLI_L3_PACKET_256 = 8;
+pub const BLLI_L3_PACKET_512 = 9;
+pub const BLLI_L3_PACKET_1024 = 10;
+pub const BLLI_L3_PACKET_2048 = 11;
+pub const BLLI_L3_PACKET_4096 = 12;
+pub const PI_ALLOWED = 0;
+pub const PI_RESTRICTED = 64;
+pub const PI_NUMBER_NOT_AVAILABLE = 128;
+pub const SI_USER_NOT_SCREENED = 0;
+pub const SI_USER_PASSED = 1;
+pub const SI_USER_FAILED = 2;
+pub const SI_NETWORK = 3;
+pub const CAUSE_LOC_USER = 0;
+pub const CAUSE_LOC_PRIVATE_LOCAL = 1;
+pub const CAUSE_LOC_PUBLIC_LOCAL = 2;
+pub const CAUSE_LOC_TRANSIT_NETWORK = 3;
+pub const CAUSE_LOC_PUBLIC_REMOTE = 4;
+pub const CAUSE_LOC_PRIVATE_REMOTE = 5;
+pub const CAUSE_LOC_INTERNATIONAL_NETWORK = 7;
+pub const CAUSE_LOC_BEYOND_INTERWORKING = 10;
+pub const CAUSE_UNALLOCATED_NUMBER = 1;
+pub const CAUSE_NO_ROUTE_TO_TRANSIT_NETWORK = 2;
+pub const CAUSE_NO_ROUTE_TO_DESTINATION = 3;
+pub const CAUSE_VPI_VCI_UNACCEPTABLE = 10;
+pub const CAUSE_NORMAL_CALL_CLEARING = 16;
+pub const CAUSE_USER_BUSY = 17;
+pub const CAUSE_NO_USER_RESPONDING = 18;
+pub const CAUSE_CALL_REJECTED = 21;
+pub const CAUSE_NUMBER_CHANGED = 22;
+pub const CAUSE_USER_REJECTS_CLIR = 23;
+pub const CAUSE_DESTINATION_OUT_OF_ORDER = 27;
+pub const CAUSE_INVALID_NUMBER_FORMAT = 28;
+pub const CAUSE_STATUS_ENQUIRY_RESPONSE = 30;
+pub const CAUSE_NORMAL_UNSPECIFIED = 31;
+pub const CAUSE_VPI_VCI_UNAVAILABLE = 35;
+pub const CAUSE_NETWORK_OUT_OF_ORDER = 38;
+pub const CAUSE_TEMPORARY_FAILURE = 41;
+pub const CAUSE_ACCESS_INFORMAION_DISCARDED = 43;
+pub const CAUSE_NO_VPI_VCI_AVAILABLE = 45;
+pub const CAUSE_RESOURCE_UNAVAILABLE = 47;
+pub const CAUSE_QOS_UNAVAILABLE = 49;
+pub const CAUSE_USER_CELL_RATE_UNAVAILABLE = 51;
+pub const CAUSE_BEARER_CAPABILITY_UNAUTHORIZED = 57;
+pub const CAUSE_BEARER_CAPABILITY_UNAVAILABLE = 58;
+pub const CAUSE_OPTION_UNAVAILABLE = 63;
+pub const CAUSE_BEARER_CAPABILITY_UNIMPLEMENTED = 65;
+pub const CAUSE_UNSUPPORTED_TRAFFIC_PARAMETERS = 73;
+pub const CAUSE_INVALID_CALL_REFERENCE = 81;
+pub const CAUSE_CHANNEL_NONEXISTENT = 82;
+pub const CAUSE_INCOMPATIBLE_DESTINATION = 88;
+pub const CAUSE_INVALID_ENDPOINT_REFERENCE = 89;
+pub const CAUSE_INVALID_TRANSIT_NETWORK_SELECTION = 91;
+pub const CAUSE_TOO_MANY_PENDING_ADD_PARTY = 92;
+pub const CAUSE_AAL_PARAMETERS_UNSUPPORTED = 93;
+pub const CAUSE_MANDATORY_IE_MISSING = 96;
+pub const CAUSE_UNIMPLEMENTED_MESSAGE_TYPE = 97;
+pub const CAUSE_UNIMPLEMENTED_IE = 99;
+pub const CAUSE_INVALID_IE_CONTENTS = 100;
+pub const CAUSE_INVALID_STATE_FOR_MESSAGE = 101;
+pub const CAUSE_RECOVERY_ON_TIMEOUT = 102;
+pub const CAUSE_INCORRECT_MESSAGE_LENGTH = 104;
+pub const CAUSE_PROTOCOL_ERROR = 111;
+pub const CAUSE_COND_UNKNOWN = 0;
+pub const CAUSE_COND_PERMANENT = 1;
+pub const CAUSE_COND_TRANSIENT = 2;
+pub const CAUSE_REASON_USER = 0;
+pub const CAUSE_REASON_IE_MISSING = 4;
+pub const CAUSE_REASON_IE_INSUFFICIENT = 8;
+pub const CAUSE_PU_PROVIDER = 0;
+pub const CAUSE_PU_USER = 8;
+pub const CAUSE_NA_NORMAL = 0;
+pub const CAUSE_NA_ABNORMAL = 4;
+pub const QOS_CLASS0 = 0;
+pub const QOS_CLASS1 = 1;
+pub const QOS_CLASS2 = 2;
+pub const QOS_CLASS3 = 3;
+pub const QOS_CLASS4 = 4;
+pub const TNS_TYPE_NATIONAL = 64;
+pub const TNS_PLAN_CARRIER_ID_CODE = 1;
+pub const SIO_GET_NUMBER_OF_ATM_DEVICES = 1343619073;
+pub const SIO_GET_ATM_ADDRESS = 3491102722;
+pub const SIO_ASSOCIATE_PVC = 2417360899;
+pub const SIO_GET_ATM_CONNECTION_ID = 1343619076;
+pub const RIO_MSG_DONT_NOTIFY = 1;
+pub const RIO_MSG_DEFER = 2;
+pub const RIO_MSG_WAITALL = 4;
+pub const RIO_MSG_COMMIT_ONLY = 8;
+pub const RIO_MAX_CQ_SIZE = 134217728;
+pub const RIO_CORRUPT_CQ = 4294967295;
+pub const WINDOWS_AF_IRDA = 26;
+pub const WCE_AF_IRDA = 22;
+pub const IRDA_PROTO_SOCK_STREAM = 1;
+pub const SOL_IRLMP = 255;
+pub const IRLMP_ENUMDEVICES = 16;
+pub const IRLMP_IAS_SET = 17;
+pub const IRLMP_IAS_QUERY = 18;
+pub const IRLMP_SEND_PDU_LEN = 19;
+pub const IRLMP_EXCLUSIVE_MODE = 20;
+pub const IRLMP_IRLPT_MODE = 21;
+pub const IRLMP_9WIRE_MODE = 22;
+pub const IRLMP_TINYTP_MODE = 23;
+pub const IRLMP_PARAMETERS = 24;
+pub const IRLMP_DISCOVERY_MODE = 25;
+pub const IRLMP_SHARP_MODE = 32;
+pub const IAS_ATTRIB_NO_CLASS = 16;
+pub const IAS_ATTRIB_NO_ATTRIB = 0;
+pub const IAS_ATTRIB_INT = 1;
+pub const IAS_ATTRIB_OCTETSEQ = 2;
+pub const IAS_ATTRIB_STR = 3;
+pub const IAS_MAX_USER_STRING = 256;
+pub const IAS_MAX_OCTET_STRING = 1024;
+pub const IAS_MAX_CLASSNAME = 64;
+pub const IAS_MAX_ATTRIBNAME = 256;
+pub const LmCharSetASCII = 0;
+pub const LmCharSetISO_8859_1 = 1;
+pub const LmCharSetISO_8859_2 = 2;
+pub const LmCharSetISO_8859_3 = 3;
+pub const LmCharSetISO_8859_4 = 4;
+pub const LmCharSetISO_8859_5 = 5;
+pub const LmCharSetISO_8859_6 = 6;
+pub const LmCharSetISO_8859_7 = 7;
+pub const LmCharSetISO_8859_8 = 8;
+pub const LmCharSetISO_8859_9 = 9;
+pub const LmCharSetUNICODE = 255;
+pub const LM_BAUD_1200 = 1200;
+pub const LM_BAUD_2400 = 2400;
+pub const LM_BAUD_9600 = 9600;
+pub const LM_BAUD_19200 = 19200;
+pub const LM_BAUD_38400 = 38400;
+pub const LM_BAUD_57600 = 57600;
+pub const LM_BAUD_115200 = 115200;
+pub const LM_BAUD_576K = 576000;
+pub const LM_BAUD_1152K = 1152000;
+pub const LM_BAUD_4M = 4000000;
+pub const LM_BAUD_16M = 16000000;
+pub const IPX_PTYPE = 16384;
+pub const IPX_FILTERPTYPE = 16385;
+pub const IPX_STOPFILTERPTYPE = 16387;
+pub const IPX_DSTYPE = 16386;
+pub const IPX_EXTENDED_ADDRESS = 16388;
+pub const IPX_RECVHDR = 16389;
+pub const IPX_MAXSIZE = 16390;
+pub const IPX_ADDRESS = 16391;
+pub const IPX_GETNETINFO = 16392;
+pub const IPX_GETNETINFO_NORIP = 16393;
+pub const IPX_SPXGETCONNECTIONSTATUS = 16395;
+pub const IPX_ADDRESS_NOTIFY = 16396;
+pub const IPX_MAX_ADAPTER_NUM = 16397;
+pub const IPX_RERIPNETNUMBER = 16398;
+pub const IPX_RECEIVE_BROADCAST = 16399;
+pub const IPX_IMMEDIATESPXACK = 16400;
+pub const IPPROTO_RM = 113;
+pub const MAX_MCAST_TTL = 255;
+pub const RM_OPTIONSBASE = 1000;
+pub const RM_RATE_WINDOW_SIZE = 1001;
+pub const RM_SET_MESSAGE_BOUNDARY = 1002;
+pub const RM_FLUSHCACHE = 1003;
+pub const RM_SENDER_WINDOW_ADVANCE_METHOD = 1004;
+pub const RM_SENDER_STATISTICS = 1005;
+pub const RM_LATEJOIN = 1006;
+pub const RM_SET_SEND_IF = 1007;
+pub const RM_ADD_RECEIVE_IF = 1008;
+pub const RM_DEL_RECEIVE_IF = 1009;
+pub const RM_SEND_WINDOW_ADV_RATE = 1010;
+pub const RM_USE_FEC = 1011;
+pub const RM_SET_MCAST_TTL = 1012;
+pub const RM_RECEIVER_STATISTICS = 1013;
+pub const RM_HIGH_SPEED_INTRANET_OPT = 1014;
+pub const SENDER_DEFAULT_RATE_KBITS_PER_SEC = 56;
+pub const SENDER_DEFAULT_WINDOW_ADV_PERCENTAGE = 15;
+pub const MAX_WINDOW_INCREMENT_PERCENTAGE = 25;
+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;
+pub const SOCKET_SETTINGS_ALLOW_INSECURE = 2;
+pub const SOCKET_SETTINGS_IPSEC_SKIP_FILTER_INSTANTIATION = 1;
+pub const SOCKET_SETTINGS_IPSEC_OPTIONAL_PEER_NAME_VERIFICATION = 2;
+pub const SOCKET_SETTINGS_IPSEC_ALLOW_FIRST_INBOUND_PKT_UNENCRYPTED = 4;
+pub const SOCKET_SETTINGS_IPSEC_PEER_NAME_IS_RAW_FORMAT = 8;
+pub const SOCKET_QUERY_IPSEC2_ABORT_CONNECTION_ON_FIELD_CHANGE = 1;
+pub const SOCKET_QUERY_IPSEC2_FIELD_MASK_MM_SA_ID = 1;
+pub const SOCKET_QUERY_IPSEC2_FIELD_MASK_QM_SA_ID = 2;
+pub const SOCKET_INFO_CONNECTION_SECURED = 1;
+pub const SOCKET_INFO_CONNECTION_ENCRYPTED = 2;
+pub const SOCKET_INFO_CONNECTION_IMPERSONATED = 4;
+pub const IN4ADDR_LOOPBACK = 16777343;
+pub const IN4ADDR_LOOPBACKPREFIX_LENGTH = 8;
+pub const IN4ADDR_LINKLOCALPREFIX_LENGTH = 16;
+pub const IN4ADDR_MULTICASTPREFIX_LENGTH = 4;
+pub const IFF_UP = 1;
+pub const IFF_BROADCAST = 2;
+pub const IFF_LOOPBACK = 4;
+pub const IFF_POINTTOPOINT = 8;
+pub const IFF_MULTICAST = 16;
+pub const IP_OPTIONS = 1;
+pub const IP_HDRINCL = 2;
+pub const IP_TOS = 3;
+pub const IP_TTL = 4;
+pub const IP_MULTICAST_IF = 9;
+pub const IP_MULTICAST_TTL = 10;
+pub const IP_MULTICAST_LOOP = 11;
+pub const IP_ADD_MEMBERSHIP = 12;
+pub const IP_DROP_MEMBERSHIP = 13;
+pub const IP_DONTFRAGMENT = 14;
+pub const IP_ADD_SOURCE_MEMBERSHIP = 15;
+pub const IP_DROP_SOURCE_MEMBERSHIP = 16;
+pub const IP_BLOCK_SOURCE = 17;
+pub const IP_UNBLOCK_SOURCE = 18;
+pub const IP_PKTINFO = 19;
+pub const IP_HOPLIMIT = 21;
+pub const IP_RECVTTL = 21;
+pub const IP_RECEIVE_BROADCAST = 22;
+pub const IP_RECVIF = 24;
+pub const IP_RECVDSTADDR = 25;
+pub const IP_IFLIST = 28;
+pub const IP_ADD_IFLIST = 29;
+pub const IP_DEL_IFLIST = 30;
+pub const IP_UNICAST_IF = 31;
+pub const IP_RTHDR = 32;
+pub const IP_GET_IFLIST = 33;
+pub const IP_RECVRTHDR = 38;
+pub const IP_TCLASS = 39;
+pub const IP_RECVTCLASS = 40;
+pub const IP_RECVTOS = 40;
+pub const IP_ORIGINAL_ARRIVAL_IF = 47;
+pub const IP_ECN = 50;
+pub const IP_PKTINFO_EX = 51;
+pub const IP_WFP_REDIRECT_RECORDS = 60;
+pub const IP_WFP_REDIRECT_CONTEXT = 70;
+pub const IP_MTU_DISCOVER = 71;
+pub const IP_MTU = 73;
+pub const IP_NRT_INTERFACE = 74;
+pub const IP_RECVERR = 75;
+pub const IP_USER_MTU = 76;
+pub const IP_UNSPECIFIED_TYPE_OF_SERVICE = -1;
+pub const IN6ADDR_LINKLOCALPREFIX_LENGTH = 64;
+pub const IN6ADDR_MULTICASTPREFIX_LENGTH = 8;
+pub const IN6ADDR_SOLICITEDNODEMULTICASTPREFIX_LENGTH = 104;
+pub const IN6ADDR_V4MAPPEDPREFIX_LENGTH = 96;
+pub const IN6ADDR_6TO4PREFIX_LENGTH = 16;
+pub const IN6ADDR_TEREDOPREFIX_LENGTH = 32;
+pub const MCAST_JOIN_GROUP = 41;
+pub const MCAST_LEAVE_GROUP = 42;
+pub const MCAST_BLOCK_SOURCE = 43;
+pub const MCAST_UNBLOCK_SOURCE = 44;
+pub const MCAST_JOIN_SOURCE_GROUP = 45;
+pub const MCAST_LEAVE_SOURCE_GROUP = 46;
+pub const IPV6_HOPOPTS = 1;
+pub const IPV6_HDRINCL = 2;
+pub const IPV6_UNICAST_HOPS = 4;
+pub const IPV6_MULTICAST_IF = 9;
+pub const IPV6_MULTICAST_HOPS = 10;
+pub const IPV6_MULTICAST_LOOP = 11;
+pub const IPV6_ADD_MEMBERSHIP = 12;
+pub const IPV6_DROP_MEMBERSHIP = 13;
+pub const IPV6_DONTFRAG = 14;
+pub const IPV6_PKTINFO = 19;
+pub const IPV6_HOPLIMIT = 21;
+pub const IPV6_PROTECTION_LEVEL = 23;
+pub const IPV6_RECVIF = 24;
+pub const IPV6_RECVDSTADDR = 25;
+pub const IPV6_CHECKSUM = 26;
+pub const IPV6_V6ONLY = 27;
+pub const IPV6_IFLIST = 28;
+pub const IPV6_ADD_IFLIST = 29;
+pub const IPV6_DEL_IFLIST = 30;
+pub const IPV6_UNICAST_IF = 31;
+pub const IPV6_RTHDR = 32;
+pub const IPV6_GET_IFLIST = 33;
+pub const IPV6_RECVRTHDR = 38;
+pub const IPV6_TCLASS = 39;
+pub const IPV6_RECVTCLASS = 40;
+pub const IPV6_ECN = 50;
+pub const IPV6_PKTINFO_EX = 51;
+pub const IPV6_WFP_REDIRECT_RECORDS = 60;
+pub const IPV6_WFP_REDIRECT_CONTEXT = 70;
+pub const IPV6_MTU_DISCOVER = 71;
+pub const IPV6_MTU = 72;
+pub const IPV6_NRT_INTERFACE = 74;
+pub const IPV6_RECVERR = 75;
+pub const IPV6_USER_MTU = 76;
+pub const IP_UNSPECIFIED_HOP_LIMIT = -1;
+pub const PROTECTION_LEVEL_UNRESTRICTED = 10;
+pub const PROTECTION_LEVEL_EDGERESTRICTED = 20;
+pub const PROTECTION_LEVEL_RESTRICTED = 30;
+pub const INET_ADDRSTRLEN = 22;
+pub const INET6_ADDRSTRLEN = 65;
+pub const TCP_OFFLOAD_NO_PREFERENCE = 0;
+pub const TCP_OFFLOAD_NOT_PREFERRED = 1;
+pub const TCP_OFFLOAD_PREFERRED = 2;
+pub const TCP_EXPEDITED_1122 = 2;
+pub const TCP_KEEPALIVE = 3;
+pub const TCP_MAXSEG = 4;
+pub const TCP_MAXRT = 5;
+pub const TCP_STDURG = 6;
+pub const TCP_NOURG = 7;
+pub const TCP_ATMARK = 8;
+pub const TCP_NOSYNRETRIES = 9;
+pub const TCP_TIMESTAMPS = 10;
+pub const TCP_OFFLOAD_PREFERENCE = 11;
+pub const TCP_CONGESTION_ALGORITHM = 12;
+pub const TCP_DELAY_FIN_ACK = 13;
+pub const TCP_MAXRTMS = 14;
+pub const TCP_FASTOPEN = 15;
+pub const TCP_KEEPCNT = 16;
+pub const TCP_KEEPINTVL = 17;
+pub const TCP_FAIL_CONNECT_ON_ICMP_ERROR = 18;
+pub const TCP_ICMP_ERROR_INFO = 19;
+pub const UDP_SEND_MSG_SIZE = 2;
+pub const UDP_RECV_MAX_COALESCED_SIZE = 3;
+pub const UDP_COALESCED_INFO = 3;
+pub const AF_UNSPEC = 0;
+pub const AF_UNIX = 1;
+pub const AF_INET = 2;
+pub const AF_IMPLINK = 3;
+pub const AF_PUP = 4;
+pub const AF_CHAOS = 5;
+pub const AF_NS = 6;
+pub const AF_ISO = 7;
+pub const AF_ECMA = 8;
+pub const AF_DATAKIT = 9;
+pub const AF_CCITT = 10;
+pub const AF_SNA = 11;
+pub const AF_DECnet = 12;
+pub const AF_DLI = 13;
+pub const AF_LAT = 14;
+pub const AF_HYLINK = 15;
+pub const AF_APPLETALK = 16;
+pub const AF_NETBIOS = 17;
+pub const AF_VOICEVIEW = 18;
+pub const AF_FIREFOX = 19;
+pub const AF_UNKNOWN1 = 20;
+pub const AF_BAN = 21;
+pub const AF_ATM = 22;
+pub const AF_INET6 = 23;
+pub const AF_CLUSTER = 24;
+pub const AF_12844 = 25;
+pub const AF_IRDA = 26;
+pub const AF_NETDES = 28;
+pub const AF_MAX = 29;
+pub const AF_TCNPROCESS = 29;
+pub const AF_TCNMESSAGE = 30;
+pub const AF_ICLFXBM = 31;
+pub const AF_LINK = 33;
+pub const AF_HYPERV = 34;
+pub const SOCK_STREAM = 1;
+pub const SOCK_DGRAM = 2;
+pub const SOCK_RAW = 3;
+pub const SOCK_RDM = 4;
+pub const SOCK_SEQPACKET = 5;
+pub const SOL_SOCKET = 65535;
+pub const SO_DEBUG = 1;
+pub const SO_ACCEPTCONN = 2;
+pub const SO_REUSEADDR = 4;
+pub const SO_KEEPALIVE = 8;
+pub const SO_DONTROUTE = 16;
+pub const SO_BROADCAST = 32;
+pub const SO_USELOOPBACK = 64;
+pub const SO_LINGER = 128;
+pub const SO_OOBINLINE = 256;
+pub const SO_SNDBUF = 4097;
+pub const SO_RCVBUF = 4098;
+pub const SO_SNDLOWAT = 4099;
+pub const SO_RCVLOWAT = 4100;
+pub const SO_SNDTIMEO = 4101;
+pub const SO_RCVTIMEO = 4102;
+pub const SO_ERROR = 4103;
+pub const SO_TYPE = 4104;
+pub const SO_BSP_STATE = 4105;
+pub const SO_GROUP_ID = 8193;
+pub const SO_GROUP_PRIORITY = 8194;
+pub const SO_MAX_MSG_SIZE = 8195;
+pub const SO_CONDITIONAL_ACCEPT = 12290;
+pub const SO_PAUSE_ACCEPT = 12291;
+pub const SO_COMPARTMENT_ID = 12292;
+pub const SO_RANDOMIZE_PORT = 12293;
+pub const SO_PORT_SCALABILITY = 12294;
+pub const SO_REUSE_UNICASTPORT = 12295;
+pub const SO_REUSE_MULTICASTPORT = 12296;
+pub const SO_ORIGINAL_DST = 12303;
+pub const WSK_SO_BASE = 16384;
+pub const TCP_NODELAY = 1;
+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;
+pub const SIO_BASE_HANDLE = IOC_OUT | IOC_WS2 | 34;
+pub const IPPROTO_IP = 0;
+pub const IPPORT_TCPMUX = 1;
+pub const IPPORT_ECHO = 7;
+pub const IPPORT_DISCARD = 9;
+pub const IPPORT_SYSTAT = 11;
+pub const IPPORT_DAYTIME = 13;
+pub const IPPORT_NETSTAT = 15;
+pub const IPPORT_QOTD = 17;
+pub const IPPORT_MSP = 18;
+pub const IPPORT_CHARGEN = 19;
+pub const IPPORT_FTP_DATA = 20;
+pub const IPPORT_FTP = 21;
+pub const IPPORT_TELNET = 23;
+pub const IPPORT_SMTP = 25;
+pub const IPPORT_TIMESERVER = 37;
+pub const IPPORT_NAMESERVER = 42;
+pub const IPPORT_WHOIS = 43;
+pub const IPPORT_MTP = 57;
+pub const IPPORT_TFTP = 69;
+pub const IPPORT_RJE = 77;
+pub const IPPORT_FINGER = 79;
+pub const IPPORT_TTYLINK = 87;
+pub const IPPORT_SUPDUP = 95;
+pub const IPPORT_POP3 = 110;
+pub const IPPORT_NTP = 123;
+pub const IPPORT_EPMAP = 135;
+pub const IPPORT_NETBIOS_NS = 137;
+pub const IPPORT_NETBIOS_DGM = 138;
+pub const IPPORT_NETBIOS_SSN = 139;
+pub const IPPORT_IMAP = 143;
+pub const IPPORT_SNMP = 161;
+pub const IPPORT_SNMP_TRAP = 162;
+pub const IPPORT_IMAP3 = 220;
+pub const IPPORT_LDAP = 389;
+pub const IPPORT_HTTPS = 443;
+pub const IPPORT_MICROSOFT_DS = 445;
+pub const IPPORT_EXECSERVER = 512;
+pub const IPPORT_LOGINSERVER = 513;
+pub const IPPORT_CMDSERVER = 514;
+pub const IPPORT_EFSSERVER = 520;
+pub const IPPORT_BIFFUDP = 512;
+pub const IPPORT_WHOSERVER = 513;
+pub const IPPORT_ROUTESERVER = 520;
+pub const IPPORT_RESERVED = 1024;
+pub const IPPORT_REGISTERED_MAX = 49151;
+pub const IPPORT_DYNAMIC_MIN = 49152;
+pub const IPPORT_DYNAMIC_MAX = 65535;
+pub const IN_CLASSA_NET = 4278190080;
+pub const IN_CLASSA_NSHIFT = 24;
+pub const IN_CLASSA_HOST = 16777215;
+pub const IN_CLASSA_MAX = 128;
+pub const IN_CLASSB_NET = 4294901760;
+pub const IN_CLASSB_NSHIFT = 16;
+pub const IN_CLASSB_HOST = 65535;
+pub const IN_CLASSB_MAX = 65536;
+pub const IN_CLASSC_NET = 4294967040;
+pub const IN_CLASSC_NSHIFT = 8;
+pub const IN_CLASSC_HOST = 255;
+pub const IN_CLASSD_NET = 4026531840;
+pub const IN_CLASSD_NSHIFT = 28;
+pub const IN_CLASSD_HOST = 268435455;
+pub const INADDR_LOOPBACK = 2130706433;
+pub const INADDR_NONE = 4294967295;
+pub const IOCPARM_MASK = 127;
+pub const IOC_VOID = 536870912;
+pub const IOC_OUT = 1073741824;
+pub const IOC_IN = 2147483648;
+pub const MSG_TRUNC = 256;
+pub const MSG_CTRUNC = 512;
+pub const MSG_BCAST = 1024;
+pub const MSG_MCAST = 2048;
+pub const MSG_ERRQUEUE = 4096;
+pub const AI_PASSIVE = 1;
+pub const AI_CANONNAME = 2;
+pub const AI_NUMERICHOST = 4;
+pub const AI_NUMERICSERV = 8;
+pub const AI_DNS_ONLY = 16;
+pub const AI_ALL = 256;
+pub const AI_ADDRCONFIG = 1024;
+pub const AI_V4MAPPED = 2048;
+pub const AI_NON_AUTHORITATIVE = 16384;
+pub const AI_SECURE = 32768;
+pub const AI_RETURN_PREFERRED_NAMES = 65536;
+pub const AI_FQDN = 131072;
+pub const AI_FILESERVER = 262144;
+pub const AI_DISABLE_IDN_ENCODING = 524288;
+pub const AI_EXTENDED = 2147483648;
+pub const AI_RESOLUTION_HANDLE = 1073741824;
+pub const FIONBIO = -2147195266;
+pub const ADDRINFOEX_VERSION_2 = 2;
+pub const ADDRINFOEX_VERSION_3 = 3;
+pub const ADDRINFOEX_VERSION_4 = 4;
+pub const NS_ALL = 0;
+pub const NS_SAP = 1;
+pub const NS_NDS = 2;
+pub const NS_PEER_BROWSE = 3;
+pub const NS_SLP = 5;
+pub const NS_DHCP = 6;
+pub const NS_TCPIP_LOCAL = 10;
+pub const NS_TCPIP_HOSTS = 11;
+pub const NS_DNS = 12;
+pub const NS_NETBT = 13;
+pub const NS_WINS = 14;
+pub const NS_NLA = 15;
+pub const NS_NBP = 20;
+pub const NS_MS = 30;
+pub const NS_STDA = 31;
+pub const NS_NTDS = 32;
+pub const NS_EMAIL = 37;
+pub const NS_X500 = 40;
+pub const NS_NIS = 41;
+pub const NS_NISPLUS = 42;
+pub const NS_WRQ = 50;
+pub const NS_NETDES = 60;
+pub const NI_NOFQDN = 1;
+pub const NI_NUMERICHOST = 2;
+pub const NI_NAMEREQD = 4;
+pub const NI_NUMERICSERV = 8;
+pub const NI_DGRAM = 16;
+pub const NI_MAXHOST = 1025;
+pub const NI_MAXSERV = 32;
+pub const INCL_WINSOCK_API_PROTOTYPES = 1;
+pub const INCL_WINSOCK_API_TYPEDEFS = 0;
+pub const FD_SETSIZE = 64;
+pub const IMPLINK_IP = 155;
+pub const IMPLINK_LOWEXPER = 156;
+pub const IMPLINK_HIGHEXPER = 158;
pub const WSADESCRIPTION_LEN = 256;
pub const WSASYS_STATUS_LEN = 128;
+pub const SOCKET_ERROR = -1;
+pub const FROM_PROTOCOL_INFO = -1;
+pub const SO_PROTOCOL_INFOA = 8196;
+pub const SO_PROTOCOL_INFOW = 8197;
+pub const PVD_CONFIG = 12289;
+pub const SOMAXCONN = 2147483647;
+pub const MSG_PEEK = 2;
+pub const MSG_WAITALL = 8;
+pub const MSG_PUSH_IMMEDIATE = 32;
+pub const MSG_PARTIAL = 32768;
+pub const MSG_INTERRUPT = 16;
+pub const MSG_MAXIOVLEN = 16;
+pub const MAXGETHOSTSTRUCT = 1024;
+pub const FD_READ_BIT = 0;
+pub const FD_WRITE_BIT = 1;
+pub const FD_OOB_BIT = 2;
+pub const FD_ACCEPT_BIT = 3;
+pub const FD_CONNECT_BIT = 4;
+pub const FD_CLOSE_BIT = 5;
+pub const FD_QOS_BIT = 6;
+pub const FD_GROUP_QOS_BIT = 7;
+pub const FD_ROUTING_INTERFACE_CHANGE_BIT = 8;
+pub const FD_ADDRESS_LIST_CHANGE_BIT = 9;
+pub const FD_MAX_EVENTS = 10;
+pub const CF_ACCEPT = 0;
+pub const CF_REJECT = 1;
+pub const CF_DEFER = 2;
+pub const SD_RECEIVE = 0;
+pub const SD_SEND = 1;
+pub const SD_BOTH = 2;
+pub const SG_UNCONSTRAINED_GROUP = 1;
+pub const SG_CONSTRAINED_GROUP = 2;
+pub const MAX_PROTOCOL_CHAIN = 7;
+pub const BASE_PROTOCOL = 1;
+pub const LAYERED_PROTOCOL = 0;
+pub const WSAPROTOCOL_LEN = 255;
+pub const PFL_MULTIPLE_PROTO_ENTRIES = 1;
+pub const PFL_RECOMMENDED_PROTO_ENTRY = 2;
+pub const PFL_HIDDEN = 4;
+pub const PFL_MATCHES_PROTOCOL_ZERO = 8;
+pub const PFL_NETWORKDIRECT_PROVIDER = 16;
+pub const XP1_CONNECTIONLESS = 1;
+pub const XP1_GUARANTEED_DELIVERY = 2;
+pub const XP1_GUARANTEED_ORDER = 4;
+pub const XP1_MESSAGE_ORIENTED = 8;
+pub const XP1_PSEUDO_STREAM = 16;
+pub const XP1_GRACEFUL_CLOSE = 32;
+pub const XP1_EXPEDITED_DATA = 64;
+pub const XP1_CONNECT_DATA = 128;
+pub const XP1_DISCONNECT_DATA = 256;
+pub const XP1_SUPPORT_BROADCAST = 512;
+pub const XP1_SUPPORT_MULTIPOINT = 1024;
+pub const XP1_MULTIPOINT_CONTROL_PLANE = 2048;
+pub const XP1_MULTIPOINT_DATA_PLANE = 4096;
+pub const XP1_QOS_SUPPORTED = 8192;
+pub const XP1_INTERRUPT = 16384;
+pub const XP1_UNI_SEND = 32768;
+pub const XP1_UNI_RECV = 65536;
+pub const XP1_IFS_HANDLES = 131072;
+pub const XP1_PARTIAL_MESSAGE = 262144;
+pub const XP1_SAN_SUPPORT_SDP = 524288;
+pub const BIGENDIAN = 0;
+pub const LITTLEENDIAN = 1;
+pub const SECURITY_PROTOCOL_NONE = 0;
+pub const JL_SENDER_ONLY = 1;
+pub const JL_RECEIVER_ONLY = 2;
+pub const JL_BOTH = 4;
+pub const WSA_FLAG_OVERLAPPED = 1;
+pub const WSA_FLAG_MULTIPOINT_C_ROOT = 2;
+pub const WSA_FLAG_MULTIPOINT_C_LEAF = 4;
+pub const WSA_FLAG_MULTIPOINT_D_ROOT = 8;
+pub const WSA_FLAG_MULTIPOINT_D_LEAF = 16;
+pub const WSA_FLAG_ACCESS_SYSTEM_SECURITY = 64;
+pub const WSA_FLAG_NO_HANDLE_INHERIT = 128;
+pub const WSA_FLAG_REGISTERED_IO = 256;
+pub const TH_NETDEV = 1;
+pub const TH_TAPI = 2;
+pub const SERVICE_MULTIPLE = 1;
+pub const NS_LOCALNAME = 19;
+pub const RES_UNUSED_1 = 1;
+pub const RES_FLUSH_CACHE = 2;
+pub const RES_SERVICE = 4;
+pub const LUP_DEEP = 1;
+pub const LUP_CONTAINERS = 2;
+pub const LUP_NOCONTAINERS = 4;
+pub const LUP_NEAREST = 8;
+pub const LUP_RETURN_NAME = 16;
+pub const LUP_RETURN_TYPE = 32;
+pub const LUP_RETURN_VERSION = 64;
+pub const LUP_RETURN_COMMENT = 128;
+pub const LUP_RETURN_ADDR = 256;
+pub const LUP_RETURN_BLOB = 512;
+pub const LUP_RETURN_ALIASES = 1024;
+pub const LUP_RETURN_QUERY_STRING = 2048;
+pub const LUP_RETURN_ALL = 4080;
+pub const LUP_RES_SERVICE = 32768;
+pub const LUP_FLUSHCACHE = 4096;
+pub const LUP_FLUSHPREVIOUS = 8192;
+pub const LUP_NON_AUTHORITATIVE = 16384;
+pub const LUP_SECURE = 32768;
+pub const LUP_RETURN_PREFERRED_NAMES = 65536;
+pub const LUP_DNS_ONLY = 131072;
+pub const LUP_ADDRCONFIG = 1048576;
+pub const LUP_DUAL_ADDR = 2097152;
+pub const LUP_FILESERVER = 4194304;
+pub const LUP_DISABLE_IDN_ENCODING = 8388608;
+pub const LUP_API_ANSI = 16777216;
+pub const LUP_RESOLUTION_HANDLE = 2147483648;
+pub const RESULT_IS_ALIAS = 1;
+pub const RESULT_IS_ADDED = 16;
+pub const RESULT_IS_CHANGED = 32;
+pub const RESULT_IS_DELETED = 64;
+pub const POLLRDNORM = 256;
+pub const POLLRDBAND = 512;
+pub const POLLPRI = 1024;
+pub const POLLWRNORM = 16;
+pub const POLLWRBAND = 32;
+pub const POLLERR = 1;
+pub const POLLHUP = 2;
+pub const POLLNVAL = 4;
+pub const SO_CONNDATA = 28672;
+pub const SO_CONNOPT = 28673;
+pub const SO_DISCDATA = 28674;
+pub const SO_DISCOPT = 28675;
+pub const SO_CONNDATALEN = 28676;
+pub const SO_CONNOPTLEN = 28677;
+pub const SO_DISCDATALEN = 28678;
+pub const SO_DISCOPTLEN = 28679;
+pub const SO_OPENTYPE = 28680;
+pub const SO_SYNCHRONOUS_ALERT = 16;
+pub const SO_SYNCHRONOUS_NONALERT = 32;
+pub const SO_MAXDG = 28681;
+pub const SO_MAXPATHDG = 28682;
+pub const SO_UPDATE_ACCEPT_CONTEXT = 28683;
+pub const SO_CONNECT_TIME = 28684;
+pub const SO_UPDATE_CONNECT_CONTEXT = 28688;
+pub const TCP_BSDURGENT = 28672;
+pub const TF_DISCONNECT = 1;
+pub const TF_REUSE_SOCKET = 2;
+pub const TF_WRITE_BEHIND = 4;
+pub const TF_USE_DEFAULT_WORKER = 0;
+pub const TF_USE_SYSTEM_THREAD = 16;
+pub const TF_USE_KERNEL_APC = 32;
+pub const TP_ELEMENT_MEMORY = 1;
+pub const TP_ELEMENT_FILE = 2;
+pub const TP_ELEMENT_EOP = 4;
+pub const NLA_ALLUSERS_NETWORK = 1;
+pub const NLA_FRIENDLY_NAME = 2;
+pub const WSPDESCRIPTION_LEN = 255;
+pub const WSS_OPERATION_IN_PROGRESS = 259;
+pub const LSP_SYSTEM = 2147483648;
+pub const LSP_INSPECTOR = 1;
+pub const LSP_REDIRECTOR = 2;
+pub const LSP_PROXY = 4;
+pub const LSP_FIREWALL = 8;
+pub const LSP_INBOUND_MODIFY = 16;
+pub const LSP_OUTBOUND_MODIFY = 32;
+pub const LSP_CRYPTO_COMPRESS = 64;
+pub const LSP_LOCAL_CACHE = 128;
+pub const IPPROTO_ICMP = 1;
+pub const IPPROTO_IGMP = 2;
+pub const IPPROTO_GGP = 3;
+pub const IPPROTO_TCP = 6;
+pub const IPPROTO_PUP = 12;
+pub const IPPROTO_UDP = 17;
+pub const IPPROTO_IDP = 22;
+pub const IPPROTO_ND = 77;
+pub const IPPROTO_RAW = 255;
+pub const IPPROTO_MAX = 256;
+pub const IP_DEFAULT_MULTICAST_TTL = 1;
+pub const IP_DEFAULT_MULTICAST_LOOP = 1;
+pub const IP_MAX_MEMBERSHIPS = 20;
+pub const AF_IPX = 6;
+pub const FD_READ = 1;
+pub const FD_WRITE = 2;
+pub const FD_OOB = 4;
+pub const FD_ACCEPT = 8;
+pub const FD_CONNECT = 16;
+pub const FD_CLOSE = 32;
+pub const SERVICE_RESOURCE = 1;
+pub const SERVICE_SERVICE = 2;
+pub const SERVICE_LOCAL = 4;
+pub const SERVICE_FLAG_DEFER = 1;
+pub const SERVICE_FLAG_HARD = 2;
+pub const PROP_COMMENT = 1;
+pub const PROP_LOCALE = 2;
+pub const PROP_DISPLAY_HINT = 4;
+pub const PROP_VERSION = 8;
+pub const PROP_START_TIME = 16;
+pub const PROP_MACHINE = 32;
+pub const PROP_ADDRESSES = 256;
+pub const PROP_SD = 512;
+pub const PROP_ALL = 2147483648;
+pub const SERVICE_ADDRESS_FLAG_RPC_CN = 1;
+pub const SERVICE_ADDRESS_FLAG_RPC_DG = 2;
+pub const SERVICE_ADDRESS_FLAG_RPC_NB = 4;
+pub const NS_DEFAULT = 0;
+pub const NS_VNS = 50;
+pub const NSTYPE_HIERARCHICAL = 1;
+pub const NSTYPE_DYNAMIC = 2;
+pub const NSTYPE_ENUMERABLE = 4;
+pub const NSTYPE_WORKGROUP = 8;
+pub const XP_CONNECTIONLESS = 1;
+pub const XP_GUARANTEED_DELIVERY = 2;
+pub const XP_GUARANTEED_ORDER = 4;
+pub const XP_MESSAGE_ORIENTED = 8;
+pub const XP_PSEUDO_STREAM = 16;
+pub const XP_GRACEFUL_CLOSE = 32;
+pub const XP_EXPEDITED_DATA = 64;
+pub const XP_CONNECT_DATA = 128;
+pub const XP_DISCONNECT_DATA = 256;
+pub const XP_SUPPORTS_BROADCAST = 512;
+pub const XP_SUPPORTS_MULTICAST = 1024;
+pub const XP_BANDWIDTH_ALLOCATION = 2048;
+pub const XP_FRAGMENTATION = 4096;
+pub const XP_ENCRYPTS = 8192;
+pub const RES_SOFT_SEARCH = 1;
+pub const RES_FIND_MULTIPLE = 2;
+pub const SET_SERVICE_PARTIAL_SUCCESS = 1;
+pub const UDP_NOCHECKSUM = 1;
+pub const UDP_CHECKSUM_COVERAGE = 20;
+pub const GAI_STRERROR_BUFFER_SIZE = 1024;
+
+pub const LPCONDITIONPROC = fn (
+ lpCallerId: *WSABUF,
+ lpCallerData: *WSABUF,
+ lpSQOS: *QOS,
+ lpGQOS: *QOS,
+ lpCalleeId: *WSABUF,
+ lpCalleeData: *WSABUF,
+ g: *u32,
+ dwCallbackData: usize,
+) callconv(WINAPI) i32;
+
+pub const LPWSAOVERLAPPED_COMPLETION_ROUTINE = fn (
+ dwError: u32,
+ cbTransferred: u32,
+ lpOverlapped: *OVERLAPPED,
+ dwFlags: u32,
+) callconv(WINAPI) void;
+
+pub const FLOWSPEC = extern struct {
+ TokenRate: u32,
+ TokenBucketSize: u32,
+ PeakBandwidth: u32,
+ Latency: u32,
+ DelayVariation: u32,
+ ServiceType: u32,
+ MaxSduSize: u32,
+ MinimumPolicedSize: u32,
+};
+
+pub const QOS = extern struct {
+ SendingFlowspec: FLOWSPEC,
+ ReceivingFlowspec: FLOWSPEC,
+ ProviderSpecific: WSABUF,
+};
+
+pub const SOCKET_ADDRESS = extern struct {
+ lpSockaddr: *sockaddr,
+ iSockaddrLength: i32,
+};
+
+pub const SOCKET_ADDRESS_LIST = extern struct {
+ iAddressCount: i32,
+ Address: [1]SOCKET_ADDRESS,
+};
pub const WSADATA = if (@sizeOf(usize) == @sizeOf(u64))
extern struct {
@@ -33,15 +952,11 @@ else
lpVendorInfo: *u8,
};
-pub const MAX_PROTOCOL_CHAIN = 7;
-
pub const WSAPROTOCOLCHAIN = extern struct {
ChainLen: c_int,
ChainEntries: [MAX_PROTOCOL_CHAIN]DWORD,
};
-pub const WSAPROTOCOL_LEN = 255;
-
pub const WSAPROTOCOL_INFOA = extern struct {
dwServiceFlags1: DWORD,
dwServiceFlags2: DWORD,
@@ -88,20 +1003,20 @@ pub const WSAPROTOCOL_INFOW = extern struct {
szProtocol: [WSAPROTOCOL_LEN + 1]WCHAR,
};
-pub const GROUP = u32;
-
-pub const SG_UNCONSTRAINED_GROUP = 0x1;
-pub const SG_CONSTRAINED_GROUP = 0x2;
+pub const sockproto = extern struct {
+ sp_family: u16,
+ sp_protocol: u16,
+};
-pub const WSA_FLAG_OVERLAPPED = 0x01;
-pub const WSA_FLAG_MULTIPOINT_C_ROOT = 0x02;
-pub const WSA_FLAG_MULTIPOINT_C_LEAF = 0x04;
-pub const WSA_FLAG_MULTIPOINT_D_ROOT = 0x08;
-pub const WSA_FLAG_MULTIPOINT_D_LEAF = 0x10;
-pub const WSA_FLAG_ACCESS_SYSTEM_SECURITY = 0x40;
-pub const WSA_FLAG_NO_HANDLE_INHERIT = 0x80;
+pub const linger = extern struct {
+ l_onoff: u16,
+ l_linger: u16,
+};
-pub const WSAEVENT = HANDLE;
+pub const WSANETWORKEVENTS = extern struct {
+ lNetworkEvents: i32,
+ iErrorCode: [10]i32,
+};
pub const WSAOVERLAPPED = extern struct {
Internal: DWORD,
@@ -111,82 +1026,9 @@ pub const WSAOVERLAPPED = extern struct {
hEvent: ?WSAEVENT,
};
-pub const WSAOVERLAPPED_COMPLETION_ROUTINE = fn (dwError: DWORD, cbTransferred: DWORD, lpOverlapped: *WSAOVERLAPPED, dwFlags: DWORD) callconv(.C) void;
-
-pub const ADDRESS_FAMILY = u16;
-
-// Microsoft use the signed c_int for this, but it should never be negative
-pub const socklen_t = u32;
+pub const addrinfo = addrinfoa;
-pub const AF_UNSPEC = 0;
-pub const AF_UNIX = 1;
-pub const AF_INET = 2;
-pub const AF_IMPLINK = 3;
-pub const AF_PUP = 4;
-pub const AF_CHAOS = 5;
-pub const AF_NS = 6;
-pub const AF_IPX = AF_NS;
-pub const AF_ISO = 7;
-pub const AF_OSI = AF_ISO;
-pub const AF_ECMA = 8;
-pub const AF_DATAKIT = 9;
-pub const AF_CCITT = 10;
-pub const AF_SNA = 11;
-pub const AF_DECnet = 12;
-pub const AF_DLI = 13;
-pub const AF_LAT = 14;
-pub const AF_HYLINK = 15;
-pub const AF_APPLETALK = 16;
-pub const AF_NETBIOS = 17;
-pub const AF_VOICEVIEW = 18;
-pub const AF_FIREFOX = 19;
-pub const AF_UNKNOWN1 = 20;
-pub const AF_BAN = 21;
-pub const AF_ATM = 22;
-pub const AF_INET6 = 23;
-pub const AF_CLUSTER = 24;
-pub const AF_12844 = 25;
-pub const AF_IRDA = 26;
-pub const AF_NETDES = 28;
-pub const AF_TCNPROCESS = 29;
-pub const AF_TCNMESSAGE = 30;
-pub const AF_ICLFXBM = 31;
-pub const AF_BTH = 32;
-pub const AF_MAX = 33;
-
-pub const SOCK_STREAM = 1;
-pub const SOCK_DGRAM = 2;
-pub const SOCK_RAW = 3;
-pub const SOCK_RDM = 4;
-pub const SOCK_SEQPACKET = 5;
-
-pub const IPPROTO_ICMP = 1;
-pub const IPPROTO_IGMP = 2;
-pub const BTHPROTO_RFCOMM = 3;
-pub const IPPROTO_TCP = 6;
-pub const IPPROTO_UDP = 17;
-pub const IPPROTO_ICMPV6 = 58;
-pub const IPPROTO_RM = 113;
-
-pub const AI_PASSIVE = 0x00001;
-pub const AI_CANONNAME = 0x00002;
-pub const AI_NUMERICHOST = 0x00004;
-pub const AI_NUMERICSERV = 0x00008;
-pub const AI_ADDRCONFIG = 0x00400;
-pub const AI_V4MAPPED = 0x00800;
-pub const AI_NON_AUTHORITATIVE = 0x04000;
-pub const AI_SECURE = 0x08000;
-pub const AI_RETURN_PREFERRED_NAMES = 0x10000;
-pub const AI_DISABLE_IDN_ENCODING = 0x80000;
-
-pub const FIONBIO = -2147195266;
-
-pub const sockaddr = extern struct {
- family: ADDRESS_FAMILY,
- data: [14]u8,
-};
-
-pub const addrinfo = extern struct {
+pub const addrinfoa = extern struct {
flags: i32,
family: i32,
socktype: i32,
@@ -197,6 +1039,32 @@ pub const addrinfo = extern struct {
next: ?*addrinfo,
};
+pub const addrinfoexA = extern struct {
+ ai_flags: i32,
+ ai_family: i32,
+ ai_socktype: i32,
+ ai_protocol: i32,
+ ai_addrlen: usize,
+ ai_canonname: [*:0]u8,
+ ai_addr: *sockaddr,
+ ai_blob: *c_void,
+ ai_bloblen: usize,
+ ai_provider: *GUID,
+ ai_next: *addrinfoexA,
+};
+
+pub const sockaddr = extern struct {
+ family: ADDRESS_FAMILY,
+ data: [14]u8,
+};
+
+pub const sockaddr_storage = extern struct {
+ family: ADDRESS_FAMILY,
+ __pad1: [6]u8,
+ __align: i64,
+ __pad2: [112]u8,
+};
+
/// IPv4 socket address
pub const sockaddr_in = extern struct {
family: ADDRESS_FAMILY = AF_INET,
@@ -225,7 +1093,10 @@ pub const WSABUF = extern struct {
buf: [*]u8,
};
-pub const WSAMSG = extern struct {
+pub const msghdr = WSAMSG;
+pub const msghdr_const = WSAMSG_const;
+
+pub const WSAMSG_const = extern struct {
name: *const sockaddr,
namelen: INT,
lpBuffers: [*]WSABUF,
@@ -234,26 +1105,108 @@ pub const WSAMSG = extern struct {
dwFlags: DWORD,
};
+pub const WSAMSG = extern struct {
+ name: *sockaddr,
+ namelen: INT,
+ lpBuffers: [*]WSABUF,
+ dwBufferCount: DWORD,
+ Control: WSABUF,
+ dwFlags: DWORD,
+};
+
+pub const WSAPOLLFD = pollfd;
+
pub const pollfd = extern struct {
fd: SOCKET,
events: SHORT,
revents: SHORT,
};
-// Event flag definitions for WSAPoll().
+pub const TRANSMIT_FILE_BUFFERS = extern struct {
+ Head: *c_void,
+ HeadLength: u32,
+ Tail: *c_void,
+ TailLength: u32,
+};
+
+pub const LPFN_TRANSMITFILE = fn (
+ hSocket: SOCKET,
+ hFile: HANDLE,
+ nNumberOfBytesToWrite: u32,
+ nNumberOfBytesPerSend: u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpTransmitBuffers: ?*TRANSMIT_FILE_BUFFERS,
+ dwReserved: u32,
+) callconv(WINAPI) BOOL;
+
+pub const LPFN_ACCEPTEX = fn (
+ sListenSocket: SOCKET,
+ sAcceptSocket: SOCKET,
+ lpOutputBuffer: *c_void,
+ dwReceiveDataLength: u32,
+ dwLocalAddressLength: u32,
+ dwRemoteAddressLength: u32,
+ lpdwBytesReceived: *u32,
+ lpOverlapped: *OVERLAPPED,
+) callconv(WINAPI) BOOL;
+
+pub const LPFN_GETACCEPTEXSOCKADDRS = fn (
+ lpOutputBuffer: *c_void,
+ dwReceiveDataLength: u32,
+ dwLocalAddressLength: u32,
+ dwRemoteAddressLength: u32,
+ LocalSockaddr: **sockaddr,
+ LocalSockaddrLength: *i32,
+ RemoteSockaddr: **sockaddr,
+ RemoteSockaddrLength: *i32,
+) callconv(WINAPI) void;
+
+pub const LPFN_WSASENDMSG = fn (
+ s: SOCKET,
+ lpMsg: *const WSAMSG_const,
+ dwFlags: u32,
+ lpNumberOfBytesSent: ?*u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
-pub const POLLRDNORM = 0x0100;
-pub const POLLRDBAND = 0x0200;
-pub const POLLIN = (POLLRDNORM | POLLRDBAND);
-pub const POLLPRI = 0x0400;
+pub const LPFN_WSARECVMSG = fn (
+ s: SOCKET,
+ lpMsg: *WSAMSG,
+ lpdwNumberOfBytesRecv: ?*u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
-pub const POLLWRNORM = 0x0010;
-pub const POLLOUT = (POLLWRNORM);
-pub const POLLWRBAND = 0x0020;
+pub const LPSERVICE_CALLBACK_PROC = fn (
+ lParam: LPARAM,
+ hAsyncTaskHandle: HANDLE,
+) callconv(WINAPI) void;
-pub const POLLERR = 0x0001;
-pub const POLLHUP = 0x0002;
-pub const POLLNVAL = 0x0004;
+pub const SERVICE_ASYNC_INFO = extern struct {
+ lpServiceCallbackProc: LPSERVICE_CALLBACK_PROC,
+ lParam: LPARAM,
+ hAsyncTaskHandle: HANDLE,
+};
+
+pub const LPLOOKUPSERVICE_COMPLETION_ROUTINE = fn (
+ dwError: u32,
+ dwBytes: u32,
+ lpOverlapped: *OVERLAPPED,
+) callconv(WINAPI) void;
+
+pub const fd_set = extern struct {
+ fd_count: u32,
+ fd_array: [64]SOCKET,
+};
+
+pub const hostent = extern struct {
+ h_name: [*]u8,
+ h_aliases: **i8,
+ h_addrtype: i16,
+ h_length: i16,
+ h_addr_list: **i8,
+};
// https://docs.microsoft.com/en-au/windows/win32/winsock/windows-sockets-error-codes-2
pub const WinsockError = extern enum(u16) {
@@ -704,180 +1657,649 @@ pub const WinsockError = extern enum(u16) {
_,
};
-/// no parameters
-const IOC_VOID = 0x80000000;
+pub extern "ws2_32" fn accept(
+ s: SOCKET,
+ addr: ?*sockaddr,
+ addrlen: ?*i32,
+) callconv(WINAPI) SOCKET;
-/// copy out parameters
-const IOC_OUT = 0x40000000;
+pub extern "ws2_32" fn bind(
+ s: SOCKET,
+ name: *const sockaddr,
+ namelen: i32,
+) callconv(WINAPI) i32;
-/// copy in parameters
-const IOC_IN = 0x80000000;
+pub extern "ws2_32" fn closesocket(
+ s: SOCKET,
+) callconv(WINAPI) i32;
-/// The IOCTL is a generic Windows Sockets 2 IOCTL code. New IOCTL codes defined for Windows Sockets 2 will have T == 1.
-const IOC_WS2 = 0x08000000;
+pub extern "ws2_32" fn connect(
+ s: SOCKET,
+ name: *const sockaddr,
+ namelen: i32,
+) callconv(WINAPI) i32;
-pub const SIO_BASE_HANDLE = IOC_OUT | IOC_WS2 | 34;
+pub extern "ws2_32" fn ioctlsocket(
+ s: SOCKET,
+ cmd: i32,
+ argp: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn getpeername(
+ s: SOCKET,
+ name: *sockaddr,
+ namelen: *i32,
+) callconv(WINAPI) i32;
-pub const SOL_SOCKET = 0xffff;
-
-pub const SO_DEBUG = 0x0001;
-pub const SO_ACCEPTCONN = 0x0002;
-pub const SO_REUSEADDR = 0x0004;
-pub const SO_KEEPALIVE = 0x0008;
-pub const SO_DONTROUTE = 0x0010;
-pub const SO_BROADCAST = 0x0020;
-pub const SO_USELOOPBACK = 0x0040;
-pub const SO_LINGER = 0x0080;
-pub const SO_OOBINLINE = 0x0100;
-
-pub const SO_DONTLINGER = ~@as(u32, SO_LINGER);
-pub const SO_EXCLUSIVEADDRUSE = ~@as(u32, SO_REUSEADDR);
-
-pub const SO_SNDBUF = 0x1001;
-pub const SO_RCVBUF = 0x1002;
-pub const SO_SNDLOWAT = 0x1003;
-pub const SO_RCVLOWAT = 0x1004;
-pub const SO_SNDTIMEO = 0x1005;
-pub const SO_RCVTIMEO = 0x1006;
-pub const SO_ERROR = 0x1007;
-pub const SO_TYPE = 0x1008;
-
-pub const SO_GROUP_ID = 0x2001;
-pub const SO_GROUP_PRIORITY = 0x2002;
-pub const SO_MAX_MSG_SIZE = 0x2003;
-pub const SO_PROTOCOL_INFOA = 0x2004;
-pub const SO_PROTOCOL_INFOW = 0x2005;
-
-pub const PVD_CONFIG = 0x3001;
-pub const SO_CONDITIONAL_ACCEPT = 0x3002;
-
-pub const TCP_NODELAY = 0x0001;
+pub extern "ws2_32" fn getsockname(
+ s: SOCKET,
+ name: *sockaddr,
+ namelen: *i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn getsockopt(
+ s: SOCKET,
+ level: i32,
+ optname: i32,
+ optval: [*]u8,
+ optlen: *i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn htonl(
+ hostlong: u32,
+) callconv(WINAPI) u32;
+
+pub extern "ws2_32" fn htons(
+ hostshort: u16,
+) callconv(WINAPI) u16;
+
+pub extern "ws2_32" fn inet_addr(
+ cp: ?[*]const u8,
+) callconv(WINAPI) u32;
+
+pub extern "ws2_32" fn listen(
+ s: SOCKET,
+ backlog: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn ntohl(
+ netlong: u32,
+) callconv(WINAPI) u32;
+
+pub extern "ws2_32" fn ntohs(
+ netshort: u16,
+) callconv(WINAPI) u16;
+
+pub extern "ws2_32" fn recv(
+ s: SOCKET,
+ buf: [*]u8,
+ len: i32,
+ flags: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn recvfrom(
+ s: SOCKET,
+ buf: [*]u8,
+ len: i32,
+ flags: i32,
+ from: ?*sockaddr,
+ fromlen: ?*i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn select(
+ nfds: i32,
+ readfds: ?*fd_set,
+ writefds: ?*fd_set,
+ exceptfds: ?*fd_set,
+ timeout: ?*const timeval,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn send(
+ s: SOCKET,
+ buf: [*]const u8,
+ len: i32,
+ flags: u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn sendto(
+ s: SOCKET,
+ buf: [*]const u8,
+ len: i32,
+ flags: i32,
+ to: *const sockaddr,
+ tolen: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn setsockopt(
+ s: SOCKET,
+ level: i32,
+ optname: i32,
+ optval: ?[*]const u8,
+ optlen: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn shutdown(
+ s: SOCKET,
+ how: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn socket(
+ af: i32,
+ @"type": i32,
+ protocol: i32,
+) callconv(WINAPI) SOCKET;
pub extern "ws2_32" fn WSAStartup(
wVersionRequired: WORD,
lpWSAData: *WSADATA,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn WSACleanup() callconv(WINAPI) c_int;
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSACleanup() callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSASetLastError(iError: i32) callconv(WINAPI) void;
+
pub extern "ws2_32" fn WSAGetLastError() callconv(WINAPI) WinsockError;
-pub extern "ws2_32" fn WSASocketA(
- af: c_int,
- type: c_int,
- protocol: c_int,
- lpProtocolInfo: ?*WSAPROTOCOL_INFOA,
- g: GROUP,
- dwFlags: DWORD,
-) callconv(WINAPI) SOCKET;
-pub extern "ws2_32" fn WSASocketW(
- af: c_int,
- type: c_int,
- protocol: c_int,
- lpProtocolInfo: ?*WSAPROTOCOL_INFOW,
- g: GROUP,
- dwFlags: DWORD,
-) callconv(WINAPI) SOCKET;
-pub extern "ws2_32" fn closesocket(s: SOCKET) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn WSAIoctl(
+
+pub extern "ws2_32" fn WSAIsBlocking() callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSAUnhookBlockingHook() callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSASetBlockingHook(lpBlockFunc: FARPROC) callconv(WINAPI) FARPROC;
+
+pub extern "ws2_32" fn WSACancelBlockingCall() callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAAsyncGetServByName(
+ hWnd: HWND,
+ wMsg: u32,
+ name: [*:0]const u8,
+ proto: ?[*:0]const u8,
+ buf: [*]u8,
+ buflen: i32,
+) callconv(WINAPI) HANDLE;
+
+pub extern "ws2_32" fn WSAAsyncGetServByPort(
+ hWnd: HWND,
+ wMsg: u32,
+ port: i32,
+ proto: ?[*:0]const u8,
+ buf: [*]u8,
+ buflen: i32,
+) callconv(WINAPI) HANDLE;
+
+pub extern "ws2_32" fn WSAAsyncGetProtoByName(
+ hWnd: HWND,
+ wMsg: u32,
+ name: [*:0]const u8,
+ buf: [*]u8,
+ buflen: i32,
+) callconv(WINAPI) HANDLE;
+
+pub extern "ws2_32" fn WSAAsyncGetProtoByNumber(
+ hWnd: HWND,
+ wMsg: u32,
+ number: i32,
+ buf: [*]u8,
+ buflen: i32,
+) callconv(WINAPI) HANDLE;
+
+pub extern "ws2_32" fn WSACancelAsyncRequest(hAsyncTaskHandle: HANDLE) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAAsyncSelect(
s: SOCKET,
- dwIoControlCode: DWORD,
- lpvInBuffer: ?*const c_void,
- cbInBuffer: DWORD,
- lpvOutBuffer: ?LPVOID,
- cbOutBuffer: DWORD,
- lpcbBytesReturned: LPDWORD,
- lpOverlapped: ?*WSAOVERLAPPED,
- lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn accept(
+ hWnd: HWND,
+ wMsg: u32,
+ lEvent: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAAccept(
s: SOCKET,
addr: ?*sockaddr,
- addrlen: ?*c_int,
+ addrlen: ?*i32,
+ lpfnCondition: ?LPCONDITIONPROC,
+ dwCallbackData: usize,
) callconv(WINAPI) SOCKET;
-pub extern "ws2_32" fn bind(
+
+pub extern "ws2_32" fn WSACloseEvent(hEvent: HANDLE) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSAConnect(
s: SOCKET,
- addr: ?*const sockaddr,
- addrlen: c_int,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn connect(
+ name: *const sockaddr,
+ namelen: i32,
+ lpCallerData: ?*WSABUF,
+ lpCalleeData: ?*WSABUF,
+ lpSQOS: ?*QOS,
+ lpGQOS: ?*QOS,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAConnectByNameW(
+ s: SOCKET,
+ nodename: [*:0]const u16,
+ servicename: [*:0]const u16,
+ LocalAddressLength: ?*u32,
+ LocalAddress: ?*sockaddr,
+ RemoteAddressLength: ?*u32,
+ RemoteAddress: ?*sockaddr,
+ timeout: ?*const timeval,
+ Reserved: *OVERLAPPED,
+) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSAConnectByNameA(
+ s: SOCKET,
+ nodename: [*:0]const u8,
+ servicename: [*:0]const u8,
+ LocalAddressLength: ?*u32,
+ LocalAddress: ?*sockaddr,
+ RemoteAddressLength: ?*u32,
+ RemoteAddress: ?*sockaddr,
+ timeout: ?*const timeval,
+ Reserved: *OVERLAPPED,
+) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSAConnectByList(
+ s: SOCKET,
+ SocketAddress: *SOCKET_ADDRESS_LIST,
+ LocalAddressLength: ?*u32,
+ LocalAddress: ?*sockaddr,
+ RemoteAddressLength: ?*u32,
+ RemoteAddress: ?*sockaddr,
+ timeout: ?*const timeval,
+ Reserved: *OVERLAPPED,
+) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSACreateEvent() callconv(WINAPI) HANDLE;
+
+pub extern "ws2_32" fn WSADuplicateSocketA(
+ s: SOCKET,
+ dwProcessId: u32,
+ lpProtocolInfo: *WSAPROTOCOL_INFOA,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSADuplicateSocketW(
+ s: SOCKET,
+ dwProcessId: u32,
+ lpProtocolInfo: *WSAPROTOCOL_INFOW,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAEnumNetworkEvents(
+ s: SOCKET,
+ hEventObject: HANDLE,
+ lpNetworkEvents: *WSANETWORKEVENTS,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAEnumProtocolsA(
+ lpiProtocols: ?*i32,
+ lpProtocolBuffer: ?*WSAPROTOCOL_INFOA,
+ lpdwBufferLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAEnumProtocolsW(
+ lpiProtocols: ?*i32,
+ lpProtocolBuffer: ?*WSAPROTOCOL_INFOW,
+ lpdwBufferLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAEventSelect(
+ s: SOCKET,
+ hEventObject: HANDLE,
+ lNetworkEvents: i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAGetOverlappedResult(
+ s: SOCKET,
+ lpOverlapped: *OVERLAPPED,
+ lpcbTransfer: *u32,
+ fWait: BOOL,
+ lpdwFlags: *u32,
+) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSAGetQOSByName(
+ s: SOCKET,
+ lpQOSName: *WSABUF,
+ lpQOS: *QOS,
+) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSAHtonl(
+ s: SOCKET,
+ hostlong: u32,
+ lpnetlong: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAHtons(
+ s: SOCKET,
+ hostshort: u16,
+ lpnetshort: *u16,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAIoctl(
+ s: SOCKET,
+ dwIoControlCode: u32,
+ lpvInBuffer: ?*const c_void,
+ cbInBuffer: u32,
+ lpvOutbuffer: ?*c_void,
+ cbOutbuffer: u32,
+ lpcbBytesReturned: *u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAJoinLeaf(
s: SOCKET,
name: *const sockaddr,
- namelen: c_int,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn listen(
+ namelen: i32,
+ lpCallerdata: ?*WSABUF,
+ lpCalleeData: ?*WSABUF,
+ lpSQOS: ?*QOS,
+ lpGQOS: ?*QOS,
+ dwFlags: u32,
+) callconv(WINAPI) SOCKET;
+
+pub extern "ws2_32" fn WSANtohl(
+ s: SOCKET,
+ netlong: u32,
+ lphostlong: *u32,
+) callconv(WINAPI) u32;
+
+pub extern "ws2_32" fn WSANtohs(
s: SOCKET,
- backlog: c_int,
-) callconv(WINAPI) c_int;
+ netshort: u16,
+ lphostshort: *u16,
+) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn WSARecv(
s: SOCKET,
- lpBuffers: [*]const WSABUF,
- dwBufferCount: DWORD,
- lpNumberOfBytesRecvd: ?*DWORD,
- lpFlags: *DWORD,
- lpOverlapped: ?*WSAOVERLAPPED,
- lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
-) callconv(WINAPI) c_int;
+ lpBuffers: [*]WSABUF,
+ dwBufferCouynt: u32,
+ lpNumberOfBytesRecv: ?*u32,
+ lpFlags: *u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSARecvDisconnect(
+ s: SOCKET,
+ lpInboundDisconnectData: ?*WSABUF,
+) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn WSARecvFrom(
s: SOCKET,
- lpBuffers: [*]const WSABUF,
- dwBufferCount: DWORD,
- lpNumberOfBytesRecvd: ?*DWORD,
- lpFlags: *DWORD,
+ lpBuffers: [*]WSABUF,
+ dwBuffercount: u32,
+ lpNumberOfBytesRecvd: ?*u32,
+ lpFlags: *u32,
lpFrom: ?*sockaddr,
- lpFromlen: ?*socklen_t,
- lpOverlapped: ?*WSAOVERLAPPED,
- lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
-) callconv(WINAPI) c_int;
+ lpFromlen: ?*i32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAResetEvent(hEvent: HANDLE) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn WSASend(
s: SOCKET,
lpBuffers: [*]WSABUF,
- dwBufferCount: DWORD,
- lpNumberOfBytesSent: ?*DWORD,
- dwFlags: DWORD,
- lpOverlapped: ?*WSAOVERLAPPED,
- lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
-) callconv(WINAPI) c_int;
+ dwBufferCount: u32,
+ lpNumberOfBytesSent: ?*u32,
+ dwFlags: u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSASendMsg(
+ s: SOCKET,
+ lpMsg: *const WSAMSG_const,
+ dwFlags: u32,
+ lpNumberOfBytesSent: ?*u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSARecvMsg(
+ s: SOCKET,
+ lpMsg: *WSAMSG,
+ lpdwNumberOfBytesRecv: ?*u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSASendDisconnect(
+ s: SOCKET,
+ lpOutboundDisconnectData: ?*WSABUF,
+) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn WSASendTo(
s: SOCKET,
lpBuffers: [*]WSABUF,
- dwBufferCount: DWORD,
- lpNumberOfBytesSent: ?*DWORD,
- dwFlags: DWORD,
+ dwBufferCount: u32,
+ lpNumberOfBytesSent: ?*u32,
+ dwFlags: u32,
lpTo: ?*const sockaddr,
- iTolen: c_int,
- lpOverlapped: ?*WSAOVERLAPPED,
- lpCompletionRoutine: ?WSAOVERLAPPED_COMPLETION_ROUTINE,
-) callconv(WINAPI) c_int;
+ iToLen: i32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRounte: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSASetEvent(
+ hEvent: HANDLE,
+) callconv(WINAPI) BOOL;
+
+pub extern "ws2_32" fn WSASocketA(
+ af: i32,
+ @"type": i32,
+ protocol: i32,
+ lpProtocolInfo: ?*WSAPROTOCOL_INFOA,
+ g: u32,
+ dwFlags: u32,
+) callconv(WINAPI) SOCKET;
+
+pub extern "ws2_32" fn WSASocketW(
+ af: i32,
+ @"type": i32,
+ protocol: i32,
+ lpProtocolInfo: ?*WSAPROTOCOL_INFOW,
+ g: u32,
+ dwFlags: u32,
+) callconv(WINAPI) SOCKET;
+
+pub extern "ws2_32" fn WSAWaitForMultipleEvents(
+ cEvents: u32,
+ lphEvents: [*]const HANDLE,
+ fWaitAll: BOOL,
+ dwTimeout: u32,
+ fAlertable: BOOL,
+) callconv(WINAPI) u32;
+
+pub extern "ws2_32" fn WSAAddressToStringA(
+ lpsaAddress: *sockaddr,
+ dwAddressLength: u32,
+ lpProtocolInfo: ?*WSAPROTOCOL_INFOA,
+ lpszAddressString: [*]u8,
+ lpdwAddressStringLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAAddressToStringW(
+ lpsaAddress: *sockaddr,
+ dwAddressLength: u32,
+ lpProtocolInfo: ?*WSAPROTOCOL_INFOW,
+ lpszAddressString: [*]u16,
+ lpdwAddressStringLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAStringToAddressA(
+ AddressString: [*:0]const u8,
+ AddressFamily: i32,
+ lpProtocolInfo: ?*WSAPROTOCOL_INFOA,
+ lpAddress: *sockaddr,
+ lpAddressLength: *i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAStringToAddressW(
+ AddressString: [*:0]const u16,
+ AddressFamily: i32,
+ lpProtocolInfo: ?*WSAPROTOCOL_INFOW,
+ lpAddrses: *sockaddr,
+ lpAddressLength: *i32,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn WSAProviderConfigChange(
+ lpNotificationHandle: *HANDLE,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPWSAOVERLAPPED_COMPLETION_ROUTINE,
+) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn WSAPoll(
- fdArray: [*]pollfd,
- fds: c_ulong,
- timeout: c_int,
-) callconv(WINAPI) c_int;
+ fdArray: [*]WSAPOLLFD,
+ fds: u32,
+ timeout: i32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn WSARecvEx(
+ s: SOCKET,
+ buf: [*]u8,
+ len: i32,
+ flags: *i32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn TransmitFile(
+ hSocket: SOCKET,
+ hFile: HANDLE,
+ nNumberOfBytesToWrite: u32,
+ nNumberOfBytesPerSend: u32,
+ lpOverlapped: ?*OVERLAPPED,
+ lpTransmitBuffers: ?*TRANSMIT_FILE_BUFFERS,
+ dwReserved: u32,
+) callconv(WINAPI) BOOL;
+
+pub extern "mswsock" fn AcceptEx(
+ sListenSocket: SOCKET,
+ sAcceptSocket: SOCKET,
+ lpOutputBuffer: *c_void,
+ dwReceiveDataLength: u32,
+ dwLocalAddressLength: u32,
+ dwRemoteAddressLength: u32,
+ lpdwBytesReceived: *u32,
+ lpOverlapped: *OVERLAPPED,
+) callconv(WINAPI) BOOL;
+
+pub extern "mswsock" fn GetAcceptExSockaddrs(
+ lpOutputBuffer: *c_void,
+ dwReceiveDataLength: u32,
+ dwLocalAddressLength: u32,
+ dwRemoteAddressLength: u32,
+ LocalSockaddr: **sockaddr,
+ LocalSockaddrLength: *i32,
+ RemoteSockaddr: **sockaddr,
+ RemoteSockaddrLength: *i32,
+) callconv(WINAPI) void;
+
+pub extern "ws2_32" fn WSAProviderCompleteAsyncCall(
+ hAsyncCall: HANDLE,
+ iRetCode: i32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn EnumProtocolsA(
+ lpiProtocols: ?*i32,
+ lpProtocolBuffer: *c_void,
+ lpdwBufferLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn EnumProtocolsW(
+ lpiProtocols: ?*i32,
+ lpProtocolBuffer: *c_void,
+ lpdwBufferLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn GetAddressByNameA(
+ dwNameSpace: u32,
+ lpServiceType: *GUID,
+ lpServiceName: ?[*:0]u8,
+ lpiProtocols: ?*i32,
+ dwResolution: u32,
+ lpServiceAsyncInfo: ?*SERVICE_ASYNC_INFO,
+ lpCsaddrBuffer: *c_void,
+ lpAliasBuffer: ?[*:0]const u8,
+ lpdwAliasBufferLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn GetAddressByNameW(
+ dwNameSpace: u32,
+ lpServiceType: *GUID,
+ lpServiceName: ?[*:0]u16,
+ lpiProtocols: ?*i32,
+ dwResolution: u32,
+ lpServiceAsyncInfo: ?*SERVICE_ASYNC_INFO,
+ lpCsaddrBuffer: *c_void,
+ ldwBufferLEngth: *u32,
+ lpAliasBuffer: ?[*:0]u16,
+ lpdwAliasBufferLength: *u32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn GetTypeByNameA(
+ lpServiceName: [*:0]u8,
+ lpServiceType: *GUID,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn GetTypeByNameW(
+ lpServiceName: [*:0]u16,
+ lpServiceType: *GUID,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn GetNameByTypeA(
+ lpServiceType: *GUID,
+ lpServiceName: [*:0]u8,
+ dwNameLength: u32,
+) callconv(WINAPI) i32;
+
+pub extern "mswsock" fn GetNameByTypeW(
+ lpServiceType: *GUID,
+ lpServiceName: [*:0]u16,
+ dwNameLength: u32,
+) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn getaddrinfo(
- pNodeName: [*:0]const u8,
- pServiceName: [*:0]const u8,
- pHints: *const addrinfo,
- ppResult: **addrinfo,
+ pNodeName: ?[*:0]const u8,
+ pServiceName: ?[*:0]const u8,
+ pHints: ?*const addrinfoa,
+ ppResult: **addrinfoa,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn GetAddrInfoExA(
+ pName: ?[*:0]const u8,
+ pServiceName: ?[*:0]const u8,
+ dwNameSapce: u32,
+ lpNspId: ?*GUID,
+ hints: ?*const addrinfoexA,
+ ppResult: **addrinfoexA,
+ timeout: ?*timeval,
+ lpOverlapped: ?*OVERLAPPED,
+ lpCompletionRoutine: ?LPLOOKUPSERVICE_COMPLETION_ROUTINE,
) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn GetAddrInfoExCancel(
+ lpHandle: *HANDLE,
+) callconv(WINAPI) i32;
+
+pub extern "ws2_32" fn GetAddrInfoExOverlappedResult(
+ lpOverlapped: *OVERLAPPED,
+) callconv(WINAPI) i32;
+
pub extern "ws2_32" fn freeaddrinfo(
- pAddrInfo: *addrinfo,
+ pAddrInfo: ?*addrinfoa,
) callconv(WINAPI) void;
-pub extern "ws2_32" fn ioctlsocket(
- s: SOCKET,
- cmd: c_long,
- argp: *c_ulong,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn getsockname(
- s: SOCKET,
- name: *sockaddr,
- namelen: *c_int,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn setsockopt(
- s: SOCKET,
- level: u32,
- optname: u32,
- optval: ?*const c_void,
- optlen: socklen_t,
-) callconv(WINAPI) c_int;
-pub extern "ws2_32" fn shutdown(
- s: SOCKET,
- how: c_int,
-) callconv(WINAPI) c_int;
+
+pub extern "ws2_32" fn FreeAddrInfoEx(
+ pAddrInfoEx: ?*addrinfoexA,
+) callconv(WINAPI) void;
+
+pub extern "ws2_32" fn getnameinfo(
+ pSockaddr: *const sockaddr,
+ SockaddrLength: i32,
+ pNodeBuffer: ?[*]u8,
+ NodeBufferSize: u32,
+ pServiceBuffer: ?[*]u8,
+ ServiceBufferName: u32,
+ Flags: i32,
+) callconv(WINAPI) i32;
+
+pub extern "IPHLPAPI" fn if_nametoindex(
+ InterfaceName: [*:0]const u8,
+) callconv(WINAPI) u32;
diff --git a/lib/std/x.zig b/lib/std/x.zig
index a123591470..022261bf3b 100644
--- a/lib/std/x.zig
+++ b/lib/std/x.zig
@@ -7,7 +7,7 @@
const std = @import("std.zig");
pub const os = struct {
- pub const Socket = @import("x/os/Socket.zig");
+ pub const Socket = @import("x/os/socket.zig").Socket;
pub usingnamespace @import("x/os/net.zig");
};
diff --git a/lib/std/x/net/tcp.zig b/lib/std/x/net/tcp.zig
index 0740e3ab4f..ec20d13388 100644
--- a/lib/std/x/net/tcp.zig
+++ b/lib/std/x/net/tcp.zig
@@ -6,6 +6,7 @@
const std = @import("../../std.zig");
+const io = std.io;
const os = std.os;
const ip = std.x.net.ip;
@@ -58,6 +59,28 @@ pub const Domain = extern enum(u16) {
pub const Client = struct {
socket: Socket,
+ /// Implements `std.io.Reader`.
+ pub const Reader = struct {
+ client: Client,
+ flags: u32,
+
+ /// Implements `readFn` for `std.io.Reader`.
+ pub fn read(self: Client.Reader, buffer: []u8) !usize {
+ return self.client.read(buffer, self.flags);
+ }
+ };
+
+ /// Implements `std.io.Writer`.
+ pub const Writer = struct {
+ client: Client,
+ flags: u32,
+
+ /// Implements `writeFn` for `std.io.Writer`.
+ pub fn write(self: Client.Writer, buffer: []const u8) !usize {
+ return self.client.write(buffer, self.flags);
+ }
+ };
+
/// Opens a new client.
pub fn init(domain: tcp.Domain, flags: u32) !Client {
return Client{
@@ -89,41 +112,46 @@ pub const Client = struct {
return self.socket.connect(address.into());
}
- /// Read data from the socket into the buffer provided. It returns the
- /// number of bytes read into the buffer provided.
- pub fn read(self: Client, buf: []u8) !usize {
- return self.socket.read(buf);
+ /// Extracts the error set of a function.
+ /// TODO: remove after Socket.{read, write} error unions are well-defined across different platforms
+ fn ErrorSetOf(comptime Function: anytype) type {
+ return @typeInfo(@typeInfo(@TypeOf(Function)).Fn.return_type.?).ErrorUnion.error_set;
}
- /// 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 recv(self: Client, buf: []u8, flags: u32) !usize {
- return self.socket.recv(buf, flags);
+ /// Wrap `tcp.Client` into `std.io.Reader`.
+ pub fn reader(self: Client, flags: u32) io.Reader(Client.Reader, ErrorSetOf(Client.Reader.read), Client.Reader.read) {
+ return .{ .context = .{ .client = self, .flags = flags } };
}
- /// Write a buffer of data provided to the socket. It returns the number
- /// of bytes that are written to the socket.
- pub fn write(self: Client, buf: []const u8) !usize {
- return self.socket.write(buf);
+ /// Wrap `tcp.Client` into `std.io.Writer`.
+ pub fn writer(self: Client, flags: u32) io.Writer(Client.Writer, ErrorSetOf(Client.Writer.write), Client.Writer.write) {
+ return .{ .context = .{ .client = self, .flags = flags } };
}
- /// Writes multiple I/O vectors to the socket. It returns the number
- /// of bytes that are written to the socket.
- pub fn writev(self: Client, buffers: []const os.iovec_const) !usize {
- return self.socket.writev(buffers);
+ /// 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: Client, buf: []u8, flags: u32) !usize {
+ return self.socket.read(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 send(self: Client, buf: []const u8, flags: u32) !usize {
- return self.socket.send(buf, flags);
+ pub fn write(self: Client, buf: []const u8, flags: u32) !usize {
+ return self.socket.write(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 sendmsg(self: Client, msg: os.msghdr_const, flags: u32) !usize {
- return self.socket.sendmsg(msg, flags);
+ pub fn writeVectorized(self: Client, msg: os.msghdr_const, flags: u32) !usize {
+ return self.socket.writeVectorized(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: Client, msg: *os.msghdr, flags: u32) !usize {
+ return self.socket.readVectorized(msg, flags);
}
/// Query and return the latest cached error on the client's underlying socket.
@@ -146,12 +174,41 @@ pub const Client = struct {
return ip.Address.from(try self.socket.getLocalAddress());
}
+ /// Query the address that the socket is connected to.
+ pub fn getRemoteAddress(self: Client) !ip.Address {
+ return ip.Address.from(try self.socket.getRemoteAddress());
+ }
+
+ /// Have close() or shutdown() syscalls block until all queued messages in the client 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: Client, timeout_seconds: ?u16) !void {
+ return self.socket.setLinger(timeout_seconds);
+ }
+
+ /// 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: Client, enabled: bool) !void {
+ return self.socket.setKeepAlive(enabled);
+ }
+
/// Disable Nagle's algorithm on a TCP socket. It returns `error.UnsupportedSocketOption` if
/// the host does not support sockets disabling Nagle's algorithm.
pub fn setNoDelay(self: Client, enabled: bool) !void {
if (comptime @hasDecl(os, "TCP_NODELAY")) {
const bytes = mem.asBytes(&@as(usize, @boolToInt(enabled)));
- return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_NODELAY, bytes);
+ return self.socket.setOption(os.IPPROTO_TCP, os.TCP_NODELAY, bytes);
+ }
+ return error.UnsupportedSocketOption;
+ }
+
+ /// Enables TCP Quick ACK on a TCP socket to immediately send rather than delay ACKs when necessary. It returns
+ /// `error.UnsupportedSocketOption` if the host does not support TCP Quick ACK.
+ pub fn setQuickACK(self: Client, enabled: bool) !void {
+ if (comptime @hasDecl(os, "TCP_QUICKACK")) {
+ return self.socket.setOption(os.IPPROTO_TCP, os.TCP_QUICKACK, mem.asBytes(&@as(u32, @boolToInt(enabled))));
}
return error.UnsupportedSocketOption;
}
@@ -169,7 +226,7 @@ pub const Client = struct {
/// 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: Client, milliseconds: usize) !void {
+ pub fn setWriteTimeout(self: Client, milliseconds: u32) !void {
return self.socket.setWriteTimeout(milliseconds);
}
@@ -177,7 +234,7 @@ pub const Client = struct {
/// 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: Client, milliseconds: usize) !void {
+ pub fn setReadTimeout(self: Client, milliseconds: u32) !void {
return self.socket.setReadTimeout(milliseconds);
}
};
@@ -251,16 +308,7 @@ pub const Listener = struct {
/// support TCP Fast Open.
pub fn setFastOpen(self: Listener, enabled: bool) !void {
if (comptime @hasDecl(os, "TCP_FASTOPEN")) {
- return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_FASTOPEN, mem.asBytes(&@as(usize, @boolToInt(enabled))));
- }
- return error.UnsupportedSocketOption;
- }
-
- /// Enables TCP Quick ACK on a TCP socket to immediately send rather than delay ACKs when necessary. It returns
- /// `error.UnsupportedSocketOption` if the host does not support TCP Quick ACK.
- pub fn setQuickACK(self: Listener, enabled: bool) !void {
- if (comptime @hasDecl(os, "TCP_QUICKACK")) {
- return os.setsockopt(self.socket.fd, os.IPPROTO_TCP, os.TCP_QUICKACK, mem.asBytes(&@as(usize, @boolToInt(enabled))));
+ return self.socket.setOption(os.IPPROTO_TCP, os.TCP_FASTOPEN, mem.asBytes(&@as(u32, @boolToInt(enabled))));
}
return error.UnsupportedSocketOption;
}
@@ -322,7 +370,7 @@ test "tcp/client: set read timeout of 1 millisecond on blocking client" {
defer conn.deinit();
var buf: [1]u8 = undefined;
- try testing.expectError(error.WouldBlock, client.read(&buf));
+ try testing.expectError(error.WouldBlock, client.reader(0).read(&buf));
}
test "tcp/listener: bind to unspecified ipv4 address" {
diff --git a/lib/std/x/os/Socket.zig b/lib/std/x/os/Socket.zig
deleted file mode 100644
index 3656899aea..0000000000
--- a/lib/std/x/os/Socket.zig
+++ /dev/null
@@ -1,295 +0,0 @@
-// SPDX-License-Identifier: MIT
-// Copyright (c) 2015-2021 Zig Contributors
-// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
-// The MIT license requires this copyright notice to be included in all copies
-// and substantial portions of the software.
-
-const std = @import("../../std.zig");
-const net = @import("net.zig");
-
-const os = std.os;
-const fmt = std.fmt;
-const mem = std.mem;
-const time = std.time;
-
-/// A generic socket abstraction.
-const Socket = @This();
-
-/// A socket-address pair.
-pub const Connection = struct {
- socket: Socket,
- address: Socket.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 };
- }
-};
-
-/// 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,
-
- /// 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 IPv6 host and port.
- pub fn initIPv6(host: net.IPv6, port: u16) Socket.Address {
- return .{ .ipv6 = .{ .host = host, .port = port } };
- }
-
- /// 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: 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,
- },
- },
- };
- }
-
- /// 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: 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,
-
-/// 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 = undefined;
- var address_len: u32 = @sizeOf(os.sockaddr);
-
- const socket = Socket{ .fd = try os.accept(self.fd, &address, &address_len, flags) };
- const socket_address = Socket.Address.fromNative(@alignCast(4, &address));
-
- return Socket.Connection.from(socket, socket_address);
-}
-
-/// Read data from the socket into the buffer provided. It returns the
-/// number of bytes read into the buffer provided.
-pub fn read(self: Socket, buf: []u8) !usize {
- return os.read(self.fd, buf);
-}
-
-/// 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 recv(self: Socket, buf: []u8, flags: u32) !usize {
- return os.recv(self.fd, buf, flags);
-}
-
-/// Write a buffer of data provided to the socket. It returns the number
-/// of bytes that are written to the socket.
-pub fn write(self: Socket, buf: []const u8) !usize {
- return os.write(self.fd, buf);
-}
-
-/// Writes multiple I/O vectors to the socket. It returns the number
-/// of bytes that are written to the socket.
-pub fn writev(self: Socket, buffers: []const os.iovec_const) !usize {
- return os.writev(self.fd, buffers);
-}
-
-/// 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 send(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 sendmsg(self: Socket, msg: os.msghdr_const, flags: u32) !usize {
- return os.sendmsg(self.fd, msg, flags);
-}
-
-/// Query the address that the socket is locally bounded to.
-pub fn getLocalAddress(self: Socket) !Socket.Address {
- var address: os.sockaddr = undefined;
- var address_len: u32 = @sizeOf(os.sockaddr);
- try os.getsockname(self.fd, &address, &address_len);
- return Socket.Address.fromNative(@alignCast(4, &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),
- };
-}
-
-/// 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 os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_REUSEADDR, mem.asBytes(&@as(usize, @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 os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_REUSEPORT, mem.asBytes(&@as(usize, @boolToInt(enabled))));
- }
- return error.UnsupportedSocketOption;
-}
-
-/// Set the write buffer size of the socket.
-pub fn setWriteBufferSize(self: Socket, size: u32) !void {
- return os.setsockopt(self.fd, 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 os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVBUF, mem.asBytes(&size));
-}
-
-/// 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 os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_SNDTIMEO, mem.asBytes(&timeout));
-}
-
-/// 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 os.setsockopt(self.fd, os.SOL_SOCKET, os.SO_RCVTIMEO, mem.asBytes(&timeout));
-}
diff --git a/lib/std/x/os/net.zig b/lib/std/x/os/net.zig
index 7cd400cc0a..0d13e6c7e0 100644
--- a/lib/std/x/os/net.zig
+++ b/lib/std/x/os/net.zig
@@ -20,6 +20,14 @@ pub fn resolveScopeID(name: []const u8) !u32 {
if (comptime @hasDecl(os, "IFNAMESIZE")) {
if (name.len >= os.IFNAMESIZE - 1) return error.NameTooLong;
+ if (comptime builtin.os.tag == .windows) {
+ var interface_name: [os.IFNAMESIZE]u8 = undefined;
+ mem.copy(u8, &interface_name, name);
+ interface_name[name.len] = 0;
+
+ return os.windows.ws2_32.if_nametoindex(@ptrCast([*:0]const u8, &interface_name));
+ }
+
const fd = try os.socket(os.AF_UNIX, os.SOCK_DGRAM, 0);
defer os.closeSocket(fd);
@@ -31,6 +39,7 @@ pub fn resolveScopeID(name: []const u8) !u32 {
return @bitCast(u32, f.ifru.ivalue);
}
+
return error.Unsupported;
}
diff --git a/lib/std/x/os/socket.zig b/lib/std/x/os/socket.zig
new file mode 100644
index 0000000000..963a1adca6
--- /dev/null
+++ b/lib/std/x/os/socket.zig
@@ -0,0 +1,123 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+const net = @import("net.zig");
+
+const os = std.os;
+const fmt = std.fmt;
+const mem = std.mem;
+const time = std.time;
+const builtin = std.builtin;
+
+/// A generic, cross-platform socket abstraction.
+pub const Socket = struct {
+ /// A socket-address pair.
+ pub const Connection = struct {
+ socket: Socket,
+ address: Socket.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 };
+ }
+ };
+
+ /// 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,
+
+ /// 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 IPv6 host and port.
+ pub fn initIPv6(host: net.IPv6, port: u16) Socket.Address {
+ return .{ .ipv6 = .{ .host = host, .port = port } };
+ }
+
+ /// 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: 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,
+ },
+ },
+ };
+ }
+
+ /// 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: 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);
+};
diff --git a/lib/std/x/os/socket_posix.zig b/lib/std/x/os/socket_posix.zig
new file mode 100644
index 0000000000..1e54c5c7a2
--- /dev/null
+++ b/lib/std/x/os/socket_posix.zig
@@ -0,0 +1,251 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+
+const os = std.os;
+const mem = std.mem;
+const time = std.time;
+
+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;
+ }
+
+ /// 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));
+ }
+ };
+}
diff --git a/lib/std/x/os/socket_windows.zig b/lib/std/x/os/socket_windows.zig
new file mode 100644
index 0000000000..6dd1f9a6a9
--- /dev/null
+++ b/lib/std/x/os/socket_windows.zig
@@ -0,0 +1,448 @@
+// SPDX-License-Identifier: MIT
+// Copyright (c) 2015-2021 Zig Contributors
+// This file is part of [zig](https://ziglang.org/), which is MIT licensed.
+// The MIT license requires this copyright notice to be included in all copies
+// and substantial portions of the software.
+
+const std = @import("../../std.zig");
+const net = @import("net.zig");
+
+const os = std.os;
+const mem = std.mem;
+
+const windows = std.os.windows;
+const ws2_32 = windows.ws2_32;
+
+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 };
+ }
+
+ /// 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),
+ };
+ }
+ }
+
+ /// 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),
+ };
+ }
+ }
+
+ /// 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),
+ };
+ }
+ }
+
+ /// 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),
+ };
+ }
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ /// 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);
+ }
+
+ /// 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));
+ }
+
+ /// 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));
+ }
+
+ /// 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,
+ 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));
+ }
+ };
+}