129 lines
4.5 KiB
Go
129 lines
4.5 KiB
Go
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))))
|
||
}
|
||
}
|
||
}
|