2016-05-16 1 views
2

J'utilise CFNetworking d'Apple pour obtenir un flux TLS. J'ai un peu de mal à transférer le code Objective-C vers Swift. Avec les mêmes étapes, cela fonctionne lorsque vous utilisez Objective-C, mais la prise de contact échoue systématiquement lors d'une tentative avec Swift.Différence entre Apple TLS avec Objective-C et Swift

travail 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]; 
} 

non-travail 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() 
} 

Les deux tentent de se connecter au même serveur et même port.

captures d'écran de Wireshark:

travail Obj-C

Working Wireshark screen grab

non-travail Swift

Non working Wireshark screen grab

Je suis assez désemparés quant à ce qui se passe . Je ne sais pas pourquoi la version Obj-C démarre un client Hello avec TLS v1.2, mais Swift essaie avec TLS v1.0, puis abandonne. Aucune idée pourquoi la version Swift prend autant de temps pour envoyer le client Bonjour, un paquet Keepalive est envoyé avant? Toute aide serait grandement appréciée.

+1

Cela ne changera peut-être rien, mais l'ordre dans lequel vous définissez NSStreamSocketSecurityLevelNegotiatedSSL et le délégué est inversé entre vos versions ObjC et Swift. – zneak

+0

Cela n'a pas d'importance. L'établissement de liaison ne commence pas avant le premier appel en lecture ou en écriture à chaque extrémité du flux. – nathansizemore

+0

Qu'en est-il du contexte dans lequel cette méthode 'connect()' est appelée? Est-ce sur le fil principal? –

Répondre

2

Il s'avère qu'il n'y avait pas de différence, j'étais juste un idiot. J'appelais immédiatement outputStream.write() une fois que l'événement NSStreamEvent.OpenCompleted avait été appelé pour les flux d'entrée et de sortie. Ce qui était écrit dans le tampon de la poignée de main SSL, et tout déconner.

Non trouvé avant d'avoir créé un MVP pour Obj-c et Swift, ce qui montre que si vous prenez le temps de créer un MVP valide, vous le comprendrez probablement en l'écrivant. Maintenant, si je ne peux trouver un moyen d'être informé qu'une fois la poignée de main est terminée, ce problème sera toujours évité.