emqx / CocoaMQTT

MQTT 5.0 client library for iOS and macOS written in Swift
https://www.emqx.com/en
Other
1.58k stars 413 forks source link

kCFStreamErrorDomainSSL Code=-9805 "(null)" #457

Open edoardop13 opened 2 years ago

edoardop13 commented 2 years ago

Hi, when I'm connecting to AWS IoT with cocoamqtt I receive this error in debug console: "Optional(Error Domain=kCFStreamErrorDomainSSL Code=-9805 "(null)" UserInfo={NSLocalizedRecoverySuggestion=Error code definition can be found in Apple's SecureTransport.h})

Sometimes this error not appear but anyway the client not publish any message to AWS IoT Core, include "will" message.

This is my code, same as example:

extension RotatingPlateViewModel: CocoaMQTTDelegate{
    func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
            completionHandler(true)
            print(completionHandler)
    }
    func mqtt(_ mqtt: CocoaMQTT, didConnectAck ack: CocoaMQTTConnAck) {
        if ack == .accept {
            currentAppState.setAppConnectionState(state: .connected)
        }
    }

    func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics topics: [String]) {
        currentAppState.setAppConnectionState(state: .connectedSubscribed)
    }

    func mqtt(_ mqtt: CocoaMQTT, didPublishMessage message: CocoaMQTTMessage, id: UInt16) {
        print("message: \(message.string!.description), id: \(id)")
    }

    func mqtt(_ mqtt: CocoaMQTT, didPublishAck id: UInt16) {
        print("id: \(id)")
    }

    func mqtt(_ mqtt: CocoaMQTT, didReceiveMessage message: CocoaMQTTMessage, id: UInt16) {
        print("message: \(message.description), id: \(id)")
        print(message.string!)
        currentAppState.setReceivedMessage(text: message.description)
    }

    func mqtt(_ mqtt: CocoaMQTT, didSubscribeTopics success: NSDictionary, failed: [String]) {

    }

    func mqtt(_ mqtt: CocoaMQTT, didUnsubscribeTopics topics: [String]) {
        print("topic: \(topic)")
        currentAppState.setAppConnectionState(state: .connectedUnSubscribed)
        currentAppState.clearData()
    }

    func mqttDidDisconnect(_ mqtt: CocoaMQTT, withError err: Error?) {
        print("\(err.debugDescription)")
        currentAppState.setAppConnectionState(state: .disconnected)
    }

    func mqttDidPing(_ mqtt: CocoaMQTT) {

    }

    func mqttDidReceivePong(_ mqtt: CocoaMQTT) {

    }
}

extension RotatingPlateViewModel{

    private func initAWSIoT(){
        if mqttClient != nil {
            mqttClient = nil
        }

        let clientID = "CaptureSample-" + String(ProcessInfo().processIdentifier)
        mqttClient = CocoaMQTT(clientID: clientID, host: userHost, port: 8883)

        mqttClient?.willMessage = CocoaMQTTMessage(topic: "/will", string: "dieout")
        mqttClient?.keepAlive = 60

        mqttClient?.enableSSL = true
        mqttClient?.allowUntrustCACertificate = true

        let clientCertArray = getClientCertFromP12File(certName: certFile, certPassword: certPsw)
        var sslSettings: [String: NSObject] = [:]
        sslSettings[kCFStreamSSLCertificates as String] = clientCertArray

        mqttClient?.sslSettings = sslSettings

        mqttClient?.delegate = self
    }

    private func connect() {
        if let success = mqttClient?.connect(), success {
            currentAppState.setAppConnectionState(state: .connecting)
            print(success)
        } else {
            currentAppState.setAppConnectionState(state: .disconnected)
        }
    }

    private func subscribe(topic: String) {
        mqttClient?.subscribe(topic, qos: .qos1)
    }

    func publish(with message: String) {

        print("pubblica messaggio")
        mqttClient!.publish(self.topic, withString: message, qos: .qos1)
    }

    private func getClientCertFromP12File(certName: String, certPassword: String) -> CFArray? {
        // get p12 file path

        let resourcePath = Bundle.main.path(forResource: certName, ofType: "p12")

        guard let filePath = resourcePath, let p12Data = NSData(contentsOfFile: filePath) else {
            print("Failed to open the certificate file: \(certName).p12")
            return nil
        }

        // create key dictionary for reading p12 file
        let key = kSecImportExportPassphrase as String
        let options : NSDictionary = [key: certPassword]

        var items : CFArray?
        let securityError = SecPKCS12Import(p12Data, options, &items)

        guard securityError == errSecSuccess else {
            if securityError == errSecAuthFailed {
                print("ERROR: SecPKCS12Import returned errSecAuthFailed. Incorrect password?")
            } else {
                print("Failed to open the certificate file: \(certName).p12")
            }
            return nil
        }

        guard let theArray = items, CFArrayGetCount(theArray) > 0 else {
            return nil
        }

        let dictionary = (theArray as NSArray).object(at: 0)
        guard let identity = (dictionary as AnyObject).value(forKey: kSecImportItemIdentity as String) else {
            return nil
        }
        let certArray = [identity] as CFArray

        return certArray
    }

}
liuhedong01 commented 1 year ago

遇到同样的问题

hirensinh commented 1 year ago

Try using this delegate method hope this will work.

  func mqtt(_ mqtt: CocoaMQTT, didReceive trust: SecTrust, completionHandler: @escaping (Bool) -> Void) {
        completionHandler(false)
    }