feat: 重构 WebRTC 轨道管理,支持多监听器注册,优化 SDP Offer 创建流程;更新桌面共享和语音通话业务逻辑,增强连接管理

This commit is contained in:
MatrixSeven
2026-03-05 13:28:29 +08:00
parent da3e4f1067
commit 6d02a9898f
11 changed files with 545 additions and 735 deletions

View File

@@ -53,8 +53,11 @@ export function useWebRTCConnectionCore(
const relayWsRef = useRef<WebSocket | null>(null);
const isRelayFallbackInProgress = useRef<boolean>(false);
const p2pFailureTimeout = useRef<NodeJS.Timeout | null>(null);
const iceDisconnectedTimeout = useRef<NodeJS.Timeout | null>(null);
// 标记是否已经发送过 relay-request避免重复发送
const relayRequestSent = useRef<boolean>(false);
// 通过 ref 避免闭包捕获过时的 initiateRelayFallback
const initiateRelayFallbackRef = useRef<() => void>(() => {});
// 清理连接
const cleanup = useCallback((shouldNotifyDisconnect: boolean = false) => {
@@ -70,6 +73,11 @@ export function useWebRTCConnectionCore(
p2pFailureTimeout.current = null;
}
if (iceDisconnectedTimeout.current) {
clearTimeout(iceDisconnectedTimeout.current);
iceDisconnectedTimeout.current = null;
}
if (pcRef.current) {
pcRef.current.close();
pcRef.current = null;
@@ -235,6 +243,7 @@ export function useWebRTCConnectionCore(
relayWs.onerror = (error) => {
console.error('[ConnectionCore] ❌ 中继 WebSocket 错误:', error);
isRelayFallbackInProgress.current = false;
relayRequestSent.current = false; // 重置以允许重试
stateManager.updateState({
error: 'WS 中继连接失败,请重试',
isConnecting: false,
@@ -263,6 +272,7 @@ export function useWebRTCConnectionCore(
} catch (error) {
console.error('[ConnectionCore] 创建中继连接失败:', error);
isRelayFallbackInProgress.current = false;
relayRequestSent.current = false; // 重置以允许重试
stateManager.updateState({
error: '无法建立中继连接,请重试',
isConnecting: false,
@@ -306,6 +316,9 @@ export function useWebRTCConnectionCore(
connectToRelay();
}, [connectToRelay]);
// 保持 ref 同步,避免闭包过时
initiateRelayFallbackRef.current = initiateRelayFallback;
// 创建 PeerConnection 和相关设置
const createPeerConnection = useCallback((ws: WebSocket, role: 'sender' | 'receiver', isReconnect: boolean = false) => {
console.log('[ConnectionCore] 🔧 创建PeerConnection...', { role, isReconnect });
@@ -359,18 +372,34 @@ export function useWebRTCConnectionCore(
case 'connected':
case 'completed':
console.log('[ConnectionCore] ✅ ICE连接成功');
// ICE 连接成功,清除降级定时器
// ICE 连接成功,清除所有降级定时器
if (p2pFailureTimeout.current) {
clearTimeout(p2pFailureTimeout.current);
p2pFailureTimeout.current = null;
}
if (iceDisconnectedTimeout.current) {
clearTimeout(iceDisconnectedTimeout.current);
iceDisconnectedTimeout.current = null;
}
break;
case 'failed':
console.error('[ConnectionCore] ❌ ICE连接失败启动中继降级');
initiateRelayFallback();
initiateRelayFallbackRef.current();
break;
case 'disconnected':
console.log('[ConnectionCore] 🔌 ICE连接断开');
console.log('[ConnectionCore] 🔌 ICE连接断开,设置 8 秒超时保护');
// ICE disconnected 可能是暂时的(网络抖动),也可能永不恢复
// 设置超时保护8 秒后如果仍非 connected/completed 则降级
if (iceDisconnectedTimeout.current) {
clearTimeout(iceDisconnectedTimeout.current);
}
iceDisconnectedTimeout.current = setTimeout(() => {
const iceState = pcRef.current?.iceConnectionState;
if (iceState && iceState !== 'connected' && iceState !== 'completed') {
console.log('[ConnectionCore] ⏰ ICE disconnected 超时8秒启动中继降级');
initiateRelayFallbackRef.current();
}
}, 8000);
break;
case 'closed':
console.log('[ConnectionCore] 🚫 ICE连接已关闭');
@@ -385,24 +414,28 @@ export function useWebRTCConnectionCore(
console.log('[ConnectionCore] 🔄 WebRTC正在连接中...');
stateManager.updateState({ isPeerConnected: false });
// 设置 P2P 连接超时15 秒后如果还没连上就降级
// 设置 P2P 连接超时10 秒后如果还没连上就降级
if (p2pFailureTimeout.current) {
clearTimeout(p2pFailureTimeout.current);
}
p2pFailureTimeout.current = setTimeout(() => {
if (pcRef.current && pcRef.current.connectionState !== 'connected') {
console.log('[ConnectionCore] ⏰ P2P 连接超时15秒),启动中继降级');
initiateRelayFallback();
console.log('[ConnectionCore] ⏰ P2P 连接超时10秒),启动中继降级');
initiateRelayFallbackRef.current();
}
}, 15000);
}, 10000);
break;
case 'connected':
console.log('[ConnectionCore] 🎉 WebRTC P2P连接已完全建立可以进行媒体传输');
// 清除降级定时器
// 清除所有降级定时器
if (p2pFailureTimeout.current) {
clearTimeout(p2pFailureTimeout.current);
p2pFailureTimeout.current = null;
}
if (iceDisconnectedTimeout.current) {
clearTimeout(iceDisconnectedTimeout.current);
iceDisconnectedTimeout.current = null;
}
// 确保所有连接状态都正确更新
stateManager.updateState({
isWebSocketConnected: true,
@@ -434,7 +467,7 @@ export function useWebRTCConnectionCore(
if (!isUserDisconnecting.current) {
console.log('[ConnectionCore] 启动中继降级');
stateManager.updateState({ isPeerConnected: false });
initiateRelayFallback();
initiateRelayFallbackRef.current();
}
break;
case 'disconnected':
@@ -457,7 +490,7 @@ export function useWebRTCConnectionCore(
console.log('[ConnectionCore] ✅ PeerConnection创建完成角色:', role, '是否重新连接:', isReconnect);
return pc;
}, [stateManager, dataChannelManager, initiateRelayFallback]);
}, [stateManager, dataChannelManager]);
// 连接到房间
const connect = useCallback(async (roomCode: string, role: 'sender' | 'receiver') => {