Skip to content

Commit 40068da

Browse files
authored
Merge pull request #148 from gregcotten/fix-windows
Get Windows to actually compile and pass some tests
2 parents f0735e8 + 70fb1ec commit 40068da

7 files changed

+178
-30
lines changed

FlyingSocks/Sources/Mutex.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ extension Mutex {
204204
}
205205

206206
func tryLock() -> Bool {
207-
TryAcquireSRWLockExclusive(_lock)
207+
TryAcquireSRWLockExclusive(_lock) != 0
208208
}
209209
}
210210
}

FlyingSocks/Sources/Socket+WinSock2.swift

+125-11
Original file line numberDiff line numberDiff line change
@@ -31,16 +31,17 @@
3131

3232
#if canImport(WinSDK)
3333
import WinSDK.WinSock2
34+
import Foundation
3435

3536
let O_NONBLOCK = Int32(1)
3637
let F_SETFL = Int32(1)
3738
let F_GETFL = Int32(1)
3839
var errno: Int32 { WSAGetLastError() }
3940
let EWOULDBLOCK = WSAEWOULDBLOCK
40-
let EBADF = WSA_INVALID_HANDLE
41+
let EBADF = WSAENOTSOCK
4142
let EINPROGRESS = WSAEINPROGRESS
4243
let EISCONN = WSAEISCONN
43-
public typealias sa_family_t = UInt8
44+
public typealias sa_family_t = ADDRESS_FAMILY
4445

4546
public 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

FlyingSocks/Sources/Socket.swift

+13-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
//
3131

3232
#if canImport(WinSDK)
33-
import WinSDK.WinSock2
33+
@_exported import WinSDK.WinSock2
3434
#elseif canImport(Android)
3535
@_exported import Android
3636
#endif
@@ -126,8 +126,10 @@ public struct Socket: Sendable, Hashable {
126126
switch domain {
127127
case AF_INET:
128128
try setValue(true, for: .packetInfoIP)
129+
#if !canImport(WinSDK)
129130
case AF_INET6:
130131
try setValue(true, for: .packetInfoIPv6)
132+
#endif
131133
default:
132134
return
133135
}
@@ -566,9 +568,11 @@ public extension SocketOption where Self == BoolSocketOption {
566568
BoolSocketOption(level: Socket.ipproto_ip, name: Socket.ip_pktinfo)
567569
}
568570

571+
#if !canImport(WinSDK)
569572
static var packetInfoIPv6: Self {
570573
BoolSocketOption(level: Socket.ipproto_ipv6, name: Socket.ipv6_recvpktinfo)
571574
}
575+
#endif
572576

573577
#if canImport(Darwin)
574578
// Prevents SIG_TRAP when app is paused / running in background.
@@ -597,9 +601,17 @@ package extension Socket {
597601

598602
static func makePair(flags: Flags? = nil, type: SocketType = .stream) throws -> (Socket, Socket) {
599603
let (file1, file2) = Socket.socketpair(AF_UNIX, type.rawValue, 0)
604+
605+
#if canImport(WinSDK)
606+
guard file1 != INVALID_SOCKET, file2 != INVALID_SOCKET else {
607+
throw SocketError.makeFailed("SocketPair")
608+
}
609+
#else
600610
guard file1 > -1, file2 > -1 else {
601611
throw SocketError.makeFailed("SocketPair")
602612
}
613+
#endif
614+
603615
let s1 = Socket(file: .init(rawValue: file1))
604616
let s2 = Socket(file: .init(rawValue: file2))
605617

FlyingSocks/Tests/FileManager+TemporaryFile.swift

+8-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ extension FileManager {
2020
let dirPath = temporaryDirectory.appendingPathComponent("FlyingSocks.XXXXXX")
2121
return dirPath.withUnsafeFileSystemRepresentation { maybePath in
2222
guard let path = maybePath else { return nil }
23-
var mutablePath = Array(repeating: Int8(0), count: Int(PATH_MAX))
23+
24+
#if canImport(WinSDK)
25+
let pathMax = Int(MAX_PATH)
26+
#else
27+
let pathMax = Int(PATH_MAX)
28+
#endif
29+
30+
var mutablePath = Array(repeating: Int8(0), count: pathMax)
2431
mutablePath.withUnsafeMutableBytes { mutablePathBufferPtr in
2532
mutablePathBufferPtr.baseAddress!.copyMemory(
2633
from: path, byteCount: Int(strlen(path)) + 1)

FlyingSocks/Tests/SocketErrorTests.swift

+5
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,12 @@ struct SocketErrorTests {
5252

5353
@Test
5454
func socketError_makeFailed() {
55+
#if canImport(WinSDK)
56+
WSASetLastError(EIO)
57+
#else
5558
errno = EIO
59+
#endif
60+
5661
let socketError = SocketError.makeFailed("unit-test")
5762
switch socketError {
5863
case let .failed(type: type, errno: socketErrno, message: message):

FlyingSocks/Tests/SocketPool+PollTests.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ private extension Poll {
254254
}
255255

256256
private extension pollfd {
257-
static func make(fd: Int32 = 0,
257+
static func make(fd: Socket.FileDescriptorType = 0,
258258
events: Int32 = POLLIN,
259259
revents: Int32 = POLLIN) -> Self {
260260
.init(fd: fd, events: Int16(events), revents: Int16(revents))

0 commit comments

Comments
 (0)