MultipeerConnectivityで"[ViceroyTrace] [ICE][ERROR] Send BINDING_REQUEST failed"などとエラーが出て接続できない場合の対処

MultipeerConnectivityのエラーにずっと悩まされ続けていたのをとりあえず解決にこぎつけたのでメモ.

概要

猛烈にエラーを吐いて働かないのを,暗号化周りのコードを加えればとにかく動くようになった. 元々不具合が多いフレームワークらしく,普通に使っているだけでもエラーを吐く. どうしてエラーが出るのか,根本の原因までは特定していない. 原因知っている人いたら教えて欲しい.

動作環境

実際に解決に至った動作環境は下の通りであるが,前バーションを利用した環境でも同様のエラーが出ることを確認している.

症状

  • とにかく端末同士が接続できない
  • 端末を発見してからsession(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState)が呼ばれてconnectingになるが,接続に失敗してnot connectedになる
  • 実際に吐いているエラーの文面
[ViceroyTrace] [ICE][ERROR] Send BINDING_REQUEST failed"
Failed to send a DTLS packet with 107 bytes
[GCKSession] Not in connected state, so giving up for participant [0033CD39] on channel [0].
[ERROR] ICEStopConnectivityCheck:2688 ICEStopConnectivityCheck() found no ICE check with call id (3394873)

ただ,解決後も消えなかったものがある.

解決策

  1. MCSessionの初期化時にencryptionPreference.optionalにする
let session = MCSession(peer: self.ownID, securityIdentity: nil, encryptionPreference: .optional)

2.MCSessionDelegateにdidReceiveCertificateを実装する

func session(_ session: MCSession, didReceiveCertificate certificate: [Any]?, fromPeer peerID: MCPeerID, certificateHandler: @escaping (Bool) -> Void) {
     certificateHandler(true)
}

以上2点の変更を施すとconnectedが出て,接続できるようになった.

おまけ

Edit Scheme -> Arguments -> Enviroment Variables でOS_ACTIVITY_MODEをdisableにすると邪魔なエラー類が出力されないようになるので便利.

感想

動いてくれないとかなりまずかったので助かった. 先にも書いたが,MultipeerConnectivity自体がかなり怪しいらしく,調べていると至る所で同じような症状に引っかかっている人を見つけることができた. 今後は,なるべく使わないようにしていきたい.

参考

stackoverflow.com

forums.developer.apple.com