3131
3232#if canImport(WinSDK)
3333import WinSDK. WinSock2
34+ import Foundation
3435
3536let O_NONBLOCK = Int32 ( 1 )
3637let F_SETFL = Int32 ( 1 )
3738let F_GETFL = Int32 ( 1 )
3839var errno : Int32 { WSAGetLastError ( ) }
3940let EWOULDBLOCK = WSAEWOULDBLOCK
40- let EBADF = WSA_INVALID_HANDLE
41+ let EBADF = WSAENOTSOCK
4142let EINPROGRESS = WSAEINPROGRESS
4243let EISCONN = WSAEISCONN
43- public typealias sa_family_t = UInt8
44+ public typealias sa_family_t = ADDRESS_FAMILY
4445
4546public extension Socket {
4647 typealias FileDescriptorType = UInt64
@@ -59,10 +60,9 @@ extension Socket {
5960 static let datagram = Int32 ( SOCK_DGRAM)
6061 static let in_addr_any = WinSDK . in_addr ( )
6162 static let ipproto_ip = Int32 ( IPPROTO_IP)
62- static let ipproto_ipv6 = Int32 ( IPPROTO_IPV6)
63+ static let ipproto_ipv6 = Int32 ( IPPROTO_IPV6 . rawValue )
6364 static let ip_pktinfo = Int32 ( IP_PKTINFO)
6465 static let ipv6_pktinfo = Int32 ( IPV6_PKTINFO)
65- static let ipv6_recvpktinfo = Int32 ( IPV6_RECVPKTINFO)
6666
6767 static func makeAddressINET( port: UInt16 ) -> WinSDK . sockaddr_in {
6868 WinSDK . sockaddr_in (
@@ -107,6 +107,7 @@ extension Socket {
107107 }
108108
109109 static func fcntl( _ fd: FileDescriptorType , _ cmd: Int32 ) -> Int32 {
110+ guard fd != INVALID_SOCKET else { return - 1 }
110111 return 0
111112 }
112113
@@ -123,7 +124,110 @@ extension Socket {
123124 }
124125
125126 static func socketpair( _ domain: Int32 , _ type: Int32 , _ protocol: Int32 ) -> ( FileDescriptorType , FileDescriptorType ) {
126- ( - 1 , - 1 ) // no supported
127+ guard domain == AF_UNIX else { return ( INVALID_SOCKET, INVALID_SOCKET) }
128+ func makeTempUnixPath( ) -> URL {
129+ let tempURL = FileManager . default. temporaryDirectory. appendingPathComponent ( " socketpair_ \( UUID ( ) . uuidString. prefix ( 8 ) ) .sock " , isDirectory: false )
130+ try ? FileManager . default. removeItem ( at: tempURL)
131+ return tempURL
132+ }
133+
134+ if type == SOCK_STREAM {
135+ let tempURL = makeTempUnixPath ( )
136+ defer { try ? FileManager . default. removeItem ( at: tempURL) }
137+
138+ let listener = socket ( domain, type, `protocol`)
139+
140+ guard listener != INVALID_SOCKET else { return ( INVALID_SOCKET, INVALID_SOCKET) }
141+
142+ let addr = makeAddressUnix ( path: tempURL. path)
143+
144+ let bindListenerResult = addr. withSockAddr {
145+ bind ( listener, $0, addr. size)
146+ }
147+
148+ guard bindListenerResult == 0 else { return ( INVALID_SOCKET, INVALID_SOCKET) }
149+
150+ guard listen ( listener, 1 ) == 0 else {
151+ _ = close ( listener)
152+ return ( INVALID_SOCKET, INVALID_SOCKET)
153+ }
154+
155+ let connector = socket ( domain, type, `protocol`)
156+
157+ guard connector != INVALID_SOCKET else {
158+ _ = close ( listener)
159+ return ( INVALID_SOCKET, INVALID_SOCKET)
160+ }
161+
162+ let connectResult = addr. withSockAddr { connect ( connector, $0, addr. size) == 0 }
163+
164+ guard connectResult else {
165+ _ = close ( listener)
166+ _ = close ( connector)
167+ return ( INVALID_SOCKET, INVALID_SOCKET)
168+ }
169+
170+ let acceptor = accept ( listener, nil , nil )
171+ guard acceptor != INVALID_SOCKET else {
172+ _ = close ( listener)
173+ _ = close ( connector)
174+ return ( INVALID_SOCKET, INVALID_SOCKET)
175+ }
176+
177+ _ = close ( listener)
178+
179+ return ( connector, acceptor)
180+ } else if type == SOCK_DGRAM {
181+ return ( INVALID_SOCKET, INVALID_SOCKET)
182+ // unsupported at this time: https://github.com/microsoft/WSL/issues/5272
183+ // let tempURL1 = makeTempUnixPath()
184+ // let tempURL2 = makeTempUnixPath()
185+ // guard FileManager.default.createFile(atPath: tempURL1.path, contents: nil) else { return (INVALID_SOCKET, INVALID_SOCKET) }
186+ // guard FileManager.default.createFile(atPath: tempURL2.path, contents: nil) else { return (INVALID_SOCKET, INVALID_SOCKET) }
187+
188+ // defer { try? FileManager.default.removeItem(at: tempURL1) }
189+ // defer { try? FileManager.default.removeItem(at: tempURL2) }
190+
191+ // let socket1 = socket(domain, type, `protocol`)
192+ // let socket2 = socket(domain, type, `protocol`)
193+
194+ // guard socket1 != INVALID_SOCKET, socket2 != INVALID_SOCKET else {
195+ // if socket1 != INVALID_SOCKET { _ = close(socket1) }
196+ // if socket2 != INVALID_SOCKET { _ = close(socket2) }
197+ // return (INVALID_SOCKET, INVALID_SOCKET)
198+ // }
199+
200+ // let addr1 = makeAddressUnix(path: tempURL1.path)
201+ // let addr2 = makeAddressUnix(path: tempURL2.path)
202+
203+ // guard addr1.withSockAddr({ bind(socket1, $0, addr1.size) }) == 0 else {
204+ // _ = close(socket1)
205+ // _ = close(socket2)
206+ // return (INVALID_SOCKET, INVALID_SOCKET)
207+ // }
208+
209+ // guard addr2.withSockAddr({ bind(socket2, $0, addr2.size) }) == 0 else {
210+ // _ = close(socket1)
211+ // _ = close(socket2)
212+ // return (INVALID_SOCKET, INVALID_SOCKET)
213+ // }
214+
215+ // guard addr2.withSockAddr({ connect(socket1, $0, addr2.size) }) == 0 else {
216+ // _ = close(socket1)
217+ // _ = close(socket2)
218+ // return (INVALID_SOCKET, INVALID_SOCKET)
219+ // }
220+
221+ // guard addr1.withSockAddr({ connect(socket2, $0, addr1.size) }) == 0 else {
222+ // _ = close(socket1)
223+ // _ = close(socket2)
224+ // return (INVALID_SOCKET, INVALID_SOCKET)
225+ // }
226+
227+ // return (socket1, socket2)
228+ } else {
229+ return ( INVALID_SOCKET, INVALID_SOCKET)
230+ }
127231 }
128232
129233 static func setsockopt( _ fd: FileDescriptorType , _ level: Int32 , _ name: Int32 ,
@@ -196,19 +300,29 @@ extension Socket {
196300 }
197301
198302 static func recvfrom( _ fd: FileDescriptorType , _ buffer: UnsafeMutableRawPointer ! , _ nbyte: Int , _ flags: Int32 , _ addr: UnsafeMutablePointer < sockaddr > ! , _ len: UnsafeMutablePointer < socklen_t > ! ) -> Int {
199- WinSDK . recvfrom ( fd, buffer, nbyte, flags, addr, len)
303+ Int ( WinSDK . recvfrom ( fd, buffer, Int32 ( nbyte) , flags, addr, len) )
200304 }
201305
202306 static func sendto( _ fd: FileDescriptorType , _ buffer: UnsafeRawPointer ! , _ nbyte: Int , _ flags: Int32 , _ destaddr: UnsafePointer < sockaddr > ! , _ destlen: socklen_t ) -> Int {
203- WinSDK . sendto ( fd, buffer, nbyte, flags, destaddr, destlen)
307+ Int ( WinSDK . sendto ( fd, buffer, Int32 ( nbyte) , flags, destaddr, destlen) )
204308 }
309+ }
205310
206- static func recvmsg( _ fd: FileDescriptorType , _ message: UnsafeMutablePointer < msghdr > , _ flags: Int32 ) -> Int {
207- WinSDK . recvmsg ( fd, message, flags)
311+ public extension in_addr {
312+ var s_addr : UInt32 {
313+ get {
314+ S_un . S_addr
315+ } set {
316+ S_un . S_addr = newValue
317+ }
208318 }
319+ }
209320
210- static func sendmsg( _ fd: FileDescriptorType , _ message: UnsafePointer < msghdr > , _ flags: Int32 ) -> Int {
211- WinSDK . sendmsg ( fd, message, flags)
321+ private extension URL {
322+ var fileSystemRepresentation : String {
323+ withUnsafeFileSystemRepresentation {
324+ String ( cString: $0!)
325+ }
212326 }
213327}
214328
0 commit comments