PLT-7809: Add support for Kopano Webmeetings WebRTC server (#7590)

* Add support for Kopano Webmeetings WebRTC server

Add an option to select which WebRTC server to use and add support to
use Kopano Webmeetings as backend instead of Janus. If the new
configuration is not set, WebRTC assumes Janus is used as backend.

* Fixup: remove redundant case. default to janus

* Fixup: use GatewayAdminUrl as direct prefix to admin URL entry point

* Fixup: consumeAndClose
Этот коммит содержится в:
Simon Eisenmann
2017-10-16 17:11:03 +02:00
коммит произвёл George Goldberg
родитель 34285d8cca
Коммит 868bd76f40
4 изменённых файлов: 59 добавлений и 9 удалений

Просмотреть файл

@@ -23,8 +23,9 @@ func GetWebrtcInfoForSession(sessionId string) (*model.WebrtcInfoResponse, *mode
}
result := &model.WebrtcInfoResponse{
Token: token,
GatewayUrl: *utils.Cfg.WebrtcSettings.GatewayWebsocketUrl,
Token: token,
GatewayUrl: *utils.Cfg.WebrtcSettings.GatewayWebsocketUrl,
GatewayType: *utils.Cfg.WebrtcSettings.GatewayType,
}
if len(*utils.Cfg.WebrtcSettings.StunURI) > 0 {
@@ -48,6 +49,16 @@ func GetWebrtcToken(sessionId string) (string, *model.AppError) {
return "", model.NewAppError("WebRTC.getWebrtcToken", "api.webrtc.disabled.app_error", nil, "", http.StatusNotImplemented)
}
switch strings.ToLower(*utils.Cfg.WebrtcSettings.GatewayType) {
case "kopano-webmeetings":
return GetKopanoWebmeetingsWebrtcToken(sessionId)
default:
// Default to Janus.
return GetJanusWebrtcToken(sessionId)
}
}
func GetJanusWebrtcToken(sessionId string) (string, *model.AppError) {
token := base64.StdEncoding.EncodeToString([]byte(sessionId))
data := make(map[string]string)
@@ -65,7 +76,7 @@ func GetWebrtcToken(sessionId string) (string, *model.AppError) {
defer consumeAndClose(rp)
return "", model.AppErrorFromJson(rp.Body)
} else {
janusResponse := model.GatewayResponseFromJson(rp.Body)
janusResponse := model.JanusGatewayResponseFromJson(rp.Body)
if janusResponse.Status != "success" {
return "", model.NewAppError("getWebrtcToken", "api.webrtc.register_token.app_error", nil, "", http.StatusInternalServerError)
}
@@ -74,6 +85,29 @@ func GetWebrtcToken(sessionId string) (string, *model.AppError) {
return token, nil
}
func GetKopanoWebmeetingsWebrtcToken(sessionId string) (string, *model.AppError) {
data := make(map[string]string)
data["type"] = "Token"
data["id"] = sessionId
rq, _ := http.NewRequest("POST", *utils.Cfg.WebrtcSettings.GatewayAdminUrl+"/auth/tokens", strings.NewReader(model.MapToJson(data)))
rq.Header.Set("Content-Type", "application/json")
rq.Header.Set("Authorization", "Bearer "+*utils.Cfg.WebrtcSettings.GatewayAdminSecret)
if rp, err := utils.HttpClient(true).Do(rq); err != nil {
return "", model.NewAppError("WebRTC.Token", "model.client.connecting.app_error", nil, err.Error(), http.StatusInternalServerError)
} else if rp.StatusCode >= 300 {
defer consumeAndClose(rp)
return "", model.AppErrorFromJson(rp.Body)
} else {
kwmResponse := model.KopanoWebmeetingsResponseFromJson(rp.Body)
if kwmResponse.Value == "" {
return "", model.NewAppError("getWebrtcToken", "api.webrtc.register_token.app_error", nil, "", http.StatusInternalServerError)
}
return kwmResponse.Value, nil
}
}
func GenerateTurnPassword(username string, secret string) string {
key := []byte(secret)
h := hmac.New(sha1.New, key)

Просмотреть файл

@@ -465,6 +465,7 @@ type NativeAppSettings struct {
type WebrtcSettings struct {
Enable *bool
GatewayType *string
GatewayWebsocketUrl *string
GatewayAdminUrl *string
GatewayAdminSecret *string

Просмотреть файл

@@ -11,19 +11,24 @@ import (
type WebrtcInfoResponse struct {
Token string `json:"token"`
GatewayUrl string `json:"gateway_url"`
GatewayType string `json:"gateway_type"`
StunUri string `json:"stun_uri,omitempty"`
TurnUri string `json:"turn_uri,omitempty"`
TurnPassword string `json:"turn_password,omitempty"`
TurnUsername string `json:"turn_username,omitempty"`
}
type GatewayResponse struct {
type JanusGatewayResponse struct {
Status string `json:"janus"`
}
func GatewayResponseFromJson(data io.Reader) *GatewayResponse {
type KopanoWebmeetingsResponse struct {
Value string `json:"value"`
}
func JanusGatewayResponseFromJson(data io.Reader) *JanusGatewayResponse {
decoder := json.NewDecoder(data)
var o GatewayResponse
var o JanusGatewayResponse
err := decoder.Decode(&o)
if err == nil {
return &o
@@ -51,3 +56,13 @@ func WebrtcInfoResponseFromJson(data io.Reader) *WebrtcInfoResponse {
return nil
}
}
func KopanoWebmeetingsResponseFromJson(data io.Reader) *KopanoWebmeetingsResponse {
decoder := json.NewDecoder(data)
var o KopanoWebmeetingsResponse
err := decoder.Decode(&o)
if err == nil {
return &o
}
return nil
}

Просмотреть файл

@@ -27,20 +27,20 @@ func TestWebrtcInfoResponseToFromJson(t *testing.T) {
}
}
func TestGatewayResponseFromJson(t *testing.T) {
func TestJanusGatewayResponseFromJson(t *testing.T) {
if testing.Short() {
t.SkipNow()
}
// Valid Gateway Response
s1 := `{"janus": "something"}`
g1 := GatewayResponseFromJson(strings.NewReader(s1))
g1 := JanusGatewayResponseFromJson(strings.NewReader(s1))
CheckString(t, g1.Status, "something")
// Malformed JSON
s2 := `{"wat"`
g2 := GatewayResponseFromJson(strings.NewReader(s2))
g2 := JanusGatewayResponseFromJson(strings.NewReader(s2))
if g2 != nil {
t.Fatal("expected nil")