From e4fc81f11bd4f72383697c76a75d117f47e9a808 Mon Sep 17 00:00:00 2001 From: Navan Chauhan Date: Sat, 27 Jul 2024 23:59:24 -0600 Subject: add async version --- Sources/swiftGopherClient/gopherClient.swift | 50 ++++++++++++++++++++++ .../swiftGopherClientTests.swift | 6 +++ 2 files changed, 56 insertions(+) diff --git a/Sources/swiftGopherClient/gopherClient.swift b/Sources/swiftGopherClient/gopherClient.swift index 802d646..68cca6c 100644 --- a/Sources/swiftGopherClient/gopherClient.swift +++ b/Sources/swiftGopherClient/gopherClient.swift @@ -105,6 +105,56 @@ public class GopherClient { #endif } + + @available(iOS 13.0, *) + @available(macOS 10.15, *) + public func sendRequest(to host: String, port: Int = 70, message: String) async throws -> [gopherItem] { + return try await withCheckedThrowingContinuation { continuation in + let bootstrap = self.createBootstrap(message: message) { result in + continuation.resume(with: result) + } + + bootstrap.connect(host: host, port: port).whenComplete { result in + switch result { + case .success(let channel): + channel.closeFuture.whenComplete { _ in + print("Connection Closed") + } + case .failure(let error): + continuation.resume(throwing: error) + } + } + } + } + + private func createBootstrap( + message: String, + completion: @escaping (Result<[gopherItem], Error>) -> Void + ) -> NIOClientTCPBootstrapProtocol { + let handler = GopherRequestResponseHandler(message: message, completion: completion) + + #if os(Linux) + return ClientBootstrap(group: eventLoopGroup) + .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) + .channelInitializer { channel in + channel.pipeline.addHandler(handler) + } + #else + if #available(macOS 10.14, iOS 12.0, tvOS 12.0, watchOS 6.0, visionOS 1.0, *) { + return NIOTSConnectionBootstrap(group: group) + .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) + .channelInitializer { channel in + channel.pipeline.addHandler(handler) + } + } else { + return ClientBootstrap(group: group) + .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) + .channelInitializer { channel in + channel.pipeline.addHandler(handler) + } + } + #endif + } /// Shuts down the event loop group, releasing any resources. /// diff --git a/Tests/swiftGopherClientTests/swiftGopherClientTests.swift b/Tests/swiftGopherClientTests/swiftGopherClientTests.swift index dfa46b8..47d0f24 100644 --- a/Tests/swiftGopherClientTests/swiftGopherClientTests.swift +++ b/Tests/swiftGopherClientTests/swiftGopherClientTests.swift @@ -35,4 +35,10 @@ final class GopherClientTests: XCTestCase { wait(for: [expectation], timeout: 30) } + + func testGopherClientAsync() async throws { + let client = GopherClient() + let reply = try await client.sendRequest(to: "gopher.navan.dev", message: "\r\n") + XCTAssertNotNil(reply) + } } -- cgit v1.2.3