Автоматическое удаление комнат при неактивности
All checks were successful
Build G365SFU / build (push) Successful in 10m16s
All checks were successful
Build G365SFU / build (push) Successful in 10m16s
This commit is contained in:
4
.env
4
.env
@@ -9,7 +9,7 @@ PORT=1001
|
|||||||
# SFU SECTION #
|
# SFU SECTION #
|
||||||
###############
|
###############
|
||||||
#Публичный IP адрес, который будет использоваться для ICE кандидатов (если SFU работает за NAT)
|
#Публичный IP адрес, который будет использоваться для ICE кандидатов (если SFU работает за NAT)
|
||||||
SFU_PUBLIC_IP=192.168.6.82
|
SFU_PUBLIC_IP=10.211.55.2
|
||||||
#Диапазон портов для ICE кандидатов
|
#Диапазон портов для ICE кандидатов
|
||||||
SFU_PORT_RANGE_FROM=30000
|
SFU_PORT_RANGE_FROM=30000
|
||||||
SFU_PORT_RANGE_TO=39999
|
SFU_PORT_RANGE_TO=39999
|
||||||
@@ -19,7 +19,7 @@ SFU_PORT_RANGE_TO=39999
|
|||||||
#Разрешить использовать этот SFU как TURN сервер тоже (для ретрансляции медиа трафика на сам SFU)
|
#Разрешить использовать этот SFU как TURN сервер тоже (для ретрансляции медиа трафика на сам SFU)
|
||||||
TURN_ALLOW=true
|
TURN_ALLOW=true
|
||||||
#TURN имя пользователя и пароль для аутентификации на TURN сервере (если используется)
|
#TURN имя пользователя и пароль для аутентификации на TURN сервере (если используется)
|
||||||
TURN_PUBLIC_IP=192.168.6.82
|
TURN_PUBLIC_IP=10.211.55.2
|
||||||
TURN_USER=user
|
TURN_USER=user
|
||||||
TURN_PASS=pass
|
TURN_PASS=pass
|
||||||
#Диапазон занимемых TURN сервером портов (tcp/udp)
|
#Диапазон занимемых TURN сервером портов (tcp/udp)
|
||||||
|
|||||||
57
sfu/rooms.go
57
sfu/rooms.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"g365sfu/logger"
|
"g365sfu/logger"
|
||||||
connection "g365sfu/socket/struct"
|
connection "g365sfu/socket/struct"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pion/webrtc/v4"
|
"github.com/pion/webrtc/v4"
|
||||||
)
|
)
|
||||||
@@ -34,6 +35,8 @@ type Room struct {
|
|||||||
Tracks []RoomTrack
|
Tracks []RoomTrack
|
||||||
|
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
|
|
||||||
|
emptyTimer *time.Timer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Общие переменные
|
// Общие переменные
|
||||||
@@ -42,6 +45,46 @@ var (
|
|||||||
roomsMu sync.RWMutex
|
roomsMu sync.RWMutex
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const emptyRoomTTL = 30 * time.Second
|
||||||
|
|
||||||
|
func scheduleEmptyRoomDeletion(room *Room) {
|
||||||
|
room.mu.Lock()
|
||||||
|
if len(room.Peers) > 0 {
|
||||||
|
if room.emptyTimer != nil {
|
||||||
|
room.emptyTimer.Stop()
|
||||||
|
room.emptyTimer = nil
|
||||||
|
}
|
||||||
|
room.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if room.emptyTimer != nil {
|
||||||
|
room.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
roomID := room.RoomID
|
||||||
|
var timer *time.Timer
|
||||||
|
timer = time.AfterFunc(emptyRoomTTL, func() {
|
||||||
|
currentRoom, exists := GetRoom(roomID)
|
||||||
|
if !exists {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
currentRoom.mu.Lock()
|
||||||
|
if currentRoom.emptyTimer != timer || len(currentRoom.Peers) > 0 {
|
||||||
|
currentRoom.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
currentRoom.emptyTimer = nil
|
||||||
|
currentRoom.mu.Unlock()
|
||||||
|
|
||||||
|
if err := DeleteRoom(roomID); err != nil && err != ErrRoomNotFound {
|
||||||
|
logger.LogWarnMessage("scheduleEmptyRoomDeletion: failed to delete room " + roomID + ": " + err.Error())
|
||||||
|
}
|
||||||
|
})
|
||||||
|
room.emptyTimer = timer
|
||||||
|
room.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
// CreateRoom создает комнату
|
// CreateRoom создает комнату
|
||||||
func CreateRoom(server *connection.Connection, roomID string) (*Room, error) {
|
func CreateRoom(server *connection.Connection, roomID string) (*Room, error) {
|
||||||
roomsMu.Lock()
|
roomsMu.Lock()
|
||||||
@@ -53,6 +96,7 @@ func CreateRoom(server *connection.Connection, roomID string) (*Room, error) {
|
|||||||
Peers: []Peer{},
|
Peers: []Peer{},
|
||||||
}
|
}
|
||||||
rooms[roomID] = room
|
rooms[roomID] = room
|
||||||
|
scheduleEmptyRoomDeletion(room)
|
||||||
|
|
||||||
return room, nil
|
return room, nil
|
||||||
}
|
}
|
||||||
@@ -110,6 +154,10 @@ func JoinWithOffer(roomID string, peerID string, offer webrtc.SessionDescription
|
|||||||
// Добавляем peer в комнату и сразу снимаем snapshot существующих треков
|
// Добавляем peer в комнату и сразу снимаем snapshot существующих треков
|
||||||
// в одном локе — чтобы не было race с OnTrack
|
// в одном локе — чтобы не было race с OnTrack
|
||||||
room.mu.Lock()
|
room.mu.Lock()
|
||||||
|
if room.emptyTimer != nil {
|
||||||
|
room.emptyTimer.Stop()
|
||||||
|
room.emptyTimer = nil
|
||||||
|
}
|
||||||
room.Peers = append(room.Peers, Peer{
|
room.Peers = append(room.Peers, Peer{
|
||||||
PeerID: peerID,
|
PeerID: peerID,
|
||||||
PeerConnection: peerConnection,
|
PeerConnection: peerConnection,
|
||||||
@@ -164,6 +212,10 @@ func DeleteRoom(roomID string) error {
|
|||||||
roomsMu.Unlock()
|
roomsMu.Unlock()
|
||||||
|
|
||||||
room.mu.Lock()
|
room.mu.Lock()
|
||||||
|
if room.emptyTimer != nil {
|
||||||
|
room.emptyTimer.Stop()
|
||||||
|
room.emptyTimer = nil
|
||||||
|
}
|
||||||
peers := make([]Peer, len(room.Peers))
|
peers := make([]Peer, len(room.Peers))
|
||||||
copy(peers, room.Peers)
|
copy(peers, room.Peers)
|
||||||
room.Peers = nil
|
room.Peers = nil
|
||||||
@@ -227,9 +279,10 @@ func LeaveRoom(roomID string, peerID string) error {
|
|||||||
}
|
}
|
||||||
cleanupForwardingState(roomID, peerID)
|
cleanupForwardingState(roomID, peerID)
|
||||||
|
|
||||||
// Комната пустая -> удаляем
|
// Комната пустая -> планируем удаление через TTL
|
||||||
if shouldDrop {
|
if shouldDrop {
|
||||||
return DeleteRoom(roomID)
|
scheduleEmptyRoomDeletion(room)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// renegotiation оставшимся peer после удаления треков/peer
|
// renegotiation оставшимся peer после удаления треков/peer
|
||||||
|
|||||||
Reference in New Issue
Block a user