capacitor-sockets/ios/Sources/SocketsPlugin/Socket.swift

112 lines
3.7 KiB
Swift
Raw Permalink Normal View History

2024-10-03 05:22:10 +00:00
import Foundation
import Network
protocol SocketDelegate: AnyObject {
func didChangeState(socket: String, state: SocketState)
func didReceiveMessage(socket: String, message: String)
}
public class Socket: NSObject {
var id: String
var connection: NWConnection?
weak var delegate: SocketDelegate?
2024-10-05 17:05:11 +00:00
var dataBuffer = Data()
2024-10-03 18:42:36 +00:00
public init(id: String) {
2024-10-03 05:22:10 +00:00
self.id = id
}
2024-10-03 18:42:36 +00:00
public func connect(host: String, port: Int, useTLS: Bool, acceptInvalidCertificates: Bool) {
2024-10-03 17:55:00 +00:00
let parameters = NWParameters.tcp
2024-10-03 18:42:36 +00:00
if useTLS {
2024-10-03 17:55:00 +00:00
let tls = NWProtocolTLS.Options()
2024-10-03 18:42:36 +00:00
if (acceptInvalidCertificates) {
2024-10-03 17:55:00 +00:00
sec_protocol_options_set_verify_block(tls.securityProtocolOptions, { (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in
sec_protocol_verify_complete(true)
}, DispatchQueue.global())
}
parameters.defaultProtocolStack.applicationProtocols.insert(tls, at: 0)
}
2024-10-03 18:42:36 +00:00
let connection = NWConnection(host: NWEndpoint.Host(host), port: NWEndpoint.Port(String(port))!, using: parameters)
2024-10-03 05:22:10 +00:00
connection.stateUpdateHandler = self.stateDidChange(to:)
self.receive(on: connection)
2024-10-05 17:05:11 +00:00
connection.start(queue: DispatchQueue(label: "Igloo"))
2024-10-03 05:22:10 +00:00
self.connection = connection
}
public func write(_ message: String) {
if let data = message.data(using: .utf8) {
connection?.send(content: data, completion: .idempotent)
}
}
public func disconnect() {
2024-10-05 17:05:11 +00:00
connection?.cancel()
2024-10-03 05:22:10 +00:00
}
func stateDidChange(to state: NWConnection.State) {
switch state {
case .setup:
print("connection setup")
case .waiting(let error):
print("connection waiting: \(error)")
case .preparing:
self.delegate?.didChangeState(socket: self.id, state: .connecting)
case .ready:
self.delegate?.didChangeState(socket: self.id, state: .connected)
case .failed(let error):
print("connection failed: \(error)")
2024-10-05 17:05:11 +00:00
self.delegate?.didChangeState(socket: self.id, state: .disconnected)
self.disconnect()
2024-10-03 05:22:10 +00:00
case .cancelled:
self.delegate?.didChangeState(socket: self.id, state: .disconnected)
default:
print("other")
}
}
func receive(on connection: NWConnection) {
connection.receive(minimumIncompleteLength: 1, maximumLength: 65536) { (data, contentContext, isComplete, error) in
2024-10-05 17:05:11 +00:00
if let error = error {
print("Receive error: \(error)")
self.delegate?.didChangeState(socket: self.id, state: .disconnected)
return
}
2024-10-03 05:22:10 +00:00
if let data = data, !data.isEmpty {
2024-10-05 17:05:11 +00:00
self.dataBuffer.append(data) // Append the data to the buffer
// Process buffer if enough data is available (protocol-specific logic)
if let message = String(data: self.dataBuffer, encoding: .utf8) {
2024-10-03 05:22:10 +00:00
self.delegate?.didReceiveMessage(socket: self.id, message: message)
2024-10-05 17:05:11 +00:00
self.dataBuffer.removeAll() // Clear buffer after processing
2024-10-03 05:22:10 +00:00
}
}
2024-10-05 17:05:11 +00:00
if connection.state == .ready {
2024-10-03 17:55:00 +00:00
self.receive(on: connection)
}
2024-10-05 17:05:11 +00:00
if isComplete {
print("Connection completed.")
self.delegate?.didChangeState(socket: self.id, state: .disconnected)
}
2024-10-03 05:22:10 +00:00
}
}
2024-10-05 17:05:11 +00:00
2024-10-03 05:22:10 +00:00
}