diff --git a/FlyingSocks/Sources/AsyncSocket.swift b/FlyingSocks/Sources/AsyncSocket.swift index de5a35d..f3c4670 100644 --- a/FlyingSocks/Sources/AsyncSocket.swift +++ b/FlyingSocks/Sources/AsyncSocket.swift @@ -189,7 +189,7 @@ public struct AsyncSocket: Sendable { repeat { do { let (peerAddress, bytes, interfaceIndex, localAddress) = try socket.receive(length: length) - return Message(peerAddress: peerAddress, bytes: bytes, interfaceIndex: interfaceIndex, localAddress: localAddress) + return Message(peerAddress: peerAddress, payload: Data(bytes), interfaceIndex: interfaceIndex, localAddress: localAddress) } catch SocketError.blocked { try await pool.suspendSocket(socket, untilReadyFor: .read) } catch { @@ -264,7 +264,7 @@ public struct AsyncSocket: Sendable { public func send(message: Message) async throws { try await send( - message: message.bytes, + message: message.payload, to: AnySocketAddress(message.peerAddress), interfaceIndex: message.interfaceIndex, from: message.localAddress diff --git a/FlyingSocks/Tests/AsyncSocketTests.swift b/FlyingSocks/Tests/AsyncSocketTests.swift index acb18f5..badc818 100644 --- a/FlyingSocks/Tests/AsyncSocketTests.swift +++ b/FlyingSocks/Tests/AsyncSocketTests.swift @@ -209,52 +209,43 @@ struct AsyncSocketTests { } #if !canImport(WinSDK) + #if canImport(Darwin) @Test - func datagramSocketReceivesMessageTupleAPI_WhenAvailable() async throws { - let (s1, s2, addr) = try await AsyncSocket.makeDatagramPair() + func messageSequence_sendsMessage_receivesTuple() async throws { + let (socket, port) = try await AsyncSocket.makeLoopbackDatagram() - async let d2: AsyncSocket.Message = s2.receive(atMost: 100) -#if canImport(Darwin) - try await s1.write("Swift".data(using: .utf8)!) -#else - try await s1.send(message: "Swift".data(using: .utf8)!, to: addr, from: addr) -#endif - let v2 = try await d2 - #expect(String(data: Data(v2.bytes), encoding: .utf8) == "Swift") + async let received: (any SocketAddress, [UInt8]) = socket.receive(atMost: 100) - try s1.close() - try s2.close() - try? Socket.unlink(addr) - } -#endif + let client = try await AsyncSocket.makeLoopbackDatagram().0 + let message = AsyncSocket.Message(peerAddress: .loopback(port: port), payload: "Chips 🍟") + try await client.send(message: message) -#if !canImport(WinSDK) + #expect( + try await received.1 == Array("Chips 🍟".data(using: .utf8)!) + ) + } + #else @Test - func datagramSocketReceivesMessageStructAPI_WhenAvailable() async throws { + func messageSequence_sendsMessage_receivesTuple() async throws { let (s1, s2, addr) = try await AsyncSocket.makeDatagramPair() - let messageToSend = AsyncSocket.Message( - peerAddress: addr, - bytes: Array("Swift".data(using: .utf8)!), - localAddress: addr - ) + defer { + try? s1.close() + try? s2.close() + try? Socket.unlink(addr) + } + async let received: (any SocketAddress, [UInt8]) = s2.receive(atMost: 100) - async let d2: AsyncSocket.Message = s2.receive(atMost: 100) -#if canImport(Darwin) - try await s1.write("Swift".data(using: .utf8)!) -#else - try await s1.send(message: messageToSend) -#endif - let v2 = try await d2 - #expect(String(data: Data(v2.bytes), encoding: .utf8) == "Swift") + let message = AsyncSocket.Message(peerAddress: addr, payload: "Shrimp 🦐") + try await s1.send(message: message) - try s1.close() - try s2.close() - try? Socket.unlink(addr) + #expect( + try await received.1 == Array("Shrimp 🦐".data(using: .utf8)!) + ) } -#endif + #endif @Test - func messageSequence_receives_messages() async throws { + func messageSequence_sendsData_receivesMessage() async throws { let (socket, port) = try await AsyncSocket.makeLoopbackDatagram() var messages = socket.messages @@ -267,6 +258,48 @@ struct AsyncSocketTests { try await received?.payloadString == "Fish 🐡" ) } + + #if canImport(Darwin) + @Test + func messageSequence_sendsMessage_receivesMessage() async throws { + let (socket, port) = try await AsyncSocket.makeLoopbackDatagram() + var messages = socket.messages + + async let received = messages.next() + + let client = try await AsyncSocket.makeLoopbackDatagram().0 + let message = AsyncSocket.Message(peerAddress: .loopback(port: port), payload: "Chips 🍟") + try await client.send(message: message) + + #expect( + try await received?.payloadString == "Chips 🍟" + ) + } + #else + @Test + func messageSequence_sendsMessage_receivesMessage() async throws { + let (s1, s2, addr) = try await AsyncSocket.makeDatagramPair() + defer { + try? s1.close() + try? s2.close() + try? Socket.unlink(addr) + } + var messages = socket.messages + + async let received = s2.next() + + let message = AsyncSocket.Message(peerAddress: addr, payload: "Shrimp 🦐") + try await client.send(message: message) + + async let d2: AsyncSocket.Message = s2.receive(atMost: 100) + try await s1.send(message: messageToSend) + + #expect( + try await received?.payloadString == "Shrimp 🦐" + ) + } + #endif +#endif } extension AsyncSocket { @@ -341,12 +374,19 @@ private extension AsyncSocket.Message { var payloadString: String { get throws { - guard let text = String(bytes: bytes, encoding: .utf8) else { + guard let text = String(data: payload, encoding: .utf8) else { throw SocketError.disconnected } return text } } + + init(peerAddress: some SocketAddress, payload: String) { + self.init( + peerAddress: peerAddress, + payload: payload.data(using: .utf8)! + ) + } } struct DisconnectedPool: AsyncSocketPool {