Одноранговое соединение WebRTC не устанавливается в Safari, в Chrome, Firefox - PullRequest
0 голосов
/ 24 декабря 2018

Я собрал быстрый фрагмент для проверки установления однорангового соединения WebRTC в одном и том же контексте вкладки браузера.

const peerConnection1 = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' } ] });
peerConnection1.addEventListener('signalingstatechange', _ => log('1 signaling state ' + peerConnection1.signalingState));
peerConnection1.addEventListener('icegatheringstatechange', _ => log('1 ICE gathering state ' + peerConnection1.iceGatheringState));
peerConnection1.addEventListener('connectionstatechange', _ => log('1 connection state ' + peerConnection1.connectionState));

const peerConnection2 = new RTCPeerConnection({ iceServers: [ { urls: 'stun:stun.l.google.com:19302' } ] });
peerConnection2.addEventListener('signalingstatechange', _ => log('2 signaling state ' + peerConnection1.signalingState));
peerConnection2.addEventListener('icegatheringstatechange', _ => log('2 ICE gathering state ' + peerConnection1.iceGatheringState));
peerConnection2.addEventListener('connectionstatechange', _ => log('2 connection state ' + peerConnection1.connectionState));

const dataChannel = peerConnection1.createDataChannel(null);

const offer = await peerConnection1.createOffer();
await peerConnection1.setLocalDescription(offer);
await peerConnection2.setRemoteDescription(offer);

const answer = await peerConnection2.createAnswer();
await peerConnection2.setLocalDescription(answer);
await peerConnection1.setRemoteDescription(answer);

peerConnection1.addEventListener('icecandidate', event => {
  log('1 ICE candidate ' + (event.candidate ? event.candidate.candidate : 'null'))
  if (event.candidate !== null) {
    peerConnection2.addIceCandidate(event.candidate);
  }
});

peerConnection2.addEventListener('icecandidate', event => {
  log('2 ICE candidate ' + (event.candidate ? event.candidate.candidate : 'null'))
  if (event.candidate !== null) {
    peerConnection1.addIceCandidate(event.candidate);
  }
});

dataChannel.addEventListener('open', () => {
  dataChannel.send('message from 1 to 2');
});

dataChannel.addEventListener('message', event => {
  log('2: ' + event.data);
});

peerConnection2.addEventListener('datachannel', event => {
  monitor(event.channel, 'dc 2');
  event.channel.addEventListener('open', () => {
    event.channel.send('message from 2 to 1');
  });

  event.channel.addEventListener('message', event => {
    log('1: ' + event.data);
  });
});

Этот фрагмент работает в Chrome и Firefox (пробовал обе последние версии в Windows),но не работает в Safari, ни на iOS, ни на macOS.

Журнал, видимый в рабочих браузерах:

1 onnegotiationneeded
1 onsignalingstatechange
1 signaling state have-local-offer
2 onsignalingstatechange
2 signaling state have-local-offer
2 onsignalingstatechange
2 signaling state have-local-offer
1 onsignalingstatechange
1 signaling state stable
1 onicegatheringstatechange
1 ICE gathering state gathering
1 onicecandidate
1 ICE candidate candidate:0 1 UDP 2122252543 ... 59263 typ host
1 onicecandidate
1 ICE candidate candidate:2 1 TCP 2105524479 ... 9 typ host tcptype active
2 onicegatheringstatechange
2 ICE gathering state gathering
2 onicecandidate
2 ICE candidate candidate:0 1 UDP 2122252543 ... 59264 typ host
2 onicecandidate
2 ICE candidate candidate:2 1 TCP 2105524479 ... 9 typ host tcptype active
2 oniceconnectionstatechange
1 oniceconnectionstatechange
1 oniceconnectionstatechange
2 oniceconnectionstatechange
dc 1 onopen
2 ondatachannel
dc 2 onopen
dc 2 onmessage
1: message from 1 to 2
dc 1 onmessage
2: message from 2 to 1
1 onicecandidate
1 ICE candidate candidate:1 1 UDP 1686052863 ... 59263 typ srflx raddr ... rport 59263
1 onicegatheringstatechange
1 ICE gathering state complete
1 onicecandidate
1 ICE candidate null
2 onicecandidate
2 ICE candidate candidate:1 1 UDP 1686052863 ... 59264 typ srflx raddr ... rport 59264
2 onicegatheringstatechange
2 ICE gathering state complete
2 onicecandidate
2 ICE candidate null

Журнал, видимый в нерабочих браузерах:

1 onnegotiationneeded
1 onsignalingstatechange
1 signaling state have-local-offer
1 onicegatheringstatechange
1 ICE gathering state gathering
1 onconnectionstatechange
1 connection state connecting
2 onsignalingstatechange
2 signaling state have-local-offer
2 onsignalingstatechange
2 signaling state have-local-offer
2 onicegatheringstatechange
2 ICE gathering state gathering
2 onconnectionstatechange
2 connection state connecting
1 onsignalingstatechange
1 signaling state stable
1 oniceconnectionstatechange
1 onicecandidate
1 ICE candidate candidate:842163049 1 udp 1677729535 ... 55297 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag e+HS network-cost 50
1 onicecandidate
1 ICE candidate null
1 onicegatheringstatechange
1 ICE gathering state complete
2 oniceconnectionstatechange
2 onicecandidate
2 ICE candidate candidate:842163049 1 udp 1677729535 ... 53858 typ srflx raddr 0.0.0.0 rport 0 generation 0 ufrag X+Uv network-cost 50
2 onicecandidate
2 ICE candidate null
2 onicegatheringstatechange
2 ICE gathering state complete

В чем может быть причина разницы?Похоже, что в Safari не собраны кандидаты на хостЭто мера безопасности?Могу ли я отключить его в разработке, чтобы этот код работал?Как насчет производства?Если бы это был полный пример с ICE и одноранговыми устройствами на разных устройствах, как я мог убедиться, что кандидаты были собраны для установления однорангового соединения?

1 Ответ

0 голосов
/ 24 декабря 2018

Я нашел источник проблемы и обходной путь в этом отчете об ошибке WebKit:

https://bugs.webkit.org/show_bug.cgi?id=189503

Ключ должен вызвать navigator.mediaDevices.getUserMedia({ video: true }) перед попыткой установить одноранговый узелподключение.Похоже, Safari не раскрывает кандидатов на хост, если только разрешения не были предоставлены первыми.После введения этой строки в мой пример соединение теперь успешно.

...