mirror of
https://github.com/livekit/livekit.git
synced 2026-09-17 08:05:00 +00:00
decouple websocket and RTC nodes, prep for distributed
This commit is contained in:
@@ -3,6 +3,7 @@ package auth
|
||||
type VideoGrant struct {
|
||||
RoomCreate bool `json:"room_create,omitempty"`
|
||||
RoomJoin bool `json:"room_join,omitempty"`
|
||||
RoomList bool `json:"room_list,omitempty"`
|
||||
Room string `json:"room,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -6,9 +6,8 @@ import (
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
APIPort uint32 `yaml:"api_port"`
|
||||
RTCPort uint32 `yaml:"rtc_port"`
|
||||
RTC RTCConfig `yaml:"rtc"`
|
||||
Port uint32 `yaml:"port"`
|
||||
RTC RTCConfig `yaml:"rtc"`
|
||||
|
||||
// multi-node configuration,
|
||||
MultiNode bool `yaml:"multi_node"`
|
||||
@@ -28,8 +27,7 @@ type RTCConfig struct {
|
||||
func NewConfig(confString string) (*Config, error) {
|
||||
// start with defaults
|
||||
conf := &Config{
|
||||
APIPort: 7880,
|
||||
RTCPort: 7881,
|
||||
Port: 7880,
|
||||
RTC: RTCConfig{
|
||||
ICEPortRangeStart: 8000,
|
||||
ICEPortRangeEnd: 10000,
|
||||
|
||||
+29
-4
@@ -4,9 +4,14 @@ import (
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
var logger *zap.SugaredLogger
|
||||
var (
|
||||
logger *zap.SugaredLogger
|
||||
zapOptions = []zap.Option{
|
||||
zap.AddCallerSkip(1),
|
||||
}
|
||||
)
|
||||
|
||||
func GetLogger() *zap.SugaredLogger {
|
||||
func getLogger() *zap.SugaredLogger {
|
||||
if logger == nil {
|
||||
InitDevelopment()
|
||||
}
|
||||
@@ -14,11 +19,31 @@ func GetLogger() *zap.SugaredLogger {
|
||||
}
|
||||
|
||||
func InitProduction() {
|
||||
l, _ := zap.NewProduction()
|
||||
l, _ := zap.NewProduction(zapOptions...)
|
||||
logger = l.Sugar()
|
||||
}
|
||||
|
||||
func InitDevelopment() {
|
||||
l, _ := zap.NewDevelopment()
|
||||
l, _ := zap.NewDevelopment(zapOptions...)
|
||||
logger = l.Sugar()
|
||||
}
|
||||
|
||||
func Debugw(msg string, keysAndValues ...interface{}) {
|
||||
getLogger().Debugw(msg, keysAndValues...)
|
||||
}
|
||||
|
||||
func Infow(msg string, keysAndValues ...interface{}) {
|
||||
getLogger().Infow(msg, keysAndValues...)
|
||||
}
|
||||
|
||||
func Warnw(msg string, keysAndValues ...interface{}) {
|
||||
getLogger().Warnw(msg, keysAndValues...)
|
||||
}
|
||||
|
||||
func Errorw(msg string, keysAndValues ...interface{}) {
|
||||
getLogger().Errorw(msg, keysAndValues...)
|
||||
}
|
||||
|
||||
func Desugar() *zap.Logger {
|
||||
return getLogger().Desugar()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package routing
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrNodeNotFound = errors.New("could not find node")
|
||||
ErrHandlerNotDefined = errors.New("handler not defined")
|
||||
)
|
||||
@@ -0,0 +1,38 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
|
||||
|
||||
// routes signaling message
|
||||
//counterfeiter:generate . MessageSink
|
||||
type MessageSink interface {
|
||||
WriteMessage(msg interface{}) error
|
||||
Close()
|
||||
}
|
||||
|
||||
//counterfeiter:generate . MessageSource
|
||||
type MessageSource interface {
|
||||
ReadMessage() (interface{}, error)
|
||||
}
|
||||
|
||||
type ParticipantCallback func(roomId, participantId, participantName string, requestSource MessageSource, responseSink MessageSink)
|
||||
|
||||
//counterfeiter:generate . Router
|
||||
type Router interface {
|
||||
GetNodeIdForRoom(roomName string) (string, error)
|
||||
RegisterNode(node *livekit.Node) error
|
||||
GetNode(nodeId string) (*livekit.Node, error)
|
||||
|
||||
StartParticipant(roomName, participantId, participantName, nodeId string) error
|
||||
SetRTCNode(participantId, nodeId string) error
|
||||
// functions for websocket handler
|
||||
GetRequestSink(participantId string) MessageSink
|
||||
GetResponseSource(participantId string) MessageSource
|
||||
|
||||
OnNewParticipant(callback ParticipantCallback)
|
||||
Start() error
|
||||
Stop()
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
// a router of messages
|
||||
type LocalRouter struct {
|
||||
currentNode LocalNode
|
||||
lock sync.RWMutex
|
||||
// channels for each participant
|
||||
requestChannels map[string]*MessageChannel
|
||||
responseChannels map[string]*MessageChannel
|
||||
onNewParticipant ParticipantCallback
|
||||
}
|
||||
|
||||
func NewLocalRouter(currentNode LocalNode) *LocalRouter {
|
||||
return &LocalRouter{
|
||||
currentNode: currentNode,
|
||||
lock: sync.RWMutex{},
|
||||
requestChannels: make(map[string]*MessageChannel),
|
||||
responseChannels: make(map[string]*MessageChannel),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *LocalRouter) GetNodeIdForRoom(roomName string) (string, error) {
|
||||
return r.currentNode.Id, nil
|
||||
}
|
||||
|
||||
func (r *LocalRouter) RegisterNode(node *livekit.Node) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *LocalRouter) GetNode(nodeId string) (*livekit.Node, error) {
|
||||
if nodeId == r.currentNode.Id {
|
||||
return r.currentNode, nil
|
||||
}
|
||||
return nil, ErrNodeNotFound
|
||||
}
|
||||
|
||||
func (r *LocalRouter) StartParticipant(roomName, participantId, participantName, nodeId string) error {
|
||||
// treat it as a new participant connecting
|
||||
if r.onNewParticipant == nil {
|
||||
return ErrHandlerNotDefined
|
||||
}
|
||||
r.onNewParticipant(
|
||||
roomName,
|
||||
participantId,
|
||||
participantName,
|
||||
r.getOrCreateMessageChannel(r.requestChannels, participantId),
|
||||
r.getOrCreateMessageChannel(r.responseChannels, participantId),
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *LocalRouter) SetRTCNode(participantId, nodeId string) error {
|
||||
// nothing to be done
|
||||
return nil
|
||||
}
|
||||
|
||||
// for a local router, sink and source are pointing to the same spot
|
||||
func (r *LocalRouter) GetRequestSink(participantId string) MessageSink {
|
||||
return r.getOrCreateMessageChannel(r.requestChannels, participantId)
|
||||
}
|
||||
|
||||
func (r *LocalRouter) GetResponseSource(participantId string) MessageSource {
|
||||
return r.getOrCreateMessageChannel(r.responseChannels, participantId)
|
||||
}
|
||||
|
||||
func (r *LocalRouter) OnNewParticipant(callback ParticipantCallback) {
|
||||
r.onNewParticipant = callback
|
||||
}
|
||||
|
||||
func (r *LocalRouter) Start() error {
|
||||
// on local routers, Start doesn't do anything, websocket connections initiate the connections
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *LocalRouter) Stop() {
|
||||
}
|
||||
|
||||
func (r *LocalRouter) getOrCreateMessageChannel(target map[string]*MessageChannel, participantId string) *MessageChannel {
|
||||
r.lock.RLock()
|
||||
mc := target[participantId]
|
||||
r.lock.RUnlock()
|
||||
|
||||
if mc != nil {
|
||||
return mc
|
||||
}
|
||||
|
||||
mc = NewMessageChannel()
|
||||
r.lock.Lock()
|
||||
target[participantId] = mc
|
||||
r.lock.Unlock()
|
||||
|
||||
return mc
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package routing
|
||||
|
||||
import (
|
||||
"io"
|
||||
)
|
||||
|
||||
type MessageChannel struct {
|
||||
msgChan chan interface{}
|
||||
}
|
||||
|
||||
func NewMessageChannel() *MessageChannel {
|
||||
return &MessageChannel{
|
||||
msgChan: make(chan interface{}, 1),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *MessageChannel) WriteMessage(msg interface{}) error {
|
||||
m.msgChan <- msg
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *MessageChannel) ReadMessage() (interface{}, error) {
|
||||
msg := <-m.msgChan
|
||||
// channel closed
|
||||
if msg == nil {
|
||||
return nil, io.EOF
|
||||
}
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
func (m *MessageChannel) Close() {
|
||||
close(m.msgChan)
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
package node
|
||||
package routing
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"time"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/pion/stun"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
@@ -14,13 +14,6 @@ import (
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
var NodeSet = wire.NewSet(NewLocalNode)
|
||||
|
||||
type Node struct {
|
||||
livekit.Node
|
||||
config *config.Config
|
||||
}
|
||||
|
||||
type NodeStats struct {
|
||||
NumRooms int32
|
||||
NumClients int32
|
||||
@@ -29,36 +22,37 @@ type NodeStats struct {
|
||||
BytesPerMin int64
|
||||
}
|
||||
|
||||
func NewLocalNode(conf *config.Config) (*Node, error) {
|
||||
n := &Node{
|
||||
Node: livekit.Node{
|
||||
Id: utils.NewGuid(utils.NodePrefix),
|
||||
RtcPort: conf.RTCPort,
|
||||
},
|
||||
config: conf,
|
||||
}
|
||||
if err := n.DiscoverNetworkInfo(); err != nil {
|
||||
type LocalNode *livekit.Node
|
||||
|
||||
func NewLocalNode(conf *config.Config) (LocalNode, error) {
|
||||
ip, err := GetLocalIP(conf.RTC.StunServers)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return n, nil
|
||||
return &livekit.Node{
|
||||
Id: utils.NewGuid(utils.NodePrefix),
|
||||
Ip: ip,
|
||||
NumCpus: uint32(runtime.NumCPU()),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (n *Node) DiscoverNetworkInfo() error {
|
||||
if len(n.config.RTC.StunServers) == 0 {
|
||||
return errors.New("STUN servers are required but not defined")
|
||||
func GetLocalIP(stunServers []string) (string, error) {
|
||||
if len(stunServers) == 0 {
|
||||
return "", errors.New("STUN servers are required but not defined")
|
||||
}
|
||||
c, err := stun.Dial("udp4", n.config.RTC.StunServers[0])
|
||||
c, err := stun.Dial("udp4", stunServers[0])
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
message, err := stun.Build(stun.TransactionID, stun.BindingRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
var stunErr error
|
||||
var nodeIp string
|
||||
err = c.Start(message, func(res stun.Event) {
|
||||
if res.Error != nil {
|
||||
stunErr = res.Error
|
||||
@@ -72,28 +66,28 @@ func (n *Node) DiscoverNetworkInfo() error {
|
||||
}
|
||||
ip := xorAddr.IP.To4()
|
||||
if ip != nil {
|
||||
n.Ip = ip.String()
|
||||
nodeIp = ip.String()
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
for n.Ip == "" {
|
||||
for nodeIp == "" {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
msg := "could not determine public IP"
|
||||
if stunErr != nil {
|
||||
return errors.Wrap(stunErr, msg)
|
||||
return "", errors.Wrap(stunErr, msg)
|
||||
} else {
|
||||
return fmt.Errorf(msg)
|
||||
return "", fmt.Errorf(msg)
|
||||
}
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
return nodeIp, nil
|
||||
}
|
||||
@@ -0,0 +1,141 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package routingfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
)
|
||||
|
||||
type FakeMessageSink struct {
|
||||
CloseStub func()
|
||||
closeMutex sync.RWMutex
|
||||
closeArgsForCall []struct {
|
||||
}
|
||||
WriteMessageStub func(interface{}) error
|
||||
writeMessageMutex sync.RWMutex
|
||||
writeMessageArgsForCall []struct {
|
||||
arg1 interface{}
|
||||
}
|
||||
writeMessageReturns struct {
|
||||
result1 error
|
||||
}
|
||||
writeMessageReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) Close() {
|
||||
fake.closeMutex.Lock()
|
||||
fake.closeArgsForCall = append(fake.closeArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.CloseStub
|
||||
fake.recordInvocation("Close", []interface{}{})
|
||||
fake.closeMutex.Unlock()
|
||||
if stub != nil {
|
||||
fake.CloseStub()
|
||||
}
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) CloseCallCount() int {
|
||||
fake.closeMutex.RLock()
|
||||
defer fake.closeMutex.RUnlock()
|
||||
return len(fake.closeArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) CloseCalls(stub func()) {
|
||||
fake.closeMutex.Lock()
|
||||
defer fake.closeMutex.Unlock()
|
||||
fake.CloseStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) WriteMessage(arg1 interface{}) error {
|
||||
fake.writeMessageMutex.Lock()
|
||||
ret, specificReturn := fake.writeMessageReturnsOnCall[len(fake.writeMessageArgsForCall)]
|
||||
fake.writeMessageArgsForCall = append(fake.writeMessageArgsForCall, struct {
|
||||
arg1 interface{}
|
||||
}{arg1})
|
||||
stub := fake.WriteMessageStub
|
||||
fakeReturns := fake.writeMessageReturns
|
||||
fake.recordInvocation("WriteMessage", []interface{}{arg1})
|
||||
fake.writeMessageMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) WriteMessageCallCount() int {
|
||||
fake.writeMessageMutex.RLock()
|
||||
defer fake.writeMessageMutex.RUnlock()
|
||||
return len(fake.writeMessageArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) WriteMessageCalls(stub func(interface{}) error) {
|
||||
fake.writeMessageMutex.Lock()
|
||||
defer fake.writeMessageMutex.Unlock()
|
||||
fake.WriteMessageStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) WriteMessageArgsForCall(i int) interface{} {
|
||||
fake.writeMessageMutex.RLock()
|
||||
defer fake.writeMessageMutex.RUnlock()
|
||||
argsForCall := fake.writeMessageArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) WriteMessageReturns(result1 error) {
|
||||
fake.writeMessageMutex.Lock()
|
||||
defer fake.writeMessageMutex.Unlock()
|
||||
fake.WriteMessageStub = nil
|
||||
fake.writeMessageReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) WriteMessageReturnsOnCall(i int, result1 error) {
|
||||
fake.writeMessageMutex.Lock()
|
||||
defer fake.writeMessageMutex.Unlock()
|
||||
fake.WriteMessageStub = nil
|
||||
if fake.writeMessageReturnsOnCall == nil {
|
||||
fake.writeMessageReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.writeMessageReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.closeMutex.RLock()
|
||||
defer fake.closeMutex.RUnlock()
|
||||
fake.writeMessageMutex.RLock()
|
||||
defer fake.writeMessageMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSink) recordInvocation(key string, args []interface{}) {
|
||||
fake.invocationsMutex.Lock()
|
||||
defer fake.invocationsMutex.Unlock()
|
||||
if fake.invocations == nil {
|
||||
fake.invocations = map[string][][]interface{}{}
|
||||
}
|
||||
if fake.invocations[key] == nil {
|
||||
fake.invocations[key] = [][]interface{}{}
|
||||
}
|
||||
fake.invocations[key] = append(fake.invocations[key], args)
|
||||
}
|
||||
|
||||
var _ routing.MessageSink = new(FakeMessageSink)
|
||||
@@ -0,0 +1,107 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package routingfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
)
|
||||
|
||||
type FakeMessageSource struct {
|
||||
ReadMessageStub func() (interface{}, error)
|
||||
readMessageMutex sync.RWMutex
|
||||
readMessageArgsForCall []struct {
|
||||
}
|
||||
readMessageReturns struct {
|
||||
result1 interface{}
|
||||
result2 error
|
||||
}
|
||||
readMessageReturnsOnCall map[int]struct {
|
||||
result1 interface{}
|
||||
result2 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) ReadMessage() (interface{}, error) {
|
||||
fake.readMessageMutex.Lock()
|
||||
ret, specificReturn := fake.readMessageReturnsOnCall[len(fake.readMessageArgsForCall)]
|
||||
fake.readMessageArgsForCall = append(fake.readMessageArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.ReadMessageStub
|
||||
fakeReturns := fake.readMessageReturns
|
||||
fake.recordInvocation("ReadMessage", []interface{}{})
|
||||
fake.readMessageMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) ReadMessageCallCount() int {
|
||||
fake.readMessageMutex.RLock()
|
||||
defer fake.readMessageMutex.RUnlock()
|
||||
return len(fake.readMessageArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) ReadMessageCalls(stub func() (interface{}, error)) {
|
||||
fake.readMessageMutex.Lock()
|
||||
defer fake.readMessageMutex.Unlock()
|
||||
fake.ReadMessageStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) ReadMessageReturns(result1 interface{}, result2 error) {
|
||||
fake.readMessageMutex.Lock()
|
||||
defer fake.readMessageMutex.Unlock()
|
||||
fake.ReadMessageStub = nil
|
||||
fake.readMessageReturns = struct {
|
||||
result1 interface{}
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) ReadMessageReturnsOnCall(i int, result1 interface{}, result2 error) {
|
||||
fake.readMessageMutex.Lock()
|
||||
defer fake.readMessageMutex.Unlock()
|
||||
fake.ReadMessageStub = nil
|
||||
if fake.readMessageReturnsOnCall == nil {
|
||||
fake.readMessageReturnsOnCall = make(map[int]struct {
|
||||
result1 interface{}
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.readMessageReturnsOnCall[i] = struct {
|
||||
result1 interface{}
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.readMessageMutex.RLock()
|
||||
defer fake.readMessageMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeMessageSource) recordInvocation(key string, args []interface{}) {
|
||||
fake.invocationsMutex.Lock()
|
||||
defer fake.invocationsMutex.Unlock()
|
||||
if fake.invocations == nil {
|
||||
fake.invocations = map[string][][]interface{}{}
|
||||
}
|
||||
if fake.invocations[key] == nil {
|
||||
fake.invocations[key] = [][]interface{}{}
|
||||
}
|
||||
fake.invocations[key] = append(fake.invocations[key], args)
|
||||
}
|
||||
|
||||
var _ routing.MessageSource = new(FakeMessageSource)
|
||||
@@ -0,0 +1,708 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package routingfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
type FakeRouter struct {
|
||||
GetNodeStub func(string) (*livekit.Node, error)
|
||||
getNodeMutex sync.RWMutex
|
||||
getNodeArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
getNodeReturns struct {
|
||||
result1 *livekit.Node
|
||||
result2 error
|
||||
}
|
||||
getNodeReturnsOnCall map[int]struct {
|
||||
result1 *livekit.Node
|
||||
result2 error
|
||||
}
|
||||
GetNodeIdForRoomStub func(string) (string, error)
|
||||
getNodeIdForRoomMutex sync.RWMutex
|
||||
getNodeIdForRoomArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
getNodeIdForRoomReturns struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
getNodeIdForRoomReturnsOnCall map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
GetRequestSinkStub func(string) routing.MessageSink
|
||||
getRequestSinkMutex sync.RWMutex
|
||||
getRequestSinkArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
getRequestSinkReturns struct {
|
||||
result1 routing.MessageSink
|
||||
}
|
||||
getRequestSinkReturnsOnCall map[int]struct {
|
||||
result1 routing.MessageSink
|
||||
}
|
||||
GetResponseSourceStub func(string) routing.MessageSource
|
||||
getResponseSourceMutex sync.RWMutex
|
||||
getResponseSourceArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
getResponseSourceReturns struct {
|
||||
result1 routing.MessageSource
|
||||
}
|
||||
getResponseSourceReturnsOnCall map[int]struct {
|
||||
result1 routing.MessageSource
|
||||
}
|
||||
OnNewParticipantStub func(routing.ParticipantCallback)
|
||||
onNewParticipantMutex sync.RWMutex
|
||||
onNewParticipantArgsForCall []struct {
|
||||
arg1 routing.ParticipantCallback
|
||||
}
|
||||
RegisterNodeStub func(*livekit.Node) error
|
||||
registerNodeMutex sync.RWMutex
|
||||
registerNodeArgsForCall []struct {
|
||||
arg1 *livekit.Node
|
||||
}
|
||||
registerNodeReturns struct {
|
||||
result1 error
|
||||
}
|
||||
registerNodeReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
SetRTCNodeStub func(string, string) error
|
||||
setRTCNodeMutex sync.RWMutex
|
||||
setRTCNodeArgsForCall []struct {
|
||||
arg1 string
|
||||
arg2 string
|
||||
}
|
||||
setRTCNodeReturns struct {
|
||||
result1 error
|
||||
}
|
||||
setRTCNodeReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
StartStub func() error
|
||||
startMutex sync.RWMutex
|
||||
startArgsForCall []struct {
|
||||
}
|
||||
startReturns struct {
|
||||
result1 error
|
||||
}
|
||||
startReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
StartParticipantStub func(string, string, string, string) error
|
||||
startParticipantMutex sync.RWMutex
|
||||
startParticipantArgsForCall []struct {
|
||||
arg1 string
|
||||
arg2 string
|
||||
arg3 string
|
||||
arg4 string
|
||||
}
|
||||
startParticipantReturns struct {
|
||||
result1 error
|
||||
}
|
||||
startParticipantReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
StopStub func()
|
||||
stopMutex sync.RWMutex
|
||||
stopArgsForCall []struct {
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNode(arg1 string) (*livekit.Node, error) {
|
||||
fake.getNodeMutex.Lock()
|
||||
ret, specificReturn := fake.getNodeReturnsOnCall[len(fake.getNodeArgsForCall)]
|
||||
fake.getNodeArgsForCall = append(fake.getNodeArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.GetNodeStub
|
||||
fakeReturns := fake.getNodeReturns
|
||||
fake.recordInvocation("GetNode", []interface{}{arg1})
|
||||
fake.getNodeMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeCallCount() int {
|
||||
fake.getNodeMutex.RLock()
|
||||
defer fake.getNodeMutex.RUnlock()
|
||||
return len(fake.getNodeArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeCalls(stub func(string) (*livekit.Node, error)) {
|
||||
fake.getNodeMutex.Lock()
|
||||
defer fake.getNodeMutex.Unlock()
|
||||
fake.GetNodeStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeArgsForCall(i int) string {
|
||||
fake.getNodeMutex.RLock()
|
||||
defer fake.getNodeMutex.RUnlock()
|
||||
argsForCall := fake.getNodeArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeReturns(result1 *livekit.Node, result2 error) {
|
||||
fake.getNodeMutex.Lock()
|
||||
defer fake.getNodeMutex.Unlock()
|
||||
fake.GetNodeStub = nil
|
||||
fake.getNodeReturns = struct {
|
||||
result1 *livekit.Node
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeReturnsOnCall(i int, result1 *livekit.Node, result2 error) {
|
||||
fake.getNodeMutex.Lock()
|
||||
defer fake.getNodeMutex.Unlock()
|
||||
fake.GetNodeStub = nil
|
||||
if fake.getNodeReturnsOnCall == nil {
|
||||
fake.getNodeReturnsOnCall = make(map[int]struct {
|
||||
result1 *livekit.Node
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.getNodeReturnsOnCall[i] = struct {
|
||||
result1 *livekit.Node
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeIdForRoom(arg1 string) (string, error) {
|
||||
fake.getNodeIdForRoomMutex.Lock()
|
||||
ret, specificReturn := fake.getNodeIdForRoomReturnsOnCall[len(fake.getNodeIdForRoomArgsForCall)]
|
||||
fake.getNodeIdForRoomArgsForCall = append(fake.getNodeIdForRoomArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.GetNodeIdForRoomStub
|
||||
fakeReturns := fake.getNodeIdForRoomReturns
|
||||
fake.recordInvocation("GetNodeIdForRoom", []interface{}{arg1})
|
||||
fake.getNodeIdForRoomMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeIdForRoomCallCount() int {
|
||||
fake.getNodeIdForRoomMutex.RLock()
|
||||
defer fake.getNodeIdForRoomMutex.RUnlock()
|
||||
return len(fake.getNodeIdForRoomArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeIdForRoomCalls(stub func(string) (string, error)) {
|
||||
fake.getNodeIdForRoomMutex.Lock()
|
||||
defer fake.getNodeIdForRoomMutex.Unlock()
|
||||
fake.GetNodeIdForRoomStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeIdForRoomArgsForCall(i int) string {
|
||||
fake.getNodeIdForRoomMutex.RLock()
|
||||
defer fake.getNodeIdForRoomMutex.RUnlock()
|
||||
argsForCall := fake.getNodeIdForRoomArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeIdForRoomReturns(result1 string, result2 error) {
|
||||
fake.getNodeIdForRoomMutex.Lock()
|
||||
defer fake.getNodeIdForRoomMutex.Unlock()
|
||||
fake.GetNodeIdForRoomStub = nil
|
||||
fake.getNodeIdForRoomReturns = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetNodeIdForRoomReturnsOnCall(i int, result1 string, result2 error) {
|
||||
fake.getNodeIdForRoomMutex.Lock()
|
||||
defer fake.getNodeIdForRoomMutex.Unlock()
|
||||
fake.GetNodeIdForRoomStub = nil
|
||||
if fake.getNodeIdForRoomReturnsOnCall == nil {
|
||||
fake.getNodeIdForRoomReturnsOnCall = make(map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.getNodeIdForRoomReturnsOnCall[i] = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetRequestSink(arg1 string) routing.MessageSink {
|
||||
fake.getRequestSinkMutex.Lock()
|
||||
ret, specificReturn := fake.getRequestSinkReturnsOnCall[len(fake.getRequestSinkArgsForCall)]
|
||||
fake.getRequestSinkArgsForCall = append(fake.getRequestSinkArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.GetRequestSinkStub
|
||||
fakeReturns := fake.getRequestSinkReturns
|
||||
fake.recordInvocation("GetRequestSink", []interface{}{arg1})
|
||||
fake.getRequestSinkMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetRequestSinkCallCount() int {
|
||||
fake.getRequestSinkMutex.RLock()
|
||||
defer fake.getRequestSinkMutex.RUnlock()
|
||||
return len(fake.getRequestSinkArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetRequestSinkCalls(stub func(string) routing.MessageSink) {
|
||||
fake.getRequestSinkMutex.Lock()
|
||||
defer fake.getRequestSinkMutex.Unlock()
|
||||
fake.GetRequestSinkStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetRequestSinkArgsForCall(i int) string {
|
||||
fake.getRequestSinkMutex.RLock()
|
||||
defer fake.getRequestSinkMutex.RUnlock()
|
||||
argsForCall := fake.getRequestSinkArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetRequestSinkReturns(result1 routing.MessageSink) {
|
||||
fake.getRequestSinkMutex.Lock()
|
||||
defer fake.getRequestSinkMutex.Unlock()
|
||||
fake.GetRequestSinkStub = nil
|
||||
fake.getRequestSinkReturns = struct {
|
||||
result1 routing.MessageSink
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetRequestSinkReturnsOnCall(i int, result1 routing.MessageSink) {
|
||||
fake.getRequestSinkMutex.Lock()
|
||||
defer fake.getRequestSinkMutex.Unlock()
|
||||
fake.GetRequestSinkStub = nil
|
||||
if fake.getRequestSinkReturnsOnCall == nil {
|
||||
fake.getRequestSinkReturnsOnCall = make(map[int]struct {
|
||||
result1 routing.MessageSink
|
||||
})
|
||||
}
|
||||
fake.getRequestSinkReturnsOnCall[i] = struct {
|
||||
result1 routing.MessageSink
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetResponseSource(arg1 string) routing.MessageSource {
|
||||
fake.getResponseSourceMutex.Lock()
|
||||
ret, specificReturn := fake.getResponseSourceReturnsOnCall[len(fake.getResponseSourceArgsForCall)]
|
||||
fake.getResponseSourceArgsForCall = append(fake.getResponseSourceArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.GetResponseSourceStub
|
||||
fakeReturns := fake.getResponseSourceReturns
|
||||
fake.recordInvocation("GetResponseSource", []interface{}{arg1})
|
||||
fake.getResponseSourceMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetResponseSourceCallCount() int {
|
||||
fake.getResponseSourceMutex.RLock()
|
||||
defer fake.getResponseSourceMutex.RUnlock()
|
||||
return len(fake.getResponseSourceArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetResponseSourceCalls(stub func(string) routing.MessageSource) {
|
||||
fake.getResponseSourceMutex.Lock()
|
||||
defer fake.getResponseSourceMutex.Unlock()
|
||||
fake.GetResponseSourceStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetResponseSourceArgsForCall(i int) string {
|
||||
fake.getResponseSourceMutex.RLock()
|
||||
defer fake.getResponseSourceMutex.RUnlock()
|
||||
argsForCall := fake.getResponseSourceArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetResponseSourceReturns(result1 routing.MessageSource) {
|
||||
fake.getResponseSourceMutex.Lock()
|
||||
defer fake.getResponseSourceMutex.Unlock()
|
||||
fake.GetResponseSourceStub = nil
|
||||
fake.getResponseSourceReturns = struct {
|
||||
result1 routing.MessageSource
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) GetResponseSourceReturnsOnCall(i int, result1 routing.MessageSource) {
|
||||
fake.getResponseSourceMutex.Lock()
|
||||
defer fake.getResponseSourceMutex.Unlock()
|
||||
fake.GetResponseSourceStub = nil
|
||||
if fake.getResponseSourceReturnsOnCall == nil {
|
||||
fake.getResponseSourceReturnsOnCall = make(map[int]struct {
|
||||
result1 routing.MessageSource
|
||||
})
|
||||
}
|
||||
fake.getResponseSourceReturnsOnCall[i] = struct {
|
||||
result1 routing.MessageSource
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) OnNewParticipant(arg1 routing.ParticipantCallback) {
|
||||
fake.onNewParticipantMutex.Lock()
|
||||
fake.onNewParticipantArgsForCall = append(fake.onNewParticipantArgsForCall, struct {
|
||||
arg1 routing.ParticipantCallback
|
||||
}{arg1})
|
||||
stub := fake.OnNewParticipantStub
|
||||
fake.recordInvocation("OnNewParticipant", []interface{}{arg1})
|
||||
fake.onNewParticipantMutex.Unlock()
|
||||
if stub != nil {
|
||||
fake.OnNewParticipantStub(arg1)
|
||||
}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) OnNewParticipantCallCount() int {
|
||||
fake.onNewParticipantMutex.RLock()
|
||||
defer fake.onNewParticipantMutex.RUnlock()
|
||||
return len(fake.onNewParticipantArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) OnNewParticipantCalls(stub func(routing.ParticipantCallback)) {
|
||||
fake.onNewParticipantMutex.Lock()
|
||||
defer fake.onNewParticipantMutex.Unlock()
|
||||
fake.OnNewParticipantStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) OnNewParticipantArgsForCall(i int) routing.ParticipantCallback {
|
||||
fake.onNewParticipantMutex.RLock()
|
||||
defer fake.onNewParticipantMutex.RUnlock()
|
||||
argsForCall := fake.onNewParticipantArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) RegisterNode(arg1 *livekit.Node) error {
|
||||
fake.registerNodeMutex.Lock()
|
||||
ret, specificReturn := fake.registerNodeReturnsOnCall[len(fake.registerNodeArgsForCall)]
|
||||
fake.registerNodeArgsForCall = append(fake.registerNodeArgsForCall, struct {
|
||||
arg1 *livekit.Node
|
||||
}{arg1})
|
||||
stub := fake.RegisterNodeStub
|
||||
fakeReturns := fake.registerNodeReturns
|
||||
fake.recordInvocation("RegisterNode", []interface{}{arg1})
|
||||
fake.registerNodeMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) RegisterNodeCallCount() int {
|
||||
fake.registerNodeMutex.RLock()
|
||||
defer fake.registerNodeMutex.RUnlock()
|
||||
return len(fake.registerNodeArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) RegisterNodeCalls(stub func(*livekit.Node) error) {
|
||||
fake.registerNodeMutex.Lock()
|
||||
defer fake.registerNodeMutex.Unlock()
|
||||
fake.RegisterNodeStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) RegisterNodeArgsForCall(i int) *livekit.Node {
|
||||
fake.registerNodeMutex.RLock()
|
||||
defer fake.registerNodeMutex.RUnlock()
|
||||
argsForCall := fake.registerNodeArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) RegisterNodeReturns(result1 error) {
|
||||
fake.registerNodeMutex.Lock()
|
||||
defer fake.registerNodeMutex.Unlock()
|
||||
fake.RegisterNodeStub = nil
|
||||
fake.registerNodeReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) RegisterNodeReturnsOnCall(i int, result1 error) {
|
||||
fake.registerNodeMutex.Lock()
|
||||
defer fake.registerNodeMutex.Unlock()
|
||||
fake.RegisterNodeStub = nil
|
||||
if fake.registerNodeReturnsOnCall == nil {
|
||||
fake.registerNodeReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.registerNodeReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) SetRTCNode(arg1 string, arg2 string) error {
|
||||
fake.setRTCNodeMutex.Lock()
|
||||
ret, specificReturn := fake.setRTCNodeReturnsOnCall[len(fake.setRTCNodeArgsForCall)]
|
||||
fake.setRTCNodeArgsForCall = append(fake.setRTCNodeArgsForCall, struct {
|
||||
arg1 string
|
||||
arg2 string
|
||||
}{arg1, arg2})
|
||||
stub := fake.SetRTCNodeStub
|
||||
fakeReturns := fake.setRTCNodeReturns
|
||||
fake.recordInvocation("SetRTCNode", []interface{}{arg1, arg2})
|
||||
fake.setRTCNodeMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1, arg2)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) SetRTCNodeCallCount() int {
|
||||
fake.setRTCNodeMutex.RLock()
|
||||
defer fake.setRTCNodeMutex.RUnlock()
|
||||
return len(fake.setRTCNodeArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) SetRTCNodeCalls(stub func(string, string) error) {
|
||||
fake.setRTCNodeMutex.Lock()
|
||||
defer fake.setRTCNodeMutex.Unlock()
|
||||
fake.SetRTCNodeStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) SetRTCNodeArgsForCall(i int) (string, string) {
|
||||
fake.setRTCNodeMutex.RLock()
|
||||
defer fake.setRTCNodeMutex.RUnlock()
|
||||
argsForCall := fake.setRTCNodeArgsForCall[i]
|
||||
return argsForCall.arg1, argsForCall.arg2
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) SetRTCNodeReturns(result1 error) {
|
||||
fake.setRTCNodeMutex.Lock()
|
||||
defer fake.setRTCNodeMutex.Unlock()
|
||||
fake.SetRTCNodeStub = nil
|
||||
fake.setRTCNodeReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) SetRTCNodeReturnsOnCall(i int, result1 error) {
|
||||
fake.setRTCNodeMutex.Lock()
|
||||
defer fake.setRTCNodeMutex.Unlock()
|
||||
fake.SetRTCNodeStub = nil
|
||||
if fake.setRTCNodeReturnsOnCall == nil {
|
||||
fake.setRTCNodeReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.setRTCNodeReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) Start() error {
|
||||
fake.startMutex.Lock()
|
||||
ret, specificReturn := fake.startReturnsOnCall[len(fake.startArgsForCall)]
|
||||
fake.startArgsForCall = append(fake.startArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.StartStub
|
||||
fakeReturns := fake.startReturns
|
||||
fake.recordInvocation("Start", []interface{}{})
|
||||
fake.startMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartCallCount() int {
|
||||
fake.startMutex.RLock()
|
||||
defer fake.startMutex.RUnlock()
|
||||
return len(fake.startArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartCalls(stub func() error) {
|
||||
fake.startMutex.Lock()
|
||||
defer fake.startMutex.Unlock()
|
||||
fake.StartStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartReturns(result1 error) {
|
||||
fake.startMutex.Lock()
|
||||
defer fake.startMutex.Unlock()
|
||||
fake.StartStub = nil
|
||||
fake.startReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartReturnsOnCall(i int, result1 error) {
|
||||
fake.startMutex.Lock()
|
||||
defer fake.startMutex.Unlock()
|
||||
fake.StartStub = nil
|
||||
if fake.startReturnsOnCall == nil {
|
||||
fake.startReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.startReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartParticipant(arg1 string, arg2 string, arg3 string, arg4 string) error {
|
||||
fake.startParticipantMutex.Lock()
|
||||
ret, specificReturn := fake.startParticipantReturnsOnCall[len(fake.startParticipantArgsForCall)]
|
||||
fake.startParticipantArgsForCall = append(fake.startParticipantArgsForCall, struct {
|
||||
arg1 string
|
||||
arg2 string
|
||||
arg3 string
|
||||
arg4 string
|
||||
}{arg1, arg2, arg3, arg4})
|
||||
stub := fake.StartParticipantStub
|
||||
fakeReturns := fake.startParticipantReturns
|
||||
fake.recordInvocation("StartParticipant", []interface{}{arg1, arg2, arg3, arg4})
|
||||
fake.startParticipantMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1, arg2, arg3, arg4)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartParticipantCallCount() int {
|
||||
fake.startParticipantMutex.RLock()
|
||||
defer fake.startParticipantMutex.RUnlock()
|
||||
return len(fake.startParticipantArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartParticipantCalls(stub func(string, string, string, string) error) {
|
||||
fake.startParticipantMutex.Lock()
|
||||
defer fake.startParticipantMutex.Unlock()
|
||||
fake.StartParticipantStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartParticipantArgsForCall(i int) (string, string, string, string) {
|
||||
fake.startParticipantMutex.RLock()
|
||||
defer fake.startParticipantMutex.RUnlock()
|
||||
argsForCall := fake.startParticipantArgsForCall[i]
|
||||
return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartParticipantReturns(result1 error) {
|
||||
fake.startParticipantMutex.Lock()
|
||||
defer fake.startParticipantMutex.Unlock()
|
||||
fake.StartParticipantStub = nil
|
||||
fake.startParticipantReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StartParticipantReturnsOnCall(i int, result1 error) {
|
||||
fake.startParticipantMutex.Lock()
|
||||
defer fake.startParticipantMutex.Unlock()
|
||||
fake.StartParticipantStub = nil
|
||||
if fake.startParticipantReturnsOnCall == nil {
|
||||
fake.startParticipantReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.startParticipantReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) Stop() {
|
||||
fake.stopMutex.Lock()
|
||||
fake.stopArgsForCall = append(fake.stopArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.StopStub
|
||||
fake.recordInvocation("Stop", []interface{}{})
|
||||
fake.stopMutex.Unlock()
|
||||
if stub != nil {
|
||||
fake.StopStub()
|
||||
}
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StopCallCount() int {
|
||||
fake.stopMutex.RLock()
|
||||
defer fake.stopMutex.RUnlock()
|
||||
return len(fake.stopArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) StopCalls(stub func()) {
|
||||
fake.stopMutex.Lock()
|
||||
defer fake.stopMutex.Unlock()
|
||||
fake.StopStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.getNodeMutex.RLock()
|
||||
defer fake.getNodeMutex.RUnlock()
|
||||
fake.getNodeIdForRoomMutex.RLock()
|
||||
defer fake.getNodeIdForRoomMutex.RUnlock()
|
||||
fake.getRequestSinkMutex.RLock()
|
||||
defer fake.getRequestSinkMutex.RUnlock()
|
||||
fake.getResponseSourceMutex.RLock()
|
||||
defer fake.getResponseSourceMutex.RUnlock()
|
||||
fake.onNewParticipantMutex.RLock()
|
||||
defer fake.onNewParticipantMutex.RUnlock()
|
||||
fake.registerNodeMutex.RLock()
|
||||
defer fake.registerNodeMutex.RUnlock()
|
||||
fake.setRTCNodeMutex.RLock()
|
||||
defer fake.setRTCNodeMutex.RUnlock()
|
||||
fake.startMutex.RLock()
|
||||
defer fake.startMutex.RUnlock()
|
||||
fake.startParticipantMutex.RLock()
|
||||
defer fake.startParticipantMutex.RUnlock()
|
||||
fake.stopMutex.RLock()
|
||||
defer fake.stopMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeRouter) recordInvocation(key string, args []interface{}) {
|
||||
fake.invocationsMutex.Lock()
|
||||
defer fake.invocationsMutex.Unlock()
|
||||
if fake.invocations == nil {
|
||||
fake.invocations = map[string][][]interface{}{}
|
||||
}
|
||||
if fake.invocations[key] == nil {
|
||||
fake.invocations[key] = [][]interface{}{}
|
||||
}
|
||||
fake.invocations[key] = append(fake.invocations[key], args)
|
||||
}
|
||||
|
||||
var _ routing.Router = new(FakeRouter)
|
||||
+4
-2
@@ -19,7 +19,9 @@ type ReceiverConfig struct {
|
||||
maxBufferTime int
|
||||
}
|
||||
|
||||
func NewWebRTCConfig(conf *config.RTCConfig, externalIP string) (*WebRTCConfig, error) {
|
||||
type ExternalIP string
|
||||
|
||||
func NewWebRTCConfig(conf *config.RTCConfig, externalIP ExternalIP) (*WebRTCConfig, error) {
|
||||
c := webrtc.Configuration{
|
||||
SDPSemantics: webrtc.SDPSemanticsUnifiedPlan,
|
||||
}
|
||||
@@ -41,7 +43,7 @@ func NewWebRTCConfig(conf *config.RTCConfig, externalIP string) (*WebRTCConfig,
|
||||
},
|
||||
}
|
||||
if conf.UseExternalIP {
|
||||
s.SetNAT1To1IPs([]string{externalIP}, webrtc.ICECandidateTypeHost)
|
||||
s.SetNAT1To1IPs([]string{string(externalIP)}, webrtc.ICECandidateTypeHost)
|
||||
}
|
||||
|
||||
return &WebRTCConfig{
|
||||
|
||||
@@ -141,7 +141,7 @@ func (t *DataTrack) forwardWorker() {
|
||||
for _, sub := range t.subscribers {
|
||||
err := sub.SendMessage(msg)
|
||||
if err != nil {
|
||||
logger.GetLogger().Errorw("could not send data message",
|
||||
logger.Errorw("could not send data message",
|
||||
"err", err,
|
||||
"source", t.participantId,
|
||||
"dest", sub.participantId)
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
package rtc
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
// A RoomManager maintains active rooms that are hosted on the current node
|
||||
type RoomManager struct {
|
||||
rtcConf config.RTCConfig
|
||||
externalIP string
|
||||
|
||||
config WebRTCConfig
|
||||
|
||||
rooms map[string]*Room
|
||||
roomsByName map[string]*Room
|
||||
roomLock sync.RWMutex
|
||||
}
|
||||
|
||||
func NewRoomManager(rtcConf config.RTCConfig, externalIP string) (m *RoomManager, err error) {
|
||||
m = &RoomManager{
|
||||
rtcConf: rtcConf,
|
||||
externalIP: externalIP,
|
||||
rooms: make(map[string]*Room),
|
||||
roomsByName: make(map[string]*Room),
|
||||
roomLock: sync.RWMutex{},
|
||||
}
|
||||
|
||||
wc, err := NewWebRTCConfig(&rtcConf, externalIP)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m.config = *wc
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RoomManager) GetRoom(idOrName string) *Room {
|
||||
m.roomLock.RLock()
|
||||
defer m.roomLock.RUnlock()
|
||||
rm := m.rooms[idOrName]
|
||||
if rm == nil {
|
||||
rm = m.roomsByName[idOrName]
|
||||
}
|
||||
return rm
|
||||
}
|
||||
|
||||
func (m *RoomManager) GetRoomWithConstraint(idOrName string, onlyName string) (*Room, error) {
|
||||
if idOrName == "" {
|
||||
idOrName = onlyName
|
||||
}
|
||||
if idOrName == "" {
|
||||
return nil, ErrRoomIdMissing
|
||||
}
|
||||
|
||||
rm := m.GetRoom(idOrName)
|
||||
if rm == nil {
|
||||
return nil, ErrRoomNotFound
|
||||
}
|
||||
|
||||
if onlyName != "" && rm.Name != onlyName {
|
||||
return nil, ErrPermissionDenied
|
||||
}
|
||||
return rm, nil
|
||||
}
|
||||
|
||||
func (m *RoomManager) CreateRoom(req *livekit.CreateRoomRequest) (*Room, error) {
|
||||
if req.Name == "" {
|
||||
return nil, ErrInvalidRoomName
|
||||
}
|
||||
r := NewRoomForRequest(req, &m.config)
|
||||
m.roomLock.Lock()
|
||||
defer m.roomLock.Unlock()
|
||||
|
||||
if m.roomsByName[req.Name] != nil {
|
||||
return nil, ErrInvalidRoomName
|
||||
}
|
||||
|
||||
m.rooms[r.Sid] = r
|
||||
m.roomsByName[r.Name] = r
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (m *RoomManager) DeleteRoom(idOrName string) error {
|
||||
rm := m.GetRoom(idOrName)
|
||||
if rm == nil {
|
||||
return nil
|
||||
}
|
||||
m.roomLock.Lock()
|
||||
defer m.roomLock.Unlock()
|
||||
delete(m.rooms, rm.Sid)
|
||||
delete(m.roomsByName, rm.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *RoomManager) Config() *WebRTCConfig {
|
||||
return &m.config
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package rtc_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
func TestRoomManager_CreateRoom(t *testing.T) {
|
||||
man := newRoomManager(t)
|
||||
|
||||
t.Run("creation and duplicates", func(t *testing.T) {
|
||||
r := &livekit.CreateRoomRequest{Name: "basic"}
|
||||
rm, err := man.CreateRoom(r)
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, rm)
|
||||
|
||||
rm, err = man.CreateRoom(r)
|
||||
assert.Equal(t, rtc.ErrInvalidRoomName, err)
|
||||
assert.Nil(t, rm)
|
||||
})
|
||||
|
||||
t.Run("name is required", func(t *testing.T) {
|
||||
_, err := man.CreateRoom(&livekit.CreateRoomRequest{})
|
||||
assert.Equal(t, rtc.ErrInvalidRoomName, err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRoomManager_GetRoomByName(t *testing.T) {
|
||||
man := newRoomManager(t)
|
||||
_, err := man.CreateRoom(&livekit.CreateRoomRequest{
|
||||
Name: "hello",
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
|
||||
rm := man.GetRoom("hello")
|
||||
assert.Equal(t, "hello", rm.Name)
|
||||
}
|
||||
|
||||
func TestRoomManager_GetRoomWithConstraint(t *testing.T) {
|
||||
man := newRoomManager(t)
|
||||
rm, _ := man.CreateRoom(&livekit.CreateRoomRequest{
|
||||
Name: "hello",
|
||||
})
|
||||
|
||||
t.Run("no constraint, get by id", func(t *testing.T) {
|
||||
r, err := man.GetRoomWithConstraint(rm.Sid, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, r, rm)
|
||||
})
|
||||
|
||||
t.Run("no constraint, get by name", func(t *testing.T) {
|
||||
r, err := man.GetRoomWithConstraint(rm.Name, "")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, r, rm)
|
||||
})
|
||||
|
||||
t.Run("no constraint, room doesn't exist", func(t *testing.T) {
|
||||
_, err := man.GetRoomWithConstraint("wtf", "")
|
||||
assert.Equal(t, rtc.ErrRoomNotFound, err)
|
||||
})
|
||||
|
||||
t.Run("constraint, no name", func(t *testing.T) {
|
||||
r, err := man.GetRoomWithConstraint("", rm.Name)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, r, rm)
|
||||
})
|
||||
|
||||
t.Run("constraint does not match name", func(t *testing.T) {
|
||||
_, err := man.GetRoomWithConstraint(rm.Name, "anotherroom")
|
||||
assert.Equal(t, rtc.ErrPermissionDenied, err)
|
||||
})
|
||||
}
|
||||
|
||||
func newRoomManager(t *testing.T) *rtc.RoomManager {
|
||||
man, err := rtc.NewRoomManager(config.RTCConfig{}, "1.2.3.4")
|
||||
assert.NoError(t, err)
|
||||
return man
|
||||
}
|
||||
@@ -152,13 +152,13 @@ func (t *MediaTrack) AddSubscriber(participant types.Participant) error {
|
||||
// however, if the dest participant has disconnected, then we can skip
|
||||
sender := transceiver.Sender()
|
||||
if sender != nil {
|
||||
logger.GetLogger().Debugw("removing peerconnection track",
|
||||
logger.Debugw("removing peerconnection track",
|
||||
"track", t.id,
|
||||
"srcParticipant", t.participantId,
|
||||
"destParticipant", participant.ID())
|
||||
if err := participant.PeerConnection().RemoveTrack(sender); err != nil {
|
||||
if _, ok := err.(*rtcerr.InvalidStateError); !ok {
|
||||
logger.GetLogger().Warnw("could not remove remoteTrack from forwarder",
|
||||
logger.Warnw("could not remove remoteTrack from forwarder",
|
||||
"participant", participant.ID(),
|
||||
"err", err)
|
||||
}
|
||||
@@ -188,7 +188,7 @@ func (t *MediaTrack) RemoveSubscriber(participantId string) {
|
||||
}
|
||||
|
||||
func (t *MediaTrack) RemoveAllSubscribers() {
|
||||
logger.GetLogger().Debugw("removing all subscribers", "track", t.id)
|
||||
logger.Debugw("removing all subscribers", "track", t.id)
|
||||
t.lock.RLock()
|
||||
defer t.lock.RUnlock()
|
||||
for _, dt := range t.downtracks {
|
||||
@@ -244,7 +244,7 @@ func (t *MediaTrack) forwardRTPWorker() {
|
||||
}()
|
||||
|
||||
for pkt := range t.receiver.RTPChan() {
|
||||
//logger.GetLogger().Debugw("read packet from remoteTrack",
|
||||
//logger.Debugw("read packet from remoteTrack",
|
||||
// "participant", t.participantId,
|
||||
// "track", t.ID())
|
||||
// when track is muted, it's "disabled" on the client side, and will still be sending black frames
|
||||
@@ -255,7 +255,7 @@ func (t *MediaTrack) forwardRTPWorker() {
|
||||
|
||||
t.lock.RLock()
|
||||
for dstId, dt := range t.downtracks {
|
||||
//logger.GetLogger().Debugw("read packet from remoteTrack",
|
||||
//logger.Debugw("read packet from remoteTrack",
|
||||
// "srcParticipant", t.participantId,
|
||||
// "destParticipant", dstId,
|
||||
// "track", t.ID())
|
||||
@@ -271,7 +271,7 @@ func (t *MediaTrack) forwardRTPWorker() {
|
||||
if delta < maxPLIFrequency {
|
||||
continue
|
||||
}
|
||||
logger.GetLogger().Infow("keyframe required, sending PLI",
|
||||
logger.Infow("keyframe required, sending PLI",
|
||||
"srcParticipant", t.participantId)
|
||||
rtcpPkts := []rtcp.Packet{
|
||||
&rtcp.PictureLossIndication{SenderSSRC: uint32(t.ssrc), MediaSSRC: pkt.SSRC},
|
||||
@@ -279,7 +279,7 @@ func (t *MediaTrack) forwardRTPWorker() {
|
||||
t.rtcpCh <- rtcpPkts
|
||||
t.lastPLI = time.Now()
|
||||
} else if err != nil {
|
||||
logger.GetLogger().Warnw("could not forward packet to participant",
|
||||
logger.Warnw("could not forward packet to participant",
|
||||
"src", t.participantId,
|
||||
"dest", dstId,
|
||||
"remoteTrack", t.id,
|
||||
@@ -294,7 +294,7 @@ func (t *MediaTrack) handleRTCP(dt *sfu.DownTrack, rtcpBuf []byte) {
|
||||
defer Recover()
|
||||
pkts, err := rtcp.Unmarshal(rtcpBuf)
|
||||
if err != nil {
|
||||
logger.GetLogger().Warnw("could not decode RTCP packet", "err", err)
|
||||
logger.Warnw("could not decode RTCP packet", "err", err)
|
||||
}
|
||||
|
||||
var fwdPkts []rtcp.Packet
|
||||
@@ -322,7 +322,7 @@ func (t *MediaTrack) handleRTCP(dt *sfu.DownTrack, rtcpBuf []byte) {
|
||||
//log.Tracef("Slow link for sender %s, fraction packet lost %.2f", f.track.peerID, float64(p.Reports[0].FractionLost)/256)
|
||||
}
|
||||
case *rtcp.TransportLayerNack:
|
||||
logger.GetLogger().Debugw("forwarder got nack",
|
||||
logger.Debugw("forwarder got nack",
|
||||
"packet", p)
|
||||
var nackedPackets []uint16
|
||||
for _, pair := range p.Nacks {
|
||||
|
||||
+32
-30
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/pkg/sfu"
|
||||
"github.com/livekit/livekit-server/pkg/utils"
|
||||
@@ -33,7 +34,7 @@ const (
|
||||
type ParticipantImpl struct {
|
||||
id string
|
||||
peerConn types.PeerConnection
|
||||
sigConn types.SignalConnection
|
||||
responseSink routing.MessageSink
|
||||
receiverConfig ReceiverConfig
|
||||
ctx context.Context
|
||||
cancel context.CancelFunc
|
||||
@@ -69,19 +70,21 @@ func NewPeerConnection(conf *WebRTCConfig) (*webrtc.PeerConnection, error) {
|
||||
se.BufferFactory = bufferFactory.GetOrNew
|
||||
|
||||
api := webrtc.NewAPI(webrtc.WithMediaEngine(me), webrtc.WithSettingEngine(se))
|
||||
return api.NewPeerConnection(conf.Configuration)
|
||||
pc, err := api.NewPeerConnection(conf.Configuration)
|
||||
return pc, err
|
||||
}
|
||||
|
||||
func NewParticipant(pc types.PeerConnection, sc types.SignalConnection, name string, receiverConfig ReceiverConfig) (*ParticipantImpl, error) {
|
||||
func NewParticipant(participantId, name string, pc types.PeerConnection, rs routing.MessageSink, receiverConfig ReceiverConfig) (*ParticipantImpl, error) {
|
||||
// TODO: check to ensure params are valid, id and name can't be empty
|
||||
me := &webrtc.MediaEngine{}
|
||||
me.RegisterDefaultCodecs()
|
||||
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
participant := &ParticipantImpl{
|
||||
id: utils.NewGuid(utils.ParticipantPrefix),
|
||||
id: participantId,
|
||||
name: name,
|
||||
peerConn: pc,
|
||||
sigConn: sc,
|
||||
responseSink: rs,
|
||||
receiverConfig: receiverConfig,
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
@@ -96,7 +99,6 @@ func NewParticipant(pc types.PeerConnection, sc types.SignalConnection, name str
|
||||
debouncedNegotiate: debounce.New(negotiationFrequency),
|
||||
}
|
||||
|
||||
log := logger.GetLogger()
|
||||
pc.OnTrack(participant.onMediaTrack)
|
||||
|
||||
pc.OnICECandidate(func(c *webrtc.ICECandidate) {
|
||||
@@ -107,14 +109,14 @@ func NewParticipant(pc types.PeerConnection, sc types.SignalConnection, name str
|
||||
ci := c.ToJSON()
|
||||
|
||||
// write candidate
|
||||
logger.GetLogger().Debugw("sending ice candidates")
|
||||
err := sc.WriteResponse(&livekit.SignalResponse{
|
||||
logger.Debugw("sending ice candidates")
|
||||
err := rs.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Trickle{
|
||||
Trickle: ToProtoTrickle(ci),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
log.Errorw("could not send trickle", "err", err)
|
||||
logger.Errorw("could not send trickle", "err", err)
|
||||
}
|
||||
|
||||
if participant.onICECandidate != nil {
|
||||
@@ -123,7 +125,7 @@ func NewParticipant(pc types.PeerConnection, sc types.SignalConnection, name str
|
||||
})
|
||||
|
||||
pc.OnICEConnectionStateChange(func(state webrtc.ICEConnectionState) {
|
||||
logger.GetLogger().Debugw("ICE connection state changed", "state", state.String())
|
||||
logger.Debugw("ICE connection state changed", "state", state.String())
|
||||
if state == webrtc.ICEConnectionStateConnected {
|
||||
participant.updateState(livekit.ParticipantInfo_ACTIVE)
|
||||
}
|
||||
@@ -228,7 +230,7 @@ func (p *ParticipantImpl) Answer(sdp webrtc.SessionDescription) (answer webrtc.S
|
||||
}
|
||||
p.negotiationCond.L.Unlock()
|
||||
|
||||
err = p.sigConn.WriteResponse(&livekit.SignalResponse{
|
||||
err = p.responseSink.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Answer{
|
||||
Answer: ToProtoSessionDescription(answer),
|
||||
},
|
||||
@@ -252,7 +254,7 @@ func (p *ParticipantImpl) AddTrack(clientId, name string, trackType livekit.Trac
|
||||
}
|
||||
p.pendingTracks[clientId] = ti
|
||||
|
||||
p.sigConn.WriteResponse(&livekit.SignalResponse{
|
||||
p.responseSink.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_TrackPublished{
|
||||
TrackPublished: &livekit.TrackPublishedResponse{
|
||||
Cid: clientId,
|
||||
@@ -266,7 +268,7 @@ func (p *ParticipantImpl) HandleAnswer(sdp webrtc.SessionDescription) error {
|
||||
if sdp.Type != webrtc.SDPTypeAnswer {
|
||||
return ErrUnexpectedOffer
|
||||
}
|
||||
logger.GetLogger().Debugw("setting remote answer")
|
||||
logger.Debugw("setting remote answer")
|
||||
if err := p.peerConn.SetRemoteDescription(sdp); err != nil {
|
||||
return errors.Wrap(err, "could not set remote description")
|
||||
}
|
||||
@@ -288,7 +290,7 @@ func (p *ParticipantImpl) HandleClientNegotiation() {
|
||||
}
|
||||
p.negotiationState = negotiationStateClient
|
||||
p.negotiationCond.L.Unlock()
|
||||
p.sigConn.WriteResponse(&livekit.SignalResponse{
|
||||
p.responseSink.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Negotiate{
|
||||
Negotiate: &livekit.NegotiationResponse{},
|
||||
},
|
||||
@@ -329,7 +331,7 @@ func (p *ParticipantImpl) AddSubscriber(op types.Participant) error {
|
||||
defer p.lock.RUnlock()
|
||||
|
||||
for _, track := range p.publishedTracks {
|
||||
logger.GetLogger().Debugw("subscribing to remoteTrack",
|
||||
logger.Debugw("subscribing to remoteTrack",
|
||||
"srcParticipant", p.ID(),
|
||||
"dstParticipant", op.ID(),
|
||||
"remoteTrack", track.ID())
|
||||
@@ -350,9 +352,9 @@ func (p *ParticipantImpl) RemoveSubscriber(participantId string) {
|
||||
}
|
||||
|
||||
// signal connection methods
|
||||
func (p *ParticipantImpl) SendJoinResponse(roomInfo *livekit.RoomInfo, otherParticipants []types.Participant) error {
|
||||
func (p *ParticipantImpl) SendJoinResponse(roomInfo *livekit.Room, otherParticipants []types.Participant) error {
|
||||
// send Join response
|
||||
return p.sigConn.WriteResponse(&livekit.SignalResponse{
|
||||
return p.responseSink.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Join{
|
||||
Join: &livekit.JoinResponse{
|
||||
Room: roomInfo,
|
||||
@@ -364,7 +366,7 @@ func (p *ParticipantImpl) SendJoinResponse(roomInfo *livekit.RoomInfo, otherPart
|
||||
}
|
||||
|
||||
func (p *ParticipantImpl) SendParticipantUpdate(participants []*livekit.ParticipantInfo) error {
|
||||
return p.sigConn.WriteResponse(&livekit.SignalResponse{
|
||||
return p.responseSink.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Update{
|
||||
Update: &livekit.ParticipantUpdate{
|
||||
Participants: participants,
|
||||
@@ -429,10 +431,10 @@ func (p *ParticipantImpl) negotiate() {
|
||||
}
|
||||
p.negotiationCond.L.Unlock()
|
||||
|
||||
logger.GetLogger().Debugw("starting negotiation", "participant", p.ID())
|
||||
logger.Debugw("starting negotiation", "participant", p.ID())
|
||||
offer, err := p.peerConn.CreateOffer(nil)
|
||||
if err != nil {
|
||||
logger.GetLogger().Errorw("could not create offer", "err", err)
|
||||
logger.Errorw("could not create offer", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -444,18 +446,18 @@ func (p *ParticipantImpl) negotiate() {
|
||||
|
||||
err = p.peerConn.SetLocalDescription(offer)
|
||||
if err != nil {
|
||||
logger.GetLogger().Errorw("could not set local description", "err", err)
|
||||
logger.Errorw("could not set local description", "err", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.GetLogger().Debugw("sending available offer to participant")
|
||||
err = p.sigConn.WriteResponse(&livekit.SignalResponse{
|
||||
logger.Debugw("sending available offer to participant")
|
||||
err = p.responseSink.WriteMessage(&livekit.SignalResponse{
|
||||
Message: &livekit.SignalResponse_Offer{
|
||||
Offer: ToProtoSessionDescription(offer),
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logger.GetLogger().Errorw("could not send offer to peer",
|
||||
logger.Errorw("could not send offer to peer",
|
||||
"err", err)
|
||||
}
|
||||
}
|
||||
@@ -477,7 +479,7 @@ func (p *ParticipantImpl) updateState(state livekit.ParticipantInfo_State) {
|
||||
|
||||
// when a new remoteTrack is created, creates a Track and adds it to room
|
||||
func (p *ParticipantImpl) onMediaTrack(track *webrtc.TrackRemote, rtpReceiver *webrtc.RTPReceiver) {
|
||||
logger.GetLogger().Debugw("mediaTrack added", "participantId", p.ID(), "remoteTrack", track.ID())
|
||||
logger.Debugw("mediaTrack added", "participantId", p.ID(), "remoteTrack", track.ID())
|
||||
|
||||
ti := p.popPendingTrack(track.ID())
|
||||
if ti == nil {
|
||||
@@ -496,7 +498,7 @@ func (p *ParticipantImpl) onDataChannel(dc *webrtc.DataChannel) {
|
||||
if dc.Label() == placeholderDataChannel {
|
||||
return
|
||||
}
|
||||
logger.GetLogger().Debugw("dataChannel added", "participantId", p.ID(), "label", dc.Label())
|
||||
logger.Debugw("dataChannel added", "participantId", p.ID(), "label", dc.Label())
|
||||
|
||||
// data channels have numeric ids, so we use its label to identify
|
||||
ti := p.popPendingTrack(dc.Label())
|
||||
@@ -515,7 +517,7 @@ func (p *ParticipantImpl) popPendingTrack(clientId string) *livekit.TrackInfo {
|
||||
defer p.lock.Unlock()
|
||||
ti := p.pendingTracks[clientId]
|
||||
if ti == nil {
|
||||
logger.GetLogger().Errorw("track info not published prior to track", "clientId", clientId)
|
||||
logger.Errorw("track info not published prior to track", "clientId", clientId)
|
||||
} else {
|
||||
delete(p.pendingTracks, clientId)
|
||||
}
|
||||
@@ -584,7 +586,7 @@ func (p *ParticipantImpl) downTracksRTCPWorker() {
|
||||
if err == io.EOF || err == io.ErrClosedPipe {
|
||||
return
|
||||
}
|
||||
logger.GetLogger().Errorw("could not send downtrack reports",
|
||||
logger.Errorw("could not send downtrack reports",
|
||||
"participant", p.id,
|
||||
"err", err)
|
||||
}
|
||||
@@ -598,10 +600,10 @@ func (p *ParticipantImpl) rtcpSendWorker() {
|
||||
// read from rtcpChan
|
||||
for pkts := range p.rtcpCh {
|
||||
//for _, pkt := range pkts {
|
||||
// logger.GetLogger().Debugw("writing RTCP", "packet", pkt)
|
||||
// logger.Debugw("writing RTCP", "packet", pkt)
|
||||
//}
|
||||
if err := p.peerConn.WriteRTCP(pkts); err != nil {
|
||||
logger.GetLogger().Errorw("could not write RTCP to participant",
|
||||
logger.Errorw("could not write RTCP to participant",
|
||||
"participant", p.id,
|
||||
"err", err)
|
||||
}
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing/routingfakes"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types/typesfakes"
|
||||
"github.com/livekit/livekit-server/pkg/utils"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
@@ -67,6 +69,11 @@ func TestTrackPublishEvents(t *testing.T) {
|
||||
}
|
||||
|
||||
func newParticipantForTest(name string) *ParticipantImpl {
|
||||
p, _ := NewParticipant(&typesfakes.FakePeerConnection{}, &typesfakes.FakeSignalConnection{}, name, ReceiverConfig{})
|
||||
p, _ := NewParticipant(
|
||||
utils.NewGuid(utils.ParticipantPrefix),
|
||||
name,
|
||||
&typesfakes.FakePeerConnection{},
|
||||
&routingfakes.FakeMessageSink{},
|
||||
ReceiverConfig{})
|
||||
return p
|
||||
}
|
||||
|
||||
+1
-1
@@ -52,7 +52,7 @@ func NewReceiver(rtcpCh chan []rtcp.Packet, rtpReceiver *webrtc.RTPReceiver, tra
|
||||
r.rtcpReader.OnPacket(func(bytes []byte) {
|
||||
pkts, err := rtcp.Unmarshal(bytes)
|
||||
if err != nil {
|
||||
logger.GetLogger().Warnw("could not unmarshal RTCP packet")
|
||||
logger.Warnw("could not unmarshal RTCP packet")
|
||||
return
|
||||
}
|
||||
for _, pkt := range pkts {
|
||||
|
||||
+10
-32
@@ -2,13 +2,11 @@ package rtc
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/thoas/go-funk"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/pkg/utils"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
@@ -20,16 +18,10 @@ type Room struct {
|
||||
participants map[string]types.Participant
|
||||
}
|
||||
|
||||
func NewRoomForRequest(req *livekit.CreateRoomRequest, config *WebRTCConfig) *Room {
|
||||
func NewRoom(room *livekit.Room, config WebRTCConfig) *Room {
|
||||
return &Room{
|
||||
Room: livekit.Room{
|
||||
Sid: utils.NewGuid(utils.RoomPrefix),
|
||||
Name: req.Name,
|
||||
EmptyTimeout: req.EmptyTimeout,
|
||||
MaxParticipants: req.MaxParticipants,
|
||||
CreationTime: time.Now().Unix(),
|
||||
},
|
||||
config: *config,
|
||||
Room: *room,
|
||||
config: config,
|
||||
lock: sync.RWMutex{},
|
||||
participants: make(map[string]types.Participant),
|
||||
}
|
||||
@@ -47,28 +39,14 @@ func (r *Room) GetParticipants() []types.Participant {
|
||||
return funk.Values(r.participants).([]types.Participant)
|
||||
}
|
||||
|
||||
func (r *Room) ToRoomInfo(node *livekit.Node) *livekit.RoomInfo {
|
||||
ri := &livekit.RoomInfo{
|
||||
Sid: r.Sid,
|
||||
Name: r.Name,
|
||||
CreationTime: r.CreationTime,
|
||||
}
|
||||
if node != nil {
|
||||
ri.NodeIp = node.Ip
|
||||
}
|
||||
return ri
|
||||
}
|
||||
|
||||
func (r *Room) Join(participant types.Participant) error {
|
||||
r.lock.Lock()
|
||||
defer r.lock.Unlock()
|
||||
|
||||
log := logger.GetLogger()
|
||||
|
||||
// it's important to set this before connection, we don't want to miss out on any publishedTracks
|
||||
participant.OnTrackPublished(r.onTrackAdded)
|
||||
participant.OnStateChange(func(p types.Participant, oldState livekit.ParticipantInfo_State) {
|
||||
log.Debugw("participant state changed", "state", p.State(), "participant", p.ID(),
|
||||
logger.Debugw("participant state changed", "state", p.State(), "participant", p.ID(),
|
||||
"oldState", oldState)
|
||||
r.broadcastParticipantState(p)
|
||||
|
||||
@@ -81,7 +59,7 @@ func (r *Room) Join(participant types.Participant) error {
|
||||
}
|
||||
if err := op.AddSubscriber(p); err != nil {
|
||||
// TODO: log error? or disconnect?
|
||||
logger.GetLogger().Errorw("could not subscribe to participant",
|
||||
logger.Errorw("could not subscribe to participant",
|
||||
"dstParticipant", p.ID(),
|
||||
"srcParticipant", op.ID())
|
||||
}
|
||||
@@ -92,7 +70,7 @@ func (r *Room) Join(participant types.Participant) error {
|
||||
})
|
||||
participant.OnTrackUpdated(r.onTrackUpdated)
|
||||
|
||||
log.Infow("new participant joined",
|
||||
logger.Infow("new participant joined",
|
||||
"id", participant.ID(),
|
||||
"name", participant.Name(),
|
||||
"roomId", r.Sid)
|
||||
@@ -107,7 +85,7 @@ func (r *Room) Join(participant types.Participant) error {
|
||||
}
|
||||
}
|
||||
|
||||
return participant.SendJoinResponse(r.ToRoomInfo(nil), otherParticipants)
|
||||
return participant.SendJoinResponse(&r.Room, otherParticipants)
|
||||
}
|
||||
|
||||
func (r *Room) RemoveParticipant(id string) {
|
||||
@@ -145,12 +123,12 @@ func (r *Room) onTrackAdded(participant types.Participant, track types.Published
|
||||
// not fully joined. don't subscribe yet
|
||||
continue
|
||||
}
|
||||
logger.GetLogger().Debugw("subscribing to new track",
|
||||
logger.Debugw("subscribing to new track",
|
||||
"srcParticipant", participant.ID(),
|
||||
"remoteTrack", track.ID(),
|
||||
"dstParticipant", existingParticipant.ID())
|
||||
if err := track.AddSubscriber(existingParticipant); err != nil {
|
||||
logger.GetLogger().Errorw("could not subscribe to remoteTrack",
|
||||
logger.Errorw("could not subscribe to remoteTrack",
|
||||
"srcParticipant", participant.ID(),
|
||||
"remoteTrack", track.ID(),
|
||||
"dstParticipant", existingParticipant.ID())
|
||||
@@ -176,7 +154,7 @@ func (r *Room) broadcastParticipantState(p types.Participant) {
|
||||
|
||||
err := op.SendParticipantUpdate(updates)
|
||||
if err != nil {
|
||||
logger.GetLogger().Errorw("could not send update to participant",
|
||||
logger.Errorw("could not send update to participant",
|
||||
"participant", p.ID(),
|
||||
"err", err)
|
||||
}
|
||||
|
||||
+4
-27
@@ -15,32 +15,6 @@ const (
|
||||
numParticipants = 3
|
||||
)
|
||||
|
||||
func TestNewRoomForRequest(t *testing.T) {
|
||||
req := &livekit.CreateRoomRequest{
|
||||
Name: "myroom",
|
||||
EmptyTimeout: 120,
|
||||
MaxParticipants: 50,
|
||||
}
|
||||
|
||||
rm := rtc.NewRoomForRequest(req, &rtc.WebRTCConfig{})
|
||||
assert.NotEmpty(t, rm.Sid)
|
||||
assert.Equal(t, req.Name, rm.Name)
|
||||
assert.Equal(t, req.EmptyTimeout, rm.EmptyTimeout)
|
||||
assert.Equal(t, req.MaxParticipants, rm.MaxParticipants)
|
||||
}
|
||||
|
||||
func TestToRoomInfo(t *testing.T) {
|
||||
rm := rtc.NewRoomForRequest(&livekit.CreateRoomRequest{
|
||||
Name: "myroom",
|
||||
EmptyTimeout: 120,
|
||||
MaxParticipants: 50,
|
||||
}, &rtc.WebRTCConfig{})
|
||||
info := rm.ToRoomInfo(&livekit.Node{Ip: "0.0.0.0"})
|
||||
assert.Equal(t, rm.Sid, info.Sid)
|
||||
assert.Equal(t, rm.Name, info.Name)
|
||||
assert.Equal(t, "0.0.0.0", info.NodeIp)
|
||||
}
|
||||
|
||||
func TestRoomJoin(t *testing.T) {
|
||||
t.Run("joining returns existing participant data", func(t *testing.T) {
|
||||
rm := newRoomWithParticipants(t, numParticipants)
|
||||
@@ -123,7 +97,10 @@ func TestNewTrack(t *testing.T) {
|
||||
}
|
||||
|
||||
func newRoomWithParticipants(t *testing.T, num int) *rtc.Room {
|
||||
rm := rtc.NewRoomForRequest(&livekit.CreateRoomRequest{}, &rtc.WebRTCConfig{})
|
||||
rm := rtc.NewRoom(
|
||||
&livekit.Room{Name: "name"},
|
||||
rtc.WebRTCConfig{},
|
||||
)
|
||||
for i := 0; i < num; i++ {
|
||||
participant := newMockParticipant("")
|
||||
err := rm.Join(participant)
|
||||
|
||||
@@ -20,12 +20,6 @@ type WebsocketClient interface {
|
||||
WriteControl(messageType int, data []byte, deadline time.Time) error
|
||||
}
|
||||
|
||||
//counterfeiter:generate . SignalConnection
|
||||
type SignalConnection interface {
|
||||
ReadRequest() (*livekit.SignalRequest, error)
|
||||
WriteResponse(*livekit.SignalResponse) error
|
||||
}
|
||||
|
||||
//counterfeiter:generate . PeerConnection
|
||||
type PeerConnection interface {
|
||||
OnICECandidate(f func(*webrtc.ICECandidate))
|
||||
@@ -61,10 +55,11 @@ type Participant interface {
|
||||
AddTrack(clientId, name string, trackType livekit.TrackType)
|
||||
Answer(sdp webrtc.SessionDescription) (answer webrtc.SessionDescription, err error)
|
||||
HandleAnswer(sdp webrtc.SessionDescription) error
|
||||
HandleClientNegotiation()
|
||||
AddICECandidate(candidate webrtc.ICECandidateInit) error
|
||||
AddSubscriber(op Participant) error
|
||||
RemoveSubscriber(peerId string)
|
||||
SendJoinResponse(info *livekit.RoomInfo, otherParticipants []Participant) error
|
||||
SendJoinResponse(info *livekit.Room, otherParticipants []Participant) error
|
||||
SendParticipantUpdate(participants []*livekit.ParticipantInfo) error
|
||||
SetTrackMuted(trackId string, muted bool)
|
||||
|
||||
|
||||
@@ -81,6 +81,10 @@ type FakeParticipant struct {
|
||||
handleAnswerReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
HandleClientNegotiationStub func()
|
||||
handleClientNegotiationMutex sync.RWMutex
|
||||
handleClientNegotiationArgsForCall []struct {
|
||||
}
|
||||
IDStub func() string
|
||||
iDMutex sync.RWMutex
|
||||
iDArgsForCall []struct {
|
||||
@@ -167,10 +171,10 @@ type FakeParticipant struct {
|
||||
removeSubscriberArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
SendJoinResponseStub func(*livekit.RoomInfo, []types.Participant) error
|
||||
SendJoinResponseStub func(*livekit.Room, []types.Participant) error
|
||||
sendJoinResponseMutex sync.RWMutex
|
||||
sendJoinResponseArgsForCall []struct {
|
||||
arg1 *livekit.RoomInfo
|
||||
arg1 *livekit.Room
|
||||
arg2 []types.Participant
|
||||
}
|
||||
sendJoinResponseReturns struct {
|
||||
@@ -591,6 +595,30 @@ func (fake *FakeParticipant) HandleAnswerReturnsOnCall(i int, result1 error) {
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) HandleClientNegotiation() {
|
||||
fake.handleClientNegotiationMutex.Lock()
|
||||
fake.handleClientNegotiationArgsForCall = append(fake.handleClientNegotiationArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.HandleClientNegotiationStub
|
||||
fake.recordInvocation("HandleClientNegotiation", []interface{}{})
|
||||
fake.handleClientNegotiationMutex.Unlock()
|
||||
if stub != nil {
|
||||
fake.HandleClientNegotiationStub()
|
||||
}
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) HandleClientNegotiationCallCount() int {
|
||||
fake.handleClientNegotiationMutex.RLock()
|
||||
defer fake.handleClientNegotiationMutex.RUnlock()
|
||||
return len(fake.handleClientNegotiationArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) HandleClientNegotiationCalls(stub func()) {
|
||||
fake.handleClientNegotiationMutex.Lock()
|
||||
defer fake.handleClientNegotiationMutex.Unlock()
|
||||
fake.HandleClientNegotiationStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) ID() string {
|
||||
fake.iDMutex.Lock()
|
||||
ret, specificReturn := fake.iDReturnsOnCall[len(fake.iDArgsForCall)]
|
||||
@@ -1081,7 +1109,7 @@ func (fake *FakeParticipant) RemoveSubscriberArgsForCall(i int) string {
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) SendJoinResponse(arg1 *livekit.RoomInfo, arg2 []types.Participant) error {
|
||||
func (fake *FakeParticipant) SendJoinResponse(arg1 *livekit.Room, arg2 []types.Participant) error {
|
||||
var arg2Copy []types.Participant
|
||||
if arg2 != nil {
|
||||
arg2Copy = make([]types.Participant, len(arg2))
|
||||
@@ -1090,7 +1118,7 @@ func (fake *FakeParticipant) SendJoinResponse(arg1 *livekit.RoomInfo, arg2 []typ
|
||||
fake.sendJoinResponseMutex.Lock()
|
||||
ret, specificReturn := fake.sendJoinResponseReturnsOnCall[len(fake.sendJoinResponseArgsForCall)]
|
||||
fake.sendJoinResponseArgsForCall = append(fake.sendJoinResponseArgsForCall, struct {
|
||||
arg1 *livekit.RoomInfo
|
||||
arg1 *livekit.Room
|
||||
arg2 []types.Participant
|
||||
}{arg1, arg2Copy})
|
||||
stub := fake.SendJoinResponseStub
|
||||
@@ -1112,13 +1140,13 @@ func (fake *FakeParticipant) SendJoinResponseCallCount() int {
|
||||
return len(fake.sendJoinResponseArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) SendJoinResponseCalls(stub func(*livekit.RoomInfo, []types.Participant) error) {
|
||||
func (fake *FakeParticipant) SendJoinResponseCalls(stub func(*livekit.Room, []types.Participant) error) {
|
||||
fake.sendJoinResponseMutex.Lock()
|
||||
defer fake.sendJoinResponseMutex.Unlock()
|
||||
fake.SendJoinResponseStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeParticipant) SendJoinResponseArgsForCall(i int) (*livekit.RoomInfo, []types.Participant) {
|
||||
func (fake *FakeParticipant) SendJoinResponseArgsForCall(i int) (*livekit.Room, []types.Participant) {
|
||||
fake.sendJoinResponseMutex.RLock()
|
||||
defer fake.sendJoinResponseMutex.RUnlock()
|
||||
argsForCall := fake.sendJoinResponseArgsForCall[i]
|
||||
@@ -1394,6 +1422,8 @@ func (fake *FakeParticipant) Invocations() map[string][][]interface{} {
|
||||
defer fake.closeMutex.RUnlock()
|
||||
fake.handleAnswerMutex.RLock()
|
||||
defer fake.handleAnswerMutex.RUnlock()
|
||||
fake.handleClientNegotiationMutex.RLock()
|
||||
defer fake.handleClientNegotiationMutex.RUnlock()
|
||||
fake.iDMutex.RLock()
|
||||
defer fake.iDMutex.RUnlock()
|
||||
fake.isReadyMutex.RLock()
|
||||
|
||||
@@ -1,182 +0,0 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package typesfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
type FakeSignalConnection struct {
|
||||
ReadRequestStub func() (*livekit.SignalRequest, error)
|
||||
readRequestMutex sync.RWMutex
|
||||
readRequestArgsForCall []struct {
|
||||
}
|
||||
readRequestReturns struct {
|
||||
result1 *livekit.SignalRequest
|
||||
result2 error
|
||||
}
|
||||
readRequestReturnsOnCall map[int]struct {
|
||||
result1 *livekit.SignalRequest
|
||||
result2 error
|
||||
}
|
||||
WriteResponseStub func(*livekit.SignalResponse) error
|
||||
writeResponseMutex sync.RWMutex
|
||||
writeResponseArgsForCall []struct {
|
||||
arg1 *livekit.SignalResponse
|
||||
}
|
||||
writeResponseReturns struct {
|
||||
result1 error
|
||||
}
|
||||
writeResponseReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) ReadRequest() (*livekit.SignalRequest, error) {
|
||||
fake.readRequestMutex.Lock()
|
||||
ret, specificReturn := fake.readRequestReturnsOnCall[len(fake.readRequestArgsForCall)]
|
||||
fake.readRequestArgsForCall = append(fake.readRequestArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.ReadRequestStub
|
||||
fakeReturns := fake.readRequestReturns
|
||||
fake.recordInvocation("ReadRequest", []interface{}{})
|
||||
fake.readRequestMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) ReadRequestCallCount() int {
|
||||
fake.readRequestMutex.RLock()
|
||||
defer fake.readRequestMutex.RUnlock()
|
||||
return len(fake.readRequestArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) ReadRequestCalls(stub func() (*livekit.SignalRequest, error)) {
|
||||
fake.readRequestMutex.Lock()
|
||||
defer fake.readRequestMutex.Unlock()
|
||||
fake.ReadRequestStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) ReadRequestReturns(result1 *livekit.SignalRequest, result2 error) {
|
||||
fake.readRequestMutex.Lock()
|
||||
defer fake.readRequestMutex.Unlock()
|
||||
fake.ReadRequestStub = nil
|
||||
fake.readRequestReturns = struct {
|
||||
result1 *livekit.SignalRequest
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) ReadRequestReturnsOnCall(i int, result1 *livekit.SignalRequest, result2 error) {
|
||||
fake.readRequestMutex.Lock()
|
||||
defer fake.readRequestMutex.Unlock()
|
||||
fake.ReadRequestStub = nil
|
||||
if fake.readRequestReturnsOnCall == nil {
|
||||
fake.readRequestReturnsOnCall = make(map[int]struct {
|
||||
result1 *livekit.SignalRequest
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.readRequestReturnsOnCall[i] = struct {
|
||||
result1 *livekit.SignalRequest
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) WriteResponse(arg1 *livekit.SignalResponse) error {
|
||||
fake.writeResponseMutex.Lock()
|
||||
ret, specificReturn := fake.writeResponseReturnsOnCall[len(fake.writeResponseArgsForCall)]
|
||||
fake.writeResponseArgsForCall = append(fake.writeResponseArgsForCall, struct {
|
||||
arg1 *livekit.SignalResponse
|
||||
}{arg1})
|
||||
stub := fake.WriteResponseStub
|
||||
fakeReturns := fake.writeResponseReturns
|
||||
fake.recordInvocation("WriteResponse", []interface{}{arg1})
|
||||
fake.writeResponseMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) WriteResponseCallCount() int {
|
||||
fake.writeResponseMutex.RLock()
|
||||
defer fake.writeResponseMutex.RUnlock()
|
||||
return len(fake.writeResponseArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) WriteResponseCalls(stub func(*livekit.SignalResponse) error) {
|
||||
fake.writeResponseMutex.Lock()
|
||||
defer fake.writeResponseMutex.Unlock()
|
||||
fake.WriteResponseStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) WriteResponseArgsForCall(i int) *livekit.SignalResponse {
|
||||
fake.writeResponseMutex.RLock()
|
||||
defer fake.writeResponseMutex.RUnlock()
|
||||
argsForCall := fake.writeResponseArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) WriteResponseReturns(result1 error) {
|
||||
fake.writeResponseMutex.Lock()
|
||||
defer fake.writeResponseMutex.Unlock()
|
||||
fake.WriteResponseStub = nil
|
||||
fake.writeResponseReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) WriteResponseReturnsOnCall(i int, result1 error) {
|
||||
fake.writeResponseMutex.Lock()
|
||||
defer fake.writeResponseMutex.Unlock()
|
||||
fake.WriteResponseStub = nil
|
||||
if fake.writeResponseReturnsOnCall == nil {
|
||||
fake.writeResponseReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.writeResponseReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.readRequestMutex.RLock()
|
||||
defer fake.readRequestMutex.RUnlock()
|
||||
fake.writeResponseMutex.RLock()
|
||||
defer fake.writeResponseMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeSignalConnection) recordInvocation(key string, args []interface{}) {
|
||||
fake.invocationsMutex.Lock()
|
||||
defer fake.invocationsMutex.Unlock()
|
||||
if fake.invocations == nil {
|
||||
fake.invocations = map[string][][]interface{}{}
|
||||
}
|
||||
if fake.invocations[key] == nil {
|
||||
fake.invocations[key] = [][]interface{}{}
|
||||
}
|
||||
fake.invocations[key] = append(fake.invocations[key], args)
|
||||
}
|
||||
|
||||
var _ types.SignalConnection = new(FakeSignalConnection)
|
||||
+14
-1
@@ -5,8 +5,11 @@ import (
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/pion/webrtc/v3"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
@@ -16,6 +19,15 @@ const (
|
||||
trackIdSeparator = "|"
|
||||
)
|
||||
|
||||
var RTCSet = wire.NewSet(
|
||||
NewWebRTCConfig,
|
||||
RTCConfigFromConfig,
|
||||
)
|
||||
|
||||
func RTCConfigFromConfig(conf *config.Config) *config.RTCConfig {
|
||||
return &conf.RTC
|
||||
}
|
||||
|
||||
func UnpackTrackId(packed string) (peerId string, trackId string) {
|
||||
parts := strings.Split(packed, trackIdSeparator)
|
||||
if len(parts) > 1 {
|
||||
@@ -118,6 +130,7 @@ func RecoverSilent() {
|
||||
|
||||
func Recover() {
|
||||
if r := recover(); r != nil {
|
||||
logger.GetLogger().Errorw("recovered panic", "err", r)
|
||||
log := logger.Desugar().WithOptions(zap.AddCallerSkip(1))
|
||||
log.Error("recovered panic", zap.Any("error", r))
|
||||
}
|
||||
}
|
||||
|
||||
+13
-8
@@ -21,7 +21,6 @@ const (
|
||||
|
||||
var (
|
||||
ErrPermissionDenied = errors.New("permissions denied")
|
||||
AuthRequired bool
|
||||
)
|
||||
|
||||
// authentication middleware
|
||||
@@ -91,9 +90,6 @@ func SetAuthorizationToken(r *http.Request, token string) {
|
||||
}
|
||||
|
||||
func EnsureJoinPermission(ctx context.Context) (name string, err error) {
|
||||
if !AuthRequired {
|
||||
return "", nil
|
||||
}
|
||||
claims := GetGrants(ctx)
|
||||
if claims == nil || claims.Video == nil {
|
||||
err = ErrPermissionDenied
|
||||
@@ -109,9 +105,6 @@ func EnsureJoinPermission(ctx context.Context) (name string, err error) {
|
||||
}
|
||||
|
||||
func EnsureCreatePermission(ctx context.Context) error {
|
||||
if !AuthRequired {
|
||||
return nil
|
||||
}
|
||||
claims := GetGrants(ctx)
|
||||
if claims == nil {
|
||||
return ErrPermissionDenied
|
||||
@@ -123,13 +116,25 @@ func EnsureCreatePermission(ctx context.Context) error {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
func EnsureListPermission(ctx context.Context) error {
|
||||
claims := GetGrants(ctx)
|
||||
if claims == nil {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
if claims.Video.RoomList {
|
||||
return nil
|
||||
}
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
// wraps authentication errors around Twirp
|
||||
func twirpAuthError(err error) error {
|
||||
return twirp.NewError(twirp.Unauthenticated, err.Error())
|
||||
}
|
||||
|
||||
func handleError(w http.ResponseWriter, status int, msg string) {
|
||||
logger.GetLogger().Debugw("error handling request", "error", msg, "status", status)
|
||||
logger.Debugw("error handling request", "error", msg, "status", status)
|
||||
w.WriteHeader(status)
|
||||
w.Write([]byte(msg))
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package service
|
||||
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrRoomNotFound = errors.New("requested room does not exist")
|
||||
)
|
||||
@@ -0,0 +1,74 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/thoas/go-funk"
|
||||
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
// encapsulates CRUD operations for room settings
|
||||
type LocalRoomStore struct {
|
||||
// map of roomId => room
|
||||
rooms map[string]*livekit.Room
|
||||
// map of roomName => roomId
|
||||
roomIds map[string]string
|
||||
lock sync.RWMutex
|
||||
//CreateRoom(room *livekit.Room) error
|
||||
//GetRoom(idOrName string) (*livekit.Room, error)
|
||||
//DeleteRoom(idOrName string) error
|
||||
}
|
||||
|
||||
func NewLocalRoomStore() *LocalRoomStore {
|
||||
return &LocalRoomStore{
|
||||
rooms: make(map[string]*livekit.Room),
|
||||
roomIds: make(map[string]string),
|
||||
lock: sync.RWMutex{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p *LocalRoomStore) CreateRoom(room *livekit.Room) error {
|
||||
p.lock.Lock()
|
||||
p.rooms[room.Sid] = room
|
||||
p.roomIds[room.Name] = room.Sid
|
||||
p.lock.Unlock()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *LocalRoomStore) GetRoom(idOrName string) (*livekit.Room, error) {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
// see if it's an id or name
|
||||
if p.rooms[idOrName] == nil {
|
||||
idOrName = p.roomIds[idOrName]
|
||||
}
|
||||
|
||||
room := p.rooms[idOrName]
|
||||
if room == nil {
|
||||
return nil, ErrRoomNotFound
|
||||
}
|
||||
return room, nil
|
||||
}
|
||||
|
||||
func (p *LocalRoomStore) ListRooms() ([]*livekit.Room, error) {
|
||||
p.lock.RLock()
|
||||
defer p.lock.RUnlock()
|
||||
return funk.Values(p.rooms).([]*livekit.Room), nil
|
||||
}
|
||||
|
||||
func (p *LocalRoomStore) DeleteRoom(idOrName string) error {
|
||||
room, err := p.GetRoom(idOrName)
|
||||
if err == ErrRoomNotFound {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
p.lock.Lock()
|
||||
defer p.lock.Unlock()
|
||||
|
||||
delete(p.rooms, room.Sid)
|
||||
delete(p.roomIds, room.Name)
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
package service
|
||||
@@ -0,0 +1,75 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/utils"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
// A rooms service that supports a single node
|
||||
type RoomService struct {
|
||||
roomProvider RoomStore
|
||||
}
|
||||
|
||||
func NewRoomService(rp RoomStore) (svc *RoomService, err error) {
|
||||
svc = &RoomService{
|
||||
roomProvider: rp,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *RoomService) CreateRoom(ctx context.Context, req *livekit.CreateRoomRequest) (rm *livekit.Room, err error) {
|
||||
if err = EnsureCreatePermission(ctx); err != nil {
|
||||
return nil, twirpAuthError(err)
|
||||
}
|
||||
|
||||
rm = &livekit.Room{
|
||||
Sid: utils.NewGuid(utils.RoomPrefix),
|
||||
Name: req.Name,
|
||||
EmptyTimeout: req.EmptyTimeout,
|
||||
MaxParticipants: req.MaxParticipants,
|
||||
CreationTime: time.Now().Unix(),
|
||||
}
|
||||
err = s.roomProvider.CreateRoom(rm)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *RoomService) ListRooms(ctx context.Context, req *livekit.ListRoomsRequest) (res *livekit.ListRoomsResponse, err error) {
|
||||
err = EnsureListPermission(ctx)
|
||||
if err != nil {
|
||||
return nil, twirpAuthError(err)
|
||||
}
|
||||
|
||||
rooms, err := s.roomProvider.ListRooms()
|
||||
if err != nil {
|
||||
// TODO: translate error codes to twirp
|
||||
return
|
||||
}
|
||||
|
||||
res = &livekit.ListRoomsResponse{
|
||||
Rooms: rooms,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *RoomService) DeleteRoom(ctx context.Context, req *livekit.DeleteRoomRequest) (res *livekit.DeleteRoomResponse, err error) {
|
||||
if err = EnsureCreatePermission(ctx); err != nil {
|
||||
return nil, twirpAuthError(err)
|
||||
}
|
||||
err = s.roomProvider.DeleteRoom(req.Room)
|
||||
if err != nil {
|
||||
err = twirp.WrapError(twirp.InternalError("could not delete room"), err)
|
||||
return
|
||||
}
|
||||
res = &livekit.DeleteRoomResponse{}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
|
||||
|
||||
// encapsulates CRUD operations for room settings
|
||||
//counterfeiter:generate . RoomStore
|
||||
type RoomStore interface {
|
||||
CreateRoom(room *livekit.Room) error
|
||||
GetRoom(idOrName string) (*livekit.Room, error)
|
||||
ListRooms() ([]*livekit.Room, error)
|
||||
DeleteRoom(idOrName string) error
|
||||
}
|
||||
@@ -1,221 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
type RTCService struct {
|
||||
manager *rtc.RoomManager
|
||||
upgrader websocket.Upgrader
|
||||
isDev bool
|
||||
}
|
||||
|
||||
func NewRTCService(conf *config.Config, manager *rtc.RoomManager) *RTCService {
|
||||
s := &RTCService{
|
||||
manager: manager,
|
||||
upgrader: websocket.Upgrader{},
|
||||
isDev: conf.Development,
|
||||
}
|
||||
|
||||
// allow connections from any origin, since script may be hosted anywhere
|
||||
// security is enforced by access tokens
|
||||
s.upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *RTCService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
roomId := r.FormValue("room")
|
||||
var pName string
|
||||
if s.isDev {
|
||||
r.FormValue("name")
|
||||
} else {
|
||||
claims := GetGrants(r.Context())
|
||||
// require a claim
|
||||
if claims == nil || claims.Video == nil {
|
||||
handleError(w, http.StatusUnauthorized, rtc.ErrPermissionDenied.Error())
|
||||
}
|
||||
pName = claims.Identity
|
||||
}
|
||||
log := logger.GetLogger()
|
||||
|
||||
onlyName, err := EnsureJoinPermission(r.Context())
|
||||
if err != nil {
|
||||
handleError(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
room, err := s.manager.GetRoomWithConstraint(roomId, onlyName)
|
||||
if err != nil {
|
||||
// TODO: return errors/status correctly
|
||||
handleError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// upgrade only once the basics are good to go
|
||||
conn, err := s.upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.GetLogger().Warnw("could not upgrade to WS",
|
||||
"err", err,
|
||||
)
|
||||
handleError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
conn.SetCloseHandler(func(code int, text string) error {
|
||||
log.Infow("websocket closed by remote")
|
||||
return nil
|
||||
})
|
||||
signalConn := rtc.NewWSSignalConnection(conn)
|
||||
|
||||
pc, err := rtc.NewPeerConnection(s.manager.Config())
|
||||
if err != nil {
|
||||
handleError(w, http.StatusInternalServerError, "could not create peerConnection: "+err.Error())
|
||||
return
|
||||
}
|
||||
participant, err := rtc.NewParticipant(pc, signalConn, pName, s.manager.Config().Receiver)
|
||||
if err != nil {
|
||||
handleError(w, http.StatusInternalServerError, "could not create participant: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
log.Infow("new client connected",
|
||||
"roomId", roomId,
|
||||
"name", pName,
|
||||
"participant", participant.ID(),
|
||||
)
|
||||
|
||||
if err := room.Join(participant); err != nil {
|
||||
handleError(w, http.StatusInternalServerError, "could not join room: "+err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// remove peer from room upon disconnection
|
||||
room.RemoveParticipant(participant.ID())
|
||||
participant.Close()
|
||||
log.Infow("WS connection closed", "participant", participant.ID())
|
||||
}()
|
||||
|
||||
// read connection and wait for commands
|
||||
//ctx := context.Background()
|
||||
for {
|
||||
req, err := signalConn.ReadRequest()
|
||||
if err == io.EOF {
|
||||
// client disconnected from websocket
|
||||
return
|
||||
} else if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if req == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
switch msg := req.Message.(type) {
|
||||
case *livekit.SignalRequest_Offer:
|
||||
err = s.handleOffer(participant, msg.Offer)
|
||||
if err != nil {
|
||||
log.Errorw("could not handle join", "err", err, "participant", participant.ID())
|
||||
return
|
||||
}
|
||||
case *livekit.SignalRequest_AddTrack:
|
||||
log.Debugw("publishing track", "participant", participant.ID(),
|
||||
"track", msg.AddTrack.Cid)
|
||||
participant.AddTrack(msg.AddTrack.Cid, msg.AddTrack.Name, msg.AddTrack.Type)
|
||||
case *livekit.SignalRequest_Answer:
|
||||
if participant.State() == livekit.ParticipantInfo_JOINING {
|
||||
log.Errorw("cannot negotiate before peer offer", "participant", participant.ID())
|
||||
//conn.WriteJSON(jsonError(http.StatusNotAcceptable, "cannot negotiate before peer offer"))
|
||||
return
|
||||
}
|
||||
sd := rtc.FromProtoSessionDescription(msg.Answer)
|
||||
err = participant.HandleAnswer(sd)
|
||||
if err != nil {
|
||||
log.Errorw("could not handle answer", "participant", participant.ID(), "err", err)
|
||||
//conn.WriteJSON(
|
||||
// jsonError(http.StatusInternalServerError, "could not handle negotiate", err.Error()))
|
||||
return
|
||||
}
|
||||
case *livekit.SignalRequest_Negotiate:
|
||||
participant.HandleClientNegotiation()
|
||||
case *livekit.SignalRequest_Trickle:
|
||||
if participant.State() == livekit.ParticipantInfo_JOINING {
|
||||
log.Errorw("cannot trickle before peer offer", "participant", participant.ID())
|
||||
//conn.WriteJSON(jsonError(http.StatusNotAcceptable, "cannot trickle before peer offer"))
|
||||
return
|
||||
}
|
||||
|
||||
err = s.handleTrickle(participant, msg.Trickle)
|
||||
if err != nil {
|
||||
log.Errorw("could not handle trickle", "participant", participant.ID(), "err", err)
|
||||
//conn.WriteJSON(
|
||||
// jsonError(http.StatusInternalServerError, "could not handle trickle", err.Error()))
|
||||
return
|
||||
}
|
||||
case *livekit.SignalRequest_Mute:
|
||||
participant.SetTrackMuted(msg.Mute.Sid, msg.Mute.Muted)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RTCService) handleOffer(participant types.Participant, offer *livekit.SessionDescription) error {
|
||||
log := logger.GetLogger()
|
||||
|
||||
_, err := participant.Answer(rtc.FromProtoSessionDescription(offer))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "could not answer offer")
|
||||
}
|
||||
|
||||
log.Debugw("answered client offer")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *RTCService) handleTrickle(participant types.Participant, trickle *livekit.TrickleRequest) error {
|
||||
candidateInit := rtc.FromProtoTrickle(trickle)
|
||||
//logger.GetLogger().Debugw("adding peer candidate", "participant", participant.ID())
|
||||
if err := participant.AddICECandidate(candidateInit); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type errStruct struct {
|
||||
StatusCode int `json:"statusCode"`
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func writeJSONError(w http.ResponseWriter, code int, error ...string) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.WriteHeader(code)
|
||||
|
||||
json.NewEncoder(w).Encode(jsonError(code, error...))
|
||||
}
|
||||
|
||||
func jsonError(code int, error ...string) errStruct {
|
||||
es := errStruct{
|
||||
StatusCode: code,
|
||||
}
|
||||
if len(error) > 0 {
|
||||
es.Error = error[0]
|
||||
}
|
||||
if len(error) > 1 {
|
||||
es.Message = error[1]
|
||||
}
|
||||
return es
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"io"
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/pkg/rtc/types"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
// RTC runner manages the lifecycles of a WebRTC connection
|
||||
// it creates a new goroutine for each participant it manages.
|
||||
|
||||
type RTCRunner struct {
|
||||
lock sync.RWMutex
|
||||
roomProvider RoomStore
|
||||
currentNode routing.LocalNode
|
||||
router routing.Router
|
||||
config *rtc.WebRTCConfig
|
||||
rooms map[string]*rtc.Room
|
||||
}
|
||||
|
||||
func NewRTCRunner(rp RoomStore, router routing.Router, currentNode routing.LocalNode, config *rtc.WebRTCConfig) *RTCRunner {
|
||||
return &RTCRunner{
|
||||
lock: sync.RWMutex{},
|
||||
roomProvider: rp,
|
||||
config: config,
|
||||
router: router,
|
||||
currentNode: currentNode,
|
||||
rooms: make(map[string]*rtc.Room),
|
||||
}
|
||||
}
|
||||
|
||||
// starts WebRTC session when a new participant is connected
|
||||
func (r *RTCRunner) StartSession(roomName, participantId, participantName string, requestSource routing.MessageSource, responseSink routing.MessageSink) {
|
||||
room, err := r.getOrCreateRoom(roomName)
|
||||
if err != nil {
|
||||
logger.Errorw("could not create room", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
logger.Debugw("starting RTC session",
|
||||
"room", roomName,
|
||||
"participant", participantName,
|
||||
"num_participants", len(room.GetParticipants()),
|
||||
)
|
||||
|
||||
pc, err := rtc.NewPeerConnection(r.config)
|
||||
if err != nil {
|
||||
logger.Errorw("could not create peerConnection", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
participant, err := rtc.NewParticipant(participantId, participantName, pc, responseSink, r.config.Receiver)
|
||||
if err != nil {
|
||||
logger.Errorw("could not create participant", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// register participant to be on this server
|
||||
if err = r.router.SetRTCNode(participantId, r.currentNode.Id); err != nil {
|
||||
logger.Errorw("could not set RTC node", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
// join room
|
||||
if err := room.Join(participant); err != nil {
|
||||
logger.Errorw("could not join room", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
go r.sessionWorker(room, participant, requestSource)
|
||||
}
|
||||
|
||||
func (r *RTCRunner) getOrCreateRoom(roomName string) (*rtc.Room, error) {
|
||||
r.lock.RLock()
|
||||
room := r.rooms[roomName]
|
||||
r.lock.RUnlock()
|
||||
|
||||
if room != nil {
|
||||
return room, nil
|
||||
}
|
||||
|
||||
// create new room, get details first
|
||||
ri, err := r.roomProvider.GetRoom(roomName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
room = rtc.NewRoom(ri, *r.config)
|
||||
r.lock.Lock()
|
||||
r.rooms[roomName] = room
|
||||
r.lock.Unlock()
|
||||
|
||||
return room, nil
|
||||
}
|
||||
|
||||
func (r *RTCRunner) sessionWorker(room *rtc.Room, participant types.Participant, requestSource routing.MessageSource) {
|
||||
defer func() {
|
||||
logger.Debugw("RTC session finishing",
|
||||
"participant", participant.Name(),
|
||||
"room", room.Name,
|
||||
)
|
||||
// remove peer from room when participant leaves room
|
||||
room.RemoveParticipant(participant.ID())
|
||||
}()
|
||||
defer rtc.Recover()
|
||||
|
||||
for {
|
||||
obj, err := requestSource.ReadMessage()
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
|
||||
req := obj.(*livekit.SignalRequest)
|
||||
|
||||
switch msg := req.Message.(type) {
|
||||
case *livekit.SignalRequest_Offer:
|
||||
_, err := participant.Answer(rtc.FromProtoSessionDescription(msg.Offer))
|
||||
if err != nil {
|
||||
logger.Errorw("could not handle join", "err", err, "participant", participant.ID())
|
||||
return
|
||||
}
|
||||
case *livekit.SignalRequest_AddTrack:
|
||||
logger.Debugw("publishing track", "participant", participant.ID(),
|
||||
"track", msg.AddTrack.Cid)
|
||||
participant.AddTrack(msg.AddTrack.Cid, msg.AddTrack.Name, msg.AddTrack.Type)
|
||||
case *livekit.SignalRequest_Answer:
|
||||
if participant.State() == livekit.ParticipantInfo_JOINING {
|
||||
logger.Errorw("cannot negotiate before peer offer", "participant", participant.ID())
|
||||
//conn.WriteJSON(jsonError(http.StatusNotAcceptable, "cannot negotiate before peer offer"))
|
||||
return
|
||||
}
|
||||
sd := rtc.FromProtoSessionDescription(msg.Answer)
|
||||
err = participant.HandleAnswer(sd)
|
||||
if err != nil {
|
||||
logger.Errorw("could not handle answer", "participant", participant.ID(), "err", err)
|
||||
//conn.WriteJSON(
|
||||
// jsonError(http.StatusInternalServerError, "could not handle negotiate", err.Error()))
|
||||
return
|
||||
}
|
||||
case *livekit.SignalRequest_Negotiate:
|
||||
participant.HandleClientNegotiation()
|
||||
case *livekit.SignalRequest_Trickle:
|
||||
if participant.State() == livekit.ParticipantInfo_JOINING {
|
||||
logger.Errorw("cannot trickle before peer offer", "participant", participant.ID())
|
||||
//conn.WriteJSON(jsonError(http.StatusNotAcceptable, "cannot trickle before peer offer"))
|
||||
return
|
||||
}
|
||||
|
||||
candidateInit := rtc.FromProtoTrickle(msg.Trickle)
|
||||
//logger.Debugw("adding peer candidate", "participant", participant.ID())
|
||||
if err := participant.AddICECandidate(candidateInit); err != nil {
|
||||
logger.Errorw("could not handle trickle", "participant", participant.ID(), "err", err)
|
||||
//conn.WriteJSON(
|
||||
// jsonError(http.StatusInternalServerError, "could not handle trickle", err.Error()))
|
||||
return
|
||||
}
|
||||
case *livekit.SignalRequest_Mute:
|
||||
participant.SetTrackMuted(msg.Mute.Sid, msg.Mute.Muted)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/pkg/utils"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
type RTCService struct {
|
||||
router routing.Router
|
||||
roomStore RoomStore
|
||||
upgrader websocket.Upgrader
|
||||
currentNode routing.LocalNode
|
||||
isDev bool
|
||||
}
|
||||
|
||||
func NewRTCService(conf *config.Config, roomStore RoomStore, router routing.Router, currentNode routing.LocalNode) *RTCService {
|
||||
s := &RTCService{
|
||||
router: router,
|
||||
roomStore: roomStore,
|
||||
upgrader: websocket.Upgrader{},
|
||||
currentNode: currentNode,
|
||||
isDev: conf.Development,
|
||||
}
|
||||
|
||||
// allow connections from any origin, since script may be hosted anywhere
|
||||
// security is enforced by access tokens
|
||||
s.upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *RTCService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
roomName := r.FormValue("room")
|
||||
claims := GetGrants(r.Context())
|
||||
// require a claim
|
||||
if claims == nil || claims.Video == nil {
|
||||
handleError(w, http.StatusUnauthorized, rtc.ErrPermissionDenied.Error())
|
||||
}
|
||||
pName := claims.Identity
|
||||
|
||||
onlyName, err := EnsureJoinPermission(r.Context())
|
||||
if err != nil {
|
||||
handleError(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
if onlyName != "" {
|
||||
roomName = onlyName
|
||||
}
|
||||
|
||||
rm, err := s.roomStore.GetRoom(roomName)
|
||||
if err != nil {
|
||||
handleError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// upgrade only once the basics are good to go
|
||||
conn, err := s.upgrader.Upgrade(w, r, nil)
|
||||
if err != nil {
|
||||
logger.Warnw("could not upgrade to WS",
|
||||
"err", err,
|
||||
)
|
||||
handleError(w, http.StatusInternalServerError, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
sigConn := NewWSSignalConnection(conn)
|
||||
|
||||
participantId := utils.NewGuid(utils.ParticipantPrefix)
|
||||
err = s.router.StartParticipant(roomName, participantId, pName, s.currentNode.Id)
|
||||
if err != nil {
|
||||
handleError(w, http.StatusInternalServerError, "could not set signal node: "+err.Error())
|
||||
}
|
||||
|
||||
logger.Infow("new client connected",
|
||||
"room", rm.Sid,
|
||||
"roomName", rm.Name,
|
||||
"name", pName,
|
||||
)
|
||||
|
||||
reqSink := s.router.GetRequestSink(participantId)
|
||||
resSource := s.router.GetResponseSource(participantId)
|
||||
|
||||
go func() {
|
||||
for {
|
||||
msg, err := resSource.ReadMessage()
|
||||
if err == io.EOF {
|
||||
return
|
||||
}
|
||||
res, ok := msg.(*livekit.SignalResponse)
|
||||
if !ok {
|
||||
logger.Errorw("unexpected message type", "type", fmt.Sprintf("%T", msg))
|
||||
continue
|
||||
}
|
||||
|
||||
if err = sigConn.WriteResponse(res); err != nil {
|
||||
logger.Warnw("error writing to websocket", "error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
defer func() {
|
||||
logger.Infow("WS connection closed", "participant", pName)
|
||||
reqSink.Close()
|
||||
}()
|
||||
for {
|
||||
req, err := sigConn.ReadRequest()
|
||||
// normal closure
|
||||
if err == io.EOF || websocket.IsCloseError(err, websocket.CloseAbnormalClosure, websocket.CloseGoingAway, websocket.CloseNormalClosure) {
|
||||
return
|
||||
} else if err != nil {
|
||||
logger.Errorw("error reading from websocket", "error", err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = reqSink.WriteMessage(req); err != nil {
|
||||
logger.Warnw("error writing to request sink", "error", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type errStruct struct {
|
||||
StatusCode int `json:"statusCode"`
|
||||
Error string `json:"error"`
|
||||
Message string `json:"message,omitempty"`
|
||||
}
|
||||
|
||||
func writeJSONError(w http.ResponseWriter, code int, error ...string) {
|
||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
w.WriteHeader(code)
|
||||
|
||||
json.NewEncoder(w).Encode(jsonError(code, error...))
|
||||
}
|
||||
|
||||
func jsonError(code int, error ...string) errStruct {
|
||||
es := errStruct{
|
||||
StatusCode: code,
|
||||
}
|
||||
if len(error) > 0 {
|
||||
es.Error = error[0]
|
||||
}
|
||||
if len(error) > 1 {
|
||||
es.Message = error[1]
|
||||
}
|
||||
return es
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/urfave/negroni"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
type LivekitServer struct {
|
||||
config *config.Config
|
||||
roomServer livekit.TwirpServer
|
||||
rtcService *RTCService
|
||||
httpServer *http.Server
|
||||
router routing.Router
|
||||
running bool
|
||||
doneChan chan bool
|
||||
}
|
||||
|
||||
func NewLivekitServer(conf *config.Config,
|
||||
roomService livekit.RoomService,
|
||||
rtcService *RTCService,
|
||||
keyProvider auth.KeyProvider,
|
||||
router routing.Router,
|
||||
runner *RTCRunner,
|
||||
) (s *LivekitServer, err error) {
|
||||
s = &LivekitServer{
|
||||
config: conf,
|
||||
roomServer: livekit.NewRoomServiceServer(roomService),
|
||||
rtcService: rtcService,
|
||||
router: router,
|
||||
}
|
||||
|
||||
middlewares := []negroni.Handler{
|
||||
// always the first
|
||||
negroni.NewRecovery(),
|
||||
}
|
||||
if keyProvider != nil {
|
||||
middlewares = append(middlewares, NewAPIKeyAuthMiddleware(keyProvider))
|
||||
}
|
||||
|
||||
mux := http.NewServeMux()
|
||||
mux.Handle(s.roomServer.PathPrefix(), s.roomServer)
|
||||
mux.Handle("/rtc", rtcService)
|
||||
|
||||
s.httpServer = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", conf.Port),
|
||||
Handler: configureMiddlewares(mux, middlewares...),
|
||||
}
|
||||
|
||||
// hook up router to the RTC Runner
|
||||
router.OnNewParticipant(runner.StartSession)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *LivekitServer) IsRunning() bool {
|
||||
return s.running
|
||||
}
|
||||
|
||||
func (s *LivekitServer) Start() error {
|
||||
if s.running {
|
||||
return errors.New("already running")
|
||||
}
|
||||
|
||||
if err := s.router.Start(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.doneChan = make(chan bool, 1)
|
||||
|
||||
// ensure we could listen
|
||||
ln, err := net.Listen("tcp", s.httpServer.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
logger.Infow("starting LiveKit server", "address", s.httpServer.Addr)
|
||||
s.httpServer.Serve(ln)
|
||||
}()
|
||||
|
||||
s.running = true
|
||||
|
||||
<-s.doneChan
|
||||
|
||||
// wait for shutdown
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
|
||||
s.httpServer.Shutdown(ctx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *LivekitServer) Stop() {
|
||||
s.running = false
|
||||
s.router.Stop()
|
||||
s.doneChan <- true
|
||||
}
|
||||
|
||||
func configureMiddlewares(handler http.Handler, middlewares ...negroni.Handler) *negroni.Negroni {
|
||||
n := negroni.New()
|
||||
for _, m := range middlewares {
|
||||
n.Use(m)
|
||||
}
|
||||
n.UseHandler(handler)
|
||||
return n
|
||||
}
|
||||
@@ -1,147 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/urfave/negroni"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
"github.com/livekit/livekit-server/pkg/node"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
var ServiceSet = wire.NewSet(
|
||||
NewRoomService,
|
||||
NewRTCService,
|
||||
NewLivekitServer,
|
||||
newRoomManagerWithNode,
|
||||
)
|
||||
|
||||
func NewRoomService(conf *config.Config, manager *rtc.RoomManager, localNode *node.Node) (livekit.RoomService, error) {
|
||||
if conf.MultiNode {
|
||||
return nil, fmt.Errorf("multinode is not supported")
|
||||
} else {
|
||||
return NewSimpleRoomService(manager, localNode)
|
||||
}
|
||||
}
|
||||
|
||||
type LivekitServer struct {
|
||||
config *config.Config
|
||||
roomServer livekit.TwirpServer
|
||||
rtcService *RTCService
|
||||
roomHttp *http.Server
|
||||
rtcHttp *http.Server
|
||||
running bool
|
||||
doneChan chan bool
|
||||
}
|
||||
|
||||
func newRoomManagerWithNode(conf *config.Config, localNode *node.Node) (*rtc.RoomManager, error) {
|
||||
return rtc.NewRoomManager(conf.RTC, localNode.Ip)
|
||||
}
|
||||
|
||||
func NewLivekitServer(conf *config.Config,
|
||||
roomService livekit.RoomService,
|
||||
rtcService *RTCService,
|
||||
keyProvider auth.KeyProvider) (s *LivekitServer, err error) {
|
||||
s = &LivekitServer{
|
||||
config: conf,
|
||||
roomServer: livekit.NewRoomServiceServer(roomService),
|
||||
rtcService: rtcService,
|
||||
}
|
||||
|
||||
middlewares := make([]negroni.Handler, 0)
|
||||
if keyProvider != nil {
|
||||
middlewares = append(middlewares, NewAPIKeyAuthMiddleware(keyProvider))
|
||||
}
|
||||
|
||||
s.roomHttp = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", conf.APIPort),
|
||||
Handler: configureMiddlewares(s.roomServer, middlewares...),
|
||||
}
|
||||
|
||||
rtcHandler := http.NewServeMux()
|
||||
rtcHandler.Handle("/rtc", rtcService)
|
||||
s.rtcHttp = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", conf.RTCPort),
|
||||
Handler: configureMiddlewares(rtcHandler, middlewares...),
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *LivekitServer) IsRunning() bool {
|
||||
return s.running
|
||||
}
|
||||
|
||||
func (s *LivekitServer) Start() error {
|
||||
if s.running {
|
||||
return errors.New("already running")
|
||||
}
|
||||
s.doneChan = make(chan bool, 1)
|
||||
|
||||
// ensure we could listen
|
||||
roomLn, err := net.Listen("tcp", s.roomHttp.Addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rtcAddr := fmt.Sprintf(":%d", s.config.RTCPort)
|
||||
rtcLn, err := net.Listen("tcp", rtcAddr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
logger.GetLogger().Infow("starting Room service", "address", s.roomHttp.Addr)
|
||||
s.roomHttp.Serve(roomLn)
|
||||
}()
|
||||
go func() {
|
||||
logger.GetLogger().Infow("starting RTC service", "address", rtcAddr)
|
||||
s.rtcHttp.Serve(rtcLn)
|
||||
}()
|
||||
|
||||
s.running = true
|
||||
|
||||
<-s.doneChan
|
||||
|
||||
// wait for shutdown
|
||||
ctx, _ := context.WithTimeout(context.Background(), time.Second*5)
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
s.rtcHttp.Shutdown(ctx)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
s.roomHttp.Shutdown(ctx)
|
||||
}()
|
||||
wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *LivekitServer) Stop() {
|
||||
s.running = false
|
||||
s.doneChan <- true
|
||||
}
|
||||
|
||||
func configureMiddlewares(handler http.Handler, middlewares ...negroni.Handler) *negroni.Negroni {
|
||||
n := negroni.New()
|
||||
n.Use(negroni.NewRecovery())
|
||||
for _, m := range middlewares {
|
||||
n.Use(m)
|
||||
}
|
||||
n.UseHandler(handler)
|
||||
return n
|
||||
}
|
||||
@@ -0,0 +1,335 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package servicefakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/service"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
type FakeRoomStore struct {
|
||||
CreateRoomStub func(*livekit.Room) error
|
||||
createRoomMutex sync.RWMutex
|
||||
createRoomArgsForCall []struct {
|
||||
arg1 *livekit.Room
|
||||
}
|
||||
createRoomReturns struct {
|
||||
result1 error
|
||||
}
|
||||
createRoomReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
DeleteRoomStub func(string) error
|
||||
deleteRoomMutex sync.RWMutex
|
||||
deleteRoomArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
deleteRoomReturns struct {
|
||||
result1 error
|
||||
}
|
||||
deleteRoomReturnsOnCall map[int]struct {
|
||||
result1 error
|
||||
}
|
||||
GetRoomStub func(string) (*livekit.Room, error)
|
||||
getRoomMutex sync.RWMutex
|
||||
getRoomArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
getRoomReturns struct {
|
||||
result1 *livekit.Room
|
||||
result2 error
|
||||
}
|
||||
getRoomReturnsOnCall map[int]struct {
|
||||
result1 *livekit.Room
|
||||
result2 error
|
||||
}
|
||||
ListRoomsStub func() ([]*livekit.Room, error)
|
||||
listRoomsMutex sync.RWMutex
|
||||
listRoomsArgsForCall []struct {
|
||||
}
|
||||
listRoomsReturns struct {
|
||||
result1 []*livekit.Room
|
||||
result2 error
|
||||
}
|
||||
listRoomsReturnsOnCall map[int]struct {
|
||||
result1 []*livekit.Room
|
||||
result2 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) CreateRoom(arg1 *livekit.Room) error {
|
||||
fake.createRoomMutex.Lock()
|
||||
ret, specificReturn := fake.createRoomReturnsOnCall[len(fake.createRoomArgsForCall)]
|
||||
fake.createRoomArgsForCall = append(fake.createRoomArgsForCall, struct {
|
||||
arg1 *livekit.Room
|
||||
}{arg1})
|
||||
stub := fake.CreateRoomStub
|
||||
fakeReturns := fake.createRoomReturns
|
||||
fake.recordInvocation("CreateRoom", []interface{}{arg1})
|
||||
fake.createRoomMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) CreateRoomCallCount() int {
|
||||
fake.createRoomMutex.RLock()
|
||||
defer fake.createRoomMutex.RUnlock()
|
||||
return len(fake.createRoomArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) CreateRoomCalls(stub func(*livekit.Room) error) {
|
||||
fake.createRoomMutex.Lock()
|
||||
defer fake.createRoomMutex.Unlock()
|
||||
fake.CreateRoomStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) CreateRoomArgsForCall(i int) *livekit.Room {
|
||||
fake.createRoomMutex.RLock()
|
||||
defer fake.createRoomMutex.RUnlock()
|
||||
argsForCall := fake.createRoomArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) CreateRoomReturns(result1 error) {
|
||||
fake.createRoomMutex.Lock()
|
||||
defer fake.createRoomMutex.Unlock()
|
||||
fake.CreateRoomStub = nil
|
||||
fake.createRoomReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) CreateRoomReturnsOnCall(i int, result1 error) {
|
||||
fake.createRoomMutex.Lock()
|
||||
defer fake.createRoomMutex.Unlock()
|
||||
fake.CreateRoomStub = nil
|
||||
if fake.createRoomReturnsOnCall == nil {
|
||||
fake.createRoomReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.createRoomReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) DeleteRoom(arg1 string) error {
|
||||
fake.deleteRoomMutex.Lock()
|
||||
ret, specificReturn := fake.deleteRoomReturnsOnCall[len(fake.deleteRoomArgsForCall)]
|
||||
fake.deleteRoomArgsForCall = append(fake.deleteRoomArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.DeleteRoomStub
|
||||
fakeReturns := fake.deleteRoomReturns
|
||||
fake.recordInvocation("DeleteRoom", []interface{}{arg1})
|
||||
fake.deleteRoomMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) DeleteRoomCallCount() int {
|
||||
fake.deleteRoomMutex.RLock()
|
||||
defer fake.deleteRoomMutex.RUnlock()
|
||||
return len(fake.deleteRoomArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) DeleteRoomCalls(stub func(string) error) {
|
||||
fake.deleteRoomMutex.Lock()
|
||||
defer fake.deleteRoomMutex.Unlock()
|
||||
fake.DeleteRoomStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) DeleteRoomArgsForCall(i int) string {
|
||||
fake.deleteRoomMutex.RLock()
|
||||
defer fake.deleteRoomMutex.RUnlock()
|
||||
argsForCall := fake.deleteRoomArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) DeleteRoomReturns(result1 error) {
|
||||
fake.deleteRoomMutex.Lock()
|
||||
defer fake.deleteRoomMutex.Unlock()
|
||||
fake.DeleteRoomStub = nil
|
||||
fake.deleteRoomReturns = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) DeleteRoomReturnsOnCall(i int, result1 error) {
|
||||
fake.deleteRoomMutex.Lock()
|
||||
defer fake.deleteRoomMutex.Unlock()
|
||||
fake.DeleteRoomStub = nil
|
||||
if fake.deleteRoomReturnsOnCall == nil {
|
||||
fake.deleteRoomReturnsOnCall = make(map[int]struct {
|
||||
result1 error
|
||||
})
|
||||
}
|
||||
fake.deleteRoomReturnsOnCall[i] = struct {
|
||||
result1 error
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) GetRoom(arg1 string) (*livekit.Room, error) {
|
||||
fake.getRoomMutex.Lock()
|
||||
ret, specificReturn := fake.getRoomReturnsOnCall[len(fake.getRoomArgsForCall)]
|
||||
fake.getRoomArgsForCall = append(fake.getRoomArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.GetRoomStub
|
||||
fakeReturns := fake.getRoomReturns
|
||||
fake.recordInvocation("GetRoom", []interface{}{arg1})
|
||||
fake.getRoomMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) GetRoomCallCount() int {
|
||||
fake.getRoomMutex.RLock()
|
||||
defer fake.getRoomMutex.RUnlock()
|
||||
return len(fake.getRoomArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) GetRoomCalls(stub func(string) (*livekit.Room, error)) {
|
||||
fake.getRoomMutex.Lock()
|
||||
defer fake.getRoomMutex.Unlock()
|
||||
fake.GetRoomStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) GetRoomArgsForCall(i int) string {
|
||||
fake.getRoomMutex.RLock()
|
||||
defer fake.getRoomMutex.RUnlock()
|
||||
argsForCall := fake.getRoomArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) GetRoomReturns(result1 *livekit.Room, result2 error) {
|
||||
fake.getRoomMutex.Lock()
|
||||
defer fake.getRoomMutex.Unlock()
|
||||
fake.GetRoomStub = nil
|
||||
fake.getRoomReturns = struct {
|
||||
result1 *livekit.Room
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) GetRoomReturnsOnCall(i int, result1 *livekit.Room, result2 error) {
|
||||
fake.getRoomMutex.Lock()
|
||||
defer fake.getRoomMutex.Unlock()
|
||||
fake.GetRoomStub = nil
|
||||
if fake.getRoomReturnsOnCall == nil {
|
||||
fake.getRoomReturnsOnCall = make(map[int]struct {
|
||||
result1 *livekit.Room
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.getRoomReturnsOnCall[i] = struct {
|
||||
result1 *livekit.Room
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) ListRooms() ([]*livekit.Room, error) {
|
||||
fake.listRoomsMutex.Lock()
|
||||
ret, specificReturn := fake.listRoomsReturnsOnCall[len(fake.listRoomsArgsForCall)]
|
||||
fake.listRoomsArgsForCall = append(fake.listRoomsArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.ListRoomsStub
|
||||
fakeReturns := fake.listRoomsReturns
|
||||
fake.recordInvocation("ListRooms", []interface{}{})
|
||||
fake.listRoomsMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) ListRoomsCallCount() int {
|
||||
fake.listRoomsMutex.RLock()
|
||||
defer fake.listRoomsMutex.RUnlock()
|
||||
return len(fake.listRoomsArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) ListRoomsCalls(stub func() ([]*livekit.Room, error)) {
|
||||
fake.listRoomsMutex.Lock()
|
||||
defer fake.listRoomsMutex.Unlock()
|
||||
fake.ListRoomsStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) ListRoomsReturns(result1 []*livekit.Room, result2 error) {
|
||||
fake.listRoomsMutex.Lock()
|
||||
defer fake.listRoomsMutex.Unlock()
|
||||
fake.ListRoomsStub = nil
|
||||
fake.listRoomsReturns = struct {
|
||||
result1 []*livekit.Room
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) ListRoomsReturnsOnCall(i int, result1 []*livekit.Room, result2 error) {
|
||||
fake.listRoomsMutex.Lock()
|
||||
defer fake.listRoomsMutex.Unlock()
|
||||
fake.ListRoomsStub = nil
|
||||
if fake.listRoomsReturnsOnCall == nil {
|
||||
fake.listRoomsReturnsOnCall = make(map[int]struct {
|
||||
result1 []*livekit.Room
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.listRoomsReturnsOnCall[i] = struct {
|
||||
result1 []*livekit.Room
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.createRoomMutex.RLock()
|
||||
defer fake.createRoomMutex.RUnlock()
|
||||
fake.deleteRoomMutex.RLock()
|
||||
defer fake.deleteRoomMutex.RUnlock()
|
||||
fake.getRoomMutex.RLock()
|
||||
defer fake.getRoomMutex.RUnlock()
|
||||
fake.listRoomsMutex.RLock()
|
||||
defer fake.listRoomsMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeRoomStore) recordInvocation(key string, args []interface{}) {
|
||||
fake.invocationsMutex.Lock()
|
||||
defer fake.invocationsMutex.Unlock()
|
||||
if fake.invocations == nil {
|
||||
fake.invocations = map[string][][]interface{}{}
|
||||
}
|
||||
if fake.invocations[key] == nil {
|
||||
fake.invocations[key] = [][]interface{}{}
|
||||
}
|
||||
fake.invocations[key] = append(fake.invocations[key], args)
|
||||
}
|
||||
|
||||
var _ service.RoomStore = new(FakeRoomStore)
|
||||
@@ -1,69 +0,0 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/node"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
// A rooms service that supports a single node
|
||||
type SimpleRoomService struct {
|
||||
localNode *node.Node
|
||||
|
||||
manager *rtc.RoomManager
|
||||
}
|
||||
|
||||
func NewSimpleRoomService(manager *rtc.RoomManager, localNode *node.Node) (svc *SimpleRoomService, err error) {
|
||||
svc = &SimpleRoomService{
|
||||
localNode: localNode,
|
||||
manager: manager,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SimpleRoomService) CreateRoom(ctx context.Context, req *livekit.CreateRoomRequest) (res *livekit.RoomInfo, err error) {
|
||||
if err = EnsureCreatePermission(ctx); err != nil {
|
||||
return nil, twirpAuthError(err)
|
||||
}
|
||||
room, err := s.manager.CreateRoom(req)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = room.ToRoomInfo(&s.localNode.Node)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SimpleRoomService) GetRoom(ctx context.Context, req *livekit.GetRoomRequest) (res *livekit.RoomInfo, err error) {
|
||||
onlyName, err := EnsureJoinPermission(ctx)
|
||||
if err != nil {
|
||||
return nil, twirpAuthError(err)
|
||||
}
|
||||
|
||||
room, err := s.manager.GetRoomWithConstraint(req.Room, onlyName)
|
||||
if err != nil {
|
||||
// TODO: translate error codes to twirp
|
||||
return
|
||||
}
|
||||
|
||||
res = room.ToRoomInfo(&s.localNode.Node)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *SimpleRoomService) DeleteRoom(ctx context.Context, req *livekit.DeleteRoomRequest) (res *livekit.DeleteRoomResponse, err error) {
|
||||
if err = EnsureCreatePermission(ctx); err != nil {
|
||||
return nil, twirpAuthError(err)
|
||||
}
|
||||
err = s.manager.DeleteRoom(req.Room)
|
||||
if err != nil {
|
||||
err = twirp.WrapError(twirp.InternalError("could not delete room"), err)
|
||||
return
|
||||
}
|
||||
res = &livekit.DeleteRoomResponse{}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
"github.com/livekit/livekit-server/proto/livekit"
|
||||
)
|
||||
|
||||
var ServiceSet = wire.NewSet(
|
||||
NewRoomService,
|
||||
NewRTCService,
|
||||
NewLivekitServer,
|
||||
NewRTCRunner,
|
||||
wire.Bind(new(livekit.RoomService), new(*RoomService)),
|
||||
externalIpFromNode,
|
||||
)
|
||||
|
||||
// helper to construct RTCConfig
|
||||
func externalIpFromNode(currentNode routing.LocalNode) rtc.ExternalIP {
|
||||
return rtc.ExternalIP(currentNode.Ip)
|
||||
}
|
||||
+5
-3
@@ -7,13 +7,15 @@ import (
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/node"
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
)
|
||||
|
||||
func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider) (*LivekitServer, error) {
|
||||
func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider,
|
||||
roomStore RoomStore, router routing.Router, currentNode routing.LocalNode) (*LivekitServer, error) {
|
||||
wire.Build(
|
||||
node.NodeSet,
|
||||
ServiceSet,
|
||||
rtc.RTCSet,
|
||||
)
|
||||
return &LivekitServer{}, nil
|
||||
}
|
||||
|
||||
+10
-10
@@ -8,26 +8,26 @@ package service
|
||||
import (
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
"github.com/livekit/livekit-server/pkg/config"
|
||||
"github.com/livekit/livekit-server/pkg/node"
|
||||
"github.com/livekit/livekit-server/pkg/routing"
|
||||
"github.com/livekit/livekit-server/pkg/rtc"
|
||||
)
|
||||
|
||||
// Injectors from wire.go:
|
||||
|
||||
func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider) (*LivekitServer, error) {
|
||||
nodeNode, err := node.NewLocalNode(conf)
|
||||
func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider, roomStore RoomStore, router routing.Router, currentNode routing.LocalNode) (*LivekitServer, error) {
|
||||
roomService, err := NewRoomService(roomStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomManager, err := newRoomManagerWithNode(conf, nodeNode)
|
||||
rtcService := NewRTCService(conf, roomStore, router, currentNode)
|
||||
rtcConfig := rtc.RTCConfigFromConfig(conf)
|
||||
externalIP := externalIpFromNode(currentNode)
|
||||
webRTCConfig, err := rtc.NewWebRTCConfig(rtcConfig, externalIP)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomService, err := NewRoomService(conf, roomManager, nodeNode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rtcService := NewRTCService(conf, roomManager)
|
||||
livekitServer, err := NewLivekitServer(conf, roomService, rtcService, keyProvider)
|
||||
rtcRunner := NewRTCRunner(roomStore, router, currentNode, webRTCConfig)
|
||||
livekitServer, err := NewLivekitServer(conf, roomService, rtcService, keyProvider, router, rtcRunner)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package rtc
|
||||
package service
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -54,7 +54,7 @@ func (c *WSSignalConnection) ReadRequest() (*livekit.SignalRequest, error) {
|
||||
err := protojson.Unmarshal(payload, msg)
|
||||
return msg, err
|
||||
default:
|
||||
logger.GetLogger().Debugw("unsupported message", "message", messageType)
|
||||
logger.Debugw("unsupported message", "message", messageType)
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -2,4 +2,4 @@ This package is largely files from the wonderful ion-sfu project.
|
||||
|
||||
https://github.com/pion/ion-sfu
|
||||
|
||||
It's duplicated here since we needed to access a private method in various helper classes
|
||||
It's duplicated here with modifications to reference only classes that we need
|
||||
+1
-1
@@ -6,7 +6,7 @@ var (
|
||||
errPeerConnectionInitFailed = errors.New("pc init failed")
|
||||
errPtNotSupported = errors.New("payload type not supported")
|
||||
errCreatingDataChannel = errors.New("failed to create data channel")
|
||||
// router errors
|
||||
// routing errors
|
||||
errNoReceiverFound = errors.New("no receiver found")
|
||||
// Helpers errors
|
||||
errShortPacket = errors.New("packet is not large enough")
|
||||
|
||||
Reference in New Issue
Block a user