JWT token based auth

This commit is contained in:
David Zhao
2020-12-25 22:31:11 -08:00
parent 8f34bd6086
commit 804b7cb332
33 changed files with 1169 additions and 194 deletions
+2 -2
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+3 -2
View File
@@ -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
}
+2
View File
@@ -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
)
+8
View File
@@ -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=
+111
View File
@@ -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)
+119
View File
@@ -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)
+107
View File
@@ -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)
+7
View File
@@ -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"`
}
+27
View File
@@ -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
}
+41
View File
@@ -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()
}
+47
View File
@@ -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()
}
+44
View File
@@ -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]
}
+40
View File
@@ -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))
}
}
+54
View File
@@ -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
}
+52
View File
@@ -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
View File
@@ -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
View File
@@ -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
}
+1
View File
@@ -0,0 +1 @@
package rtc_test
+4 -10
View File
@@ -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
View File
@@ -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)
+126
View File
@@ -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())
}
+59
View File
@@ -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
View File
@@ -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
}
+15 -4
View File
@@ -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
+1
View File
@@ -9,6 +9,7 @@ const (
NodePrefix = "ND_"
ParticipantPrefix = "PA_"
TrackPrefix = "TR_"
APIKeyPrefix = "API"
)
func NewGuid(prefix string) string {
+12
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 {