132 lines
3.3 KiB
Go
132 lines
3.3 KiB
Go
package sfu
|
||
|
||
import (
|
||
connection "g365sfu/socket/struct"
|
||
"g365sfu/utils"
|
||
"sync"
|
||
|
||
"github.com/pion/webrtc/v4"
|
||
)
|
||
|
||
// Структуры для управления комнатами и пирами в SFU
|
||
|
||
type Peer struct {
|
||
//Идентификатор пира, который будет использоваться для связи с ним
|
||
PeerID string
|
||
//Подсоединенный пир
|
||
PeerConnection *webrtc.PeerConnection
|
||
}
|
||
|
||
type Room struct {
|
||
//Уникальный идентификатор комнаты
|
||
RoomID string
|
||
//Сервер который создал комнату
|
||
Server *connection.Connection
|
||
//Пиры которые подключились к комнате
|
||
Peers []Peer
|
||
}
|
||
|
||
// Общие переменные
|
||
var (
|
||
rooms = make(map[string]*Room)
|
||
roomsMu sync.RWMutex
|
||
)
|
||
|
||
// CreateRoom создает комнату
|
||
func CreateRoom(server *connection.Connection) (*Room, error) {
|
||
roomID := "room_" + utils.RandomString(64)
|
||
roomsMu.Lock()
|
||
defer roomsMu.Unlock()
|
||
|
||
room := &Room{
|
||
RoomID: roomID,
|
||
Server: server,
|
||
Peers: []Peer{},
|
||
}
|
||
rooms[roomID] = room
|
||
|
||
return room, nil
|
||
}
|
||
|
||
// GetRoom получает комнату по идентификатору
|
||
func GetRoom(roomID string) (*Room, bool) {
|
||
roomsMu.RLock()
|
||
defer roomsMu.RUnlock()
|
||
room, exists := rooms[roomID]
|
||
return room, exists
|
||
}
|
||
|
||
// DeleteRoom удаляет комнату по идентификатору
|
||
func DeleteRoom(roomID string) {
|
||
roomsMu.Lock()
|
||
defer roomsMu.Unlock()
|
||
delete(rooms, roomID)
|
||
}
|
||
|
||
// JoinWithOffer позволяет пиру присоединиться к комнате с помощью SDP оффера
|
||
func JoinWithOffer(roomID string, peerID string, offer webrtc.SessionDescription) (*webrtc.SessionDescription, error) {
|
||
room, exists := GetRoom(roomID)
|
||
if !exists {
|
||
return nil, ErrRoomNotFound
|
||
}
|
||
|
||
peerConnection, err := api.NewPeerConnection(pcConfig)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// SFU локальные ICE-кандидаты отправляем сначала бекенду затем тот их
|
||
// пересылает клиенту для установления соединения
|
||
peerConnection.OnICECandidate(func(c *webrtc.ICECandidate) {
|
||
if c == nil {
|
||
return // gathering finished
|
||
}
|
||
if OnLocalICECandidate != nil {
|
||
OnLocalICECandidate(roomID, peerID, c.ToJSON())
|
||
}
|
||
})
|
||
|
||
err = peerConnection.SetRemoteDescription(offer)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
answer, err := peerConnection.CreateAnswer(nil)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
err = peerConnection.SetLocalDescription(answer)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// Настраиваем пересылку RTP пакетов от издателя к другим участникам комнаты
|
||
SetupForwardingForPeer(roomID, peerID, peerConnection)
|
||
|
||
room.Peers = append(room.Peers, Peer{
|
||
PeerID: peerID,
|
||
PeerConnection: peerConnection,
|
||
})
|
||
|
||
return peerConnection.LocalDescription(), nil
|
||
}
|
||
|
||
// LeaveRoom позволяет пиру покинуть комнату
|
||
func LeaveRoom(roomID string, peerID string) error {
|
||
room, exists := GetRoom(roomID)
|
||
if !exists {
|
||
return ErrRoomNotFound
|
||
}
|
||
|
||
for i, peer := range room.Peers {
|
||
if peer.PeerID == peerID {
|
||
peer.PeerConnection.Close()
|
||
room.Peers = append(room.Peers[:i], room.Peers[i+1:]...)
|
||
break
|
||
}
|
||
}
|
||
|
||
return nil
|
||
}
|