Files
MagnumOpus/Packages/MagnumOpusCore/Sources/IMAPClient/IMAPConnection.swift

58 lines
1.6 KiB
Swift

import NIO
import NIOIMAPCore
@preconcurrency import NIOIMAP
@preconcurrency import NIOSSL
actor IMAPConnection {
private let host: String
private let port: Int
private let group: EventLoopGroup
private var channel: Channel?
private let responseHandler: IMAPResponseHandler
init(host: String, port: Int) {
self.host = host
self.port = port
self.group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
self.responseHandler = IMAPResponseHandler()
}
func connect() async throws {
let sslContext = try NIOSSLContext(configuration: TLSConfiguration.makeClientConfiguration())
let handler = responseHandler
let hostname = host
let bootstrap = ClientBootstrap(group: group)
.channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1)
.channelInitializer { channel in
let sslHandler = try! NIOSSLClientHandler(context: sslContext, serverHostname: hostname)
return channel.pipeline.addHandlers([
sslHandler,
IMAPClientHandler(),
handler,
])
}
channel = try await bootstrap.connect(host: host, port: port).get()
try await handler.waitForGreeting()
}
func sendCommand(_ tag: String, command: CommandStreamPart) async throws -> [Response] {
guard let channel else { throw IMAPError.notConnected }
let handler = responseHandler
return try await withCheckedThrowingContinuation { continuation in
handler.sendCommand(tag: tag, continuation: continuation)
channel.writeAndFlush(IMAPClientHandler.Message.part(command), promise: nil)
}
}
func disconnect() async throws {
try await channel?.close()
channel = nil
}
func shutdown() async throws {
try await group.shutdownGracefully()
}
}