Compare commits
	
		
			4 Commits
		
	
	
		
			af0f583aff
			...
			4b171b849f
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4b171b849f | |||
| fd18ba6527 | |||
| 8cb0ede570 | |||
| e1e96e1e19 | 
							
								
								
									
										1
									
								
								go.mod
									
									
									
									
									
								
							
							
						
						
									
										1
									
								
								go.mod
									
									
									
									
									
								
							@@ -12,6 +12,7 @@ require (
 | 
				
			|||||||
	github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
 | 
						github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
 | 
				
			||||||
	github.com/davecgh/go-spew v1.1.1 // indirect
 | 
						github.com/davecgh/go-spew v1.1.1 // indirect
 | 
				
			||||||
	github.com/google/uuid v1.4.0 // indirect
 | 
						github.com/google/uuid v1.4.0 // indirect
 | 
				
			||||||
 | 
						github.com/pelletier/go-toml/v2 v2.1.0 // indirect
 | 
				
			||||||
	github.com/pion/datachannel v1.5.5 // indirect
 | 
						github.com/pion/datachannel v1.5.5 // indirect
 | 
				
			||||||
	github.com/pion/dtls/v2 v2.2.8 // indirect
 | 
						github.com/pion/dtls/v2 v2.2.8 // indirect
 | 
				
			||||||
	github.com/pion/ice/v3 v3.0.2 // indirect
 | 
						github.com/pion/ice/v3 v3.0.2 // indirect
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										2
									
								
								go.sum
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								go.sum
									
									
									
									
									
								
							@@ -37,6 +37,8 @@ github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042
 | 
				
			|||||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 | 
					github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
 | 
				
			||||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 | 
					github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
 | 
				
			||||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 | 
					github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6/MHO4=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
 | 
				
			||||||
github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
 | 
					github.com/pion/datachannel v1.5.5 h1:10ef4kwdjije+M9d7Xm9im2Y3O6A6ccQb0zcqZcJew8=
 | 
				
			||||||
github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
 | 
					github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V118yimL0=
 | 
				
			||||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
 | 
					github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										47
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								main.go
									
									
									
									
									
								
							@@ -2,7 +2,10 @@ package main
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"log/slog"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.t-juice.club/torjus/ministream/server"
 | 
						"git.t-juice.club/torjus/ministream/server"
 | 
				
			||||||
@@ -11,6 +14,12 @@ import (
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
const Version = "v0.1.1"
 | 
					const Version = "v0.1.1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ctxKey string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const (
 | 
				
			||||||
 | 
						ctxKeyConfig ctxKey = "config"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	app := cli.App{
 | 
						app := cli.App{
 | 
				
			||||||
		Name:  "ministream",
 | 
							Name:  "ministream",
 | 
				
			||||||
@@ -19,12 +28,16 @@ func main() {
 | 
				
			|||||||
			{
 | 
								{
 | 
				
			||||||
				Name:   "serve",
 | 
									Name:   "serve",
 | 
				
			||||||
				Usage:  "Start livestreaming server.",
 | 
									Usage:  "Start livestreaming server.",
 | 
				
			||||||
				Action: func(ctx *cli.Context) error {
 | 
									Before: loadConfig,
 | 
				
			||||||
					store := server.NewUserStore()
 | 
									Action: func(c *cli.Context) error {
 | 
				
			||||||
 | 
										cfg := configFromCtx(c.Context)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
					srv := server.NewServer(store)
 | 
										srv := server.NewServer(cfg)
 | 
				
			||||||
					srv.Addr = ":8080"
 | 
										srv.Addr = cfg.HTTP.ListenAddr
 | 
				
			||||||
					srv.ListenAndServe()
 | 
										slog.Info("Starting HTTP-server", "addr", srv.Addr, "cfg", cfg)
 | 
				
			||||||
 | 
										if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
 | 
				
			||||||
 | 
											return err
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
					return nil
 | 
										return nil
 | 
				
			||||||
				},
 | 
									},
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
@@ -37,3 +50,27 @@ func main() {
 | 
				
			|||||||
		fmt.Println(err)
 | 
							fmt.Println(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func loadConfig(c *cli.Context) error {
 | 
				
			||||||
 | 
						cfg, err := server.ConfigFromDefault()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						c.Context = context.WithValue(c.Context, ctxKeyConfig, cfg)
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func configFromCtx(ctx context.Context) *server.Config {
 | 
				
			||||||
 | 
						value := ctx.Value(ctxKeyConfig)
 | 
				
			||||||
 | 
						if value == nil {
 | 
				
			||||||
 | 
							panic("unable to load config")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config, ok := value.(*server.Config)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							panic("config type assertion failed")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return config
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										21
									
								
								ministream.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								ministream.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					# SiteName is used for displaying title of site on frontend.
 | 
				
			||||||
 | 
					# Default: "ministream"
 | 
				
			||||||
 | 
					# Env: MINISTREAM_SITENAME
 | 
				
			||||||
 | 
					SiteName = "stream.example.org"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[HTTP]
 | 
				
			||||||
 | 
					# HTTPListenAddr is which port the HTTP server will listen on.
 | 
				
			||||||
 | 
					# Default: ":8080"
 | 
				
			||||||
 | 
					# Env: MINISTREAM_HTTP_LISTENADDR
 | 
				
			||||||
 | 
					ListenAddr = ":8080"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[WebRTC]
 | 
				
			||||||
 | 
					# UDPMin is the minimum used for ephemeral ports.
 | 
				
			||||||
 | 
					# Default: 50000
 | 
				
			||||||
 | 
					# Env: MINISTREAM_WEBRTC_UDPMIN
 | 
				
			||||||
 | 
					UDPMin = 50000
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# UDPMax is the maximum used for ephemeral ports.
 | 
				
			||||||
 | 
					# Default: 50050
 | 
				
			||||||
 | 
					# Env: MINISTREAM_WEBRTC_UDPMAX
 | 
				
			||||||
 | 
					UDPMAX = 50050
 | 
				
			||||||
							
								
								
									
										105
									
								
								server/config.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								server/config.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					package server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"os"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/pelletier/go-toml/v2"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Config struct {
 | 
				
			||||||
 | 
						SiteName string       `toml:"siteName"`
 | 
				
			||||||
 | 
						HTTP     ConfigHTTP   `toml:"http"`
 | 
				
			||||||
 | 
						WebRTC   ConfigWebRTC `toml:"WebRTC"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ConfigHTTP struct {
 | 
				
			||||||
 | 
						ListenAddr string `json:"ListenAddr" toml:"ListenAddr"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ConfigWebRTC struct {
 | 
				
			||||||
 | 
						UDPMin int `toml:"UDPMin"`
 | 
				
			||||||
 | 
						UDPMax int `toml:"UDPMax"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func DefaultConfig() *Config {
 | 
				
			||||||
 | 
						return &Config{
 | 
				
			||||||
 | 
							SiteName: "ministream",
 | 
				
			||||||
 | 
							HTTP: ConfigHTTP{
 | 
				
			||||||
 | 
								ListenAddr: ":8080",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							WebRTC: ConfigWebRTC{
 | 
				
			||||||
 | 
								UDPMin: 50000,
 | 
				
			||||||
 | 
								UDPMax: 50050,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (c *Config) OverrideFromEnv() {
 | 
				
			||||||
 | 
						if siteName, ok := os.LookupEnv("MINISTREAM_SITENAME"); ok {
 | 
				
			||||||
 | 
							c.SiteName = siteName
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if httpAddr, ok := os.LookupEnv("MINISTREAM_HTTP_LISTENADDR"); ok {
 | 
				
			||||||
 | 
							c.HTTP.ListenAddr = httpAddr
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if value, ok := os.LookupEnv("MINISTREAM_WEBRTC_UDPMIN"); ok {
 | 
				
			||||||
 | 
							min, err := strconv.Atoi(value)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic("MINISTREAM_WEBRTC_UDPMIN is invalid")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.WebRTC.UDPMin = min
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if value, ok := os.LookupEnv("MINISTREAM_WEBRTC_UDPMAX"); ok {
 | 
				
			||||||
 | 
							max, err := strconv.Atoi(value)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								panic("MINISTREAM_WEBRTC_UDPMAX is invalid")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							c.WebRTC.UDPMin = max
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ConfigFromReader(r io.Reader) (*Config, error) {
 | 
				
			||||||
 | 
						var c Config
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err := toml.NewDecoder(r).Decode(&c)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &c, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ConfigFromFile(path string) (*Config, error) {
 | 
				
			||||||
 | 
						f, err := os.Open(path)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer f.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return ConfigFromReader(f)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ConfigFromDefault() (*Config, error) {
 | 
				
			||||||
 | 
						var config *Config
 | 
				
			||||||
 | 
						defaultPaths := []string{
 | 
				
			||||||
 | 
							"ministream.toml",
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, p := range defaultPaths {
 | 
				
			||||||
 | 
							c, err := ConfigFromFile(p)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							config = c
 | 
				
			||||||
 | 
							break
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if config == nil {
 | 
				
			||||||
 | 
							config = DefaultConfig()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return config, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										37
									
								
								server/config_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								server/config_test.go
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,37 @@
 | 
				
			|||||||
 | 
					package server_test
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.t-juice.club/torjus/ministream/server"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestConfig(t *testing.T) {
 | 
				
			||||||
 | 
						t.Run("FromReader", func(t *testing.T) {
 | 
				
			||||||
 | 
							configString := `SiteName = "ministream.example.org"`
 | 
				
			||||||
 | 
							expectedSiteName := "ministream.example.org"
 | 
				
			||||||
 | 
							r := strings.NewReader(configString)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							c, err := server.ConfigFromReader(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								t.Fatalf("Error reading config: %s", err)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if c.SiteName != expectedSiteName {
 | 
				
			||||||
 | 
								t.Errorf("SiteName incorrect. Got %s want %s", c.SiteName, expectedSiteName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						t.Run("OverrideFromEnv", func(t *testing.T) {
 | 
				
			||||||
 | 
							c := server.DefaultConfig()
 | 
				
			||||||
 | 
							expectedSiteName := "ms.example.org"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							t.Setenv("MINISTREAM_SITENAME", expectedSiteName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							c.OverrideFromEnv()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if c.SiteName != expectedSiteName {
 | 
				
			||||||
 | 
								t.Errorf("SiteName incorrect. Got %s want %s", c.SiteName, expectedSiteName)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -19,15 +19,15 @@ import (
 | 
				
			|||||||
var static embed.FS
 | 
					var static embed.FS
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Server struct {
 | 
					type Server struct {
 | 
				
			||||||
	users   *UserStore
 | 
					 | 
				
			||||||
	streams *StreamStore
 | 
						streams *StreamStore
 | 
				
			||||||
 | 
						config  *Config
 | 
				
			||||||
	http.Server
 | 
						http.Server
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewServer(store *UserStore) *Server {
 | 
					func NewServer(config *Config) *Server {
 | 
				
			||||||
	srv := &Server{
 | 
						srv := &Server{
 | 
				
			||||||
		users:   store,
 | 
							streams: NewStreamStore(config),
 | 
				
			||||||
		streams: NewStreamStore(),
 | 
							config:  config,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r := chi.NewRouter()
 | 
						r := chi.NewRouter()
 | 
				
			||||||
@@ -41,6 +41,7 @@ func NewServer(store *UserStore) *Server {
 | 
				
			|||||||
	r.Patch("/whip/{streamKey}", srv.PatchHandler)
 | 
						r.Patch("/whip/{streamKey}", srv.PatchHandler)
 | 
				
			||||||
	r.Post("/whip/{streamKey}", srv.PostOfferHandler)
 | 
						r.Post("/whip/{streamKey}", srv.PostOfferHandler)
 | 
				
			||||||
	r.Get("/stats", srv.streams.StatsHandler)
 | 
						r.Get("/stats", srv.streams.StatsHandler)
 | 
				
			||||||
 | 
						r.Get("/api/siteinfo", srv.InfoHandler)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	srv.Handler = r
 | 
						srv.Handler = r
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -55,6 +56,17 @@ func corsMiddleware(next http.Handler) http.Handler {
 | 
				
			|||||||
	return http.HandlerFunc(fn)
 | 
						return http.HandlerFunc(fn)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *Server) InfoHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						var infoResponse struct {
 | 
				
			||||||
 | 
							SiteName string `json:"siteName"`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						infoResponse.SiteName = s.config.SiteName
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := json.NewEncoder(w).Encode(&infoResponse); err != nil {
 | 
				
			||||||
 | 
							slog.Warn("Error writing info response")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Server) OptionsHandler(w http.ResponseWriter, r *http.Request) {
 | 
					func (s *Server) OptionsHandler(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	slog.Info("Got OPTIONS")
 | 
						slog.Info("Got OPTIONS")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,19 +20,23 @@ var ErrNoSuchStream error = fmt.Errorf("no such stream")
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
type StreamStore struct {
 | 
					type StreamStore struct {
 | 
				
			||||||
	Streams map[string]*Stream
 | 
						Streams map[string]*Stream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						config       *Config
 | 
				
			||||||
	webRTCConfig webrtc.Configuration
 | 
						webRTCConfig webrtc.Configuration
 | 
				
			||||||
	mu           sync.Mutex
 | 
						mu           sync.Mutex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewStreamStore() *StreamStore {
 | 
					func NewStreamStore(config *Config) *StreamStore {
 | 
				
			||||||
	s := &StreamStore{
 | 
						s := &StreamStore{
 | 
				
			||||||
		Streams: make(map[string]*Stream),
 | 
							Streams: make(map[string]*Stream),
 | 
				
			||||||
 | 
							config:  config,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return s
 | 
						return s
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Stream struct {
 | 
					type Stream struct {
 | 
				
			||||||
 | 
						store                 *StreamStore
 | 
				
			||||||
	peerConnection        *webrtc.PeerConnection
 | 
						peerConnection        *webrtc.PeerConnection
 | 
				
			||||||
	peerConnectionStats   map[string]*stats.Stats
 | 
						peerConnectionStats   map[string]*stats.Stats
 | 
				
			||||||
	peerConnectionStatsMu sync.Mutex
 | 
						peerConnectionStatsMu sync.Mutex
 | 
				
			||||||
@@ -96,7 +100,10 @@ func (s *Stream) AddListener(sd *webrtc.SessionDescription) (*webrtc.SessionDesc
 | 
				
			|||||||
	//i.Add(statsInterceptorFactory)
 | 
						//i.Add(statsInterceptorFactory)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	se := webrtc.SettingEngine{}
 | 
						se := webrtc.SettingEngine{}
 | 
				
			||||||
	_ = se.SetEphemeralUDPPortRange(50000, 50050)
 | 
						_ = se.SetEphemeralUDPPortRange(
 | 
				
			||||||
 | 
							uint16(s.store.config.WebRTC.UDPMin),
 | 
				
			||||||
 | 
							uint16(s.store.config.WebRTC.UDPMax),
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	webRTCConfig := webrtc.Configuration{
 | 
						webRTCConfig := webrtc.Configuration{
 | 
				
			||||||
		ICEServers: []webrtc.ICEServer{
 | 
							ICEServers: []webrtc.ICEServer{
 | 
				
			||||||
@@ -179,6 +186,7 @@ func (s *StreamStore) Add(streamKey string, sd *webrtc.SessionDescription) (*web
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	go func() {
 | 
						go func() {
 | 
				
			||||||
		stream := &Stream{
 | 
							stream := &Stream{
 | 
				
			||||||
 | 
								store:               s,
 | 
				
			||||||
			lastUpdate:          time.Now(),
 | 
								lastUpdate:          time.Now(),
 | 
				
			||||||
			peerConnectionStats: make(map[string]*stats.Stats),
 | 
								peerConnectionStats: make(map[string]*stats.Stats),
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -226,7 +234,7 @@ func (s *StreamStore) Add(streamKey string, sd *webrtc.SessionDescription) (*web
 | 
				
			|||||||
			},
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		se := webrtc.SettingEngine{}
 | 
							se := webrtc.SettingEngine{}
 | 
				
			||||||
		_ = se.SetEphemeralUDPPortRange(50000, 50050)
 | 
							_ = se.SetEphemeralUDPPortRange(uint16(s.config.WebRTC.UDPMin), uint16(s.config.WebRTC.UDPMax))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// se.BufferFactory = func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser {
 | 
							// se.BufferFactory = func(packetType packetio.BufferPacketType, ssrc uint32) io.ReadWriteCloser {
 | 
				
			||||||
		// 	buf := packetio.NewBuffer()
 | 
							// 	buf := packetio.NewBuffer()
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user