Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions api_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -456,6 +456,10 @@ type BackendInformationEtcd struct {
MaxStreamBitrate api.Bandwidth `json:"maxstreambitrate,omitempty"`
MaxScreenBitrate api.Bandwidth `json:"maxscreenbitrate,omitempty"`

BandwidthPerRoom api.Bandwidth `json:"bitrateperroom,omitempty"`
MinPublisherBandwidth api.Bandwidth `json:"minpublisherbitrate,omitempty"`
MaxPublisherBandwidth api.Bandwidth `json:"maxpublisherbitrate,omitempty"`

SessionLimit uint64 `json:"sessionlimit,omitempty"`
}

Expand Down
33 changes: 33 additions & 0 deletions api_backend_easyjson.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,9 @@ type CommandProxyClientMessage struct {
Hostname string `json:"hostname,omitempty"`
Port int `json:"port,omitempty"`
RtcpPort int `json:"rtcpPort,omitempty"`

// Bandwidth is set if Type is "update-bandwidth"
Bandwidth api.Bandwidth `json:"bandwidth,omitempty"`
}

func (m *CommandProxyClientMessage) CheckValid() error {
Expand Down Expand Up @@ -356,6 +359,8 @@ type EventProxyServerMessage struct {
Sid string `json:"sid,omitempty"`

Bandwidth *EventProxyServerBandwidth `json:"bandwidth,omitempty"`

ClientBandwidths map[string]EventProxyServerBandwidth `json:"clientBandwidths,omitempty"`
}

// Information on a proxy in the etcd cluster.
Expand Down
66 changes: 60 additions & 6 deletions api_proxy_easyjson.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions backend_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ type Backend struct {
maxStreamBitrate api.Bandwidth
maxScreenBitrate api.Bandwidth

bandwidthPerRoom api.AtomicBandwidth
minPublisherBandwidth api.AtomicBandwidth
maxPublisherBandwidth api.AtomicBandwidth

sessionLimit uint64
sessionsLock sync.Mutex
// +checklocks:sessionsLock
Expand Down Expand Up @@ -86,6 +90,9 @@ func (b *Backend) Equal(other *Backend) bool {
b.allowHttp == other.allowHttp &&
b.maxStreamBitrate == other.maxStreamBitrate &&
b.maxScreenBitrate == other.maxScreenBitrate &&
b.bandwidthPerRoom.Load() == other.bandwidthPerRoom.Load() &&
b.minPublisherBandwidth.Load() == other.minPublisherBandwidth.Load() &&
b.maxPublisherBandwidth.Load() == other.maxPublisherBandwidth.Load() &&
b.sessionLimit == other.sessionLimit &&
bytes.Equal(b.secret, other.secret) &&
slices.Equal(b.urls, other.urls)
Expand Down
3 changes: 3 additions & 0 deletions backend_storage_etcd.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,9 @@ func (s *backendStorageEtcd) EtcdKeyUpdated(client *EtcdClient, key string, data
maxScreenBitrate: info.MaxScreenBitrate,
sessionLimit: info.SessionLimit,
}
backend.bandwidthPerRoom.Store(info.BandwidthPerRoom)
backend.minPublisherBandwidth.Store(info.MinPublisherBandwidth)
backend.maxPublisherBandwidth.Store(info.MaxPublisherBandwidth)

s.mu.Lock()
defer s.mu.Unlock()
Expand Down
28 changes: 28 additions & 0 deletions backend_storage_static.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,31 @@ type backendStorageStatic struct {
compatBackend *Backend
}

func updateBackendBandwidths(logger Logger, backend *Backend, config *goconf.ConfigFile, id string) {
bandwidthPerRoomValue, err := config.GetInt(id, "bitrateperroom")
if err != nil || bandwidthPerRoomValue < 0 {
bandwidthPerRoomValue = 0
}
minPublisherBandwidthValue, err := config.GetInt(id, "minpublisherbitrate")
if err != nil || minPublisherBandwidthValue < 0 {
minPublisherBandwidthValue = 0
}
maxPublisherBandwidthValue, err := config.GetInt(id, "maxpublisherbitrate")
if err != nil || maxPublisherBandwidthValue < 0 {
maxPublisherBandwidthValue = 0
}

bandwidthPerRoom := api.BandwidthFromBits(uint64(bandwidthPerRoomValue))
minPublisherBandwidth := api.BandwidthFromBits(uint64(minPublisherBandwidthValue))
maxPublisherBandwidth := api.BandwidthFromBits(uint64(maxPublisherBandwidthValue))
if bandwidthPerRoom > 0 && minPublisherBandwidth > 0 && maxPublisherBandwidth > 0 {
logger.Printf("Target bandwith per room: %s (min=%s, max=%s)", bandwidthPerRoom, minPublisherBandwidth, maxPublisherBandwidth)
}
backend.bandwidthPerRoom.Store(bandwidthPerRoom)
backend.minPublisherBandwidth.Store(minPublisherBandwidth)
backend.maxPublisherBandwidth.Store(maxPublisherBandwidth)
}

func NewBackendStorageStatic(logger Logger, config *goconf.ConfigFile) (BackendStorage, error) {
allowAll, _ := config.GetBool("backend", "allowall")
allowHttp, _ := config.GetBool("backend", "allowhttp")
Expand Down Expand Up @@ -80,6 +105,7 @@ func NewBackendStorageStatic(logger Logger, config *goconf.ConfigFile) (BackendS
if sessionLimit > 0 {
logger.Printf("Allow a maximum of %d sessions", sessionLimit)
}
updateBackendBandwidths(logger, compatBackend, config, "backend")
updateBackendStats(compatBackend)
backendsById[compatBackend.id] = compatBackend
numBackends++
Expand Down Expand Up @@ -135,6 +161,7 @@ func NewBackendStorageStatic(logger Logger, config *goconf.ConfigFile) (BackendS
maxStreamBitrate: api.BandwidthFromBits(uint64(maxStreamBitrate)),
maxScreenBitrate: api.BandwidthFromBits(uint64(maxScreenBitrate)),
}
updateBackendBandwidths(logger, compatBackend, config, "backend")
hosts := make([]string, 0, len(allowMap))
for host := range allowMap {
hosts = append(hosts, host)
Expand Down Expand Up @@ -349,6 +376,7 @@ func getConfiguredHosts(logger Logger, backendIds string, config *goconf.ConfigF

sessionLimit: uint64(sessionLimit),
}
updateBackendBandwidths(logger, backend, config, id)

added := make(map[string]bool)
for _, u := range urls {
Expand Down
72 changes: 72 additions & 0 deletions clientsession.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ var (
// The "/api/v1/signaling/" URL will be changed to use "v3" as the "signaling-v3"
// feature is returned by the capabilities endpoint.
PathToOcsSignalingBackend = "ocs/v2.php/apps/spreed/api/v1/signaling/backend"

// minBandwidthOfActivePublisher is the bandwidth a publisher must be sending
// to be counted as "active".
minBandwidthOfActivePublisher = api.BandwidthFromBits(64 * 1024) // +checklocksignore: Global readonly variable.
)

const (
Expand Down Expand Up @@ -1527,3 +1531,71 @@ func (s *ClientSession) ProcessResponse(message *ClientMessage) bool {

return cb(message)
}

func (s *ClientSession) Bandwidth() (uint32, uint32, *McuClientBandwidthInfo) {
s.mu.Lock()
defer s.mu.Unlock()

var publishers uint32
var subscribers uint32
var bandwidth *McuClientBandwidthInfo
for _, pub := range s.publishers {
if pub.StreamType() != StreamTypeVideo {
continue
}

if pub, ok := pub.(McuClientWithBandwidth); ok {
if bw := pub.Bandwidth(); bw != nil {
if bandwidth == nil {
bandwidth = &McuClientBandwidthInfo{}
}

bandwidth.Received += bw.Received
bandwidth.Sent += bw.Sent
if bw.Received >= minBandwidthOfActivePublisher {
publishers++
}
}
}
}

for _, sub := range s.subscribers {
if sub.StreamType() != StreamTypeVideo {
continue
}

if sub, ok := sub.(McuClientWithBandwidth); ok {
if bw := sub.Bandwidth(); bw != nil {
if bandwidth == nil {
bandwidth = &McuClientBandwidthInfo{}
}

bandwidth.Received += bw.Received
bandwidth.Sent += bw.Sent
subscribers++
}
}
}

return publishers, subscribers, bandwidth
}

func (s *ClientSession) UpdatePublisherBandwidth(ctx context.Context, streamType StreamType, bandwidth api.Bandwidth) error {
s.mu.Lock()
defer s.mu.Unlock()

for _, pub := range s.publishers {
if pub.StreamType() != streamType {
continue
}

if pub, ok := pub.(McuClientWithBandwidth); ok {
s.mu.Unlock()
defer s.mu.Lock()

return pub.SetBandwidth(ctx, bandwidth)
}
}

return nil
}
Loading
Loading