1

一般的なデータのピア 2 ピア通信を必要とするアプリケーションを構築していますが、webRTC はそれを行うための良い方法のように思えました。ただし、DataChannel との p2p 接続を確立しようとすると、特定のネットワークで ICE Candidate の障害が発生し続けます。しかし、この同じネットワークでは、MediaChannel p2p 接続は正常に機能します。

次のレポ https://github.com/fireship-io/webrtc-firebase-demoの最小限の適応でも、datachannel バリアントは機能しません。

UDP ではなく TCP に関係していると思われますが、tcp 候補を許可しないことは問題を解決しません。

DataChannel が機能しないのに MediaChannel が機能する理由は何ですか? ネットワークは大学の公衆ネットワークです。シグナリング サーバーとして firebase を使用します。Google STUN サーバー。

HTML は、ICECandidates + オファーをシグナリング サーバーにプッシュする callButton で構成され、answerButton によって別のインスタンスから接続するために使用できる ID を生成します。

ほとんどの webRTC 接続を処理する js スニペット。pcは RTCPeerConnection インスタンスです。

function startup() {
  sendChannel = pc.createDataChannel("sendChannel");
  pc.ondatachannel = receiveChannelCallback;
  
  //update HTML depending on open connection
  sendChannel.onopen = handleSendChannelStatusChange; 
  sendChannel.onclose = handleSendChannelStatusChange;
  
  callButton.disabled = false;
  answerButton.disabled = false;
};

// Create an offer
callButton.onclick = async () => {
  // Reference Firestore collections for signaling
  const callDoc = firestore.collection('calls').doc();
  const offerCandidates = callDoc.collection('offerCandidates');
  const answerCandidates = callDoc.collection('answerCandidates');

  callInput.value = callDoc.id;

  // Get candidates for caller, save to Firebase
  pc.onicecandidate = (event) => { 
  // only add ICE that are not tcp
  if (event.candidate && event.candidate.protocol !== 'tcp') {
        offerCandidates.add(event.candidate.toJSON())
      }
  };

  // Create offer
  const offerDescription = await pc.createOffer();
  await pc.setLocalDescription(offerDescription);

  const offer = {
    sdp: offerDescription.sdp,
    type: offerDescription.type,
  };

  await callDoc.set({ offer });

  // Listen for remote answer
  callDoc.onSnapshot((snapshot) => {
    const data = snapshot.data();
    if (!pc.currentRemoteDescription && data?.answer) {
      const answerDescription = new RTCSessionDescription(data.answer);
      pc.setRemoteDescription(answerDescription);
    }
  });

  // When answered, add candidate to peer connection
  answerCandidates.onSnapshot((snapshot) => {
    snapshot.docChanges().forEach((change) => {
      if (change.type === 'added') {
        const candidate = new RTCIceCandidate(change.doc.data());
        pc.addIceCandidate(candidate);
      }
    });
  });
};

// 3. Answer the call with the unique ID
answerButton.onclick = async () => {
  const callId = callInput.value;
  const callDoc = firestore.collection('calls').doc(callId);
  const answerCandidates = callDoc.collection('answerCandidates');
  const offerCandidates = callDoc.collection('offerCandidates');

  pc.onicecandidate = (event) => {
    event.candidate && answerCandidates.add(event.candidate.toJSON());
  };

  const callData = (await callDoc.get()).data();

  const offerDescription = callData.offer;
  await pc.setRemoteDescription(new RTCSessionDescription(offerDescription));

  const answerDescription = await pc.createAnswer();
  await pc.setLocalDescription(answerDescription);

  const answer = {
    type: answerDescription.type,
    sdp: answerDescription.sdp,
  };

  await callDoc.update({ answer });

  offerCandidates.onSnapshot((snapshot) => {
    snapshot.docChanges().forEach((change) => {
      console.log(change);
      if (change.type === 'added') {
        let data = change.doc.data();
        pc.addIceCandidate(new RTCIceCandidate(data));
      }
    });
  });
};

DataChannel が機能しないのに MediaChannel が機能する理由は何ですか?

4

0 に答える 0