Базовый Readme, понятные переменные окружения
This commit is contained in:
17
README.md
17
README.md
@@ -1,2 +1,15 @@
|
||||
### SFU server
|
||||
Сервер для организации видеоконференций на основе WebRTC. Написан на Go и использует библиотеку Pion WebRTC.
|
||||
### SFU сервер
|
||||
SFU - Selective Forwarding Unit - это тип медиасервера, который принимает медиа-потоки от участников видеоконференции и пересылает их другим участникам без декодирования и повторного кодирования. Это позволяет снизить нагрузку на сервер и улучшить качество видео для всех участников. Сейчас G365SFU просто пересылает RTP пакеты между участниками, не обрабатывая их содержимое (потому, что оно зашифровано). В будущем планируется добавить возможность обработки слоев улучшения.
|
||||
|
||||
### TURN сервер
|
||||
TURN - Traversal Using Relays around NAT - это протокол, который позволяет устройствам за NAT (Network Address Translation) или брандмауэром устанавливать связь с другими устройствами в интернете. TURN серверы используются для ретрансляции медиа-трафика между участниками видеоконференции, когда прямое соединение между ними невозможно из-за ограничений сети. В G365SFU используется встроенный TURN сервер, который можно включить с помощью переменной окружения `TURN_ALLOW=true`. Он будет слушать на порту 3478 и использовать диапазон портов от 40000 до 50000 для ретрансляции трафика. Параметры сервера, такие как публичный IP, имя пользователя и пароль, также настраиваются через переменные окружения. TURN сервер обеспечивает надежную связь между участниками звонка, даже если они находятся за NAT.
|
||||
|
||||
# Установка
|
||||
Для начала, нам необходимо открыть порты 30000-39999 для SFU и 40000-50000 для TURN сервера (по умолчанию, если перенастраивается .env то нужно указать другие). Это можно сделать с помощью команды `ufw`:
|
||||
```bash
|
||||
sudo ufw allow 30000:39999/udp
|
||||
sudo ufw allow 40000:50000/udp
|
||||
sudo ufw allow 30000:39999/tcp
|
||||
sudo ufw allow 40000:50000/tcp
|
||||
sudo ufw allow 3478/tcp
|
||||
```
|
||||
31
boot/boot.go
31
boot/boot.go
@@ -9,6 +9,7 @@ import (
|
||||
"g365sfu/socket"
|
||||
connection "g365sfu/socket/struct"
|
||||
"g365sfu/turn"
|
||||
"g365sfu/utils"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
@@ -32,18 +33,26 @@ func Bootstrap() {
|
||||
sfu.OnServerOffer = OnServerOffer
|
||||
sfu.OnRoomDelete = OnRoomDelete
|
||||
sfu.OnPeerDisconnected = OnPeerDisconnected
|
||||
turnServer, err := turn.Start(turn.Config{
|
||||
ListenAddr: "0.0.0.0:3478",
|
||||
PublicIP: os.Getenv("TURN_PUBLIC_IP"),
|
||||
Realm: "g365sfu",
|
||||
Username: os.Getenv("TURN_USER"),
|
||||
Password: os.Getenv("TURN_PASS"),
|
||||
})
|
||||
if err != nil {
|
||||
logger.LogWarnMessage("TURN start failed: " + err.Error())
|
||||
if os.Getenv("TURN_ALLOW") == "true" {
|
||||
turnServer, err := turn.Start(turn.Config{
|
||||
ListenAddr: "0.0.0.0:3478",
|
||||
PublicIP: os.Getenv("TURN_PUBLIC_IP"),
|
||||
Realm: "g365sfu",
|
||||
Username: os.Getenv("TURN_USER"),
|
||||
Password: os.Getenv("TURN_PASS"),
|
||||
MinRelayPort: uint16(utils.AtoiOrDefault(os.Getenv("TURN_PORT_RANGE_FROM"), 40000)),
|
||||
MaxRelayPort: uint16(utils.AtoiOrDefault(os.Getenv("TURN_PORT_RANGE_TO"), 50000)),
|
||||
})
|
||||
if err != nil {
|
||||
logger.LogWarnMessage("error while starting TURN server: " + err.Error())
|
||||
logger.LogInfoMessage("starting without TURN server, peer connections may fail if clients are behind symmetric NATs")
|
||||
} else {
|
||||
logger.LogInfoMessage("server TURN started at 0.0.0.0:3478")
|
||||
defer turnServer.Close()
|
||||
}
|
||||
} else {
|
||||
logger.LogInfoMessage("TURN started on 0.0.0.0:3478")
|
||||
defer turnServer.Close()
|
||||
// TURN сервер выключен в конфиге, что может влиять на соединение некоторых пользователей
|
||||
logger.LogInfoMessage("starting without TURN server, peer connections may fail if clients are behind symmetric NATs")
|
||||
}
|
||||
logger.LogInfoMessage("server started at x.x.x.x:" + port)
|
||||
http.ListenAndServe(":"+port, nil)
|
||||
|
||||
15
sfu/sfu.go
15
sfu/sfu.go
@@ -4,6 +4,7 @@ import (
|
||||
"errors"
|
||||
"g365sfu/logger"
|
||||
connection "g365sfu/socket/struct"
|
||||
"g365sfu/utils"
|
||||
"os"
|
||||
|
||||
"github.com/pion/interceptor"
|
||||
@@ -34,12 +35,12 @@ var (
|
||||
)
|
||||
|
||||
func InitWebRTCEngines() {
|
||||
publicIP := os.Getenv("PUBLIC_IP")
|
||||
fromPort := os.Getenv("PORT_RANGE_FROM")
|
||||
toPort := os.Getenv("PORT_RANGE_TO")
|
||||
if publicIP == "" || fromPort == "" || toPort == "" {
|
||||
publicIP := os.Getenv("SFU_PUBLIC_IP")
|
||||
fromPort := utils.AtoiOrDefault(os.Getenv("SFU_PORT_RANGE_FROM"), 30000)
|
||||
toPort := utils.AtoiOrDefault(os.Getenv("SFU_PORT_RANGE_TO"), 39999)
|
||||
if publicIP == "" || fromPort == 0 || toPort == 0 {
|
||||
// Если не указаны необходимые переменные окружения, логируем ошибку и завершаем процесс сервера
|
||||
logger.LogErrorMessage("PUBLIC_IP, PORT_RANGE_FROM and PORT_RANGE_TO environment variables must be set")
|
||||
logger.LogErrorMessage("SFU_PUBLIC_IP, SFU_PORT_RANGE_FROM and SFU_PORT_RANGE_TO environment variables must be set")
|
||||
os.Exit(-1)
|
||||
return
|
||||
}
|
||||
@@ -50,9 +51,9 @@ func InitWebRTCEngines() {
|
||||
_ = webrtc.RegisterDefaultInterceptors(m, i)
|
||||
|
||||
se := webrtc.SettingEngine{}
|
||||
_ = se.SetEphemeralUDPPortRange(40000, 50000)
|
||||
_ = se.SetEphemeralUDPPortRange(uint16(fromPort), uint16(toPort))
|
||||
|
||||
if publicIP := os.Getenv("PUBLIC_IP"); publicIP != "" {
|
||||
if publicIP := os.Getenv("SFU_PUBLIC_IP"); publicIP != "" {
|
||||
se.SetICEAddressRewriteRules(webrtc.ICEAddressRewriteRule{
|
||||
External: []string{publicIP},
|
||||
AsCandidateType: webrtc.ICECandidateTypeHost,
|
||||
|
||||
36
turn/turn.go
36
turn/turn.go
@@ -19,6 +19,25 @@ type Config struct {
|
||||
Realm string
|
||||
Username string
|
||||
Password string
|
||||
|
||||
MinRelayPort uint16
|
||||
MaxRelayPort uint16
|
||||
}
|
||||
|
||||
func relayGen(ip net.IP, minPort, maxPort uint16) pionturn.RelayAddressGenerator {
|
||||
if minPort != 0 && maxPort != 0 && minPort <= maxPort {
|
||||
return &pionturn.RelayAddressGeneratorPortRange{
|
||||
RelayAddress: ip,
|
||||
Address: "0.0.0.0",
|
||||
MinPort: minPort,
|
||||
MaxPort: maxPort,
|
||||
}
|
||||
}
|
||||
|
||||
return &pionturn.RelayAddressGeneratorStatic{
|
||||
RelayAddress: ip,
|
||||
Address: "0.0.0.0",
|
||||
}
|
||||
}
|
||||
|
||||
func Start(cfg Config) (*Server, error) {
|
||||
@@ -38,6 +57,8 @@ func Start(cfg Config) (*Server, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
rg := relayGen(ip, cfg.MinRelayPort, cfg.MaxRelayPort)
|
||||
|
||||
srv, err := pionturn.NewServer(pionturn.ServerConfig{
|
||||
Realm: cfg.Realm,
|
||||
AuthHandler: func(username, realm string, srcAddr net.Addr) ([]byte, bool) {
|
||||
@@ -48,23 +69,18 @@ func Start(cfg Config) (*Server, error) {
|
||||
},
|
||||
PacketConnConfigs: []pionturn.PacketConnConfig{
|
||||
{
|
||||
PacketConn: udpConn,
|
||||
RelayAddressGenerator: &pionturn.RelayAddressGeneratorStatic{
|
||||
RelayAddress: ip,
|
||||
Address: "0.0.0.0",
|
||||
},
|
||||
PacketConn: udpConn,
|
||||
RelayAddressGenerator: rg,
|
||||
},
|
||||
},
|
||||
ListenerConfigs: []pionturn.ListenerConfig{
|
||||
{
|
||||
Listener: tcpListener,
|
||||
RelayAddressGenerator: &pionturn.RelayAddressGeneratorStatic{
|
||||
RelayAddress: ip,
|
||||
Address: "0.0.0.0",
|
||||
},
|
||||
Listener: tcpListener,
|
||||
RelayAddressGenerator: rg,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
_ = tcpListener.Close()
|
||||
_ = udpConn.Close()
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package utils
|
||||
|
||||
import "math/rand"
|
||||
import (
|
||||
"math/rand"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Генерация случайной строки заданной длины
|
||||
func RandomString(n int) string {
|
||||
@@ -11,3 +14,14 @@ func RandomString(n int) string {
|
||||
}
|
||||
return string(b)
|
||||
}
|
||||
|
||||
func AtoiOrDefault(s string, defaultValue int) int {
|
||||
if s == "" {
|
||||
return defaultValue
|
||||
}
|
||||
n, err := strconv.Atoi(s)
|
||||
if err != nil {
|
||||
return defaultValue
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user