2016-05-16 7 views
2

AppleのCFNetworkingを使用してTLSストリームを取得しています。私はObjective-CコードをSwiftに移植するのに少し面倒です。Apple TLSとObjective-CとSwiftの相違点

まったく同じ手順で、Objective-Cを使用すると動作しますが、Swiftで試行してもハンドシェイクが失敗します。

ワーキングの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]; 
} 

非作業スウィフト

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

の両方が同じサーバーと同じポートに接続しようとしています。 wiresharkの

スクリーングラブ:

ワーキングのObj-C

Working Wireshark screen grab

非作業スウィフト

Non working Wireshark screen grab

私は何が起こっているかのようにかなり無知です。私はなぜObj-CバージョンがTLS v1.2でクライアントHelloを起動するのか分かりませんが、SwiftはTLS v1.0で試してみるだけです。 Swiftのバージョンがクライアントを送信するのに時間がかかりすぎる理由が分からないHelloこんにちは、Keepaliveパケットが先に送信されますか?どんな助けでも大歓迎です。

+1

これは何も変わらないかもしれませんが、NSStreamSocketSecurityLevelNegotiatedSSLとデリゲートを設定する順序はObjCとSwiftの間で入れ替えられます。 – zneak

+0

それは問題ではありません。ハンドシェークは、ストリームの両端で最初の読み取りまたは書き込みコールが開始されるまで開始されません。 – nathansizemore

+0

この 'connect()'メソッドが呼び出されるコンテキストはどうですか?メインスレッドにありますか? –

答えて

2

私には違いがなかったことが分かりました。私はちょうど馬鹿でした。 NSStreamEvent.OpenCompletedイベントが入力ストリームと出力ストリームの両方で呼び出されたときは、すぐにoutputStream.write()と呼びました。 SSLハンドシェークのバッファーに書いていたもので、それをすべて乱してしまった。

Obj-cとSwiftの両方のMVPを作成するまでは見つかりませんでした。これは、有効なMVPを作成する時間があれば、それを書いている間にそれを把握することになるでしょう。今、ハンドシェイクが完了した後に通知される方法しか見つけられない場合、この問題は常に回避されます。

関連する問題