Как использовать CFStreamCreatePairWithSocket с помощью CFSocketNativeHandle

Я пытаюсь написать сокет для XMPP, после установления соединения сокет должен восстановить соединение с обновленными настройками TLS. Проблема заключается в том, что методы делегирования Stream.Event.openCompleted вызываются как для outputStream, так и для inputStream, но Stream.Event.hasSpaceAvailable не вызывается после CFStreamCreatePairWithSocket.

код:-

if tls{

var readStream :Unmanaged<CFReadStream>?
var writeStream:Unmanaged<CFWriteStream>?
reset()

print("establish tls ")
tlsEnabled = true


let socketData = CFWriteStreamCopyProperty(self.outputStream as CFWriteStream,
                                           CFStreamPropertyKey.socketNativeHandle) as! CFData


let native = CFSocketNativeHandle(CFDataGetBytePtr(socketData).pointee)




inputStream.close()
outputStream.close()

inputStream.remove(from: RunLoop.current, forMode: .defaultRunLoopMode)
outputStream.remove(from: RunLoop.current, forMode: .defaultRunLoopMode)
inputStream = nil
outputStream = nil




CFStreamCreatePairWithSocket(kCFAllocatorDefault,
                             native,
                             &readStream,
                             &writeStream)




inStream             = readStream!.takeRetainedValue()
outStream            = writeStream!.takeRetainedValue()

inStream.delegate    = self
outStream.delegate   = self

inStream.setProperty(kCFBooleanTrue, forKey: kCFStreamPropertyShouldCloseNativeSocket as Stream.PropertyKey)
outStream.setProperty(kCFBooleanTrue, forKey: kCFStreamPropertyShouldCloseNativeSocket as Stream.PropertyKey)

inStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject,
                     forKey: Stream.PropertyKey.socketSecurityLevelKey)
outStream.setProperty(StreamSocketSecurityLevel.negotiatedSSL as AnyObject,
                      forKey: Stream.PropertyKey.socketSecurityLevelKey)

let settings: [NSObject: NSObject] = [kCFStreamSSLValidatesCertificateChain: NSNumber(value: false),
                                      kCFStreamSSLPeerName: kCFNull]
inStream.setProperty(settings,
                     forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)
outStream.setProperty(settings,
                      forKey: kCFStreamPropertySSLSettings as Stream.PropertyKey)


inStream.schedule(in: RunLoop.current, forMode:.defaultRunLoopMode)
outStream.schedule(in:RunLoop.current, forMode:.defaultRunLoopMode)

inStream.open()
outStream.open()

}


person Neeraj Singh    schedule 10.11.2016    source источник


Ответы (1)


Проблема, похоже, связана с созданием сокета с использованием CFSocket вместо непосредственного создания собственного дескриптора сокета.

Изменение вашего кода для создания сокета напрямую с использованием socket(_:_:_) вместо использования CFSocket и CFSocketNativeHandle приводит к тому, что для меня вызываются методы делегата потока.

/** 
 Create sockaddr_in (IPV4) address for google.com
 Note: If you need to resolve DNS for a hostname, use CFHost
 */
var remoteaddress = sockaddr_in()
inet_pton(PF_INET, 
          "207.47.131.217".cString(using: .utf8),
          &sockaddress.sin_addr)
sockaddress.sin_port = UInt16(443).bigEndian
sockaddress.sin_family = sa_family_t(AF_INET)
// Create native socket handle, if sockhandle < 0, error occurred, (check errno)
let sockhandle = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)
// if connectStatus < 0, error occurred (check errno)
let connectStatus = connect(sockhandle, 
                            &remoteaddress, 
                            socklen_t(MemoryLayout<sockaddr_in>.size))

var readStream :Unmanaged<CFReadStream>?
var writeStream:Unmanaged<CFWriteStream>?
CFStreamCreatePairWithSocket(kCFAllocatorDefault,
                             sockhandle,
                             &readStream, &writeStream)
person Eric Yanush    schedule 01.03.2017