2016-05-16 17 views
2

Ich benutze Apples CFNetworking, um einen TLS-Stream zu erhalten. Ich habe ein paar Probleme mit der Portierung des Objective-C-Codes auf Swift.Unterschied zwischen Apple TLS mit Objective-C und Swift

Mit genau den gleichen Schritten funktioniert es, wenn Sie Objective-C verwenden, aber der Handshake schlägt bei Swift-Versuchen immer fehl.

Arbeits Obj-c

- (void)connect() 
{ 
    CFReadStreamRef readStream; 
    CFWriteStreamRef writeStream; 
    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, 
             (__bridge CFStringRef)hostAddress, 
             port, 
             &readStream, 
             &writeStream); 

    self.inputStream = (__bridge_transfer NSInputStream *)readStream; 
    self.outputStream = (__bridge_transfer NSOutputStream *)writeStream; 

    [self.inputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL 
         forKey:NSStreamSocketSecurityLevelKey]; 
    [self.outputStream setProperty:NSStreamSocketSecurityLevelNegotiatedSSL 
         forKey:NSStreamSocketSecurityLevelKey]; 

    [self.inputStream setDelegate:self]; 
    [self.outputStream setDelegate:self]; 

    [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
           forMode:NSDefaultRunLoopMode]; 

    [self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] 
           forMode:NSDefaultRunLoopMode]; 

    [self.inputStream open]; 
    [self.outputStream open]; 
} 

Nichtarbeits Swift

func connect() { 
    var readStream: Unmanaged<CFReadStream>? 
    var writeStream: Unmanaged<CFWriteStream>? 

    let host = "some_host" 
    let hostAsCFString = host as NSString 
    CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, 
             hostAsCFString, 
             1337, 
             &readStream, 
             &writeStream) 

    inputStream = readStream!.takeRetainedValue() 
    outputStream = writeStream!.takeRetainedValue() 

    inputStream!.delegate = self 
    outputStream!.delegate = self 

    inputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, 
          forKey: NSStreamSocketSecurityLevelKey) 
    outputStream!.setProperty(NSStreamSocketSecurityLevelNegotiatedSSL, 
           forKey: NSStreamSocketSecurityLevelKey) 

    inputStream!.scheduleInRunLoop(.currentRunLoop(), forMode: NSDefaultRunLoopMode) 
    outputStream!.scheduleInRunLoop(.currentRunLoop(), forMode: NSDefaultRunLoopMode) 

    inputStream!.open() 
    outputStream!.open() 
} 

Beide versuchen, auf dem gleichen Server und denselben Port zu verbinden.

Bildschirm Grabs von wireshark:

Arbeiten Obj-C

Working Wireshark screen grab

Nichtarbeits Swift

Non working Wireshark screen grab

ich ziemlich ratlos bin, was los ist, . Ich habe keine Ahnung, warum die Obj-C-Version einen Client Hello mit TLS v1.2 startet, aber Swift versucht mit TLS v1.0, dann gibt er einfach auf. Keine Ahnung, warum die Swift-Version so lange braucht, um den Client zu senden Hallo, wird vorher ein Keepalive-Paket gesendet? Jede Hilfe würde sehr geschätzt werden.

+1

Dies ändert möglicherweise nichts, aber die Reihenfolge, in der Sie NStreamSocketSecurityLevelNegotiatedSSL festlegen, und der Delegat wird zwischen Ihren ObjC- und Swift-Versionen ausgetauscht. – zneak

+0

Das ist egal. Der Handshake beginnt erst beim ersten Lese- oder Schreib-Aufruf an beiden Enden des Streams. – nathansizemore

+0

Was ist mit dem Kontext, in dem diese 'connect()' Methode aufgerufen wird? Ist es auf dem Hauptthread? –

Antwort

2

Es stellte sich heraus, dass es keinen Unterschied gab, ich war nur ein Idiot. Ich rief sofort outputStream.write(), sobald das NSStreamEvent.OpenCompleted Ereignis für beide Eingangs- und Ausgangsströme aufgerufen wurde. Das war in den Puffer des SSL-Handshakes schreiben und alles durcheinander bringen.

Nicht gefunden, bis ich ein MVP für Obj-c und Swift erstellt habe, was nur zeigt, dass wenn Sie sich die Zeit nehmen, ein gültiges MVP zu erstellen, Sie es wahrscheinlich während des Schreibens herausfinden werden. Wenn ich nur einen Weg finde, benachrichtigt zu werden, sobald der Handshake abgeschlossen ist, wird dieses Problem immer vermieden.