My task is to create a remote control for Android TV for iOS. After unsuccessful attempts to find any SDK that provides such an opportunity, I decided to rewrite androidtv-remote. This library can do everything I need. To create a TLS connection, I decided to use the SocketIO. But my problem is that the TV has an untrusted certificate and the connection cannot happen.
let manager = SocketManager(
socketURL: .init(string: "https://(host):(port)")!,
config: [
.sessionDelegate(self)
]
)
self.socketManager = manager
let socket = manager.defaultSocket
socket.onAny { event in
print(event.event.uppercased())
}
socket.connect()
extension PairingManager: URLSessionDelegate {
func urlSession(
_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?
) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust else {
completionHandler(.performDefaultHandling, nil)
return
}
completionHandler(.useCredential, .init(trust: serverTrust))
}
}
-
Error Domain=NSURLErrorDomain Code=-1200 "An SSL error has occurred and a secure connection to the server cannot be made." UserInfo={NSErrorFailingURLStringKey=https://192.168.0.101:6467/socket.io/?transport=polling&b64=1&EIO=4, NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <324E645E-2EB5-4024-A361-AAC93D7895C2>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <324E645E-2EB5-4024-A361-AAC93D7895C2>.<1> -
Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.0.101” which could put your confidential information at risk." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
"<cert(0x10500e400) s: atvremote/MTCMSD6886EU/bangbae/EU 4K Android TV/1C:30:08:93:4C:CD i: atvremote/MTCMSD6886EU/bangbae/EU 4K Android TV/1C:30:08:93:4C:CD>"
), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://192.168.0.101:6467/socket.io/?transport=polling&b64=1&EIO=4, NSErrorFailingURLStringKey=https://192.168.0.101:6467/socket.io/?transport=polling&b64=1&EIO=4, NSUnderlyingError=0x2827bd110 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x2818ec0a0>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9807, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9807, kCFStreamPropertySSLPeerCertificates=(
"<cert(0x10500e400) s: atvremote/MTCMSD6886EU/bangbae/EU 4K Android TV/1C:30:08:93:4C:CD i: atvremote/MTCMSD6886EU/bangbae/EU 4K Android TV/1C:30:08:93:4C:CD>"
)}}, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <5CC821A4-3477-4201-8CBE-0E2BA018DF02>.<1>"
), _kCFStreamErrorCodeKey=-9807, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <5CC821A4-3477-4201-8CBE-0E2BA018DF02>.<1>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x2818ec0a0>, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “192.168.0.101” which could put your confidential information at risk.} -
Error Domain=NSURLErrorDomain Code=-1005 "The network connection was lost." UserInfo={_kCFStreamErrorCodeKey=-4, NSUnderlyingError=0x2803512c0 {Error Domain=kCFErrorDomainCFNetwork Code=-1005 "(null)" UserInfo={NSErrorPeerAddressKey=<CFData 0x282e15f40 [0x2208eac08]>{length = 16, capacity = 16, bytes = 0x10021943c0a800650000000000000000}, _kCFStreamErrorCodeKey=-4, _kCFStreamErrorDomainKey=4}}, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <49F62856-E6A2-4F2A-9A0F-B4FDA7473E3F>.<1>, _NSURLErrorRelatedURLSessionTaskErrorKey=(
"LocalDataTask <49F62856-E6A2-4F2A-9A0F-B4FDA7473E3F>.<1>"
), NSLocalizedDescription=The network connection was lost., NSErrorFailingURLStringKey=http://192.168.0.101:6467/socket.io/?transport=polling&b64=1&EIO=4, NSErrorFailingURLKey=http://192.168.0.101:6467/socket.io/?transport=polling&b64=1&EIO=4, _kCFStreamErrorDomainKey=4}
But as a result, I get different errors, depending on the configuration.
- The first error I get is with the above code
- The second error I get is if I don’t do the processing in the URLSessionDelegate
- The third error occurs if I establish a connection using the HTTP protocol and not HTTPS
2
Answers
Instead of using URLSessionDelegate to bypass the SSL validation, you can manually trust the certificate on the iOS device. Here’s an example code:
You should use the Network framework is have wrote Samir.
NWConnection
+NWParameters
withNWProtocolTLS.Options