mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-06-10 09:52:12 +02:00
Add MCU type "proxy" that delegates to one or multiple MCU proxies.
This commit is contained in:
parent
acbb47a100
commit
4446b07951
1
Makefile
1
Makefile
|
@ -97,6 +97,7 @@ coverhtml: dependencies vet common
|
||||||
common: easyjson \
|
common: easyjson \
|
||||||
src/signaling/api_signaling_easyjson.go \
|
src/signaling/api_signaling_easyjson.go \
|
||||||
src/signaling/api_backend_easyjson.go \
|
src/signaling/api_backend_easyjson.go \
|
||||||
|
src/signaling/api_proxy_easyjson.go \
|
||||||
src/signaling/natsclient_easyjson.go \
|
src/signaling/natsclient_easyjson.go \
|
||||||
src/signaling/room_easyjson.go
|
src/signaling/room_easyjson.go
|
||||||
|
|
||||||
|
|
|
@ -10,3 +10,4 @@ github.com/notedit/janus-go git 8e6e2c423c03884d938d84442d37d6f6f5294197 2017-06
|
||||||
github.com/oschwald/maxminddb-golang git 1960b16a5147df3a4c61ac83b2f31cd8f811d609 2019-05-23T23:57:38Z
|
github.com/oschwald/maxminddb-golang git 1960b16a5147df3a4c61ac83b2f31cd8f811d609 2019-05-23T23:57:38Z
|
||||||
golang.org/x/net git f01ecb60fe3835d80d9a0b7b2bf24b228c89260e 2017-07-11T18:12:19Z
|
golang.org/x/net git f01ecb60fe3835d80d9a0b7b2bf24b228c89260e 2017-07-11T18:12:19Z
|
||||||
golang.org/x/sys git ac767d655b305d4e9612f5f6e33120b9176c4ad4 2018-07-15T08:55:29Z
|
golang.org/x/sys git ac767d655b305d4e9612f5f6e33120b9176c4ad4 2018-07-15T08:55:29Z
|
||||||
|
gopkg.in/dgrijalva/jwt-go.v3 git 06ea1031745cb8b3dab3f6a236daf2b0aa468b7e 2018-03-08T23:13:08Z
|
||||||
|
|
|
|
@ -98,21 +98,31 @@ connectionsperhost = 8
|
||||||
#url = nats://localhost:4222
|
#url = nats://localhost:4222
|
||||||
|
|
||||||
[mcu]
|
[mcu]
|
||||||
# The type of the MCU to use. Currently only "janus" is supported.
|
# The type of the MCU to use. Currently only "janus" and "proxy" are supported.
|
||||||
type = janus
|
type = janus
|
||||||
|
|
||||||
# The URL to the websocket endpoint of the MCU server. Leave empty to disable
|
# For type "janus": the URL to the websocket endpoint of the MCU server.
|
||||||
# MCU functionality.
|
# For type "proxy": a space-separated list of proxy URLs to connect to.
|
||||||
|
# Leave empty to disable MCU functionality.
|
||||||
url =
|
url =
|
||||||
|
|
||||||
# The maximum bitrate per publishing stream (in bits per second).
|
# For type "janus": the maximum bitrate per publishing stream (in bits per
|
||||||
|
# second).
|
||||||
# Defaults to 1 mbit/sec.
|
# Defaults to 1 mbit/sec.
|
||||||
#maxstreambitrate = 1048576
|
#maxstreambitrate = 1048576
|
||||||
|
|
||||||
# The maximum bitrate per screensharing stream (in bits per second).
|
# For type "janus": the maximum bitrate per screensharing stream (in bits per
|
||||||
|
# second).
|
||||||
# Default is 2 mbit/sec.
|
# Default is 2 mbit/sec.
|
||||||
#maxscreenbitrate = 2097152
|
#maxscreenbitrate = 2097152
|
||||||
|
|
||||||
|
# For type "proxy": the id of the token to use when connecting to proxy servers.
|
||||||
|
#token_id = server1
|
||||||
|
|
||||||
|
# For type "proxy": the private key for the configured token id to use when
|
||||||
|
# connecting to proxy servers.
|
||||||
|
#token_key = privkey.pem
|
||||||
|
|
||||||
[turn]
|
[turn]
|
||||||
# API key that the MCU will need to send when requesting TURN credentials.
|
# API key that the MCU will need to send when requesting TURN credentials.
|
||||||
#apikey = the-api-key-for-the-rest-service
|
#apikey = the-api-key-for-the-rest-service
|
||||||
|
|
|
@ -166,6 +166,8 @@ func main() {
|
||||||
switch mcuType {
|
switch mcuType {
|
||||||
case signaling.McuTypeJanus:
|
case signaling.McuTypeJanus:
|
||||||
mcu, err = signaling.NewMcuJanus(mcuUrl, config, nats)
|
mcu, err = signaling.NewMcuJanus(mcuUrl, config, nats)
|
||||||
|
case signaling.McuTypeProxy:
|
||||||
|
mcu, err = signaling.NewMcuProxy(mcuUrl, config)
|
||||||
default:
|
default:
|
||||||
log.Fatal("Unsupported MCU type: ", mcuType)
|
log.Fatal("Unsupported MCU type: ", mcuType)
|
||||||
}
|
}
|
||||||
|
|
254
src/signaling/api_proxy.go
Normal file
254
src/signaling/api_proxy.go
Normal file
|
@ -0,0 +1,254 @@
|
||||||
|
/**
|
||||||
|
* Standalone signaling server for the Nextcloud Spreed app.
|
||||||
|
* Copyright (C) 2020 struktur AG
|
||||||
|
*
|
||||||
|
* @author Joachim Bauch <bauch@struktur.de>
|
||||||
|
*
|
||||||
|
* @license GNU AGPL version 3 or any later version
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Affero General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
package signaling
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"gopkg.in/dgrijalva/jwt-go.v3"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ProxyClientMessage struct {
|
||||||
|
// The unique request id (optional).
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
|
||||||
|
// The type of the request.
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
// Filled for type "hello"
|
||||||
|
Hello *HelloProxyClientMessage `json:"hello,omitempty"`
|
||||||
|
|
||||||
|
Bye *ByeProxyClientMessage `json:"bye,omitempty"`
|
||||||
|
|
||||||
|
Command *CommandProxyClientMessage `json:"command,omitempty"`
|
||||||
|
|
||||||
|
Payload *PayloadProxyClientMessage `json:"payload,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProxyClientMessage) CheckValid() error {
|
||||||
|
switch m.Type {
|
||||||
|
case "":
|
||||||
|
return fmt.Errorf("type missing")
|
||||||
|
case "hello":
|
||||||
|
if m.Hello == nil {
|
||||||
|
return fmt.Errorf("hello missing")
|
||||||
|
} else if err := m.Hello.CheckValid(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "bye":
|
||||||
|
if m.Bye != nil {
|
||||||
|
// Bye contents are optional
|
||||||
|
if err := m.Bye.CheckValid(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "command":
|
||||||
|
if m.Command == nil {
|
||||||
|
return fmt.Errorf("command missing")
|
||||||
|
} else if err := m.Command.CheckValid(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
case "payload":
|
||||||
|
if m.Payload == nil {
|
||||||
|
return fmt.Errorf("payload missing")
|
||||||
|
} else if err := m.Payload.CheckValid(); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProxyClientMessage) NewErrorServerMessage(e *Error) *ProxyServerMessage {
|
||||||
|
return &ProxyServerMessage{
|
||||||
|
Id: m.Id,
|
||||||
|
Type: "error",
|
||||||
|
Error: e,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ProxyClientMessage) NewWrappedErrorServerMessage(e error) *ProxyServerMessage {
|
||||||
|
return m.NewErrorServerMessage(NewError("internal_error", e.Error()))
|
||||||
|
}
|
||||||
|
|
||||||
|
// ProxyServerMessage is a message that is sent from the server to a client.
|
||||||
|
type ProxyServerMessage struct {
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
Error *Error `json:"error,omitempty"`
|
||||||
|
|
||||||
|
Hello *HelloProxyServerMessage `json:"hello,omitempty"`
|
||||||
|
|
||||||
|
Bye *ByeProxyServerMessage `json:"bye,omitempty"`
|
||||||
|
|
||||||
|
Command *CommandProxyServerMessage `json:"command,omitempty"`
|
||||||
|
|
||||||
|
Payload *PayloadProxyServerMessage `json:"payload,omitempty"`
|
||||||
|
|
||||||
|
Event *EventProxyServerMessage `json:"event,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ProxyServerMessage) CloseAfterSend(session Session) bool {
|
||||||
|
if r.Type == "bye" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type "hello"
|
||||||
|
|
||||||
|
type TokenClaims struct {
|
||||||
|
jwt.StandardClaims
|
||||||
|
}
|
||||||
|
|
||||||
|
type HelloProxyClientMessage struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
|
||||||
|
ResumeId string `json:"resumeid"`
|
||||||
|
|
||||||
|
Features []string `json:"features,omitempty"`
|
||||||
|
|
||||||
|
// The authentication credentials.
|
||||||
|
Token string `json:"token"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *HelloProxyClientMessage) CheckValid() error {
|
||||||
|
if m.Version != HelloVersion {
|
||||||
|
return fmt.Errorf("unsupported hello version: %s", m.Version)
|
||||||
|
}
|
||||||
|
if m.ResumeId == "" {
|
||||||
|
if m.Token == "" {
|
||||||
|
return fmt.Errorf("token missing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type HelloProxyServerMessage struct {
|
||||||
|
Version string `json:"version"`
|
||||||
|
|
||||||
|
SessionId string `json:"sessionid"`
|
||||||
|
Server *HelloServerMessageServer `json:"server,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type "bye"
|
||||||
|
|
||||||
|
type ByeProxyClientMessage struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *ByeProxyClientMessage) CheckValid() error {
|
||||||
|
// No additional validation required.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type ByeProxyServerMessage struct {
|
||||||
|
Reason string `json:"reason"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type "command"
|
||||||
|
|
||||||
|
type CommandProxyClientMessage struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
StreamType string `json:"streamType,omitempty"`
|
||||||
|
PublisherId string `json:"publisherId,omitempty"`
|
||||||
|
ClientId string `json:"clientId,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *CommandProxyClientMessage) CheckValid() error {
|
||||||
|
switch m.Type {
|
||||||
|
case "":
|
||||||
|
return fmt.Errorf("type missing")
|
||||||
|
case "create-publisher":
|
||||||
|
if m.StreamType == "" {
|
||||||
|
return fmt.Errorf("stream type missing")
|
||||||
|
}
|
||||||
|
case "create-subscriber":
|
||||||
|
if m.PublisherId == "" {
|
||||||
|
return fmt.Errorf("publisher id missing")
|
||||||
|
}
|
||||||
|
if m.StreamType == "" {
|
||||||
|
return fmt.Errorf("stream type missing")
|
||||||
|
}
|
||||||
|
case "delete-publisher":
|
||||||
|
fallthrough
|
||||||
|
case "delete-subscriber":
|
||||||
|
if m.ClientId == "" {
|
||||||
|
return fmt.Errorf("client id missing")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type CommandProxyServerMessage struct {
|
||||||
|
Id string `json:"id,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type "payload"
|
||||||
|
|
||||||
|
type PayloadProxyClientMessage struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
ClientId string `json:"clientId"`
|
||||||
|
Payload map[string]interface{} `json:"payload,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *PayloadProxyClientMessage) CheckValid() error {
|
||||||
|
switch m.Type {
|
||||||
|
case "":
|
||||||
|
return fmt.Errorf("type missing")
|
||||||
|
case "offer":
|
||||||
|
fallthrough
|
||||||
|
case "answer":
|
||||||
|
fallthrough
|
||||||
|
case "candidate":
|
||||||
|
if len(m.Payload) == 0 {
|
||||||
|
return fmt.Errorf("payload missing")
|
||||||
|
}
|
||||||
|
case "endOfCandidates":
|
||||||
|
fallthrough
|
||||||
|
case "requestoffer":
|
||||||
|
// No payload required.
|
||||||
|
}
|
||||||
|
if m.ClientId == "" {
|
||||||
|
return fmt.Errorf("client id missing")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PayloadProxyServerMessage struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
ClientId string `json:"clientId"`
|
||||||
|
Payload map[string]interface{} `json:"payload"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// Type "event"
|
||||||
|
|
||||||
|
type EventProxyServerMessage struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
|
||||||
|
ClientId string `json:"clientId,omitempty"`
|
||||||
|
Load int64 `json:"load,omitempty"`
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import (
|
||||||
|
|
||||||
const (
|
const (
|
||||||
McuTypeJanus = "janus"
|
McuTypeJanus = "janus"
|
||||||
|
McuTypeProxy = "proxy"
|
||||||
|
|
||||||
McuTypeDefault = McuTypeJanus
|
McuTypeDefault = McuTypeJanus
|
||||||
)
|
)
|
||||||
|
|
1035
src/signaling/mcu_proxy.go
Normal file
1035
src/signaling/mcu_proxy.go
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue