Исправление Race при renegotiation
This commit is contained in:
@@ -90,6 +90,7 @@ func BindPeerLifecycle(roomID, peerID string, pc *webrtc.PeerConnection) {
|
||||
mu sync.Mutex
|
||||
disconnecting bool
|
||||
timer *time.Timer
|
||||
leaveOnce sync.Once
|
||||
)
|
||||
|
||||
room, exists := GetRoom(roomID)
|
||||
@@ -99,6 +100,26 @@ func BindPeerLifecycle(roomID, peerID string, pc *webrtc.PeerConnection) {
|
||||
}
|
||||
server := room.Server
|
||||
|
||||
cancelTimer := func() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if timer != nil {
|
||||
timer.Stop()
|
||||
timer = nil
|
||||
}
|
||||
disconnecting = false
|
||||
}
|
||||
|
||||
leaveAndNotify := func(reason DisconnectReason) {
|
||||
leaveOnce.Do(func() {
|
||||
cancelTimer()
|
||||
err := LeaveRoom(roomID, peerID)
|
||||
if OnPeerDisconnected != nil && err == nil {
|
||||
OnPeerDisconnected(roomID, peerID, server, reason)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
startTimer := func() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
@@ -114,35 +135,20 @@ func BindPeerLifecycle(roomID, peerID string, pc *webrtc.PeerConnection) {
|
||||
mu.Unlock()
|
||||
return
|
||||
}
|
||||
_ = LeaveRoom(roomID, peerID)
|
||||
if OnPeerDisconnected != nil {
|
||||
OnPeerDisconnected(roomID, peerID, server)
|
||||
}
|
||||
leaveAndNotify(DisconnectReasonFailed)
|
||||
})
|
||||
}
|
||||
|
||||
cancelTimer := func() {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
if timer != nil {
|
||||
timer.Stop()
|
||||
timer = nil
|
||||
}
|
||||
disconnecting = false
|
||||
}
|
||||
|
||||
pc.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {
|
||||
switch state {
|
||||
case webrtc.ICEConnectionStateConnected, webrtc.ICEConnectionStateCompleted:
|
||||
cancelTimer()
|
||||
case webrtc.ICEConnectionStateDisconnected:
|
||||
startTimer()
|
||||
case webrtc.ICEConnectionStateFailed, webrtc.ICEConnectionStateClosed:
|
||||
cancelTimer()
|
||||
_ = LeaveRoom(roomID, peerID)
|
||||
if OnPeerDisconnected != nil {
|
||||
OnPeerDisconnected(roomID, peerID, server)
|
||||
}
|
||||
case webrtc.ICEConnectionStateClosed:
|
||||
leaveAndNotify(DisconnectReasonClosed)
|
||||
case webrtc.ICEConnectionStateFailed:
|
||||
leaveAndNotify(DisconnectReasonFailed)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -152,16 +158,15 @@ func BindPeerLifecycle(roomID, peerID string, pc *webrtc.PeerConnection) {
|
||||
cancelTimer()
|
||||
case webrtc.PeerConnectionStateDisconnected:
|
||||
startTimer()
|
||||
case webrtc.PeerConnectionStateFailed, webrtc.PeerConnectionStateClosed:
|
||||
cancelTimer()
|
||||
_ = LeaveRoom(roomID, peerID)
|
||||
if OnPeerDisconnected != nil {
|
||||
OnPeerDisconnected(roomID, peerID, server)
|
||||
}
|
||||
case webrtc.PeerConnectionStateClosed:
|
||||
leaveAndNotify(DisconnectReasonClosed)
|
||||
case webrtc.PeerConnectionStateFailed:
|
||||
leaveAndNotify(DisconnectReasonFailed)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// Вызывается при JoinWithOffer для ретрансляции RTP пакетов от издателя к другим участникам комнаты
|
||||
// Вызывается при JoinWithOffer для ретрансляции RTP пакетов от издателя к другим участникам комнаты
|
||||
func SetupForwardingForPeer(roomID string, publisherPeerID string, publisherPC *webrtc.PeerConnection) {
|
||||
publisherPC.OnTrack(func(remote *webrtc.TrackRemote, _ *webrtc.RTPReceiver) {
|
||||
@@ -178,7 +183,7 @@ func SetupForwardingForPeer(roomID string, publisherPeerID string, publisherPC *
|
||||
remote.StreamID(),
|
||||
)
|
||||
if err != nil {
|
||||
logger.LogErrorMessage("SetupForwardingForPeer: NewTrackLocalStaticRTP error")
|
||||
logger.LogErrorMessage("SetupForwardingForPeer: NewTrackLocalStaticRTP error: " + err.Error())
|
||||
return
|
||||
}
|
||||
defer removeRoomTrack(roomID, localTrack.ID())
|
||||
@@ -203,32 +208,35 @@ func SetupForwardingForPeer(roomID string, publisherPeerID string, publisherPC *
|
||||
continue
|
||||
}
|
||||
|
||||
// Не трогаем закрытые/failed соединения
|
||||
if !isPeerConnectionAlive(sub.PeerConnection) {
|
||||
fmt.Println("SetupForwardingForPeer: skipping dead peer:", sub.PeerID,
|
||||
sub.PeerConnection.ConnectionState().String())
|
||||
continue
|
||||
}
|
||||
|
||||
sender, err := sub.PeerConnection.AddTrack(localTrack)
|
||||
if err != nil {
|
||||
fmt.Println("SetupForwardingForPeer: AddTrack error:", roomID, sub.PeerID, err)
|
||||
logger.LogWarnMessage("SetupForwardingForPeer: AddTrack error: " + sub.PeerID + " " + err.Error())
|
||||
continue
|
||||
}
|
||||
|
||||
// RTCP drain
|
||||
senderCopy := sender
|
||||
go func() {
|
||||
buf := make([]byte, 1500)
|
||||
for {
|
||||
if _, _, e := sender.Read(buf); e != nil {
|
||||
if _, _, e := senderCopy.Read(buf); e != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err = renegotiatePeer(roomID, sub.PeerID, sub.PeerConnection); err != nil {
|
||||
fmt.Println("SetupForwardingForPeer: renegotiatePeer error:", roomID, sub.PeerID, err)
|
||||
}
|
||||
subID := sub.PeerID
|
||||
subPC := sub.PeerConnection
|
||||
|
||||
go func() {
|
||||
logger.LogInfoMessage("SetupForwardingForPeer: starting renegotiation for peer=" + subID)
|
||||
if err := renegotiatePeer(roomID, subID, subPC); err != nil {
|
||||
logger.LogWarnMessage("SetupForwardingForPeer: renegotiatePeer error: " + subID + " " + err.Error())
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// Для video просим keyframe
|
||||
@@ -245,11 +253,11 @@ func SetupForwardingForPeer(roomID string, publisherPeerID string, publisherPC *
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
fmt.Println("SetupForwardingForPeer: ReadRTP error:", err)
|
||||
logger.LogWarnMessage("SetupForwardingForPeer: ReadRTP error: " + err.Error())
|
||||
return
|
||||
}
|
||||
if err = localTrack.WriteRTP(pkt); err != nil {
|
||||
fmt.Println("SetupForwardingForPeer: WriteRTP error:", err)
|
||||
logger.LogWarnMessage("SetupForwardingForPeer: WriteRTP error: " + err.Error())
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user