mirror of
https://github.com/livekit/livekit.git
synced 2026-10-15 04:30:16 +00:00
JWT token based auth
This commit is contained in:
@@ -62,7 +62,7 @@ func createRoom(c *cli.Context) error {
|
||||
func getRoom(c *cli.Context) error {
|
||||
roomId := c.String("room-id")
|
||||
room, err := roomClient.GetRoom(context.Background(), &livekit.GetRoomRequest{
|
||||
RoomId: roomId,
|
||||
Room: roomId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -75,7 +75,7 @@ func getRoom(c *cli.Context) error {
|
||||
func deleteRoom(c *cli.Context) error {
|
||||
roomId := c.String("room-id")
|
||||
_, err := roomClient.DeleteRoom(context.Background(), &livekit.DeleteRoomRequest{
|
||||
RoomId: roomId,
|
||||
Room: roomId,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
+54
-7
@@ -1,6 +1,7 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"github.com/urfave/cli/v2"
|
||||
"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"
|
||||
@@ -29,10 +31,22 @@ func main() {
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "config",
|
||||
Usage: "path to LiveKit config",
|
||||
EnvVars: []string{"LIVEKIT_CONFIG"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "key-file",
|
||||
Usage: "path to file that contains API keys/secrets",
|
||||
EnvVars: []string{"KEY_FILE"},
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "keys",
|
||||
Usage: "API keys/secret pairs (key:secret, one per line)",
|
||||
EnvVars: []string{"KEY_FILE"},
|
||||
},
|
||||
&cli.BoolFlag{
|
||||
Name: "dev",
|
||||
Name: "dev",
|
||||
Usage: "when set, token validation will be disabled",
|
||||
},
|
||||
},
|
||||
Action: startServer,
|
||||
@@ -50,14 +64,20 @@ func startServer(c *cli.Context) error {
|
||||
}
|
||||
|
||||
conf.UpdateFromCLI(c)
|
||||
var keyProvider auth.KeyProvider
|
||||
|
||||
if conf.Development {
|
||||
logger.InitDevelopment()
|
||||
} else {
|
||||
logger.InitProduction()
|
||||
// require a key provider
|
||||
if keyProvider, err = createKeyProvider(c.String("key-file"), c.String("keys")); err != nil {
|
||||
return err
|
||||
}
|
||||
service.AuthRequired = true
|
||||
}
|
||||
|
||||
server, err := InitializeServer(conf)
|
||||
server, err := InitializeServer(conf, keyProvider)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -74,6 +94,25 @@ func startServer(c *cli.Context) error {
|
||||
return server.Start()
|
||||
}
|
||||
|
||||
func createKeyProvider(keyFile, keys string) (auth.KeyProvider, error) {
|
||||
// prefer keyfile if set
|
||||
if keyFile != "" {
|
||||
f, err := os.Open(keyFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer f.Close()
|
||||
return auth.NewFileBasedKeyProvider(f)
|
||||
}
|
||||
|
||||
if keys != "" {
|
||||
r := bytes.NewReader([]byte(keys))
|
||||
return auth.NewFileBasedKeyProvider(r)
|
||||
}
|
||||
|
||||
return nil, errors.New("one of key-file or keys must be provided in order to support a secure installation")
|
||||
}
|
||||
|
||||
type LivekitServer struct {
|
||||
config *config.Config
|
||||
roomServer livekit.TwirpServer
|
||||
@@ -86,24 +125,29 @@ type LivekitServer struct {
|
||||
|
||||
func NewLivekitServer(conf *config.Config,
|
||||
roomService livekit.RoomService,
|
||||
rtcService *service.RTCService) (s *LivekitServer, err error) {
|
||||
rtcService *service.RTCService,
|
||||
keyProvider auth.KeyProvider) (s *LivekitServer, err error) {
|
||||
s = &LivekitServer{
|
||||
config: conf,
|
||||
roomServer: livekit.NewRoomServiceServer(roomService),
|
||||
rtcService: rtcService,
|
||||
}
|
||||
|
||||
roomHandler := configureMiddlewares(conf, s.roomServer)
|
||||
middlewares := make([]negroni.Handler, 0)
|
||||
if keyProvider != nil {
|
||||
middlewares = append(middlewares, service.NewAPIKeyAuthMiddleware(keyProvider))
|
||||
}
|
||||
|
||||
s.roomHttp = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", conf.APIPort),
|
||||
Handler: roomHandler,
|
||||
Handler: configureMiddlewares(conf, s.roomServer, middlewares...),
|
||||
}
|
||||
|
||||
rtcHandler := http.NewServeMux()
|
||||
rtcHandler.Handle("/rtc", rtcService)
|
||||
s.rtcHttp = &http.Server{
|
||||
Addr: fmt.Sprintf(":%d", conf.RTCPort),
|
||||
Handler: configureMiddlewares(conf, rtcHandler),
|
||||
Handler: configureMiddlewares(conf, rtcHandler, middlewares...),
|
||||
}
|
||||
|
||||
return
|
||||
@@ -162,9 +206,12 @@ func (s *LivekitServer) Stop() {
|
||||
s.doneChan <- true
|
||||
}
|
||||
|
||||
func configureMiddlewares(conf *config.Config, handler http.Handler) *negroni.Negroni {
|
||||
func configureMiddlewares(conf *config.Config, 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
|
||||
}
|
||||
|
||||
+2
-1
@@ -5,12 +5,13 @@ package main
|
||||
import (
|
||||
"github.com/google/wire"
|
||||
|
||||
"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/service"
|
||||
)
|
||||
|
||||
func InitializeServer(conf *config.Config) (*LivekitServer, error) {
|
||||
func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider) (*LivekitServer, error) {
|
||||
wire.Build(
|
||||
NewLivekitServer,
|
||||
node.NodeSet,
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package main
|
||||
|
||||
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/service"
|
||||
@@ -13,7 +14,7 @@ import (
|
||||
|
||||
// Injectors from wire.go:
|
||||
|
||||
func InitializeServer(conf *config.Config) (*LivekitServer, error) {
|
||||
func InitializeServer(conf *config.Config, keyProvider auth.KeyProvider) (*LivekitServer, error) {
|
||||
nodeNode, err := node.NewLocalNode(conf)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -27,7 +28,7 @@ func InitializeServer(conf *config.Config) (*LivekitServer, error) {
|
||||
return nil, err
|
||||
}
|
||||
rtcService := service.NewRTCService(conf, roomManager)
|
||||
livekitServer, err := NewLivekitServer(conf, roomService, rtcService)
|
||||
livekitServer, err := NewLivekitServer(conf, roomService, rtcService, keyProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ require (
|
||||
github.com/gorilla/websocket v1.4.2
|
||||
github.com/lithammer/shortuuid/v3 v3.0.4
|
||||
github.com/lunixbochs/vtclean v1.0.0 // indirect
|
||||
github.com/lytics/base62 v0.0.0-20180808010106-0ee4de5a5d6d
|
||||
github.com/magefile/mage v1.10.0
|
||||
github.com/manifoldco/promptui v0.8.0
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.3.0
|
||||
@@ -30,5 +31,6 @@ require (
|
||||
golang.org/x/mod v0.4.0 // indirect
|
||||
golang.org/x/tools v0.0.0-20201222163215-f2e330f49058 // indirect
|
||||
google.golang.org/protobuf v1.25.0
|
||||
gopkg.in/square/go-jose.v2 v2.5.1
|
||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776
|
||||
)
|
||||
|
||||
@@ -21,9 +21,11 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
|
||||
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d h1:UQZhZ2O0vMHr2cI+DC1Mbh0TJxzA3RcLoMsFw+aXw7E=
|
||||
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
@@ -71,6 +73,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/desertbit/timer v0.0.0-20180107155436-c41aec40b27f/go.mod h1:xH/i4TFMt8koVQZ6WFms69WAsDWr2XsYL3Hkl7jkoLE=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
@@ -224,6 +227,8 @@ github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQN
|
||||
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
|
||||
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
|
||||
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
|
||||
github.com/lytics/base62 v0.0.0-20180808010106-0ee4de5a5d6d h1:HONlVR8gkr5QibYNVFtj8ajfqRAKt21DmdzeZXZl6VQ=
|
||||
github.com/lytics/base62 v0.0.0-20180808010106-0ee4de5a5d6d/go.mod h1:nFZ1y9JiUDciefRL0X6OTobqQGgFCR+lbnn1lWsoQk0=
|
||||
github.com/magefile/mage v1.10.0 h1:3HiXzCUY12kh9bIuyXShaVe529fJfyqoVM42o/uom2g=
|
||||
github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
||||
github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4=
|
||||
@@ -672,6 +677,7 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
|
||||
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
|
||||
google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
@@ -686,6 +692,8 @@ gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
|
||||
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.51.1/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1 h1:7odma5RETjNHWJnR32wx8t+Io4djHE1PqxCFx3iiZ2w=
|
||||
gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package authfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
)
|
||||
|
||||
type FakeKeyProvider struct {
|
||||
GetSecretStub func(string) string
|
||||
getSecretMutex sync.RWMutex
|
||||
getSecretArgsForCall []struct {
|
||||
arg1 string
|
||||
}
|
||||
getSecretReturns struct {
|
||||
result1 string
|
||||
}
|
||||
getSecretReturnsOnCall map[int]struct {
|
||||
result1 string
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) GetSecret(arg1 string) string {
|
||||
fake.getSecretMutex.Lock()
|
||||
ret, specificReturn := fake.getSecretReturnsOnCall[len(fake.getSecretArgsForCall)]
|
||||
fake.getSecretArgsForCall = append(fake.getSecretArgsForCall, struct {
|
||||
arg1 string
|
||||
}{arg1})
|
||||
stub := fake.GetSecretStub
|
||||
fakeReturns := fake.getSecretReturns
|
||||
fake.recordInvocation("GetSecret", []interface{}{arg1})
|
||||
fake.getSecretMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1
|
||||
}
|
||||
return fakeReturns.result1
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) GetSecretCallCount() int {
|
||||
fake.getSecretMutex.RLock()
|
||||
defer fake.getSecretMutex.RUnlock()
|
||||
return len(fake.getSecretArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) GetSecretCalls(stub func(string) string) {
|
||||
fake.getSecretMutex.Lock()
|
||||
defer fake.getSecretMutex.Unlock()
|
||||
fake.GetSecretStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) GetSecretArgsForCall(i int) string {
|
||||
fake.getSecretMutex.RLock()
|
||||
defer fake.getSecretMutex.RUnlock()
|
||||
argsForCall := fake.getSecretArgsForCall[i]
|
||||
return argsForCall.arg1
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) GetSecretReturns(result1 string) {
|
||||
fake.getSecretMutex.Lock()
|
||||
defer fake.getSecretMutex.Unlock()
|
||||
fake.GetSecretStub = nil
|
||||
fake.getSecretReturns = struct {
|
||||
result1 string
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) GetSecretReturnsOnCall(i int, result1 string) {
|
||||
fake.getSecretMutex.Lock()
|
||||
defer fake.getSecretMutex.Unlock()
|
||||
fake.GetSecretStub = nil
|
||||
if fake.getSecretReturnsOnCall == nil {
|
||||
fake.getSecretReturnsOnCall = make(map[int]struct {
|
||||
result1 string
|
||||
})
|
||||
}
|
||||
fake.getSecretReturnsOnCall[i] = struct {
|
||||
result1 string
|
||||
}{result1}
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.getSecretMutex.RLock()
|
||||
defer fake.getSecretMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeKeyProvider) 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 _ auth.KeyProvider = new(FakeKeyProvider)
|
||||
@@ -0,0 +1,119 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package authfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
)
|
||||
|
||||
type FakeTokenIssuer struct {
|
||||
CreateTokenStub func(*auth.GrantClaims, time.Duration) (string, error)
|
||||
createTokenMutex sync.RWMutex
|
||||
createTokenArgsForCall []struct {
|
||||
arg1 *auth.GrantClaims
|
||||
arg2 time.Duration
|
||||
}
|
||||
createTokenReturns struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
createTokenReturnsOnCall map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) CreateToken(arg1 *auth.GrantClaims, arg2 time.Duration) (string, error) {
|
||||
fake.createTokenMutex.Lock()
|
||||
ret, specificReturn := fake.createTokenReturnsOnCall[len(fake.createTokenArgsForCall)]
|
||||
fake.createTokenArgsForCall = append(fake.createTokenArgsForCall, struct {
|
||||
arg1 *auth.GrantClaims
|
||||
arg2 time.Duration
|
||||
}{arg1, arg2})
|
||||
stub := fake.CreateTokenStub
|
||||
fakeReturns := fake.createTokenReturns
|
||||
fake.recordInvocation("CreateToken", []interface{}{arg1, arg2})
|
||||
fake.createTokenMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub(arg1, arg2)
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) CreateTokenCallCount() int {
|
||||
fake.createTokenMutex.RLock()
|
||||
defer fake.createTokenMutex.RUnlock()
|
||||
return len(fake.createTokenArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) CreateTokenCalls(stub func(*auth.GrantClaims, time.Duration) (string, error)) {
|
||||
fake.createTokenMutex.Lock()
|
||||
defer fake.createTokenMutex.Unlock()
|
||||
fake.CreateTokenStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) CreateTokenArgsForCall(i int) (*auth.GrantClaims, time.Duration) {
|
||||
fake.createTokenMutex.RLock()
|
||||
defer fake.createTokenMutex.RUnlock()
|
||||
argsForCall := fake.createTokenArgsForCall[i]
|
||||
return argsForCall.arg1, argsForCall.arg2
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) CreateTokenReturns(result1 string, result2 error) {
|
||||
fake.createTokenMutex.Lock()
|
||||
defer fake.createTokenMutex.Unlock()
|
||||
fake.CreateTokenStub = nil
|
||||
fake.createTokenReturns = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) CreateTokenReturnsOnCall(i int, result1 string, result2 error) {
|
||||
fake.createTokenMutex.Lock()
|
||||
defer fake.createTokenMutex.Unlock()
|
||||
fake.CreateTokenStub = nil
|
||||
if fake.createTokenReturnsOnCall == nil {
|
||||
fake.createTokenReturnsOnCall = make(map[int]struct {
|
||||
result1 string
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.createTokenReturnsOnCall[i] = struct {
|
||||
result1 string
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.createTokenMutex.RLock()
|
||||
defer fake.createTokenMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeTokenIssuer) 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 _ auth.TokenIssuer = new(FakeTokenIssuer)
|
||||
@@ -0,0 +1,107 @@
|
||||
// Code generated by counterfeiter. DO NOT EDIT.
|
||||
package authfakes
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
)
|
||||
|
||||
type FakeTokenVerifier struct {
|
||||
VerifyStub func() (*auth.GrantClaims, error)
|
||||
verifyMutex sync.RWMutex
|
||||
verifyArgsForCall []struct {
|
||||
}
|
||||
verifyReturns struct {
|
||||
result1 *auth.GrantClaims
|
||||
result2 error
|
||||
}
|
||||
verifyReturnsOnCall map[int]struct {
|
||||
result1 *auth.GrantClaims
|
||||
result2 error
|
||||
}
|
||||
invocations map[string][][]interface{}
|
||||
invocationsMutex sync.RWMutex
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) Verify() (*auth.GrantClaims, error) {
|
||||
fake.verifyMutex.Lock()
|
||||
ret, specificReturn := fake.verifyReturnsOnCall[len(fake.verifyArgsForCall)]
|
||||
fake.verifyArgsForCall = append(fake.verifyArgsForCall, struct {
|
||||
}{})
|
||||
stub := fake.VerifyStub
|
||||
fakeReturns := fake.verifyReturns
|
||||
fake.recordInvocation("Verify", []interface{}{})
|
||||
fake.verifyMutex.Unlock()
|
||||
if stub != nil {
|
||||
return stub()
|
||||
}
|
||||
if specificReturn {
|
||||
return ret.result1, ret.result2
|
||||
}
|
||||
return fakeReturns.result1, fakeReturns.result2
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) VerifyCallCount() int {
|
||||
fake.verifyMutex.RLock()
|
||||
defer fake.verifyMutex.RUnlock()
|
||||
return len(fake.verifyArgsForCall)
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) VerifyCalls(stub func() (*auth.GrantClaims, error)) {
|
||||
fake.verifyMutex.Lock()
|
||||
defer fake.verifyMutex.Unlock()
|
||||
fake.VerifyStub = stub
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) VerifyReturns(result1 *auth.GrantClaims, result2 error) {
|
||||
fake.verifyMutex.Lock()
|
||||
defer fake.verifyMutex.Unlock()
|
||||
fake.VerifyStub = nil
|
||||
fake.verifyReturns = struct {
|
||||
result1 *auth.GrantClaims
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) VerifyReturnsOnCall(i int, result1 *auth.GrantClaims, result2 error) {
|
||||
fake.verifyMutex.Lock()
|
||||
defer fake.verifyMutex.Unlock()
|
||||
fake.VerifyStub = nil
|
||||
if fake.verifyReturnsOnCall == nil {
|
||||
fake.verifyReturnsOnCall = make(map[int]struct {
|
||||
result1 *auth.GrantClaims
|
||||
result2 error
|
||||
})
|
||||
}
|
||||
fake.verifyReturnsOnCall[i] = struct {
|
||||
result1 *auth.GrantClaims
|
||||
result2 error
|
||||
}{result1, result2}
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) Invocations() map[string][][]interface{} {
|
||||
fake.invocationsMutex.RLock()
|
||||
defer fake.invocationsMutex.RUnlock()
|
||||
fake.verifyMutex.RLock()
|
||||
defer fake.verifyMutex.RUnlock()
|
||||
copiedInvocations := map[string][][]interface{}{}
|
||||
for key, value := range fake.invocations {
|
||||
copiedInvocations[key] = value
|
||||
}
|
||||
return copiedInvocations
|
||||
}
|
||||
|
||||
func (fake *FakeTokenVerifier) 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 _ auth.TokenVerifier = new(FakeTokenVerifier)
|
||||
@@ -0,0 +1,7 @@
|
||||
package auth
|
||||
|
||||
type GrantClaims struct {
|
||||
RoomCreate bool `json:"room_create,omitempty"`
|
||||
RoomJoin bool `json:"room_join,omitempty"`
|
||||
Room string `json:"room"`
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"time"
|
||||
)
|
||||
|
||||
//go:generate go run github.com/maxbrunsfeld/counterfeiter/v6 -generate
|
||||
|
||||
var (
|
||||
ErrKeysMissing = errors.New("missing API key or secret key")
|
||||
)
|
||||
|
||||
//counterfeiter:generate . TokenIssuer
|
||||
type TokenIssuer interface {
|
||||
CreateToken(claims *GrantClaims, validFor time.Duration) (string, error)
|
||||
}
|
||||
|
||||
//counterfeiter:generate . TokenVerifier
|
||||
type TokenVerifier interface {
|
||||
Verify() (*GrantClaims, error)
|
||||
}
|
||||
|
||||
//counterfeiter:generate . KeyProvider
|
||||
type KeyProvider interface {
|
||||
GetSecret(key string) string
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
// Signer that produces token signed with API key and secret
|
||||
type APIKeyTokenIssuer struct {
|
||||
APIKey string
|
||||
SecretKey string
|
||||
}
|
||||
|
||||
func NewAPIKeyTokenIssuer(key string, secret string) *APIKeyTokenIssuer {
|
||||
return &APIKeyTokenIssuer{
|
||||
APIKey: key,
|
||||
SecretKey: secret,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *APIKeyTokenIssuer) CreateToken(claims *GrantClaims, validFor time.Duration) (string, error) {
|
||||
if s.APIKey == "" || s.SecretKey == "" {
|
||||
return "", ErrKeysMissing
|
||||
}
|
||||
sig, err := jose.NewSigner(jose.SigningKey{Algorithm: jose.HS256, Key: []byte(s.SecretKey)},
|
||||
(&jose.SignerOptions{}).WithType("JWT"))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
cl := jwt.Claims{
|
||||
Issuer: s.APIKey,
|
||||
Subject: s.APIKey,
|
||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
||||
Expiry: jwt.NewNumericDate(time.Now().Add(validFor)),
|
||||
}
|
||||
|
||||
return jwt.Signed(sig).Claims(cl).Claims(claims).CompactSerialize()
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
"github.com/livekit/livekit-server/pkg/utils"
|
||||
)
|
||||
|
||||
func TestAPIIssuer(t *testing.T) {
|
||||
t.Run("keys must be set", func(t *testing.T) {
|
||||
s := auth.NewAPIKeyTokenIssuer("", "")
|
||||
_, err := s.CreateToken(&auth.GrantClaims{}, time.Hour)
|
||||
assert.Equal(t, auth.ErrKeysMissing, err)
|
||||
})
|
||||
|
||||
t.Run("generates a decodeable key", func(t *testing.T) {
|
||||
apiKey, secret := apiKeypair()
|
||||
//fmt.Println(apiKey, secret)
|
||||
s := auth.NewAPIKeyTokenIssuer(apiKey, secret)
|
||||
claims := auth.GrantClaims{RoomJoin: true, Room: "myroom"}
|
||||
raw, err := s.CreateToken(&claims, time.Hour)
|
||||
//fmt.Println(raw)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Len(t, strings.Split(raw, "."), 3)
|
||||
|
||||
// ensure it's a valid JWT
|
||||
token, err := jwt.ParseSigned(raw)
|
||||
assert.NoError(t, err)
|
||||
|
||||
decodedGrant := auth.GrantClaims{}
|
||||
err = token.UnsafeClaimsWithoutVerification(&decodedGrant)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.EqualValues(t, &claims, &decodedGrant)
|
||||
})
|
||||
}
|
||||
|
||||
func apiKeypair() (string, string) {
|
||||
return utils.NewGuid(utils.APIKeyPrefix), utils.RandomSecret()
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type FileBasedKeyProvider struct {
|
||||
keys map[string]string
|
||||
}
|
||||
|
||||
func NewFileBasedKeyProvider(r io.Reader) (p *FileBasedKeyProvider, err error) {
|
||||
scanner := bufio.NewScanner(r)
|
||||
keys := make(map[string]string)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
log.Println("line", line)
|
||||
//break
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
parts := strings.Split(string(line), ":")
|
||||
if len(parts) != 2 {
|
||||
return nil, fmt.Errorf("invalid api key/secret pair, must be api_key:secret: %v", line)
|
||||
}
|
||||
keys[strings.TrimSpace(parts[0])] = strings.TrimSpace(parts[1])
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
return
|
||||
}
|
||||
p = &FileBasedKeyProvider{
|
||||
keys: keys,
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (p *FileBasedKeyProvider) GetSecret(key string) string {
|
||||
return p.keys[key]
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
)
|
||||
|
||||
func TestFileBasedKeyProvider(t *testing.T) {
|
||||
keys := map[string]string{
|
||||
"key1": "secret1",
|
||||
"key2": "secret2",
|
||||
"key3": "secret3",
|
||||
}
|
||||
f, err := ioutil.TempFile("", "keyfile")
|
||||
assert.NoError(t, err)
|
||||
defer func() {
|
||||
os.Remove(f.Name())
|
||||
}()
|
||||
|
||||
f.WriteString("key1:secret1\n")
|
||||
f.WriteString(" key2: secret2 \r\n")
|
||||
f.WriteString("\n")
|
||||
f.WriteString("key3 : secret3")
|
||||
|
||||
f.Close()
|
||||
|
||||
r, err := os.Open(f.Name())
|
||||
defer r.Close()
|
||||
p, err := auth.NewFileBasedKeyProvider(r)
|
||||
assert.NoError(t, err)
|
||||
|
||||
for key, val := range keys {
|
||||
assert.Equal(t, val, p.GetSecret(key))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package auth
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"gopkg.in/square/go-jose.v2/jwt"
|
||||
)
|
||||
|
||||
type APIKeyTokenVerifier struct {
|
||||
token *jwt.JSONWebToken
|
||||
apiKey string
|
||||
secretKey string
|
||||
}
|
||||
|
||||
func ParseAPIToken(raw string) (*APIKeyTokenVerifier, error) {
|
||||
tok, err := jwt.ParseSigned(raw)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
out := jwt.Claims{}
|
||||
if err := tok.UnsafeClaimsWithoutVerification(&out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &APIKeyTokenVerifier{
|
||||
token: tok,
|
||||
apiKey: out.Issuer,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Returns the API key this token was signed with
|
||||
func (v *APIKeyTokenVerifier) APIKey() string {
|
||||
return v.apiKey
|
||||
}
|
||||
|
||||
func (v *APIKeyTokenVerifier) SetSecretKey(secret string) {
|
||||
v.secretKey = secret
|
||||
}
|
||||
|
||||
func (v *APIKeyTokenVerifier) Verify() (*GrantClaims, error) {
|
||||
if v.secretKey == "" {
|
||||
return nil, ErrKeysMissing
|
||||
}
|
||||
out := jwt.Claims{}
|
||||
claims := GrantClaims{}
|
||||
if err := v.token.Claims([]byte(v.secretKey), &out, &claims); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := out.Validate(jwt.Expected{Issuer: v.apiKey, Time: time.Now()}); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &claims, nil
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package auth_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
)
|
||||
|
||||
func TestAPIVerifier(t *testing.T) {
|
||||
apiKey := "APID3B67uxk4Nj2GKiRPibAZ9"
|
||||
secret := "YHC-CUhbQhGeVCaYgn1BNA++"
|
||||
accessToken := "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE2MDg5MzAzMDgsImlzcyI6IkFQSUQzQjY3dXhrNE5qMkdLaVJQaWJBWjkiLCJuYmYiOjE2MDg5MjY3MDgsInJvb21fam9pbiI6dHJ1ZSwicm9vbV9zaWQiOiJteWlkIiwic3ViIjoiQVBJRDNCNjd1eGs0TmoyR0tpUlBpYkFaOSJ9.cmHEBq0MLyRqphmVLM2cLXg5ao5Sro7am8yXhcYKcwE"
|
||||
t.Run("cannot decode with incorrect key", func(t *testing.T) {
|
||||
v, err := auth.ParseAPIToken(accessToken)
|
||||
assert.NoError(t, err)
|
||||
|
||||
assert.Equal(t, apiKey, v.APIKey())
|
||||
_, err = v.Verify()
|
||||
assert.Error(t, err)
|
||||
|
||||
v.SetSecretKey("anothersecret")
|
||||
_, err = v.Verify()
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("key has expired", func(t *testing.T) {
|
||||
v, err := auth.ParseAPIToken(accessToken)
|
||||
v.SetSecretKey(secret)
|
||||
|
||||
_, err = v.Verify()
|
||||
assert.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("unexpired token is verified", func(t *testing.T) {
|
||||
s := auth.NewAPIKeyTokenIssuer(apiKey, secret)
|
||||
claim := auth.GrantClaims{RoomCreate: true}
|
||||
authToken, err := s.CreateToken(&claim, time.Minute)
|
||||
assert.NoError(t, err)
|
||||
|
||||
v, err := auth.ParseAPIToken(authToken)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, apiKey, v.APIKey())
|
||||
|
||||
v.SetSecretKey(secret)
|
||||
decoded, err := v.Verify()
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &claim, decoded)
|
||||
})
|
||||
}
|
||||
+3
-1
@@ -3,5 +3,7 @@ package rtc
|
||||
import "errors"
|
||||
|
||||
var (
|
||||
ErrRoomIdMissing = errors.New("roomId is not set")
|
||||
ErrRoomIdMissing = errors.New("room is not passed in")
|
||||
ErrRoomNotFound = errors.New("requested room does not exist")
|
||||
ErrPermissionDenied = errors.New("no permissions to access the room")
|
||||
)
|
||||
|
||||
+43
-14
@@ -7,22 +7,25 @@ import (
|
||||
"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
|
||||
roomLock sync.RWMutex
|
||||
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),
|
||||
roomLock: sync.RWMutex{},
|
||||
rtcConf: rtcConf,
|
||||
externalIP: externalIP,
|
||||
rooms: make(map[string]*Room),
|
||||
roomsByName: make(map[string]*Room),
|
||||
roomLock: sync.RWMutex{},
|
||||
}
|
||||
|
||||
wc, err := NewWebRTCConfig(&rtcConf, externalIP)
|
||||
@@ -33,27 +36,53 @@ func NewRoomManager(rtcConf config.RTCConfig, externalIP string) (m *RoomManager
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RoomManager) GetRoom(roomId string) *Room {
|
||||
func (m *RoomManager) GetRoom(idOrName string) *Room {
|
||||
m.roomLock.RLock()
|
||||
defer m.roomLock.RUnlock()
|
||||
return m.rooms[roomId]
|
||||
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) (r *Room, err error) {
|
||||
r, err = NewRoomForRequest(req, &m.config)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
r = NewRoomForRequest(req, &m.config)
|
||||
m.roomLock.Lock()
|
||||
defer m.roomLock.Unlock()
|
||||
m.rooms[r.Sid] = r
|
||||
m.roomsByName[r.Name] = r
|
||||
return
|
||||
}
|
||||
|
||||
func (m *RoomManager) DeleteRoom(roomId string) error {
|
||||
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, roomId)
|
||||
delete(m.rooms, rm.Sid)
|
||||
delete(m.roomsByName, rm.Name)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
package rtc_test
|
||||
+4
-10
@@ -4,7 +4,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/thoas/go-funk"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/logger"
|
||||
@@ -22,24 +21,19 @@ type Room struct {
|
||||
//tracks map[string][]Track
|
||||
}
|
||||
|
||||
func NewRoomForRequest(req *livekit.CreateRoomRequest, config *WebRTCConfig) (*Room, error) {
|
||||
id, err := uuid.NewRandom()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func NewRoomForRequest(req *livekit.CreateRoomRequest, 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(),
|
||||
Token: id.String(),
|
||||
},
|
||||
config: *config,
|
||||
lock: sync.RWMutex{},
|
||||
participants: make(map[string]Participant),
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Room) GetParticipant(id string) Participant {
|
||||
@@ -57,9 +51,9 @@ func (r *Room) GetParticipants() []Participant {
|
||||
func (r *Room) ToRoomInfo(node *livekit.Node) *livekit.RoomInfo {
|
||||
return &livekit.RoomInfo{
|
||||
Sid: r.Sid,
|
||||
Name: r.Name,
|
||||
NodeIp: node.Ip,
|
||||
CreationTime: r.CreationTime,
|
||||
Token: r.Token,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-4
@@ -15,6 +15,32 @@ 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)
|
||||
@@ -96,10 +122,7 @@ func TestNewTrack(t *testing.T) {
|
||||
}
|
||||
|
||||
func newRoomWithParticipants(t *testing.T, num int) *rtc.Room {
|
||||
rm, err := rtc.NewRoomForRequest(&livekit.CreateRoomRequest{}, &rtc.WebRTCConfig{})
|
||||
if err != nil {
|
||||
panic("could not create a room")
|
||||
}
|
||||
rm := rtc.NewRoomForRequest(&livekit.CreateRoomRequest{}, &rtc.WebRTCConfig{})
|
||||
for i := 0; i < num; i++ {
|
||||
participant := newMockParticipant("")
|
||||
err := rm.Join(participant)
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/twitchtv/twirp"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
)
|
||||
|
||||
const (
|
||||
authorizationHeader = "Authorization"
|
||||
bearerPrefix = "Bearer "
|
||||
grantsKey = "grants"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrPermissionDenied = errors.New("permissions denied")
|
||||
AuthRequired bool
|
||||
)
|
||||
|
||||
// authentication middleware
|
||||
type APIKeyAuthMiddleware struct {
|
||||
provider auth.KeyProvider
|
||||
}
|
||||
|
||||
func NewAPIKeyAuthMiddleware(provider auth.KeyProvider) *APIKeyAuthMiddleware {
|
||||
return &APIKeyAuthMiddleware{
|
||||
provider: provider,
|
||||
}
|
||||
}
|
||||
|
||||
func (m *APIKeyAuthMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request, next http.HandlerFunc) {
|
||||
authHeader := r.Header.Get(authorizationHeader)
|
||||
|
||||
if authHeader != "" {
|
||||
if !strings.HasPrefix(authHeader, bearerPrefix) {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("invalid authorization header. Must start with " + bearerPrefix))
|
||||
return
|
||||
}
|
||||
|
||||
authToken := authHeader[len(bearerPrefix):]
|
||||
v, err := auth.ParseAPIToken(authToken)
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("invalid authorization token"))
|
||||
return
|
||||
}
|
||||
|
||||
secret := m.provider.GetSecret(v.APIKey())
|
||||
if secret == "" {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("invalid API key"))
|
||||
return
|
||||
}
|
||||
|
||||
v.SetSecretKey(secret)
|
||||
|
||||
grants, err := v.Verify()
|
||||
if err != nil {
|
||||
w.WriteHeader(http.StatusUnauthorized)
|
||||
w.Write([]byte("invalid token: " + err.Error()))
|
||||
return
|
||||
}
|
||||
|
||||
// set grants in context
|
||||
ctx := r.Context()
|
||||
r = r.WithContext(context.WithValue(ctx, grantsKey, grants))
|
||||
}
|
||||
|
||||
next.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func GetGrants(ctx context.Context) *auth.GrantClaims {
|
||||
claims, ok := ctx.Value(grantsKey).(*auth.GrantClaims)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return claims
|
||||
}
|
||||
|
||||
func SetAuthorizationToken(r *http.Request, token string) {
|
||||
r.Header.Set(authorizationHeader, bearerPrefix+token)
|
||||
}
|
||||
|
||||
func EnsureJoinPermission(ctx context.Context) (name string, err error) {
|
||||
if !AuthRequired {
|
||||
return "", nil
|
||||
}
|
||||
claims := GetGrants(ctx)
|
||||
if claims == nil {
|
||||
err = ErrPermissionDenied
|
||||
return
|
||||
}
|
||||
|
||||
if claims.RoomJoin {
|
||||
name = claims.Room
|
||||
} else {
|
||||
err = ErrPermissionDenied
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func EnsureCreatePermission(ctx context.Context) error {
|
||||
if !AuthRequired {
|
||||
return nil
|
||||
}
|
||||
claims := GetGrants(ctx)
|
||||
if claims == nil {
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
if claims.RoomCreate {
|
||||
return nil
|
||||
}
|
||||
return ErrPermissionDenied
|
||||
}
|
||||
|
||||
// wraps authentication errors around Twirp
|
||||
func twirpAuthError(err error) error {
|
||||
return twirp.NewError(twirp.Unauthenticated, err.Error())
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package service_test
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/livekit/livekit-server/pkg/auth"
|
||||
"github.com/livekit/livekit-server/pkg/auth/authfakes"
|
||||
"github.com/livekit/livekit-server/pkg/service"
|
||||
)
|
||||
|
||||
func TestAuthMiddleware(t *testing.T) {
|
||||
api := "APIabcdefg"
|
||||
secret := "somesecretencodedinbase62"
|
||||
provider := &authfakes.FakeKeyProvider{}
|
||||
provider.GetSecretReturns(secret)
|
||||
|
||||
m := service.NewAPIKeyAuthMiddleware(provider)
|
||||
var grants *auth.GrantClaims
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
grants = service.GetGrants(r.Context())
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
// ensure that the original claim could be retrieved
|
||||
issuer := auth.NewAPIKeyTokenIssuer(api, secret)
|
||||
orig := &auth.GrantClaims{Room: "abcdefg", RoomJoin: true}
|
||||
token, err := issuer.CreateToken(orig, time.Minute)
|
||||
assert.NoError(t, err)
|
||||
|
||||
r := &http.Request{Header: http.Header{}}
|
||||
w := httptest.NewRecorder()
|
||||
service.SetAuthorizationToken(r, token)
|
||||
m.ServeHTTP(w, r, handler)
|
||||
|
||||
assert.NotNil(t, grants)
|
||||
assert.EqualValues(t, orig, grants)
|
||||
|
||||
// no authorization == no claims
|
||||
grants = nil
|
||||
w = httptest.NewRecorder()
|
||||
r = &http.Request{Header: http.Header{}}
|
||||
m.ServeHTTP(w, r, handler)
|
||||
assert.Nil(t, grants)
|
||||
assert.Equal(t, http.StatusOK, w.Code)
|
||||
|
||||
// incorrect authorization: error
|
||||
grants = nil
|
||||
w = httptest.NewRecorder()
|
||||
r = &http.Request{Header: http.Header{}}
|
||||
service.SetAuthorizationToken(r, "invalid token")
|
||||
m.ServeHTTP(w, r, handler)
|
||||
assert.Nil(t, grants)
|
||||
assert.Equal(t, http.StatusUnauthorized, w.Code)
|
||||
}
|
||||
+9
-10
@@ -15,9 +15,8 @@ import (
|
||||
)
|
||||
|
||||
type RTCService struct {
|
||||
skipTokenCheck bool
|
||||
manager *rtc.RoomManager
|
||||
upgrader websocket.Upgrader
|
||||
manager *rtc.RoomManager
|
||||
upgrader websocket.Upgrader
|
||||
}
|
||||
|
||||
func NewRTCService(conf *config.Config, manager *rtc.RoomManager) *RTCService {
|
||||
@@ -27,7 +26,6 @@ func NewRTCService(conf *config.Config, manager *rtc.RoomManager) *RTCService {
|
||||
}
|
||||
|
||||
if conf.Development {
|
||||
s.skipTokenCheck = true
|
||||
s.upgrader.CheckOrigin = func(r *http.Request) bool {
|
||||
// allow all in dev
|
||||
return true
|
||||
@@ -39,18 +37,19 @@ func NewRTCService(conf *config.Config, manager *rtc.RoomManager) *RTCService {
|
||||
|
||||
func (s *RTCService) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
roomId := r.FormValue("room_id")
|
||||
token := r.FormValue("token")
|
||||
pName := r.FormValue("name")
|
||||
log := logger.GetLogger()
|
||||
|
||||
room := s.manager.GetRoom(roomId)
|
||||
if room == nil {
|
||||
writeJSONError(w, http.StatusNotFound, "room not found")
|
||||
onlyName, err := EnsureJoinPermission(r.Context())
|
||||
if err != nil {
|
||||
writeJSONError(w, http.StatusUnauthorized, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !s.skipTokenCheck && room.Token != token {
|
||||
writeJSONError(w, http.StatusUnauthorized, "invalid room token")
|
||||
room, err := s.manager.GetRoomWithConstraint(roomId, onlyName)
|
||||
if err != nil {
|
||||
// TODO: return errors/status correctly
|
||||
writeJSONError(w, http.StatusNotFound, err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,9 @@ func NewSimpleRoomService(manager *rtc.RoomManager, localNode *node.Node) (svc *
|
||||
}
|
||||
|
||||
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
|
||||
@@ -37,9 +40,14 @@ func (s *SimpleRoomService) CreateRoom(ctx context.Context, req *livekit.CreateR
|
||||
}
|
||||
|
||||
func (s *SimpleRoomService) GetRoom(ctx context.Context, req *livekit.GetRoomRequest) (res *livekit.RoomInfo, err error) {
|
||||
room := s.manager.GetRoom(req.RoomId)
|
||||
if room == nil {
|
||||
err = twirp.NewError(twirp.NotFound, "room does not exist")
|
||||
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
|
||||
}
|
||||
|
||||
@@ -48,7 +56,10 @@ func (s *SimpleRoomService) GetRoom(ctx context.Context, req *livekit.GetRoomReq
|
||||
}
|
||||
|
||||
func (s *SimpleRoomService) DeleteRoom(ctx context.Context, req *livekit.DeleteRoomRequest) (res *livekit.DeleteRoomResponse, err error) {
|
||||
err = s.manager.DeleteRoom(req.RoomId)
|
||||
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
|
||||
|
||||
@@ -9,6 +9,7 @@ const (
|
||||
NodePrefix = "ND_"
|
||||
ParticipantPrefix = "PA_"
|
||||
TrackPrefix = "TR_"
|
||||
APIKeyPrefix = "API"
|
||||
)
|
||||
|
||||
func NewGuid(prefix string) string {
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/lytics/base62"
|
||||
)
|
||||
|
||||
func RandomSecret() string {
|
||||
// cannot error
|
||||
bin, _ := uuid.New().MarshalBinary()
|
||||
return base62.StdEncoding.EncodeToString(bin)
|
||||
}
|
||||
+70
-70
@@ -28,7 +28,7 @@ const _ = proto.ProtoPackageIsVersion4
|
||||
type ParticipantInfo_State int32
|
||||
|
||||
const (
|
||||
// websocket connected, but not offered yet
|
||||
// websocket' connected, but not offered yet
|
||||
ParticipantInfo_JOINING ParticipantInfo_State = 0
|
||||
// server received client offer
|
||||
ParticipantInfo_JOINED ParticipantInfo_State = 1
|
||||
@@ -263,10 +263,10 @@ type Room struct {
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Sid string `protobuf:"bytes,1,opt,name=sid,proto3" json:"sid,omitempty"`
|
||||
EmptyTimeout uint32 `protobuf:"varint,2,opt,name=empty_timeout,json=emptyTimeout,proto3" json:"empty_timeout,omitempty"`
|
||||
MaxParticipants uint32 `protobuf:"varint,3,opt,name=max_participants,json=maxParticipants,proto3" json:"max_participants,omitempty"`
|
||||
CreationTime int64 `protobuf:"varint,4,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
|
||||
Token string `protobuf:"bytes,5,opt,name=token,proto3" json:"token,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
EmptyTimeout uint32 `protobuf:"varint,3,opt,name=empty_timeout,json=emptyTimeout,proto3" json:"empty_timeout,omitempty"`
|
||||
MaxParticipants uint32 `protobuf:"varint,4,opt,name=max_participants,json=maxParticipants,proto3" json:"max_participants,omitempty"`
|
||||
CreationTime int64 `protobuf:"varint,5,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
|
||||
}
|
||||
|
||||
func (x *Room) Reset() {
|
||||
@@ -308,6 +308,13 @@ func (x *Room) GetSid() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Room) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Room) GetEmptyTimeout() uint32 {
|
||||
if x != nil {
|
||||
return x.EmptyTimeout
|
||||
@@ -329,22 +336,15 @@ func (x *Room) GetCreationTime() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Room) GetToken() string {
|
||||
if x != nil {
|
||||
return x.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type RoomInfo struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Sid string `protobuf:"bytes,1,opt,name=sid,proto3" json:"sid,omitempty"`
|
||||
NodeIp string `protobuf:"bytes,2,opt,name=node_ip,json=nodeIp,proto3" json:"node_ip,omitempty"`
|
||||
CreationTime int64 `protobuf:"varint,3,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
|
||||
Token string `protobuf:"bytes,4,opt,name=token,proto3" json:"token,omitempty"`
|
||||
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
|
||||
NodeIp string `protobuf:"bytes,3,opt,name=node_ip,json=nodeIp,proto3" json:"node_ip,omitempty"`
|
||||
CreationTime int64 `protobuf:"varint,4,opt,name=creation_time,json=creationTime,proto3" json:"creation_time,omitempty"`
|
||||
}
|
||||
|
||||
func (x *RoomInfo) Reset() {
|
||||
@@ -386,6 +386,13 @@ func (x *RoomInfo) GetSid() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RoomInfo) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *RoomInfo) GetNodeIp() string {
|
||||
if x != nil {
|
||||
return x.NodeIp
|
||||
@@ -400,13 +407,6 @@ func (x *RoomInfo) GetCreationTime() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *RoomInfo) GetToken() string {
|
||||
if x != nil {
|
||||
return x.Token
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type ParticipantInfo struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -637,55 +637,55 @@ var file_model_proto_rawDesc = []byte{
|
||||
0x12, 0x1b, 0x0a, 0x09, 0x6e, 0x75, 0x6d, 0x5f, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x05, 0x52, 0x08, 0x6e, 0x75, 0x6d, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x1f, 0x0a,
|
||||
0x0b, 0x6e, 0x75, 0x6d, 0x5f, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x05, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa3,
|
||||
0x28, 0x05, 0x52, 0x0a, 0x6e, 0x75, 0x6d, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x73, 0x22, 0xa1,
|
||||
0x01, 0x0a, 0x04, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6d, 0x70,
|
||||
0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x0c, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x29,
|
||||
0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e,
|
||||
0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x72,
|
||||
0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x63, 0x72, 0x65,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03,
|
||||
0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x14,
|
||||
0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x22, 0x70, 0x0a, 0x08, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73,
|
||||
0x69, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x70, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x70, 0x12, 0x23, 0x0a, 0x0d, 0x63,
|
||||
0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x03, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x05, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x22, 0xd9, 0x01, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x74, 0x69,
|
||||
0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x12, 0x34, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
||||
0x1e, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63,
|
||||
0x69, 0x70, 0x61, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
|
||||
0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73,
|
||||
0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74,
|
||||
0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63,
|
||||
0x6b, 0x73, 0x22, 0x3e, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x4a,
|
||||
0x4f, 0x49, 0x4e, 0x49, 0x4e, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4a, 0x4f, 0x49, 0x4e,
|
||||
0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02,
|
||||
0x12, 0x10, 0x0a, 0x0c, 0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44,
|
||||
0x10, 0x03, 0x22, 0x86, 0x01, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73,
|
||||
0x69, 0x64, 0x12, 0x2b, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
|
||||
0x32, 0x17, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12,
|
||||
0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x22, 0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x41,
|
||||
0x55, 0x44, 0x49, 0x4f, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x49, 0x44, 0x45, 0x4f, 0x10,
|
||||
0x01, 0x12, 0x08, 0x0a, 0x04, 0x44, 0x41, 0x54, 0x41, 0x10, 0x02, 0x22, 0x46, 0x0a, 0x0b, 0x44,
|
||||
0x61, 0x74, 0x61, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x04, 0x74, 0x65,
|
||||
0x78, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74,
|
||||
0x12, 0x18, 0x0a, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x48, 0x00, 0x52, 0x06, 0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61,
|
||||
0x6c, 0x75, 0x65, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f,
|
||||
0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69,
|
||||
0x74, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a,
|
||||
0x0d, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f,
|
||||
0x75, 0x74, 0x12, 0x29, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63,
|
||||
0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x61,
|
||||
0x78, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a,
|
||||
0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x22, 0x6e, 0x0a, 0x08, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10,
|
||||
0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64,
|
||||
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x17, 0x0a, 0x07, 0x6e, 0x6f, 0x64, 0x65, 0x5f, 0x69, 0x70, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6e, 0x6f, 0x64, 0x65, 0x49, 0x70, 0x12, 0x23, 0x0a,
|
||||
0x0d, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04,
|
||||
0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x63, 0x72, 0x65, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x69,
|
||||
0x6d, 0x65, 0x22, 0xd9, 0x01, 0x0a, 0x0f, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61,
|
||||
0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x69, 0x64, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x34, 0x0a, 0x05,
|
||||
0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e,
|
||||
0x74, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x05, 0x73, 0x74, 0x61,
|
||||
0x74, 0x65, 0x12, 0x2a, 0x0a, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x18, 0x04, 0x20, 0x03,
|
||||
0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x54, 0x72, 0x61,
|
||||
0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x73, 0x22, 0x3e,
|
||||
0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x4a, 0x4f, 0x49, 0x4e, 0x49,
|
||||
0x4e, 0x47, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4a, 0x4f, 0x49, 0x4e, 0x45, 0x44, 0x10, 0x01,
|
||||
0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x54, 0x49, 0x56, 0x45, 0x10, 0x02, 0x12, 0x10, 0x0a, 0x0c,
|
||||
0x44, 0x49, 0x53, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x03, 0x22, 0x86,
|
||||
0x01, 0x0a, 0x09, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x10, 0x0a, 0x03,
|
||||
0x73, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x69, 0x64, 0x12, 0x2b,
|
||||
0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x17, 0x2e, 0x6c,
|
||||
0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x54, 0x72, 0x61, 0x63, 0x6b, 0x49, 0x6e, 0x66, 0x6f,
|
||||
0x2e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e,
|
||||
0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x22,
|
||||
0x26, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x41, 0x55, 0x44, 0x49, 0x4f,
|
||||
0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x56, 0x49, 0x44, 0x45, 0x4f, 0x10, 0x01, 0x12, 0x08, 0x0a,
|
||||
0x04, 0x44, 0x41, 0x54, 0x41, 0x10, 0x02, 0x22, 0x46, 0x0a, 0x0b, 0x44, 0x61, 0x74, 0x61, 0x4d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x04, 0x74, 0x65, 0x78, 0x74, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x04, 0x74, 0x65, 0x78, 0x74, 0x12, 0x18, 0x0a, 0x06,
|
||||
0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x06,
|
||||
0x62, 0x69, 0x6e, 0x61, 0x72, 0x79, 0x42, 0x07, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x42,
|
||||
0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x65,
|
||||
0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b,
|
||||
0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
+47
-38
@@ -30,9 +30,10 @@ type CreateRoomRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
|
||||
// number of seconds the room should cleanup after being empty
|
||||
EmptyTimeout uint32 `protobuf:"varint,1,opt,name=empty_timeout,json=emptyTimeout,proto3" json:"empty_timeout,omitempty"`
|
||||
MaxParticipants uint32 `protobuf:"varint,2,opt,name=max_participants,json=maxParticipants,proto3" json:"max_participants,omitempty"`
|
||||
EmptyTimeout uint32 `protobuf:"varint,2,opt,name=empty_timeout,json=emptyTimeout,proto3" json:"empty_timeout,omitempty"`
|
||||
MaxParticipants uint32 `protobuf:"varint,3,opt,name=max_participants,json=maxParticipants,proto3" json:"max_participants,omitempty"`
|
||||
}
|
||||
|
||||
func (x *CreateRoomRequest) Reset() {
|
||||
@@ -67,6 +68,13 @@ func (*CreateRoomRequest) Descriptor() ([]byte, []int) {
|
||||
return file_room_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *CreateRoomRequest) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *CreateRoomRequest) GetEmptyTimeout() uint32 {
|
||||
if x != nil {
|
||||
return x.EmptyTimeout
|
||||
@@ -86,7 +94,7 @@ type GetRoomRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"`
|
||||
Room string `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"`
|
||||
}
|
||||
|
||||
func (x *GetRoomRequest) Reset() {
|
||||
@@ -121,9 +129,9 @@ func (*GetRoomRequest) Descriptor() ([]byte, []int) {
|
||||
return file_room_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *GetRoomRequest) GetRoomId() string {
|
||||
func (x *GetRoomRequest) GetRoom() string {
|
||||
if x != nil {
|
||||
return x.RoomId
|
||||
return x.Room
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -133,7 +141,7 @@ type DeleteRoomRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
RoomId string `protobuf:"bytes,1,opt,name=room_id,json=roomId,proto3" json:"room_id,omitempty"`
|
||||
Room string `protobuf:"bytes,1,opt,name=room,proto3" json:"room,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DeleteRoomRequest) Reset() {
|
||||
@@ -168,9 +176,9 @@ func (*DeleteRoomRequest) Descriptor() ([]byte, []int) {
|
||||
return file_room_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *DeleteRoomRequest) GetRoomId() string {
|
||||
func (x *DeleteRoomRequest) GetRoom() string {
|
||||
if x != nil {
|
||||
return x.RoomId
|
||||
return x.Room
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -218,36 +226,37 @@ var File_room_proto protoreflect.FileDescriptor
|
||||
var file_room_proto_rawDesc = []byte{
|
||||
0x0a, 0x0a, 0x72, 0x6f, 0x6f, 0x6d, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x07, 0x6c, 0x69,
|
||||
0x76, 0x65, 0x6b, 0x69, 0x74, 0x1a, 0x0b, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x2e, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x22, 0x63, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x23, 0x0a, 0x0d, 0x65, 0x6d, 0x70, 0x74, 0x79,
|
||||
0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0c,
|
||||
0x65, 0x6d, 0x70, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x12, 0x29, 0x0a, 0x10,
|
||||
0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x50, 0x61, 0x72, 0x74, 0x69,
|
||||
0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x29, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x52, 0x6f,
|
||||
0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f,
|
||||
0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d,
|
||||
0x49, 0x64, 0x22, 0x2c, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x17, 0x0a, 0x07, 0x72, 0x6f, 0x6f, 0x6d, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, 0x6f, 0x6f, 0x6d, 0x49, 0x64,
|
||||
0x22, 0x14, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x32, 0xc8, 0x01, 0x0a, 0x0b, 0x52, 0x6f, 0x6f, 0x6d, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65,
|
||||
0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x1a, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x43,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x11, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x49,
|
||||
0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x17,
|
||||
0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69,
|
||||
0x74, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x45, 0x0a, 0x0a, 0x44, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x1a, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b,
|
||||
0x69, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x44,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x42, 0x31, 0x5a, 0x2f, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2d,
|
||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x6b, 0x69, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x74, 0x6f, 0x22, 0x77, 0x0a, 0x11, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x65,
|
||||
0x6d, 0x70, 0x74, 0x79, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01,
|
||||
0x28, 0x0d, 0x52, 0x0c, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x54, 0x69, 0x6d, 0x65, 0x6f, 0x75, 0x74,
|
||||
0x12, 0x29, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x70, 0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70,
|
||||
0x61, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0f, 0x6d, 0x61, 0x78, 0x50,
|
||||
0x61, 0x72, 0x74, 0x69, 0x63, 0x69, 0x70, 0x61, 0x6e, 0x74, 0x73, 0x22, 0x24, 0x0a, 0x0e, 0x47,
|
||||
0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a,
|
||||
0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6f,
|
||||
0x6d, 0x22, 0x27, 0x0a, 0x11, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x18, 0x01,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6f, 0x6d, 0x22, 0x14, 0x0a, 0x12, 0x44, 0x65,
|
||||
0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x32, 0xc8, 0x01, 0x0a, 0x0b, 0x52, 0x6f, 0x6f, 0x6d, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x12, 0x3b, 0x0a, 0x0a, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x1a,
|
||||
0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x52,
|
||||
0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x6c, 0x69, 0x76,
|
||||
0x65, 0x6b, 0x69, 0x74, 0x2e, 0x52, 0x6f, 0x6f, 0x6d, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x35, 0x0a,
|
||||
0x07, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x12, 0x17, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b,
|
||||
0x69, 0x74, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x11, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x52, 0x6f, 0x6f, 0x6d,
|
||||
0x49, 0x6e, 0x66, 0x6f, 0x12, 0x45, 0x0a, 0x0a, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x6f,
|
||||
0x6f, 0x6d, 0x12, 0x1a, 0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x44, 0x65, 0x6c,
|
||||
0x65, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b,
|
||||
0x2e, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52,
|
||||
0x6f, 0x6f, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x31, 0x5a, 0x2f, 0x67,
|
||||
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69,
|
||||
0x74, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
|
||||
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x6c, 0x69, 0x76, 0x65, 0x6b, 0x69, 0x74, 0x62, 0x06,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
+19
-19
@@ -1595,23 +1595,23 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error)
|
||||
}
|
||||
|
||||
var twirpFileDescriptor0 = []byte{
|
||||
// 283 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x74, 0x91, 0x4f, 0x4f, 0x83, 0x40,
|
||||
0x10, 0xc5, 0x53, 0x0f, 0x25, 0x4e, 0xad, 0xca, 0xc6, 0xa4, 0x0d, 0x5e, 0x0c, 0x5e, 0x6c, 0xa2,
|
||||
0x10, 0x35, 0x9e, 0xbc, 0xf9, 0x27, 0xa6, 0x37, 0x83, 0x9e, 0xbc, 0x10, 0x0a, 0xa3, 0x6e, 0x64,
|
||||
0x19, 0x5c, 0x06, 0x52, 0xbf, 0xa1, 0x1f, 0xcb, 0xb0, 0xd0, 0x96, 0xa6, 0xf5, 0x44, 0xe6, 0xf7,
|
||||
0x1e, 0x3b, 0xef, 0xed, 0x02, 0x68, 0x22, 0xe5, 0xe5, 0x9a, 0x98, 0x84, 0x95, 0xca, 0x0a, 0xbf,
|
||||
0x24, 0x3b, 0x03, 0x45, 0x09, 0xa6, 0x0d, 0x75, 0x63, 0xb0, 0xef, 0x35, 0x46, 0x8c, 0x01, 0x91,
|
||||
0x0a, 0xf0, 0xbb, 0xc4, 0x82, 0xc5, 0x29, 0x0c, 0x51, 0xe5, 0xfc, 0x13, 0xb2, 0x54, 0x48, 0x25,
|
||||
0x8f, 0x7b, 0x27, 0xbd, 0xb3, 0x61, 0xb0, 0x67, 0xe0, 0x6b, 0xc3, 0xc4, 0x04, 0x0e, 0x55, 0x34,
|
||||
0x0f, 0xf3, 0x48, 0xb3, 0x8c, 0x65, 0x1e, 0x65, 0x5c, 0x8c, 0x77, 0x8c, 0xef, 0x40, 0x45, 0xf3,
|
||||
0xe7, 0x0e, 0x76, 0x27, 0xb0, 0xff, 0x84, 0xdc, 0xdd, 0x30, 0x02, 0xab, 0x8e, 0x16, 0xca, 0xc4,
|
||||
0x9c, 0xbd, 0x1b, 0xf4, 0xeb, 0x71, 0x9a, 0xb8, 0xe7, 0x60, 0x3f, 0x60, 0x8a, 0xeb, 0x79, 0xfe,
|
||||
0x75, 0x1f, 0x81, 0xe8, 0xba, 0x8b, 0x9c, 0xb2, 0x02, 0xaf, 0x7e, 0x7b, 0x30, 0xa8, 0xc1, 0x0b,
|
||||
0xea, 0x4a, 0xc6, 0x28, 0x6e, 0x01, 0x56, 0x1d, 0x85, 0xe3, 0xb5, 0x17, 0xe1, 0x6d, 0x14, 0x77,
|
||||
0xec, 0xa5, 0x56, 0xd3, 0x69, 0xf6, 0x4e, 0xe2, 0x06, 0xac, 0x36, 0xbb, 0x18, 0x2d, 0xd5, 0xf5,
|
||||
0x36, 0xdb, 0x7e, 0x7b, 0x04, 0x58, 0x25, 0xeb, 0xec, 0xdc, 0x28, 0xe7, 0x1c, 0x6f, 0xd5, 0x9a,
|
||||
0x2a, 0x77, 0x97, 0x6f, 0xfe, 0x87, 0xe4, 0xcf, 0x72, 0xe6, 0xc5, 0xa4, 0xfc, 0xd6, 0xb8, 0xf8,
|
||||
0x5e, 0x14, 0xa8, 0x2b, 0xd4, 0xbe, 0x79, 0xc9, 0x05, 0x9c, 0xf5, 0xcd, 0x78, 0xfd, 0x17, 0x00,
|
||||
0x00, 0xff, 0xff, 0xb4, 0xf1, 0xcd, 0x1a, 0xfc, 0x01, 0x00, 0x00,
|
||||
// 288 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x6c, 0x91, 0x4f, 0x4b, 0xc3, 0x40,
|
||||
0x10, 0xc5, 0x89, 0x8a, 0xc5, 0xa9, 0x55, 0xbb, 0x08, 0x86, 0x78, 0x29, 0x51, 0xb0, 0x1e, 0x4c,
|
||||
0x50, 0xf1, 0xe4, 0xcd, 0x3f, 0x88, 0x37, 0x89, 0x9e, 0xbc, 0x94, 0x6d, 0x1c, 0x75, 0x31, 0x9b,
|
||||
0x89, 0x9b, 0x49, 0xac, 0xdf, 0xd0, 0x8f, 0x25, 0xf9, 0xd7, 0x46, 0xd3, 0xd3, 0xce, 0xfe, 0xe6,
|
||||
0x2d, 0xf3, 0xde, 0x2c, 0x80, 0x21, 0xd2, 0x5e, 0x62, 0x88, 0x49, 0xf4, 0x22, 0x95, 0xe3, 0x87,
|
||||
0x62, 0xa7, 0xaf, 0xe9, 0x05, 0xa3, 0x8a, 0xba, 0x5f, 0x30, 0xbc, 0x36, 0x28, 0x19, 0x03, 0x22,
|
||||
0x1d, 0xe0, 0x67, 0x86, 0x29, 0x0b, 0x01, 0x6b, 0xb1, 0xd4, 0x68, 0x5b, 0x23, 0x6b, 0xbc, 0x11,
|
||||
0x94, 0xb5, 0x38, 0x80, 0x01, 0xea, 0x84, 0xbf, 0x27, 0xac, 0x34, 0x52, 0xc6, 0xf6, 0xca, 0xc8,
|
||||
0x1a, 0x0f, 0x82, 0xcd, 0x12, 0x3e, 0x55, 0x4c, 0x1c, 0xc3, 0x8e, 0x96, 0xb3, 0x49, 0x22, 0x0d,
|
||||
0xab, 0x50, 0x25, 0x32, 0xe6, 0xd4, 0x5e, 0x2d, 0x75, 0xdb, 0x5a, 0xce, 0x1e, 0x5a, 0xd8, 0x3d,
|
||||
0x84, 0xad, 0x3b, 0xe4, 0x7f, 0x53, 0x0b, 0xbb, 0xcd, 0xd4, 0xa2, 0x76, 0x8f, 0x60, 0x78, 0x83,
|
||||
0x11, 0x76, 0xec, 0x75, 0x84, 0xbb, 0x20, 0xda, 0xc2, 0x34, 0xa1, 0x38, 0xc5, 0xb3, 0x1f, 0x0b,
|
||||
0xfa, 0x05, 0x78, 0x44, 0x93, 0xab, 0x10, 0xc5, 0x25, 0xc0, 0x22, 0xad, 0x70, 0xbc, 0x7a, 0x25,
|
||||
0x5e, 0x67, 0x05, 0xce, 0x70, 0xde, 0x2b, 0xe8, 0x7d, 0xfc, 0x4a, 0xe2, 0x02, 0x7a, 0xb5, 0x63,
|
||||
0xb1, 0x37, 0xef, 0xfe, 0xcd, 0xb0, 0xec, 0xd9, 0x2d, 0xc0, 0xc2, 0x59, 0x6b, 0x66, 0x27, 0x97,
|
||||
0xb3, 0xbf, 0xb4, 0x57, 0x45, 0xb9, 0x3a, 0x7d, 0xf6, 0xdf, 0x14, 0xbf, 0x67, 0x53, 0x2f, 0x24,
|
||||
0xed, 0xd7, 0xc2, 0xe6, 0x3c, 0x49, 0xd1, 0xe4, 0x68, 0xfc, 0xf2, 0x4f, 0x1b, 0x38, 0x5d, 0x2f,
|
||||
0xaf, 0xe7, 0xbf, 0x01, 0x00, 0x00, 0xff, 0xff, 0x9f, 0xf2, 0xc7, 0x37, 0x06, 0x02, 0x00, 0x00,
|
||||
}
|
||||
|
||||
+8
-8
@@ -18,22 +18,22 @@ message NodeStats {
|
||||
// internal type, for serialization with proto
|
||||
message Room {
|
||||
string sid = 1;
|
||||
uint32 empty_timeout = 2;
|
||||
uint32 max_participants = 3;
|
||||
int64 creation_time = 4;
|
||||
string token = 5;
|
||||
string name = 2;
|
||||
uint32 empty_timeout = 3;
|
||||
uint32 max_participants = 4;
|
||||
int64 creation_time = 5;
|
||||
}
|
||||
|
||||
message RoomInfo {
|
||||
string sid = 1;
|
||||
string node_ip = 2;
|
||||
int64 creation_time = 3;
|
||||
string token = 4;
|
||||
string name = 2;
|
||||
string node_ip = 3;
|
||||
int64 creation_time = 4;
|
||||
}
|
||||
|
||||
message ParticipantInfo {
|
||||
enum State {
|
||||
// websocket connected, but not offered yet
|
||||
// websocket' connected, but not offered yet
|
||||
JOINING = 0;
|
||||
// server received client offer
|
||||
JOINED = 1;
|
||||
|
||||
+5
-4
@@ -16,17 +16,18 @@ service RoomService {
|
||||
}
|
||||
|
||||
message CreateRoomRequest {
|
||||
string name = 1;
|
||||
// number of seconds the room should cleanup after being empty
|
||||
uint32 empty_timeout = 1;
|
||||
uint32 max_participants = 2;
|
||||
uint32 empty_timeout = 2;
|
||||
uint32 max_participants = 3;
|
||||
}
|
||||
|
||||
message GetRoomRequest {
|
||||
string room_id = 1;
|
||||
string room = 1;
|
||||
}
|
||||
|
||||
message DeleteRoomRequest {
|
||||
string room_id = 1;
|
||||
string room = 1;
|
||||
}
|
||||
|
||||
message DeleteRoomResponse {
|
||||
|
||||
Reference in New Issue
Block a user