Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port Socket::Addrinfo to win32 #10650

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spec/std/socket/addrinfo_spec.cr
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
require "spec"
require "socket"
require "socket/addrinfo"

describe Socket::Addrinfo do
describe ".resolve" do
Expand Down
2 changes: 1 addition & 1 deletion spec/win32_std_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ require "./std/set_spec.cr"
# require "./std/signal_spec.cr" (failed codegen)
require "./std/slice_spec.cr"
require "./std/socket/address_spec.cr"
# require "./std/socket/addrinfo_spec.cr" (failed codegen)
require "./std/socket/addrinfo_spec.cr"
# require "./std/socket/socket_spec.cr" (failed codegen)
# require "./std/socket/tcp_server_spec.cr" (failed codegen)
# require "./std/socket/tcp_socket_spec.cr" (failed codegen)
Expand Down
1 change: 1 addition & 0 deletions src/lib_c/x86_64-windows-msvc/c/winbase.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ lib LibC
FORMAT_MESSAGE_FROM_HMODULE = 0x00000800_u32
FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000_u32
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000_u32
FORMAT_MESSAGE_MAX_WIDTH_MASK = 0x000000FF_u32

fun FormatMessageW(dwFlags : DWORD, lpSource : Void*, dwMessageId : DWORD, dwLanguageId : DWORD,
lpBuffer : LPWSTR, nSize : DWORD, arguments : Void*) : DWORD
Expand Down
17 changes: 17 additions & 0 deletions src/lib_c/x86_64-windows-msvc/c/winsock2.cr
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,27 @@ lib LibC
AF_IRDA = 26
AF_BTH = 32

SOCK_STREAM = 1
SOCK_DGRAM = 2
SOCK_RAW = 3
SOCK_RDM = 4
SOCK_SEQPACKET = 5

struct InAddr
s_addr : UInt32
end

struct WSAData
wVersion : WORD
wHighVersion : WORD
szDescription : Char[257]
szSystemStatus : Char[129]
iMaxSockets : UInt16
iMaxUdpDg : UInt16
lpVendorInfo : Char*
end

fun htons(hostshort : UShort) : UShort
fun ntohs(netshort : UShort) : UShort
fun WSAStartup(wVersionRequired : WORD, lpWSAData : WSAData*) : Int
end
24 changes: 24 additions & 0 deletions src/lib_c/x86_64-windows-msvc/c/ws2def.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,32 @@ lib LibC
IPPROTO_ICMPV6 = 58
IPPROTO_RAW = 255

AI_PASSIVE = 0x0001
AI_CANONNAME = 0x0002
AI_NUMERICHOST = 0x0004
AI_ALL = 0x0100
AI_ADDRCONFIG = 0x0400
AI_V4MAPPED = 0x0800
AI_NON_AUTHORITATIVE = 0x04000
AI_SECURE = 0x08000
AI_RETURN_PREFERRED_NAMES = 0x010000
AI_FQDN = 0x00020000
AI_FILESERVER = 0x00040000
AI_NUMERICSERV = 0x00000008

struct Sockaddr
sa_family : UInt8
sa_data : Char[14]
end

struct Addrinfo
ai_flags : Int
ai_family : Int
ai_socktype : Int
ai_protocol : Int
ai_addrlen : SizeT
ai_canonname : Char*
ai_addr : Sockaddr*
ai_next : Addrinfo*
end
end
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-windows-msvc/c/ws2tcpip.cr
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@ require "./winsock2"
require "./ws2ipdef"

lib LibC
EAI_AGAIN = WinError::WSATRY_AGAIN
EAI_BADFLAGS = WinError::WSAEINVAL
EAI_FAIL = WinError::WSANO_RECOVERY
EAI_FAMILY = WinError::WSAEAFNOSUPPORT
EAI_MEMORY = WinError::WSA_NOT_ENOUGH_MEMORY
EAI_NOSECURENAME = WinError::WSA_SECURE_HOST_NOT_FOUND
EAI_NONAME = WinError::WSAHOST_NOT_FOUND
EAI_SERVICE = WinError::WSATYPE_NOT_FOUND
EAI_SOCKTYPE = WinError::WSAESOCKTNOSUPPORT
EAI_IPSECPOLICY = WinError::WSA_IPSEC_NAME_POLICY_ERROR

fun freeaddrinfo(pAddrInfo : Addrinfo*) : Void
fun getaddrinfo(pNodeName : Char*, pServiceName : Char*, pHints : Addrinfo*, ppResult : Addrinfo**) : Int
fun inet_ntop(family : Int, pAddr : Void*, pStringBuf : Char*, stringBufSize : SizeT) : Char*
fun inet_pton(family : Int, pszAddrString : Char*, pAddrBuf : Void*) : Int
end
7 changes: 0 additions & 7 deletions src/socket.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,6 @@ class Socket < IO
include IO::Buffered
include IO::Evented

enum Type
STREAM = LibC::SOCK_STREAM
DGRAM = LibC::SOCK_DGRAM
RAW = LibC::SOCK_RAW
SEQPACKET = LibC::SOCK_SEQPACKET
end

# :nodoc:
SOMAXCONN = 128

Expand Down
13 changes: 12 additions & 1 deletion src/socket/addrinfo.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require "uri/punycode"
require "./address"

class Socket
# Domain name resolver.
Expand Down Expand Up @@ -83,12 +84,22 @@ class Socket
getter error_code : Int32

def self.new(error_code, domain)
new error_code, String.new(LibC.gai_strerror(error_code)), domain
new error_code, error_string(error_code), domain
end

def initialize(@error_code, message, domain)
super("Hostname lookup for #{domain} failed: #{message}")
end

def self.error_string(error_code)
{% if flag?(:win32) %}
# gai_strerror is defined as a macro in WS2tcpip.h, we can just use
# WinError for this
return WinError.new(error_code.to_u32).message
{% else %}
String.new(LibC.gai_strerror(error_code))
{% end %}
end
end

private def self.getaddrinfo(domain, service, family, type, protocol, timeout)
Expand Down
22 changes: 22 additions & 0 deletions src/socket/common.cr
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,21 @@
{% end %}

class Socket
{% if flag?(:win32) %}
begin
# Initialize Windows Socket API and expect version 2.2
wsa_version = 0x202
err = LibC.WSAStartup(wsa_version, out wsadata)
unless err.zero?
raise IO::Error.from_winerror("WSAStartup", WinError.new(err.to_u32))
end

if wsadata.wVersion != wsa_version
raise IO::Error.new("Unsuitable version of the Windows Socket API: 0x#{wsadata.wVersion.to_s(16)}")
end
end
{% end %}

enum Protocol
IP = LibC::IPPROTO_IP
TCP = LibC::IPPROTO_TCP
Expand All @@ -30,6 +45,13 @@ class Socket
INET6 = LibC::AF_INET6
end

enum Type
beta-ziliani marked this conversation as resolved.
Show resolved Hide resolved
STREAM = LibC::SOCK_STREAM
DGRAM = LibC::SOCK_DGRAM
RAW = LibC::SOCK_RAW
SEQPACKET = LibC::SOCK_SEQPACKET
end

class Error < IO::Error
private def self.new_from_errno(message, errno, **opts)
case errno
Expand Down