package sfu import ( connection "g365sfu/socket/struct" "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, roomID string) (*Room, error) { 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 }