From b63867287b0d061eecf81737aba51d61d01cb3a5 Mon Sep 17 00:00:00 2001 From: set Date: Wed, 11 Mar 2026 19:32:18 +0200 Subject: [PATCH] =?UTF-8?q?=D0=A0=D0=B5=D0=B0=D0=BB=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BA=D0=BE=D0=BC=D0=BD=D0=B0=D1=82=20?= =?UTF-8?q?=D1=81=20RoomID?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sfu/rooms.go | 127 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 sfu/rooms.go diff --git a/sfu/rooms.go b/sfu/rooms.go new file mode 100644 index 0000000..71cd525 --- /dev/null +++ b/sfu/rooms.go @@ -0,0 +1,127 @@ +package sfu + +import ( + "g365sfu/socket" + "g365sfu/utils" + "sync" + + "github.com/pion/webrtc/v4" +) + +// Общие переменные +var ( + rooms = make(map[string]*Room) + roomsMu sync.RWMutex +) + +type Peer struct { + //Идентификатор пира, который будет использоваться для связи с ним + PeerID string + //Подсоединенный пир + PeerConnection *webrtc.PeerConnection +} + +type Room struct { + //Уникальный идентификатор комнаты + RoomID string + //Сервер который создал комнату + Server []*socket.Connection + //Пиры которые подключились к комнате + Peers []Peer +} + +// CreateRoom создает комнату +func CreateRoom() (*Room, error) { + roomID := "room_" + utils.RandomString(64) + roomsMu.Lock() + defer roomsMu.Unlock() + + room := &Room{ + RoomID: roomID, + Server: []*socket.Connection{}, + 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 +} + +// AddICECandidate добавляет ICE-кандидата к пиру +func AddICECandidate(roomID string, peerID string, candidate webrtc.ICECandidateInit) error { + room, exists := GetRoom(roomID) + if !exists { + return ErrRoomNotFound + } + + for _, peer := range room.Peers { + if peer.PeerID == peerID { + return peer.PeerConnection.AddICECandidate(candidate) + } + } + + return ErrPeerNotFound +}