У меня есть простое приложение WebRTC, которое передает только текстовые данные.Он работает хорошо, за исключением обработки спящего режима.
Например, я провожу локальное тестирование с двумя пользователями на двух разных вкладках на моем компьютере, а затем переводю свой компьютер (macOS) в спящий режим.Различные ситуации:
- оба пользователя в Chrome : соединение rtc сразу разрывается с обеих сторон при переходе в спящий режим, легко обрабатывается и восстанавливается, OK
- оба пользователя в Firefox : соединение rtc не прерывается ни с одной стороны, если компьютер скоро просыпается, или с обеих сторон, если сон достаточно длинный, его легкообрабатывать и восстанавливать, OK
- один пользователь в Chrome и один в Firefox : при переходе в спящий режим пользователь Chrome мгновенно отключается (вызывается dataChannel onclose),но пользователь Firefox не работает и все еще думает, что dataChannel работает (использование send не вызывает ошибок, но, очевидно, пользователь в Chrome не получает сообщения, поскольку он закрыт на его стороне), PROBLEM
Почему событие onclose не запускается на стороне Firefox, а на другой стороне?
Существуют ли альтернативные решения длянайти, если соединение разорвано?
Несколько частей моего кода, если это поможет:
const configuration = {
iceServers: [
{urls: 'stun:stun.l.google.com:19302'},
{urls: 'turn:numb.viagenie.ca', username: '...', credential: '...'},
]
}
// Keep track of all RTCPeerConnection.
// Key is userId aka peerId, value is object with 'conn' and 'dataChannel' keys.
let peers = {}
const onNewPeer = (peerId, username) => {
if (peerId in peers) {
log('Already connected to peer ' + peerId)
return
}
const peerconn = new RTCPeerConnection(configuration)
// 'onicecandidate' notifies us whenever an ICE agent needs to deliver a
// message to the other peer through the signaling server
peerconn.onicecandidate = event => {
if (event.candidate)
sendSignalingMessage({ candidate: event.candidate, toUserId: peerId })
}
// OFFERER SPECIFIC PART
peerconn.onnegotiationneeded = () => {
peerconn.createOffer().then(desc => setLocalDescription(desc, peerId), error => console.error(error))
}
const dataChannel = peerconn.createDataChannel('chat') // RTCDataChannel
setupDataChannel(dataChannel, peerId, username)
sendSignalingMessage({ type: 'ADD_PEER_ANSWER', toUserId: peerId })
// END OFFERER SPECIFIC
peers[peerId] = { conn: peerconn, username: username, dataChannel: dataChannel }
}
const onNewPeerAnswer = (peerId, username) => {
if (peerId in peers) {
log('Already connected to peer ', peerId)
return
}
const peerconn = new RTCPeerConnection(configuration)
// 'onicecandidate' notifies us whenever an ICE agent needs to deliver a
// message to the other peer through the signaling server
peerconn.onicecandidate = event => {
if (event.candidate)
sendSignalingMessage({ candidate: event.candidate, toUserId: peerId })
}
// ANSWERER SPECIFIC PART
// If user is not the offerer, let's wait for a data channel
peerconn.ondatachannel = event => {
const dataChannel = event.channel // RTCDataChannel
setupDataChannel(dataChannel, peerId, username)
peers[peerId]['dataChannel'] = dataChannel
}
// END ANSWERER SPECIFIC
peers[peerId] = { conn: peerconn, username: username }
}
const setupDataChannel = (dataChannel, peerId, username) => {
dataChannel.onopen = () => {
console.log(`%cYou are now connected to ${peerId} aka ${username}`, 'color: green;')
}
// PROBLEM: this is triggered on Chrome when going to sleep,
// but on firefox side this is not triggered and firefox still
// thinks this dataChannel is opened after waking up.
dataChannel.onclose = () => {
delete peers[peerId]
console.log(`%cDisconnected from ${peerId} aka ${username}`, 'color: red;')
}
dataChannel.onerror = () => {
delete peers[peerId]
console.log(`%cDisconnected from ${peerId} aka ${username} (onerror)`, 'color: red;')
}
dataChannel.onmessage = event => {
log('Received through WebRTC: ', JSON.parse(event.data))
}
}