diff options
| author | Colin Davidson <colrdavidson@gmail.com> | 2023-03-01 07:58:30 -0800 |
|---|---|---|
| committer | Colin Davidson <colrdavidson@gmail.com> | 2023-03-01 07:58:30 -0800 |
| commit | 28f7f572473c4e97ccd6133bb4f5fa6f45505530 (patch) | |
| tree | 0bd159c24c617df409f72b0ec75daa086372e94d /core/sys | |
| parent | 3567c006e6683d989805c078db48a95a901d9e72 (diff) | |
manually start merging core_net
Diffstat (limited to 'core/sys')
| -rw-r--r-- | core/sys/unix/syscalls_linux.odin | 36 | ||||
| -rw-r--r-- | core/sys/windows/dnsapi.odin | 10 | ||||
| -rw-r--r-- | core/sys/windows/ip_helper.odin | 234 | ||||
| -rw-r--r-- | core/sys/windows/types.odin | 369 | ||||
| -rw-r--r-- | core/sys/windows/util.odin | 21 | ||||
| -rw-r--r-- | core/sys/windows/ws2_32.odin | 14 |
6 files changed, 538 insertions, 146 deletions
diff --git a/core/sys/unix/syscalls_linux.odin b/core/sys/unix/syscalls_linux.odin index 91c0accfa..3659d8437 100644 --- a/core/sys/unix/syscalls_linux.odin +++ b/core/sys/unix/syscalls_linux.odin @@ -2008,6 +2008,42 @@ sys_utimensat :: proc "contextless" (dfd: int, path: cstring, times: rawptr, fla return int(intrinsics.syscall(SYS_utimensat, uintptr(dfd), uintptr(rawptr(path)), uintptr(times), uintptr(flags))) } +sys_socket :: proc "contextless" (domain: int, type: int, protocol: int) -> int { + return int(intrinsics.syscall(unix.SYS_socket, uintptr(domain), uintptr(type), uintptr(protocol))) +} + +sys_connect :: proc "contextless" (sd: int, addr: rawptr, len: socklen_t) -> int { + return int(intrinsics.syscall(unix.SYS_connect, uintptr(sd), uintptr(addr), uintptr(len))) +} + +sys_accept :: proc "contextless" (sd: int, addr: rawptr, len: rawptr) -> int { + return int(intrinsics.syscall(unix.SYS_accept4, uintptr(sd), uintptr(addr), uintptr(len), uintptr(0))) +} + +sys_listen :: proc "contextless" (sd: int, backlog: int) -> int { + return int(intrinsics.syscall(unix.SYS_listen, uintptr(sd), uintptr(backlog))) +} + +sys_bind :: proc "contextless" (sd: int, addr: rawptr, len: socklen_t) -> int { + return int(intrinsics.syscall(unix.SYS_bind, uintptr(sd), uintptr(addr), uintptr(len))) +} + +sys_setsockopt :: proc "contextless" (sd: int, level: int, optname: int, optval: rawptr, optlen: socklen_t) -> int { + return int(intrinsics.syscall(unix.SYS_setsockopt, uintptr(sd), uintptr(level), uintptr(optname), uintptr(optval), uintptr(optlen))) +} + +sys_recvfrom :: proc "contextless" (sd: int, buf: rawptr, len: uint, flags: int, addr: rawptr, alen: uintptr) -> i64 { + return i64(intrinsics.syscall(unix.SYS_recvfrom, uintptr(sd), uintptr(buf), uintptr(len), uintptr(flags), uintptr(addr), uintptr(alen))) +} + +sys_sendto :: proc "contextless" (sd: int, buf: rawptr, len: uint, flags: int, addr: rawptr, alen: socklen_t) -> i64 { + return i64(intrinsics.syscall(unix.SYS_sendto, uintptr(sd), uintptr(buf), uintptr(len), uintptr(flags), uintptr(addr), uintptr(alen))) +} + +sys_shutdown :: proc "contextless" (sd: int, how: int) -> int { + return int(intrinsics.syscall(unix.SYS_shutdown, uintptr(sd), uintptr(how))) +} + sys_perf_event_open :: proc "contextless" (event_attr: rawptr, pid: i32, cpu: i32, group_fd: i32, flags: u32) -> int { return int(intrinsics.syscall(SYS_perf_event_open, uintptr(event_attr), uintptr(pid), uintptr(cpu), uintptr(group_fd), uintptr(flags))) } diff --git a/core/sys/windows/dnsapi.odin b/core/sys/windows/dnsapi.odin new file mode 100644 index 000000000..623fa2889 --- /dev/null +++ b/core/sys/windows/dnsapi.odin @@ -0,0 +1,10 @@ +// +build windows +package sys_windows + +foreign import "system:Dnsapi.lib" + +@(default_calling_convention="std") +foreign Dnsapi { + DnsQuery_UTF8 :: proc(name: cstring, type: u16, options: DWORD, extra: PVOID, results: ^^DNS_RECORD, reserved: PVOID) -> DNS_STATUS --- + DnsRecordListFree :: proc(list: ^DNS_RECORD, options: DWORD) --- +} diff --git a/core/sys/windows/ip_helper.odin b/core/sys/windows/ip_helper.odin new file mode 100644 index 000000000..d8f93f533 --- /dev/null +++ b/core/sys/windows/ip_helper.odin @@ -0,0 +1,234 @@ +// +build windows +package sys_windows + +foreign import "system:iphlpapi.lib" + +Address_Family :: enum u32 { + Unspecified = 0, // Return both IPv4 and IPv6 addresses associated with adapters with them enabled. + IPv4 = 2, // Return only IPv4 addresses associated with adapters with it enabled. + IPv6 = 23, // Return only IPv6 addresses associated with adapters with it enabled. +} + +GAA_Flag :: enum u32 { + Skip_Unicast = 0, // Do not return unicast addresses. + Skip_Anycast = 1, // Do not return IPv6 anycast addresses. + Skip_Multicast = 2, // Do not return multicast addresses. + Skip_DNS_Server = 3, // Do not return addresses of DNS servers. + Include_Prefix = 4, // (XP SP1+) Return a list of IP address prefixes on this adapter. When this flag is set, IP address prefixes are returned for both IPv6 and IPv4 addresses. + Skip_Friendly_Name = 5, // Do not return the adapter friendly name. + Include_WINS_info = 6, // (Vista+) Return addresses of Windows Internet Name Service (WINS) servers. + Include_Gateways = 7, // (Vista+) Return the addresses of default gateways. + Include_All_Interfaces = 8, // (Vista+) Return addresses for all NDIS interfaces. + Include_All_Compartments = 9, // (Reserved, Unsupported) Return addresses in all routing compartments. + Include_Tunnel_Binding_Order = 10, // (Vista+) Return the adapter addresses sorted in tunnel binding order. +} +GAA_Flags :: bit_set[GAA_Flag; u32] + +IP_Adapter_Addresses :: struct { + Raw: struct #raw_union { + Alignment: u64, + Anonymous: struct { + Length: u32, + IfIndex: u32, + }, + }, + Next: ^IP_Adapter_Addresses, + AdapterName: cstring, + FirstUnicastAddress: ^IP_ADAPTER_UNICAST_ADDRESS_LH, + FirstAnycastAddress: ^IP_ADAPTER_ANYCAST_ADDRESS_XP, + FirstMulticastAddress: ^IP_ADAPTER_MULTICAST_ADDRESS_XP, + FirstDnsServerAddress: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP, + DnsSuffix: ^u16, + Description: ^u16, + FriendlyName: ^u16, + PhysicalAddress: [8]u8, + PhysicalAddressLength: u32, + Anonymous2: struct #raw_union { + Flags: u32, + Anonymous: struct { + _bitfield: u32, + }, + }, + MTU: u32, + IfType: u32, + OperStatus: IF_OPER_STATUS, + Ipv6IfIndex: u32, + ZoneIndices: [16]u32, + FirstPrefix: rawptr, // ^IP_ADAPTER_PREFIX_XP, + TransmitLinkSpeed: u64, + ReceiveLinkSpeed: u64, + FirstWinsServerAddress: rawptr, // ^IP_ADAPTER_WINS_SERVER_ADDRESS_LH, + FirstGatewayAddress: ^IP_ADAPTER_GATEWAY_ADDRESS_LH, + Ipv4Metric: u32, + Ipv6Metric: u32, + Luid: NET_LUID_LH, + Dhcpv4Server: SOCKET_ADDRESS, + CompartmentId: u32, + NetworkGuid: GUID, + ConnectionType: NET_IF_CONNECTION_TYPE, + TunnelType: TUNNEL_TYPE, + Dhcpv6Server: SOCKET_ADDRESS, + Dhcpv6ClientDuid: [130]u8, + Dhcpv6ClientDuidLength: u32, + Dhcpv6Iaid: u32, + FirstDnsSuffix: rawptr, // ^IP_ADAPTER_DNS_SUFFIX, +} + +IP_ADAPTER_UNICAST_ADDRESS_LH :: struct { + Anonymous: struct #raw_union { + Alignment: u64, + Anonymous: struct { + Length: u32, + Flags: u32, + }, + }, + Next: ^IP_ADAPTER_UNICAST_ADDRESS_LH, + Address: SOCKET_ADDRESS, + PrefixOrigin: NL_PREFIX_ORIGIN, + SuffixOrigin: NL_SUFFIX_ORIGIN, + DadState: NL_DAD_STATE, + ValidLifetime: u32, + PreferredLifetime: u32, + LeaseLifetime: u32, + OnLinkPrefixLength: u8, +} + +IP_ADAPTER_ANYCAST_ADDRESS_XP :: struct { + Anonymous: struct #raw_union { + Alignment: u64, + Anonymous: struct { + Length: u32, + Flags: u32, + }, + }, + Next: ^IP_ADAPTER_ANYCAST_ADDRESS_XP, + Address: SOCKET_ADDRESS, +} + +IP_ADAPTER_MULTICAST_ADDRESS_XP :: struct { + Anonymous: struct #raw_union { + Alignment: u64, + Anonymous: struct { + Length: u32, + Flags: u32, + }, + }, + Next: ^IP_ADAPTER_MULTICAST_ADDRESS_XP, + Address: SOCKET_ADDRESS, +} + +IP_ADAPTER_GATEWAY_ADDRESS_LH :: struct { + Anonymous: struct #raw_union { + Alignment: u64, + Anonymous: struct { + Length: u32, + Reserved: u32, + }, + }, + Next: ^IP_ADAPTER_GATEWAY_ADDRESS_LH, + Address: SOCKET_ADDRESS, +} + +IP_ADAPTER_DNS_SERVER_ADDRESS_XP :: struct { + Anonymous: struct #raw_union { + Alignment: u64, + Anonymous: struct { + Length: u32, + Reserved: u32, + }, + }, + Next: ^IP_ADAPTER_DNS_SERVER_ADDRESS_XP, + Address: SOCKET_ADDRESS, +} + +IF_OPER_STATUS :: enum i32 { + Up = 1, + Down = 2, + Testing = 3, + Unknown = 4, + Dormant = 5, + NotPresent = 6, + LowerLayerDown = 7, +} + +NET_LUID_LH :: struct #raw_union { + Value: u64, + Info: struct { + _bitfield: u64, + }, +} + +SOCKET_ADDRESS :: struct { + lpSockaddr: ^SOCKADDR, + iSockaddrLength: i32, +} + +NET_IF_CONNECTION_TYPE :: enum i32 { + NET_IF_CONNECTION_DEDICATED = 1, + NET_IF_CONNECTION_PASSIVE = 2, + NET_IF_CONNECTION_DEMAND = 3, + NET_IF_CONNECTION_MAXIMUM = 4, +} + +TUNNEL_TYPE :: enum i32 { + TUNNEL_TYPE_NONE = 0, + TUNNEL_TYPE_OTHER = 1, + TUNNEL_TYPE_DIRECT = 2, + TUNNEL_TYPE_6TO4 = 11, + TUNNEL_TYPE_ISATAP = 13, + TUNNEL_TYPE_TEREDO = 14, + TUNNEL_TYPE_IPHTTPS = 15, +} +NL_PREFIX_ORIGIN :: enum i32 { + IpPrefixOriginOther = 0, + IpPrefixOriginManual = 1, + IpPrefixOriginWellKnown = 2, + IpPrefixOriginDhcp = 3, + IpPrefixOriginRouterAdvertisement = 4, + IpPrefixOriginUnchanged = 16, +} + +NL_SUFFIX_ORIGIN :: enum i32 { + NlsoOther = 0, + NlsoManual = 1, + NlsoWellKnown = 2, + NlsoDhcp = 3, + NlsoLinkLayerAddress = 4, + NlsoRandom = 5, + IpSuffixOriginOther = 0, + IpSuffixOriginManual = 1, + IpSuffixOriginWellKnown = 2, + IpSuffixOriginDhcp = 3, + IpSuffixOriginLinkLayerAddress = 4, + IpSuffixOriginRandom = 5, + IpSuffixOriginUnchanged = 16, +} + +NL_DAD_STATE :: enum i32 { + NldsInvalid = 0, + NldsTentative = 1, + NldsDuplicate = 2, + NldsDeprecated = 3, + NldsPreferred = 4, + IpDadStateInvalid = 0, + IpDadStateTentative = 1, + IpDadStateDuplicate = 2, + IpDadStateDeprecated = 3, + IpDadStatePreferred = 4, +} + +@(default_calling_convention = "std") +foreign iphlpapi { + /* + The GetAdaptersAddresses function retrieves the addresses associated with the adapters on the local computer. + See: https://docs.microsoft.com/en-us/windows/win32/api/iphlpapi/nf-iphlpapi-getadaptersaddresses + */ + @(link_name="GetAdaptersAddresses") get_adapters_addresses :: proc( + family: Address_Family, + flags: GAA_Flags, + _reserved: rawptr, + adapter_addresses: [^]IP_Adapter_Addresses, + size: ^u32, + ) -> ULONG --- + +} diff --git a/core/sys/windows/types.odin b/core/sys/windows/types.odin index 1d5bdaf04..cb2c55cd3 100644 --- a/core/sys/windows/types.odin +++ b/core/sys/windows/types.odin @@ -154,10 +154,6 @@ TIMER_QUERY_STATE :: 0x0001 TIMER_MODIFY_STATE :: 0x0002 TIMER_ALL_ACCESS :: STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | TIMER_QUERY_STATE | TIMER_MODIFY_STATE -SOCKET :: distinct uintptr // TODO -socklen_t :: c_int -ADDRESS_FAMILY :: USHORT - TRUE :: BOOL(true) FALSE :: BOOL(false) @@ -1868,30 +1864,6 @@ BI_BITFIELDS :: 3 BI_JPEG :: 4 BI_PNG :: 5 -WSA_FLAG_OVERLAPPED: DWORD : 0x01 -WSA_FLAG_NO_HANDLE_INHERIT: DWORD : 0x80 - -WSADESCRIPTION_LEN :: 256 -WSASYS_STATUS_LEN :: 128 -WSAPROTOCOL_LEN: DWORD : 255 -INVALID_SOCKET :: ~SOCKET(0) - -WSAEACCES: c_int : 10013 -WSAEINVAL: c_int : 10022 -WSAEWOULDBLOCK: c_int : 10035 -WSAEPROTOTYPE: c_int : 10041 -WSAEADDRINUSE: c_int : 10048 -WSAEADDRNOTAVAIL: c_int : 10049 -WSAECONNABORTED: c_int : 10053 -WSAECONNRESET: c_int : 10054 -WSAENOTCONN: c_int : 10057 -WSAESHUTDOWN: c_int : 10058 -WSAETIMEDOUT: c_int : 10060 -WSAECONNREFUSED: c_int : 10061 -WSATRY_AGAIN: c_int : 11002 - -MAX_PROTOCOL_CHAIN: DWORD : 7 - MAXIMUM_REPARSE_DATA_BUFFER_SIZE :: 16 * 1024 FSCTL_GET_REPARSE_POINT: DWORD : 0x900a8 IO_REPARSE_TAG_SYMLINK: DWORD : 0xa000000c @@ -1949,44 +1921,6 @@ CREATE_NEW_PROCESS_GROUP: DWORD : 0x00000200 CREATE_UNICODE_ENVIRONMENT: DWORD : 0x00000400 STARTF_USESTDHANDLES: DWORD : 0x00000100 -AF_INET: c_int : 2 -AF_INET6: c_int : 23 -SD_BOTH: c_int : 2 -SD_RECEIVE: c_int : 0 -SD_SEND: c_int : 1 -SOCK_DGRAM: c_int : 2 -SOCK_STREAM: c_int : 1 -SOL_SOCKET: c_int : 0xffff -SO_RCVTIMEO: c_int : 0x1006 -SO_SNDTIMEO: c_int : 0x1005 -SO_REUSEADDR: c_int : 0x0004 -IPPROTO_IP: c_int : 0 -IPPROTO_TCP: c_int : 6 -IPPROTO_IPV6: c_int : 41 -TCP_NODELAY: c_int : 0x0001 -IP_TTL: c_int : 4 -IPV6_V6ONLY: c_int : 27 -SO_ERROR: c_int : 0x1007 -SO_BROADCAST: c_int : 0x0020 -IP_MULTICAST_LOOP: c_int : 11 -IPV6_MULTICAST_LOOP: c_int : 11 -IP_MULTICAST_TTL: c_int : 10 -IP_ADD_MEMBERSHIP: c_int : 12 -IP_DROP_MEMBERSHIP: c_int : 13 -IPV6_ADD_MEMBERSHIP: c_int : 12 -IPV6_DROP_MEMBERSHIP: c_int : 13 -MSG_PEEK: c_int : 0x2 - -ip_mreq :: struct { - imr_multiaddr: in_addr, - imr_interface: in_addr, -} - -ipv6_mreq :: struct { - ipv6mr_multiaddr: in6_addr, - ipv6mr_interface: c_uint, -} - VOLUME_NAME_DOS: DWORD : 0x0 MOVEFILE_REPLACE_EXISTING: DWORD : 1 @@ -2369,11 +2303,6 @@ STARTUPINFO :: struct { hStdError: HANDLE, } -SOCKADDR :: struct { - sa_family: ADDRESS_FAMILY, - sa_data: [14]CHAR, -} - FILETIME :: struct { dwLowDateTime: DWORD, dwHighDateTime: DWORD, @@ -2406,74 +2335,6 @@ ADDRESS_MODE :: enum c_int { AddrModeFlat, } -SOCKADDR_STORAGE_LH :: struct { - ss_family: ADDRESS_FAMILY, - __ss_pad1: [6]CHAR, - __ss_align: i64, - __ss_pad2: [112]CHAR, -} - -ADDRINFOA :: struct { - ai_flags: c_int, - ai_family: c_int, - ai_socktype: c_int, - ai_protocol: c_int, - ai_addrlen: size_t, - ai_canonname: ^c_char, - ai_addr: ^SOCKADDR, - ai_next: ^ADDRINFOA, -} - -PADDRINFOEXW :: ^ADDRINFOEXW -LPADDRINFOEXW :: ^ADDRINFOEXW -ADDRINFOEXW :: struct { - ai_flags: c_int, - ai_family: c_int, - ai_socktype: c_int, - ai_protocol: c_int, - ai_addrlen: size_t, - ai_canonname: wstring, - ai_addr: ^sockaddr, - ai_blob: rawptr, - ai_bloblen: size_t, - ai_provider: LPGUID, - ai_next: ^ADDRINFOEXW, -} - -LPLOOKUPSERVICE_COMPLETION_ROUTINE :: #type proc "stdcall" ( - dwErrorCode: DWORD, - dwNumberOfBytesTransfered: DWORD, - lpOverlapped: LPOVERLAPPED, -) - -sockaddr :: struct { - sa_family: USHORT, - sa_data: [14]byte, -} - -sockaddr_in :: struct { - sin_family: ADDRESS_FAMILY, - sin_port: USHORT, - sin_addr: in_addr, - sin_zero: [8]CHAR, -} - -sockaddr_in6 :: struct { - sin6_family: ADDRESS_FAMILY, - sin6_port: USHORT, - sin6_flowinfo: c_ulong, - sin6_addr: in6_addr, - sin6_scope_id: c_ulong, -} - -in_addr :: struct { - s_addr: u32, -} - -in6_addr :: struct { - s6_addr: [16]u8, -} - EXCEPTION_DISPOSITION :: enum c_int { ExceptionContinueExecution, ExceptionContinueSearch, @@ -3884,3 +3745,233 @@ COORD :: struct { X: SHORT, Y: SHORT, } + +// +// Networking +// +WSA_FLAG_OVERLAPPED :: 1 +WSA_FLAG_MULTIPOINT_C_ROOT :: 2 +WSA_FLAG_MULTIPOINT_C_LEAF :: 4 +WSA_FLAG_MULTIPOINT_D_ROOT :: 8 +WSA_FLAG_MULTIPOINT_D_LEAF :: 16 +WSA_FLAG_ACCESS_SYSTEM_SECURITY :: 32 +WSA_FLAG_NO_HANDLE_INHERIT :: 128 +WSADESCRIPTION_LEN :: 256 +WSASYS_STATUS_LEN :: 128 +WSAPROTOCOL_LEN :: 255 +INVALID_SOCKET :: ~SOCKET(0) +SOMAXCONN :: 128 // The number of messages that can be queued in memory after being received; use 2-4 for Bluetooth. + // This is for the 'backlog' parameter to listen(). +SOCKET_ERROR :: -1 + +// Networking errors +WSAEINTR :: 10004 // Call interrupted. CancelBlockingCall was called. (This is different on Linux.) +WSAEACCES :: 10013 // If you try to bind a Udp socket to the broadcast address without the socket option set. +WSAEFAULT :: 10014 // A pointer that was passed to a WSA function is invalid, such as a buffer size is smaller than you said it was +WSAEINVAL :: 10022 // Invalid argument supplied +WSAEMFILE :: 10024 // SOCKET handles exhausted +WSAEWOULDBLOCK :: 10035 // No data is ready yet +WSAENOTSOCK :: 10038 // Not a socket. +WSAEINPROGRESS :: 10036 // WS1.1 call is in progress or callback function is still being processed +WSAEALREADY :: 10037 // Already connecting in parallel. +WSAEMSGSIZE :: 10040 // Message was truncated because it exceeded max datagram size. +WSAEPROTOTYPE :: 10041 // Wrong protocol for the provided socket +WSAENOPROTOOPT :: 10042 // TODO +WSAEPROTONOSUPPORT :: 10043 // Protocol not supported +WSAESOCKTNOSUPPORT :: 10044 // Socket type not supported in the given address family +WSAEAFNOSUPPORT :: 10047 // Address family not supported +WSAEOPNOTSUPP :: 10045 // Attempt to accept on non-stream socket, etc. +WSAEADDRINUSE :: 10048 // Endpoint being bound is in use by another socket. +WSAEADDRNOTAVAIL :: 10049 // Not a valid local IP address on this computer. +WSAENETDOWN :: 10050 // Network subsystem failure on the local machine. +WSAENETUNREACH :: 10051 // The local machine is not connected to the network. +WSAENETRESET :: 10052 // Keepalive failure detected, or TTL exceeded when receiving UDP packets. +WSAECONNABORTED :: 10053 // Connection has been aborted by software in the host machine. +WSAECONNRESET :: 10054 // The connection was reset while trying to accept, read or write. +WSAENOBUFS :: 10055 // No buffer space is available. The outgoing queue may be full in which case you should probably try again after a pause. +WSAEISCONN :: 10056 // The socket is already connected. +WSAENOTCONN :: 10057 // The socket is not connected yet, or no address was supplied to sendto. +WSAESHUTDOWN :: 10058 // The socket has been shutdown in the direction required. +WSAETIMEDOUT :: 10060 // The timeout duration was reached before any data was received / before all data was sent. +WSAECONNREFUSED :: 10061 // The remote machine is not listening on that endpoint. +WSAEHOSTDOWN :: 10064 // Destination host was down. +WSAEHOSTUNREACH :: 10065 // The remote machine is not connected to the network. +WSAENOTINITIALISED :: 10093 // Needs WSAStartup call +WSAEINVALIDPROCTABLE :: 10104 // Invalid or incomplete procedure table was returned +WSAEINVALIDPROVIDER :: 10105 // Service provider version is not 2.2 +WSAEPROVIDERFAILEDINIT :: 10106 // Service provider failed to initialize + +// Address families +AF_UNSPEC : c_int : 0 // Unspecified +AF_INET : c_int : 2 // IPv4 +AF_INET6 : c_int : 23 // IPv6 +AF_IRDA : c_int : 26 // Infrared +AF_BTH : c_int : 32 // Bluetooth + +// Socket types +SOCK_STREAM : c_int : 1 // TCP +SOCK_DGRAM : c_int : 2 // UDP +SOCK_RAW : c_int : 3 // Requires options IP_HDRINCL for v4, IPV6_HDRINCL for v6, on the socket +SOCK_RDM : c_int : 4 // Requires "Reliable Multicast Protocol" to be installed - see WSAEnumProtocols +SOCK_SEQPACKET : c_int : 5 // Provides psuedo-stream packet based on DGRAMs. + +// Protocols +IPPROTO_IP : c_int : 0 +IPPROTO_ICMP : c_int : 1 // (AF_UNSPEC, AF_INET, AF_INET6) + SOCK_RAW | not specified +IPPROTO_IGMP : c_int : 2 // (AF_UNSPEC, AF_INET, AF_INET6) + SOCK_RAW | not specified +BTHPROTO_RFCOMM : c_int : 3 // Bluetooth: AF_BTH + SOCK_STREAM +IPPROTO_TCP : c_int : 6 // (AF_INET, AF_INET6) + SOCK_STREAM +IPPROTO_UDP : c_int : 17 // (AF_INET, AF_INET6) + SOCK_DGRAM +IPPROTO_ICMPV6 : c_int : 58 // (AF_UNSPEC, AF_INET, AF_INET6) + SOCK_RAW +IPPROTO_RM : c_int : 113 // AF_INET + SOCK_RDM [requires "Reliable Multicast Protocol" to be installed - see WSAEnumProtocols] + +// Shutdown manners +SD_RECEIVE : c_int : 0 +SD_SEND : c_int : 1 +SD_BOTH : c_int : 2 + +// Socket 'levels' +SOL_SOCKET : c_int : 0xffff // Socket options for any socket. +IPPROTO_IPV6 : c_int : 41 // Socket options for IPV6. + +// Options for any sockets +SO_ACCEPTCONN : c_int : 0x0002 +SO_REUSEADDR : c_int : 0x0004 +SO_KEEPALIVE : c_int : 0x0008 +SO_SNDTIMEO : c_int : 0x1005 +SO_RCVTIMEO : c_int : 0x1006 +SO_EXCLUSIVEADDRUSE : c_int : ~SO_REUSEADDR +SO_CONDITIONAL_ACCEPT : c_int : 0x3002 +SO_DONTLINGER : c_int : ~SO_LINGER +SO_OOBINLINE : c_int : 0x0100 +SO_LINGER : c_int : 0x0080 +SO_RCVBUF : c_int : 0x1002 +SO_SNDBUF : c_int : 0x1001 +SO_ERROR : c_int : 0x1007 +SO_BROADCAST : c_int : 0x0020 + +TCP_NODELAY: c_int : 0x0001 +IP_TTL: c_int : 4 +IPV6_V6ONLY: c_int : 27 +IP_MULTICAST_LOOP: c_int : 11 +IPV6_MULTICAST_LOOP: c_int : 11 +IP_MULTICAST_TTL: c_int : 10 +IP_ADD_MEMBERSHIP: c_int : 12 + +IPV6_ADD_MEMBERSHIP: c_int : 12 +IPV6_DROP_MEMBERSHIP: c_int : 13 + +MAX_PROTOCOL_CHAIN: DWORD : 7 + +// Used with the SO_LINGER socket option to setsockopt(). +LINGER :: struct { + l_onoff: c.ushort, + l_linger: c.ushort, +} +// Send/Receive flags. +MSG_OOB : c_int : 1 // `send`/`recv` should process out-of-band data. +MSG_PEEK : c_int : 2 // `recv` should not remove the data from the buffer. Only valid for non-overlapped operations. + + +SOCKET :: distinct uintptr // TODO +socklen_t :: c_int +ADDRESS_FAMILY :: USHORT + +ip_mreq :: struct { + imr_multiaddr: in_addr, + imr_interface: in_addr, +} + +ipv6_mreq :: struct { + ipv6mr_multiaddr: in6_addr, + ipv6mr_interface: c_uint, +} + +SOCKADDR_STORAGE_LH :: struct { + ss_family: ADDRESS_FAMILY, + __ss_pad1: [6]CHAR, + __ss_align: i64, + __ss_pad2: [112]CHAR, +} + +ADDRINFOA :: struct { + ai_flags: c_int, + ai_family: c_int, + ai_socktype: c_int, + ai_protocol: c_int, + ai_addrlen: size_t, + ai_canonname: ^c_char, + ai_addr: ^SOCKADDR, + ai_next: ^ADDRINFOA, +} + +sockaddr_in :: struct { + sin_family: ADDRESS_FAMILY, + sin_port: u16be, + sin_addr: in_addr, + sin_zero: [8]CHAR, +} +sockaddr_in6 :: struct { + sin6_family: ADDRESS_FAMILY, + sin6_port: u16be, + sin6_flowinfo: c_ulong, + sin6_addr: in6_addr, + sin6_scope_id: c_ulong, +} + +in_addr :: struct { + s_addr: u32, +} + +in6_addr :: struct { + s6_addr: [16]u8, +} + + +DNS_STATUS :: distinct DWORD // zero is success +DNS_INFO_NO_RECORDS :: 9501 +DNS_QUERY_NO_RECURSION :: 0x00000004 + +DNS_RECORD :: struct { + pNext: ^DNS_RECORD, + pName: cstring, + wType: WORD, + wDataLength: USHORT, + Flags: DWORD, + dwTtl: DWORD, + _: DWORD, + Data: struct #raw_union { + CNAME: DNS_PTR_DATAA, + A: u32be, // Ipv4 Address + AAAA: u128be, // Ipv6 Address + TXT: DNS_TXT_DATAA, + NS: DNS_PTR_DATAA, + MX: DNS_MX_DATAA, + SRV: DNS_SRV_DATAA, + }, +} + +DNS_TXT_DATAA :: struct { + dwStringCount: DWORD, + pStringArray: cstring, +} + +DNS_PTR_DATAA :: cstring + +DNS_MX_DATAA :: struct { + pNameExchange: cstring, // the hostname + wPreference: WORD, // lower values preferred + _: WORD, // padding. +} +DNS_SRV_DATAA :: struct { + pNameTarget: cstring, + wPriority: u16, + wWeight: u16, + wPort: u16, + _: WORD, // padding +} + +SOCKADDR :: struct { + sa_family: ADDRESS_FAMILY, + sa_data: [14]CHAR, +} diff --git a/core/sys/windows/util.odin b/core/sys/windows/util.odin index 298588cb6..7f8e51d38 100644 --- a/core/sys/windows/util.odin +++ b/core/sys/windows/util.odin @@ -485,3 +485,24 @@ run_as_user :: proc(username, password, application, commandline: string, pi: ^P return false } } + +ensure_winsock_initialized :: proc() { + @static gate := false + @static initted := false + + if initted { + return + } + + for intrinsics.atomic_compare_exchange_strong(&gate, false, true) { + intrinsics.cpu_relax() + } + defer intrinsics.atomic_store(&gate, false) + + unused_info: WSADATA + version_requested := WORD(2) << 8 | 2 + res := WSAStartup(version_requested, &unused_info) + assert(res == 0, "unable to initialized Winsock2") + + initted = true +} diff --git a/core/sys/windows/ws2_32.odin b/core/sys/windows/ws2_32.odin index 09af86bce..30515d430 100644 --- a/core/sys/windows/ws2_32.odin +++ b/core/sys/windows/ws2_32.odin @@ -54,7 +54,7 @@ foreign ws2_32 { buf: rawptr, len: c_int, flags: c_int, - addr: ^SOCKADDR, + addr: ^SOCKADDR_STORAGE_LH, addrlen: ^c_int, ) -> c_int --- sendto :: proc( @@ -62,11 +62,11 @@ foreign ws2_32 { buf: rawptr, len: c_int, flags: c_int, - addr: ^SOCKADDR, + addr: ^SOCKADDR_STORAGE_LH, addrlen: c_int, ) -> c_int --- shutdown :: proc(socket: SOCKET, how: c_int) -> c_int --- - accept :: proc(socket: SOCKET, address: ^SOCKADDR, address_len: ^c_int) -> SOCKET --- + accept :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: ^c_int) -> SOCKET --- setsockopt :: proc( s: SOCKET, @@ -75,11 +75,11 @@ foreign ws2_32 { optval: rawptr, optlen: c_int, ) -> c_int --- - getsockname :: proc(socket: SOCKET, address: ^SOCKADDR, address_len: ^c_int) -> c_int --- - getpeername :: proc(socket: SOCKET, address: ^SOCKADDR, address_len: ^c_int) -> c_int --- - bind :: proc(socket: SOCKET, address: ^SOCKADDR, address_len: socklen_t) -> c_int --- + getsockname :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: ^c_int) -> c_int --- + getpeername :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: ^c_int) -> c_int --- + bind :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, address_len: socklen_t) -> c_int --- listen :: proc(socket: SOCKET, backlog: c_int) -> c_int --- - connect :: proc(socket: SOCKET, address: ^SOCKADDR, len: c_int) -> c_int --- + connect :: proc(socket: SOCKET, address: ^SOCKADDR_STORAGE_LH, len: c_int) -> c_int --- getaddrinfo :: proc( node: cstring, service: cstring, |