Буферизация ICE кандидатов (для избежания гонки)
This commit is contained in:
@@ -71,15 +71,40 @@ export function CallProvider(props : CallProviderProps) {
|
||||
const roleRef = useRef<CallRole | null>(null);
|
||||
const [sharedSecret, setSharedSecret] = useState<string>("");
|
||||
const iceServersRef = useRef<RTCIceServer[]>([]);
|
||||
const remoteAudioRef = useRef<HTMLAudioElement>(null);
|
||||
const iceCandidatesBufferRef = useRef<RTCIceCandidate[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
/**
|
||||
/**
|
||||
* Нам нужно получить ICE серверы для установки соединения из разных сетей
|
||||
* Получаем их от сервера
|
||||
*/
|
||||
let packet = new PacketIceServers();
|
||||
send(packet);
|
||||
}, []);
|
||||
|
||||
//debug
|
||||
|
||||
setInterval(async () => {
|
||||
if(callState == CallState.ACTIVE){
|
||||
if(peerConnectionRef.current){
|
||||
const stats = await peerConnectionRef.current.getStats();
|
||||
stats.forEach((report) => {
|
||||
|
||||
if (report.type === "inbound-rtp" && !report.isRemote) {
|
||||
const kind = (report as any).kind || (report as any).mediaType;
|
||||
const bytesReceived = (report as any).bytesReceived ?? 0;
|
||||
const packetsReceived = (report as any).packetsReceived ?? 0;
|
||||
const packetsLost = (report as any).packetsLost ?? 0;
|
||||
|
||||
console.log(
|
||||
`[inbound ${kind}] bytesReceived=${bytesReceived}, packetsReceived=${packetsReceived}, packetsLost=${packetsLost}`
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, 2000);
|
||||
}, [callState, peerConnectionRef]);
|
||||
|
||||
usePacket(28, async (packet: PacketIceServers) => {
|
||||
let iceServers = packet.getIceServers();
|
||||
@@ -118,6 +143,15 @@ export function CallProvider(props : CallProviderProps) {
|
||||
*/
|
||||
const sdp = JSON.parse(packet.getSdpOrCandidate());
|
||||
await peerConnectionRef.current?.setRemoteDescription(new RTCSessionDescription(sdp));
|
||||
if(iceCandidatesBufferRef.current.length > 0){
|
||||
/**
|
||||
* У нас есть буферизированные ICE кандидаты, которые мы получили до установки удаленного описания, теперь мы можем их добавить в PeerConnection
|
||||
*/
|
||||
for(let i = 0; i < iceCandidatesBufferRef.current.length; i++){
|
||||
await peerConnectionRef.current?.addIceCandidate(iceCandidatesBufferRef.current[i]);
|
||||
}
|
||||
iceCandidatesBufferRef.current = [];
|
||||
}
|
||||
info("Received WebRTC answer and set remote description");
|
||||
return;
|
||||
}
|
||||
@@ -127,6 +161,14 @@ export function CallProvider(props : CallProviderProps) {
|
||||
*/
|
||||
const candidate = JSON.parse(packet.getSdpOrCandidate());
|
||||
console.info(candidate);
|
||||
if(peerConnectionRef.current?.remoteDescription == null){
|
||||
/**
|
||||
* Удаленное описание еще не установлено, буферизуем кандидата, чтобы добавить его после установки удаленного описания
|
||||
*/
|
||||
iceCandidatesBufferRef.current.push(new RTCIceCandidate(candidate));
|
||||
info("Received WebRTC ICE candidate but remote description is not set yet, buffering candidate");
|
||||
return;
|
||||
}
|
||||
await peerConnectionRef.current?.addIceCandidate(new RTCIceCandidate(candidate));
|
||||
info("Received WebRTC ICE candidate and added to peer connection");
|
||||
return;
|
||||
@@ -165,13 +207,7 @@ export function CallProvider(props : CallProviderProps) {
|
||||
/**
|
||||
* Сбросили звонок
|
||||
*/
|
||||
setActiveCall("");
|
||||
setCallState(CallState.ENDED);
|
||||
setShowCallView(false);
|
||||
setSessionKeys(null);
|
||||
setSharedSecret("");
|
||||
setDuration(0);
|
||||
roleRef.current = null;
|
||||
end();
|
||||
return;
|
||||
}
|
||||
if(signalType == SignalType.CALL){
|
||||
@@ -276,7 +312,12 @@ export function CallProvider(props : CallProviderProps) {
|
||||
* При получении медиа-трека с другой стороны
|
||||
*/
|
||||
console.info("TRACK RECV!!!!!");
|
||||
if(remoteAudioRef.current){
|
||||
console.info(event.streams);
|
||||
remoteAudioRef.current.srcObject = event.streams[0];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Запрашиваем Аудио поток с микрофона и добавляем его в PeerConnection, чтобы другая сторона могла его получить и воспроизвести,
|
||||
* когда мы установим WebRTC соединение
|
||||
@@ -291,7 +332,7 @@ export function CallProvider(props : CallProviderProps) {
|
||||
* Отправляем свой оффер другой стороне
|
||||
*/
|
||||
let offer = await peerConnectionRef.current.createOffer();
|
||||
peerConnectionRef.current.setLocalDescription(offer);
|
||||
await peerConnectionRef.current.setLocalDescription(offer);
|
||||
let offerSignal = new PacketWebRTC();
|
||||
offerSignal.setSignalType(WebRTCSignalType.OFFER);
|
||||
offerSignal.setSdpOrCandidate(JSON.stringify(offer));
|
||||
@@ -325,6 +366,11 @@ export function CallProvider(props : CallProviderProps) {
|
||||
packetSignal.setDst(activeCall);
|
||||
packetSignal.setSignalType(SignalType.END_CALL);
|
||||
send(packetSignal);
|
||||
end();
|
||||
}
|
||||
|
||||
const end = () => {
|
||||
peerConnectionRef.current?.close();
|
||||
peerConnectionRef.current = null;
|
||||
roomIdRef.current = "";
|
||||
setActiveCall("");
|
||||
@@ -386,6 +432,7 @@ export function CallProvider(props : CallProviderProps) {
|
||||
return (
|
||||
<CallContext.Provider value={context}>
|
||||
{props.children}
|
||||
<audio ref={remoteAudioRef} autoPlay playsInline style={{ display: 'none' }} />
|
||||
{showCallView && <Call context={context}></Call>}
|
||||
</CallContext.Provider>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user