Crackord/fullstream/app/internal/handlers/room.go

129 lines
4.5 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package handlers
import (
"fmt"
"moxitech_fullstream/pkg/chat"
w "moxitech_fullstream/pkg/webrtc"
"os"
"time"
"crypto/sha256"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/websocket/v2"
guuid "github.com/google/uuid"
"github.com/pion/webrtc/v3"
)
func RoomCreate(c *fiber.Ctx) error {
return c.Redirect(fmt.Sprintf("/room/%s", guuid.New().String()))
}
func Room(c *fiber.Ctx) error {
uuid := c.Params("uuid")
if uuid == "" {
c.Status(400)
return nil
}
ws := "ws"
if os.Getenv("ENVIRONMENT") == "PRODUCTION" {
ws = "wss"
}
uuid, suuid, _ := createOrGetRoom(uuid)
return c.Render("peer", fiber.Map{
"RoomWebsocketAddr": fmt.Sprintf("%s://%s/room/%s/websocket", ws, c.Hostname(), uuid),
"RoomLink": fmt.Sprintf("%s://%s/room/%s", c.Protocol(), c.Hostname(), uuid),
"ChatWebsocketAddr": fmt.Sprintf("%s://%s/room/%s/chat/websocket", ws, c.Hostname(), uuid),
"ViewerWebsocketAddr": fmt.Sprintf("%s://%s/room/%s/viewer/websocket", ws, c.Hostname(), uuid),
"StreamLink": fmt.Sprintf("%s://%s/stream/%s", c.Protocol(), c.Hostname(), suuid),
"Type": "room",
}, "layouts/main")
}
func RoomWebsocket(c *websocket.Conn) {
uuid := c.Params("uuid")
if uuid == "" {
return
}
_, _, room := createOrGetRoom(uuid)
w.RoomConn(c, room.Peers)
}
// createOrGetRoom создает или возвращает комнату с заданным идентификатором.
// Она блокирует доступ к словарю комнат, проверяет, существует ли комната с таким идентификатором, и если да, то возвращает ее.
// Если комнаты не существует, она создает новую комнату, добавляет ее в словарь комнат и возвращает ее.
// Она также создает новый идентификатор для стрима и добавляет комнату в словарь стримов.
// Затем она запускает горутину для работы хаба чата комнаты.
func createOrGetRoom(uuid string) (string, string, *w.Room) {
w.RoomsLock.Lock()
defer w.RoomsLock.Unlock()
h := sha256.New()
h.Write([]byte(uuid))
suuid := fmt.Sprintf("%x", h.Sum(nil))
if room := w.Rooms[uuid]; room != nil {
if _, ok := w.Streams[suuid]; !ok {
w.Streams[suuid] = room
}
return uuid, suuid, room
}
hub := chat.NewHub()
p := &w.Peers{}
p.TrackLocals = make(map[string]*webrtc.TrackLocalStaticRTP)
room := &w.Room{
Peers: p,
Hub: hub,
}
w.Rooms[uuid] = room
w.Streams[suuid] = room
go hub.Run()
return uuid, suuid, room
}
// RoomViewerWebsocket обрабатывает websocket-соединение для просмотра комнат.
// Она получает идентификатор комнаты из параметров запроса.
// Затем она блокирует доступ к словарю комнат, проверяет, существует ли комната с таким идентификатором, и если да, то подключает клиента к комнате.
// Если комнаты не существует, она разблокирует доступ к словарю комнат и возвращает.
func RoomViewerWebsocket(c *websocket.Conn) {
uuid := c.Params("uuid")
if uuid == "" {
return
}
w.RoomsLock.Lock()
if peer, ok := w.Rooms[uuid]; ok {
w.RoomsLock.Unlock()
roomViewerConn(c, peer.Peers)
return
}
w.RoomsLock.Unlock()
}
// roomViewerConn обрабатывает websocket-соединение для просмотра комнат.
// Функция создает новый таймер, который тикает каждую секунду.
// Когда тикает таймер, она пытается получить следующий текстовый поток для отправки данных.
// Если происходит ошибка, соединение закрывается.
// В противном случае, она отправляет количество подключенных к комнате клиентов.
func roomViewerConn(c *websocket.Conn, p *w.Peers) {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()
defer c.Close()
for {
select {
case <-ticker.C:
w, err := c.Conn.NextWriter(websocket.TextMessage)
if err != nil {
return
}
w.Write([]byte(fmt.Sprintf("%d", len(p.Connections))))
}
}
}