mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-05-21 15:06:38 +02:00
Merge pull request #100 from strukturag/lint-fixes
Fix various issues found by golangci-lint.
This commit is contained in:
commit
4298c082eb
|
@ -49,8 +49,8 @@ func newRandomString(length int) string {
|
||||||
|
|
||||||
func CalculateBackendChecksum(random string, body []byte, secret []byte) string {
|
func CalculateBackendChecksum(random string, body []byte, secret []byte) string {
|
||||||
mac := hmac.New(sha256.New, secret)
|
mac := hmac.New(sha256.New, secret)
|
||||||
mac.Write([]byte(random))
|
mac.Write([]byte(random)) // nolint
|
||||||
mac.Write(body)
|
mac.Write(body) // nolint
|
||||||
return hex.EncodeToString(mac.Sum(nil))
|
return hex.EncodeToString(mac.Sum(nil))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -109,11 +109,12 @@ type ProxyServerMessage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ProxyServerMessage) CloseAfterSend(session Session) bool {
|
func (r *ProxyServerMessage) CloseAfterSend(session Session) bool {
|
||||||
if r.Type == "bye" {
|
switch r.Type {
|
||||||
|
case "bye":
|
||||||
return true
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Type "hello"
|
// Type "hello"
|
||||||
|
|
|
@ -39,7 +39,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrUseLastResponse = fmt.Errorf("Use last response")
|
ErrUseLastResponse = fmt.Errorf("use last response")
|
||||||
)
|
)
|
||||||
|
|
||||||
type BackendClient struct {
|
type BackendClient struct {
|
||||||
|
@ -236,7 +236,7 @@ func performRequestWithRedirects(ctx context.Context, client *http.Client, req *
|
||||||
// fails, the Transport won't reuse it anyway.
|
// fails, the Transport won't reuse it anyway.
|
||||||
const maxBodySlurpSize = 2 << 10
|
const maxBodySlurpSize = 2 << 10
|
||||||
if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
|
if resp.ContentLength == -1 || resp.ContentLength <= maxBodySlurpSize {
|
||||||
io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize)
|
io.CopyN(ioutil.Discard, resp.Body, maxBodySlurpSize) // nolint
|
||||||
}
|
}
|
||||||
resp.Body.Close()
|
resp.Body.Close()
|
||||||
}
|
}
|
||||||
|
@ -289,12 +289,12 @@ func performRequestWithRedirects(ctx context.Context, client *http.Client, req *
|
||||||
// the result into "response".
|
// the result into "response".
|
||||||
func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, request interface{}, response interface{}) error {
|
func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, request interface{}, response interface{}) error {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
return fmt.Errorf("No url passed to perform JSON request %+v", request)
|
return fmt.Errorf("no url passed to perform JSON request %+v", request)
|
||||||
}
|
}
|
||||||
|
|
||||||
secret := b.backends.GetSecret(u)
|
secret := b.backends.GetSecret(u)
|
||||||
if secret == nil {
|
if secret == nil {
|
||||||
return fmt.Errorf("No backend secret configured for for %s", u)
|
return fmt.Errorf("no backend secret configured for for %s", u)
|
||||||
}
|
}
|
||||||
|
|
||||||
pool, err := b.getPool(u)
|
pool, err := b.getPool(u)
|
||||||
|
@ -367,7 +367,7 @@ func (b *BackendClient) PerformJSONRequest(ctx context.Context, u *url.URL, requ
|
||||||
return err
|
return err
|
||||||
} else if ocs.Ocs == nil || ocs.Ocs.Data == nil {
|
} else if ocs.Ocs == nil || ocs.Ocs.Data == nil {
|
||||||
log.Printf("Incomplete OCS response %s from %s", string(body), u)
|
log.Printf("Incomplete OCS response %s from %s", string(body), u)
|
||||||
return fmt.Errorf("Incomplete OCS response")
|
return fmt.Errorf("incomplete OCS response")
|
||||||
} else if err := json.Unmarshal(*ocs.Ocs.Data, response); err != nil {
|
} else if err := json.Unmarshal(*ocs.Ocs.Data, response); err != nil {
|
||||||
log.Printf("Could not decode OCS response body %s from %s: %s", string(*ocs.Ocs.Data), u, err)
|
log.Printf("Could not decode OCS response body %s from %s: %s", string(*ocs.Ocs.Data), u, err)
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -71,7 +71,9 @@ func TestPostOnRedirect(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(data)
|
if _, err := w.Write(data); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
server := httptest.NewServer(r)
|
server := httptest.NewServer(r)
|
||||||
|
|
|
@ -99,16 +99,16 @@ func TestIsUrlAllowed_Compat(t *testing.T) {
|
||||||
|
|
||||||
func TestIsUrlAllowed(t *testing.T) {
|
func TestIsUrlAllowed(t *testing.T) {
|
||||||
valid_urls := [][]string{
|
valid_urls := [][]string{
|
||||||
[]string{"https://domain.invalid/foo", string(testBackendSecret) + "-foo"},
|
{"https://domain.invalid/foo", string(testBackendSecret) + "-foo"},
|
||||||
[]string{"https://domain.invalid/foo/", string(testBackendSecret) + "-foo"},
|
{"https://domain.invalid/foo/", string(testBackendSecret) + "-foo"},
|
||||||
[]string{"https://domain.invalid:443/foo/", string(testBackendSecret) + "-foo"},
|
{"https://domain.invalid:443/foo/", string(testBackendSecret) + "-foo"},
|
||||||
[]string{"https://domain.invalid/foo/folder", string(testBackendSecret) + "-foo"},
|
{"https://domain.invalid/foo/folder", string(testBackendSecret) + "-foo"},
|
||||||
[]string{"https://domain.invalid/bar", string(testBackendSecret) + "-bar"},
|
{"https://domain.invalid/bar", string(testBackendSecret) + "-bar"},
|
||||||
[]string{"https://domain.invalid/bar/", string(testBackendSecret) + "-bar"},
|
{"https://domain.invalid/bar/", string(testBackendSecret) + "-bar"},
|
||||||
[]string{"https://domain.invalid:443/bar/", string(testBackendSecret) + "-bar"},
|
{"https://domain.invalid:443/bar/", string(testBackendSecret) + "-bar"},
|
||||||
[]string{"https://domain.invalid/bar/folder/", string(testBackendSecret) + "-bar"},
|
{"https://domain.invalid/bar/folder/", string(testBackendSecret) + "-bar"},
|
||||||
[]string{"https://otherdomain.invalid/", string(testBackendSecret) + "-lala"},
|
{"https://otherdomain.invalid/", string(testBackendSecret) + "-lala"},
|
||||||
[]string{"https://otherdomain.invalid/folder/", string(testBackendSecret) + "-lala"},
|
{"https://otherdomain.invalid/folder/", string(testBackendSecret) + "-lala"},
|
||||||
}
|
}
|
||||||
invalid_urls := []string{
|
invalid_urls := []string{
|
||||||
"https://domain.invalid",
|
"https://domain.invalid",
|
||||||
|
@ -176,13 +176,13 @@ type ParseBackendIdsTestcase struct {
|
||||||
|
|
||||||
func TestParseBackendIds(t *testing.T) {
|
func TestParseBackendIds(t *testing.T) {
|
||||||
testcases := []ParseBackendIdsTestcase{
|
testcases := []ParseBackendIdsTestcase{
|
||||||
ParseBackendIdsTestcase{"", nil},
|
{"", nil},
|
||||||
ParseBackendIdsTestcase{"backend1", []string{"backend1"}},
|
{"backend1", []string{"backend1"}},
|
||||||
ParseBackendIdsTestcase{" backend1 ", []string{"backend1"}},
|
{" backend1 ", []string{"backend1"}},
|
||||||
ParseBackendIdsTestcase{"backend1,", []string{"backend1"}},
|
{"backend1,", []string{"backend1"}},
|
||||||
ParseBackendIdsTestcase{"backend1,backend1", []string{"backend1"}},
|
{"backend1,backend1", []string{"backend1"}},
|
||||||
ParseBackendIdsTestcase{"backend1, backend2", []string{"backend1", "backend2"}},
|
{"backend1, backend2", []string{"backend1", "backend2"}},
|
||||||
ParseBackendIdsTestcase{"backend1,backend2, backend1", []string{"backend1", "backend2"}},
|
{"backend1,backend2, backend1", []string{"backend1", "backend2"}},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range testcases {
|
for _, test := range testcases {
|
||||||
|
|
|
@ -85,10 +85,10 @@ func NewBackendServer(config *goconf.ConfigFile, hub *Hub, version string) (*Bac
|
||||||
|
|
||||||
if len(turnserverslist) != 0 {
|
if len(turnserverslist) != 0 {
|
||||||
if turnapikey == "" {
|
if turnapikey == "" {
|
||||||
return nil, fmt.Errorf("Need a TURN API key if TURN servers are configured.")
|
return nil, fmt.Errorf("need a TURN API key if TURN servers are configured")
|
||||||
}
|
}
|
||||||
if turnsecret == "" {
|
if turnsecret == "" {
|
||||||
return nil, fmt.Errorf("Need a shared TURN secret if TURN servers are configured.")
|
return nil, fmt.Errorf("need a shared TURN secret if TURN servers are configured")
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Printf("Using configured TURN API key")
|
log.Printf("Using configured TURN API key")
|
||||||
|
@ -169,14 +169,14 @@ func (b *BackendServer) setComonHeaders(f func(http.ResponseWriter, *http.Reques
|
||||||
func (b *BackendServer) welcomeFunc(w http.ResponseWriter, r *http.Request) {
|
func (b *BackendServer) welcomeFunc(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
io.WriteString(w, b.welcomeMessage)
|
io.WriteString(w, b.welcomeMessage) // nolint
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateTurnSecret(username string, secret []byte, valid time.Duration) (string, string) {
|
func calculateTurnSecret(username string, secret []byte, valid time.Duration) (string, string) {
|
||||||
expires := time.Now().Add(valid)
|
expires := time.Now().Add(valid)
|
||||||
username = fmt.Sprintf("%d:%s", expires.Unix(), username)
|
username = fmt.Sprintf("%d:%s", expires.Unix(), username)
|
||||||
m := hmac.New(sha1.New, secret)
|
m := hmac.New(sha1.New, secret)
|
||||||
m.Write([]byte(username))
|
m.Write([]byte(username)) // nolint
|
||||||
password := base64.StdEncoding.EncodeToString(m.Sum(nil))
|
password := base64.StdEncoding.EncodeToString(m.Sum(nil))
|
||||||
return username, password
|
return username, password
|
||||||
}
|
}
|
||||||
|
@ -192,19 +192,19 @@ func (b *BackendServer) getTurnCredentials(w http.ResponseWriter, r *http.Reques
|
||||||
}
|
}
|
||||||
if service != "turn" || key == "" {
|
if service != "turn" || key == "" {
|
||||||
w.WriteHeader(http.StatusBadRequest)
|
w.WriteHeader(http.StatusBadRequest)
|
||||||
io.WriteString(w, "Invalid service and/or key sent.\n")
|
io.WriteString(w, "Invalid service and/or key sent.\n") // nolint
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if key != b.turnapikey {
|
if key != b.turnapikey {
|
||||||
w.WriteHeader(http.StatusForbidden)
|
w.WriteHeader(http.StatusForbidden)
|
||||||
io.WriteString(w, "Not allowed to access this service.\n")
|
io.WriteString(w, "Not allowed to access this service.\n") // nolint
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(b.turnservers) == 0 {
|
if len(b.turnservers) == 0 {
|
||||||
w.WriteHeader(http.StatusNotFound)
|
w.WriteHeader(http.StatusNotFound)
|
||||||
io.WriteString(w, "No TURN servers available.\n")
|
io.WriteString(w, "No TURN servers available.\n") // nolint
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ func (b *BackendServer) getTurnCredentials(w http.ResponseWriter, r *http.Reques
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Could not serialize TURN credentials %+v: %s", result, err)
|
log.Printf("Could not serialize TURN credentials %+v: %s", result, err)
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
io.WriteString(w, "Could not serialize credentials.")
|
io.WriteString(w, "Could not serialize credentials.") // nolint
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -235,7 +235,7 @@ func (b *BackendServer) getTurnCredentials(w http.ResponseWriter, r *http.Reques
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(data)
|
w.Write(data) // nolint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BackendServer) parseRequestBody(f func(http.ResponseWriter, *http.Request, []byte)) func(http.ResponseWriter, *http.Request) {
|
func (b *BackendServer) parseRequestBody(f func(http.ResponseWriter, *http.Request, []byte)) func(http.ResponseWriter, *http.Request) {
|
||||||
|
@ -285,7 +285,9 @@ func (b *BackendServer) sendRoomInvite(roomid string, backend *Backend, userids
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, userid := range userids {
|
for _, userid := range userids {
|
||||||
b.nats.PublishMessage(GetSubjectForUserId(userid, backend), msg)
|
if err := b.nats.PublishMessage(GetSubjectForUserId(userid, backend), msg); err != nil {
|
||||||
|
log.Printf("Could not publish room invite for user %s in backend %s: %s", userid, backend.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +306,9 @@ func (b *BackendServer) sendRoomDisinvite(roomid string, backend *Backend, reaso
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, userid := range userids {
|
for _, userid := range userids {
|
||||||
b.nats.PublishMessage(GetSubjectForUserId(userid, backend), msg)
|
if err := b.nats.PublishMessage(GetSubjectForUserId(userid, backend), msg); err != nil {
|
||||||
|
log.Printf("Could not publish room disinvite for user %s in backend %s: %s", userid, backend.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
timeout := time.Second
|
timeout := time.Second
|
||||||
|
@ -321,7 +325,9 @@ func (b *BackendServer) sendRoomDisinvite(roomid string, backend *Backend, reaso
|
||||||
if sid, err := b.lookupByRoomSessionId(sessionid, nil, timeout); err != nil {
|
if sid, err := b.lookupByRoomSessionId(sessionid, nil, timeout); err != nil {
|
||||||
log.Printf("Could not lookup by room session %s: %s", sessionid, err)
|
log.Printf("Could not lookup by room session %s: %s", sessionid, err)
|
||||||
} else if sid != "" {
|
} else if sid != "" {
|
||||||
b.nats.PublishMessage("session."+sid, msg)
|
if err := b.nats.PublishMessage("session."+sid, msg); err != nil {
|
||||||
|
log.Printf("Could not publish room disinvite for session %s: %s", sid, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}(sessionid)
|
}(sessionid)
|
||||||
}
|
}
|
||||||
|
@ -350,7 +356,9 @@ func (b *BackendServer) sendRoomUpdate(roomid string, backend *Backend, notified
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
b.nats.PublishMessage(GetSubjectForUserId(userid, backend), msg)
|
if err := b.nats.PublishMessage(GetSubjectForUserId(userid, backend), msg); err != nil {
|
||||||
|
log.Printf("Could not publish room update for user %s in backend %s: %s", userid, backend.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -590,7 +598,7 @@ func (b *BackendServer) roomHandler(w http.ResponseWriter, r *http.Request, body
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
// TODO(jojo): Return better response struct.
|
// TODO(jojo): Return better response struct.
|
||||||
w.Write([]byte("{}"))
|
w.Write([]byte("{}")) // nolint
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b *BackendServer) validateStatsRequest(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
func (b *BackendServer) validateStatsRequest(f func(http.ResponseWriter, *http.Request)) func(http.ResponseWriter, *http.Request) {
|
||||||
|
@ -622,5 +630,5 @@ func (b *BackendServer) statsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(statsData)
|
w.Write(statsData) // nolint
|
||||||
}
|
}
|
||||||
|
|
|
@ -328,7 +328,11 @@ func TestBackendServer_RoomInvite(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer sub.Unsubscribe()
|
defer func() {
|
||||||
|
if err := sub.Unsubscribe(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
msg := &BackendServerRoomRequest{
|
msg := &BackendServerRoomRequest{
|
||||||
Type: "invite",
|
Type: "invite",
|
||||||
|
@ -419,7 +423,11 @@ func TestBackendServer_RoomDisinvite(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer sub.Unsubscribe()
|
defer func() {
|
||||||
|
if err := sub.Unsubscribe(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
msg := &BackendServerRoomRequest{
|
msg := &BackendServerRoomRequest{
|
||||||
Type: "disinvite",
|
Type: "disinvite",
|
||||||
|
@ -635,7 +643,11 @@ func TestBackendServer_RoomUpdate(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer sub.Unsubscribe()
|
defer func() {
|
||||||
|
if err := sub.Unsubscribe(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
msg := &BackendServerRoomRequest{
|
msg := &BackendServerRoomRequest{
|
||||||
Type: "update",
|
Type: "update",
|
||||||
|
@ -714,7 +726,11 @@ func TestBackendServer_RoomDelete(t *testing.T) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer sub.Unsubscribe()
|
defer func() {
|
||||||
|
if err := sub.Unsubscribe(); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
msg := &BackendServerRoomRequest{
|
msg := &BackendServerRoomRequest{
|
||||||
Type: "delete",
|
Type: "delete",
|
||||||
|
@ -832,21 +848,21 @@ func TestBackendServer_ParticipantsUpdatePermissions(t *testing.T) {
|
||||||
Type: "participants",
|
Type: "participants",
|
||||||
Participants: &BackendRoomParticipantsRequest{
|
Participants: &BackendRoomParticipantsRequest{
|
||||||
Changed: []map[string]interface{}{
|
Changed: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
||||||
"permissions": []Permission{PERMISSION_MAY_PUBLISH_MEDIA},
|
"permissions": []Permission{PERMISSION_MAY_PUBLISH_MEDIA},
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
||||||
"permissions": []Permission{PERMISSION_MAY_PUBLISH_SCREEN},
|
"permissions": []Permission{PERMISSION_MAY_PUBLISH_SCREEN},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Users: []map[string]interface{}{
|
Users: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
||||||
"permissions": []Permission{PERMISSION_MAY_PUBLISH_MEDIA},
|
"permissions": []Permission{PERMISSION_MAY_PUBLISH_MEDIA},
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
||||||
"permissions": []Permission{PERMISSION_MAY_PUBLISH_SCREEN},
|
"permissions": []Permission{PERMISSION_MAY_PUBLISH_SCREEN},
|
||||||
},
|
},
|
||||||
|
@ -928,13 +944,13 @@ func TestBackendServer_ParticipantsUpdateEmptyPermissions(t *testing.T) {
|
||||||
Type: "participants",
|
Type: "participants",
|
||||||
Participants: &BackendRoomParticipantsRequest{
|
Participants: &BackendRoomParticipantsRequest{
|
||||||
Changed: []map[string]interface{}{
|
Changed: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello.Hello.SessionId,
|
"sessionId": roomId + "-" + hello.Hello.SessionId,
|
||||||
"permissions": []Permission{},
|
"permissions": []Permission{},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Users: []map[string]interface{}{
|
Users: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello.Hello.SessionId,
|
"sessionId": roomId + "-" + hello.Hello.SessionId,
|
||||||
"permissions": []Permission{},
|
"permissions": []Permission{},
|
||||||
},
|
},
|
||||||
|
@ -1022,21 +1038,21 @@ func TestBackendServer_ParticipantsUpdateTimeout(t *testing.T) {
|
||||||
InCall: &BackendRoomInCallRequest{
|
InCall: &BackendRoomInCallRequest{
|
||||||
InCall: json.RawMessage("7"),
|
InCall: json.RawMessage("7"),
|
||||||
Changed: []map[string]interface{}{
|
Changed: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
||||||
"inCall": 7,
|
"inCall": 7,
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": "unknown-room-session-id",
|
"sessionId": "unknown-room-session-id",
|
||||||
"inCall": 3,
|
"inCall": 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Users: []map[string]interface{}{
|
Users: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
||||||
"inCall": 7,
|
"inCall": 7,
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": "unknown-room-session-id",
|
"sessionId": "unknown-room-session-id",
|
||||||
"inCall": 3,
|
"inCall": 3,
|
||||||
},
|
},
|
||||||
|
@ -1075,21 +1091,21 @@ func TestBackendServer_ParticipantsUpdateTimeout(t *testing.T) {
|
||||||
InCall: &BackendRoomInCallRequest{
|
InCall: &BackendRoomInCallRequest{
|
||||||
InCall: json.RawMessage("7"),
|
InCall: json.RawMessage("7"),
|
||||||
Changed: []map[string]interface{}{
|
Changed: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
||||||
"inCall": 7,
|
"inCall": 7,
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
||||||
"inCall": 3,
|
"inCall": 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Users: []map[string]interface{}{
|
Users: []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
"sessionId": roomId + "-" + hello1.Hello.SessionId,
|
||||||
"inCall": 7,
|
"inCall": 7,
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
"sessionId": roomId + "-" + hello2.Hello.SessionId,
|
||||||
"inCall": 3,
|
"inCall": 3,
|
||||||
},
|
},
|
||||||
|
@ -1277,7 +1293,7 @@ func TestBackendServer_TurnCredentials(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
m := hmac.New(sha1.New, []byte(turnSecret))
|
m := hmac.New(sha1.New, []byte(turnSecret))
|
||||||
m.Write([]byte(cred.Username))
|
m.Write([]byte(cred.Username)) // nolint
|
||||||
password := base64.StdEncoding.EncodeToString(m.Sum(nil))
|
password := base64.StdEncoding.EncodeToString(m.Sum(nil))
|
||||||
if cred.Password != password {
|
if cred.Password != password {
|
||||||
t.Errorf("Expected password %s, got %s", password, cred.Password)
|
t.Errorf("Expected password %s, got %s", password, cred.Password)
|
||||||
|
|
18
client.go
18
client.go
|
@ -238,7 +238,7 @@ func (c *Client) ReadPump() {
|
||||||
conn.SetReadLimit(maxMessageSize)
|
conn.SetReadLimit(maxMessageSize)
|
||||||
conn.SetPongHandler(func(msg string) error {
|
conn.SetPongHandler(func(msg string) error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
conn.SetReadDeadline(now.Add(pongWait))
|
conn.SetReadDeadline(now.Add(pongWait)) // nolint
|
||||||
if msg == "" {
|
if msg == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -258,7 +258,7 @@ func (c *Client) ReadPump() {
|
||||||
decodeBuffer := bufferPool.Get().(*bytes.Buffer)
|
decodeBuffer := bufferPool.Get().(*bytes.Buffer)
|
||||||
defer bufferPool.Put(decodeBuffer)
|
defer bufferPool.Put(decodeBuffer)
|
||||||
for {
|
for {
|
||||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
conn.SetReadDeadline(time.Now().Add(pongWait)) // nolint
|
||||||
messageType, reader, err := conn.NextReader()
|
messageType, reader, err := conn.NextReader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(*websocket.CloseError); !ok || websocket.IsUnexpectedCloseError(err,
|
if _, ok := err.(*websocket.CloseError); !ok || websocket.IsUnexpectedCloseError(err,
|
||||||
|
@ -301,7 +301,7 @@ func (c *Client) ReadPump() {
|
||||||
func (c *Client) writeInternal(message json.Marshaler) bool {
|
func (c *Client) writeInternal(message json.Marshaler) bool {
|
||||||
var closeData []byte
|
var closeData []byte
|
||||||
|
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
writer, err := c.conn.NextWriter(websocket.TextMessage)
|
writer, err := c.conn.NextWriter(websocket.TextMessage)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
if m, ok := (interface{}(message)).(easyjson.Marshaler); ok {
|
if m, ok := (interface{}(message)).(easyjson.Marshaler); ok {
|
||||||
|
@ -330,7 +330,7 @@ func (c *Client) writeInternal(message json.Marshaler) bool {
|
||||||
return true
|
return true
|
||||||
|
|
||||||
close:
|
close:
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
if err := c.conn.WriteMessage(websocket.CloseMessage, closeData); err != nil {
|
if err := c.conn.WriteMessage(websocket.CloseMessage, closeData); err != nil {
|
||||||
if session := c.GetSession(); session != nil {
|
if session := c.GetSession(); session != nil {
|
||||||
log.Printf("Could not send close message to client %s: %v", session.PublicId(), err)
|
log.Printf("Could not send close message to client %s: %v", session.PublicId(), err)
|
||||||
|
@ -341,7 +341,7 @@ close:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) writeError(e error) bool {
|
func (c *Client) writeError(e error) bool { // nolint
|
||||||
message := &ServerMessage{
|
message := &ServerMessage{
|
||||||
Type: "error",
|
Type: "error",
|
||||||
Error: NewError("internal_error", e.Error()),
|
Error: NewError("internal_error", e.Error()),
|
||||||
|
@ -357,7 +357,7 @@ func (c *Client) writeError(e error) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
closeData := websocket.FormatCloseMessage(websocket.CloseInternalServerErr, e.Error())
|
closeData := websocket.FormatCloseMessage(websocket.CloseInternalServerErr, e.Error())
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
if err := c.conn.WriteMessage(websocket.CloseMessage, closeData); err != nil {
|
if err := c.conn.WriteMessage(websocket.CloseMessage, closeData); err != nil {
|
||||||
if session := c.GetSession(); session != nil {
|
if session := c.GetSession(); session != nil {
|
||||||
log.Printf("Could not send close message to client %s: %v", session.PublicId(), err)
|
log.Printf("Could not send close message to client %s: %v", session.PublicId(), err)
|
||||||
|
@ -385,8 +385,8 @@ func (c *Client) writeMessageLocked(message WritableClientMessage) bool {
|
||||||
|
|
||||||
session := c.GetSession()
|
session := c.GetSession()
|
||||||
if message.CloseAfterSend(session) {
|
if message.CloseAfterSend(session) {
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
c.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
c.conn.WriteMessage(websocket.CloseMessage, []byte{}) // nolint
|
||||||
if session != nil {
|
if session != nil {
|
||||||
go session.Close()
|
go session.Close()
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ func (c *Client) sendPing() bool {
|
||||||
|
|
||||||
now := time.Now().UnixNano()
|
now := time.Now().UnixNano()
|
||||||
msg := strconv.FormatInt(now, 10)
|
msg := strconv.FormatInt(now, 10)
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
if err := c.conn.WriteMessage(websocket.PingMessage, []byte(msg)); err != nil {
|
if err := c.conn.WriteMessage(websocket.PingMessage, []byte(msg)); err != nil {
|
||||||
if session := c.GetSession(); session != nil {
|
if session := c.GetSession(); session != nil {
|
||||||
log.Printf("Could not send ping to client %s: %v", session.PublicId(), err)
|
log.Printf("Could not send ping to client %s: %v", session.PublicId(), err)
|
||||||
|
|
|
@ -47,7 +47,7 @@ import (
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/mailru/easyjson"
|
"github.com/mailru/easyjson"
|
||||||
|
|
||||||
"github.com/strukturag/nextcloud-spreed-signaling"
|
signaling "github.com/strukturag/nextcloud-spreed-signaling"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -177,8 +177,8 @@ func (c *SignalingClient) Close() {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
c.publicSessionId = ""
|
c.publicSessionId = ""
|
||||||
c.privateSessionId = ""
|
c.privateSessionId = ""
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, "")) // nolint
|
||||||
c.conn.Close()
|
c.conn.Close()
|
||||||
c.conn = nil
|
c.conn = nil
|
||||||
c.lock.Unlock()
|
c.lock.Unlock()
|
||||||
|
@ -271,15 +271,15 @@ func (c *SignalingClient) readPump() {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
conn.SetReadLimit(maxMessageSize)
|
conn.SetReadLimit(maxMessageSize)
|
||||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
conn.SetReadDeadline(time.Now().Add(pongWait)) // nolint
|
||||||
conn.SetPongHandler(func(string) error {
|
conn.SetPongHandler(func(string) error {
|
||||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
conn.SetReadDeadline(time.Now().Add(pongWait)) // nolint
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
var decodeBuffer bytes.Buffer
|
var decodeBuffer bytes.Buffer
|
||||||
for {
|
for {
|
||||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
conn.SetReadDeadline(time.Now().Add(pongWait)) // nolint
|
||||||
messageType, reader, err := conn.NextReader()
|
messageType, reader, err := conn.NextReader()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if websocket.IsUnexpectedCloseError(err,
|
if websocket.IsUnexpectedCloseError(err,
|
||||||
|
@ -319,7 +319,7 @@ func (c *SignalingClient) readPump() {
|
||||||
func (c *SignalingClient) writeInternal(message *signaling.ClientMessage) bool {
|
func (c *SignalingClient) writeInternal(message *signaling.ClientMessage) bool {
|
||||||
var closeData []byte
|
var closeData []byte
|
||||||
|
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
writer, err := c.conn.NextWriter(websocket.TextMessage)
|
writer, err := c.conn.NextWriter(websocket.TextMessage)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
_, err = easyjson.MarshalToWriter(message, writer)
|
_, err = easyjson.MarshalToWriter(message, writer)
|
||||||
|
@ -341,8 +341,8 @@ func (c *SignalingClient) writeInternal(message *signaling.ClientMessage) bool {
|
||||||
return true
|
return true
|
||||||
|
|
||||||
close:
|
close:
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
c.conn.WriteMessage(websocket.CloseMessage, closeData)
|
c.conn.WriteMessage(websocket.CloseMessage, closeData) // nolint
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +353,7 @@ func (c *SignalingClient) sendPing() bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
if err := c.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
if err := c.conn.WriteMessage(websocket.PingMessage, []byte{}); err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -476,7 +476,7 @@ func registerAuthHandler(router *mux.Router) {
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(jsonpayload)
|
w.Write(jsonpayload) // nolint
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +562,7 @@ func main() {
|
||||||
Handler: r,
|
Handler: r,
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
server.Serve(listener)
|
server.Serve(listener) // nolint
|
||||||
}()
|
}()
|
||||||
backendUrl := "http://" + listener.Addr().String()
|
backendUrl := "http://" + listener.Addr().String()
|
||||||
log.Println("Backend server running on", backendUrl)
|
log.Println("Backend server running on", backendUrl)
|
||||||
|
|
|
@ -322,11 +322,15 @@ func (s *ClientSession) closeAndWait(wait bool) {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
if s.userSubscription != nil {
|
if s.userSubscription != nil {
|
||||||
s.userSubscription.Unsubscribe()
|
if err := s.userSubscription.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error closing user subscription in session %s: %s", s.PublicId(), err)
|
||||||
|
}
|
||||||
s.userSubscription = nil
|
s.userSubscription = nil
|
||||||
}
|
}
|
||||||
if s.sessionSubscription != nil {
|
if s.sessionSubscription != nil {
|
||||||
s.sessionSubscription.Unsubscribe()
|
if err := s.sessionSubscription.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error closing session subscription in session %s: %s", s.PublicId(), err)
|
||||||
|
}
|
||||||
s.sessionSubscription = nil
|
s.sessionSubscription = nil
|
||||||
}
|
}
|
||||||
go func(virtualSessions map[*VirtualSession]bool) {
|
go func(virtualSessions map[*VirtualSession]bool) {
|
||||||
|
@ -434,7 +438,9 @@ func (s *ClientSession) UnsubscribeRoomNats() {
|
||||||
|
|
||||||
func (s *ClientSession) doUnsubscribeRoomNats(notify bool) {
|
func (s *ClientSession) doUnsubscribeRoomNats(notify bool) {
|
||||||
if s.roomSubscription != nil {
|
if s.roomSubscription != nil {
|
||||||
s.roomSubscription.Unsubscribe()
|
if err := s.roomSubscription.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error closing room subscription in session %s: %s", s.PublicId(), err)
|
||||||
|
}
|
||||||
s.roomSubscription = nil
|
s.roomSubscription = nil
|
||||||
}
|
}
|
||||||
s.hub.roomSessions.DeleteRoomSession(s)
|
s.hub.roomSessions.DeleteRoomSession(s)
|
||||||
|
|
|
@ -40,26 +40,26 @@ type EqualTestData struct {
|
||||||
|
|
||||||
func Test_permissionsEqual(t *testing.T) {
|
func Test_permissionsEqual(t *testing.T) {
|
||||||
tests := []EqualTestData{
|
tests := []EqualTestData{
|
||||||
EqualTestData{
|
{
|
||||||
a: nil,
|
a: nil,
|
||||||
b: nil,
|
b: nil,
|
||||||
equal: true,
|
equal: true,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: map[Permission]bool{
|
a: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
},
|
},
|
||||||
b: nil,
|
b: nil,
|
||||||
equal: false,
|
equal: false,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: nil,
|
a: nil,
|
||||||
b: map[Permission]bool{
|
b: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
},
|
},
|
||||||
equal: false,
|
equal: false,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: map[Permission]bool{
|
a: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
},
|
},
|
||||||
|
@ -68,7 +68,7 @@ func Test_permissionsEqual(t *testing.T) {
|
||||||
},
|
},
|
||||||
equal: true,
|
equal: true,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: map[Permission]bool{
|
a: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
PERMISSION_MAY_PUBLISH_SCREEN: true,
|
PERMISSION_MAY_PUBLISH_SCREEN: true,
|
||||||
|
@ -78,7 +78,7 @@ func Test_permissionsEqual(t *testing.T) {
|
||||||
},
|
},
|
||||||
equal: false,
|
equal: false,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: map[Permission]bool{
|
a: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
},
|
},
|
||||||
|
@ -88,7 +88,7 @@ func Test_permissionsEqual(t *testing.T) {
|
||||||
},
|
},
|
||||||
equal: false,
|
equal: false,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: map[Permission]bool{
|
a: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
PERMISSION_MAY_PUBLISH_SCREEN: true,
|
PERMISSION_MAY_PUBLISH_SCREEN: true,
|
||||||
|
@ -99,7 +99,7 @@ func Test_permissionsEqual(t *testing.T) {
|
||||||
},
|
},
|
||||||
equal: true,
|
equal: true,
|
||||||
},
|
},
|
||||||
EqualTestData{
|
{
|
||||||
a: map[Permission]bool{
|
a: map[Permission]bool{
|
||||||
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
PERMISSION_MAY_PUBLISH_MEDIA: true,
|
||||||
PERMISSION_MAY_PUBLISH_SCREEN: true,
|
PERMISSION_MAY_PUBLISH_SCREEN: true,
|
||||||
|
|
508
continentmap.go
508
continentmap.go
|
@ -5,259 +5,259 @@ package signaling
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ContinentMap map[string][]string = map[string][]string{
|
ContinentMap map[string][]string = map[string][]string{
|
||||||
"AD": []string{"EU"},
|
"AD": {"EU"},
|
||||||
"AE": []string{"AS"},
|
"AE": {"AS"},
|
||||||
"AF": []string{"AS"},
|
"AF": {"AS"},
|
||||||
"AG": []string{"NA"},
|
"AG": {"NA"},
|
||||||
"AI": []string{"NA"},
|
"AI": {"NA"},
|
||||||
"AL": []string{"EU"},
|
"AL": {"EU"},
|
||||||
"AM": []string{"EU", "AS"},
|
"AM": {"EU", "AS"},
|
||||||
"AN": []string{"NA"},
|
"AN": {"NA"},
|
||||||
"AO": []string{"AF"},
|
"AO": {"AF"},
|
||||||
"AQ": []string{"AN"},
|
"AQ": {"AN"},
|
||||||
"AR": []string{"SA"},
|
"AR": {"SA"},
|
||||||
"AS": []string{"OC"},
|
"AS": {"OC"},
|
||||||
"AT": []string{"EU"},
|
"AT": {"EU"},
|
||||||
"AU": []string{"OC"},
|
"AU": {"OC"},
|
||||||
"AW": []string{"NA"},
|
"AW": {"NA"},
|
||||||
"AX": []string{"EU"},
|
"AX": {"EU"},
|
||||||
"AZ": []string{"EU", "AS"},
|
"AZ": {"EU", "AS"},
|
||||||
"BA": []string{"EU"},
|
"BA": {"EU"},
|
||||||
"BB": []string{"NA"},
|
"BB": {"NA"},
|
||||||
"BD": []string{"AS"},
|
"BD": {"AS"},
|
||||||
"BE": []string{"EU"},
|
"BE": {"EU"},
|
||||||
"BF": []string{"AF"},
|
"BF": {"AF"},
|
||||||
"BG": []string{"EU"},
|
"BG": {"EU"},
|
||||||
"BH": []string{"AS"},
|
"BH": {"AS"},
|
||||||
"BI": []string{"AF"},
|
"BI": {"AF"},
|
||||||
"BJ": []string{"AF"},
|
"BJ": {"AF"},
|
||||||
"BL": []string{"NA"},
|
"BL": {"NA"},
|
||||||
"BM": []string{"NA"},
|
"BM": {"NA"},
|
||||||
"BN": []string{"AS"},
|
"BN": {"AS"},
|
||||||
"BO": []string{"SA"},
|
"BO": {"SA"},
|
||||||
"BQ": []string{"NA"},
|
"BQ": {"NA"},
|
||||||
"BR": []string{"SA"},
|
"BR": {"SA"},
|
||||||
"BS": []string{"NA"},
|
"BS": {"NA"},
|
||||||
"BT": []string{"AS"},
|
"BT": {"AS"},
|
||||||
"BV": []string{"AN"},
|
"BV": {"AN"},
|
||||||
"BW": []string{"AF"},
|
"BW": {"AF"},
|
||||||
"BY": []string{"EU"},
|
"BY": {"EU"},
|
||||||
"BZ": []string{"NA"},
|
"BZ": {"NA"},
|
||||||
"CA": []string{"NA"},
|
"CA": {"NA"},
|
||||||
"CC": []string{"AS"},
|
"CC": {"AS"},
|
||||||
"CD": []string{"AF"},
|
"CD": {"AF"},
|
||||||
"CF": []string{"AF"},
|
"CF": {"AF"},
|
||||||
"CG": []string{"AF"},
|
"CG": {"AF"},
|
||||||
"CH": []string{"EU"},
|
"CH": {"EU"},
|
||||||
"CI": []string{"AF"},
|
"CI": {"AF"},
|
||||||
"CK": []string{"OC"},
|
"CK": {"OC"},
|
||||||
"CL": []string{"SA"},
|
"CL": {"SA"},
|
||||||
"CM": []string{"AF"},
|
"CM": {"AF"},
|
||||||
"CN": []string{"AS"},
|
"CN": {"AS"},
|
||||||
"CO": []string{"SA"},
|
"CO": {"SA"},
|
||||||
"CR": []string{"NA"},
|
"CR": {"NA"},
|
||||||
"CU": []string{"NA"},
|
"CU": {"NA"},
|
||||||
"CV": []string{"AF"},
|
"CV": {"AF"},
|
||||||
"CW": []string{"NA"},
|
"CW": {"NA"},
|
||||||
"CX": []string{"AS"},
|
"CX": {"AS"},
|
||||||
"CY": []string{"EU", "AS"},
|
"CY": {"EU", "AS"},
|
||||||
"CZ": []string{"EU"},
|
"CZ": {"EU"},
|
||||||
"DE": []string{"EU"},
|
"DE": {"EU"},
|
||||||
"DJ": []string{"AF"},
|
"DJ": {"AF"},
|
||||||
"DK": []string{"EU"},
|
"DK": {"EU"},
|
||||||
"DM": []string{"NA"},
|
"DM": {"NA"},
|
||||||
"DO": []string{"NA"},
|
"DO": {"NA"},
|
||||||
"DZ": []string{"AF"},
|
"DZ": {"AF"},
|
||||||
"EC": []string{"SA"},
|
"EC": {"SA"},
|
||||||
"EE": []string{"EU"},
|
"EE": {"EU"},
|
||||||
"EG": []string{"AF"},
|
"EG": {"AF"},
|
||||||
"EH": []string{"AF"},
|
"EH": {"AF"},
|
||||||
"ER": []string{"AF"},
|
"ER": {"AF"},
|
||||||
"ES": []string{"EU"},
|
"ES": {"EU"},
|
||||||
"ET": []string{"AF"},
|
"ET": {"AF"},
|
||||||
"FI": []string{"EU"},
|
"FI": {"EU"},
|
||||||
"FJ": []string{"OC"},
|
"FJ": {"OC"},
|
||||||
"FK": []string{"SA"},
|
"FK": {"SA"},
|
||||||
"FM": []string{"OC"},
|
"FM": {"OC"},
|
||||||
"FO": []string{"EU"},
|
"FO": {"EU"},
|
||||||
"FR": []string{"EU"},
|
"FR": {"EU"},
|
||||||
"GA": []string{"AF"},
|
"GA": {"AF"},
|
||||||
"GB": []string{"EU"},
|
"GB": {"EU"},
|
||||||
"GD": []string{"NA"},
|
"GD": {"NA"},
|
||||||
"GE": []string{"EU", "AS"},
|
"GE": {"EU", "AS"},
|
||||||
"GF": []string{"SA"},
|
"GF": {"SA"},
|
||||||
"GG": []string{"EU"},
|
"GG": {"EU"},
|
||||||
"GH": []string{"AF"},
|
"GH": {"AF"},
|
||||||
"GI": []string{"EU"},
|
"GI": {"EU"},
|
||||||
"GL": []string{"NA"},
|
"GL": {"NA"},
|
||||||
"GM": []string{"AF"},
|
"GM": {"AF"},
|
||||||
"GN": []string{"AF"},
|
"GN": {"AF"},
|
||||||
"GP": []string{"NA"},
|
"GP": {"NA"},
|
||||||
"GQ": []string{"AF"},
|
"GQ": {"AF"},
|
||||||
"GR": []string{"EU"},
|
"GR": {"EU"},
|
||||||
"GS": []string{"AN"},
|
"GS": {"AN"},
|
||||||
"GT": []string{"NA"},
|
"GT": {"NA"},
|
||||||
"GU": []string{"OC"},
|
"GU": {"OC"},
|
||||||
"GW": []string{"AF"},
|
"GW": {"AF"},
|
||||||
"GY": []string{"SA"},
|
"GY": {"SA"},
|
||||||
"HK": []string{"AS"},
|
"HK": {"AS"},
|
||||||
"HM": []string{"AN"},
|
"HM": {"AN"},
|
||||||
"HN": []string{"NA"},
|
"HN": {"NA"},
|
||||||
"HR": []string{"EU"},
|
"HR": {"EU"},
|
||||||
"HT": []string{"NA"},
|
"HT": {"NA"},
|
||||||
"HU": []string{"EU"},
|
"HU": {"EU"},
|
||||||
"ID": []string{"AS"},
|
"ID": {"AS"},
|
||||||
"IE": []string{"EU"},
|
"IE": {"EU"},
|
||||||
"IL": []string{"AS"},
|
"IL": {"AS"},
|
||||||
"IM": []string{"EU"},
|
"IM": {"EU"},
|
||||||
"IN": []string{"AS"},
|
"IN": {"AS"},
|
||||||
"IO": []string{"AS"},
|
"IO": {"AS"},
|
||||||
"IQ": []string{"AS"},
|
"IQ": {"AS"},
|
||||||
"IR": []string{"AS"},
|
"IR": {"AS"},
|
||||||
"IS": []string{"EU"},
|
"IS": {"EU"},
|
||||||
"IT": []string{"EU"},
|
"IT": {"EU"},
|
||||||
"JE": []string{"EU"},
|
"JE": {"EU"},
|
||||||
"JM": []string{"NA"},
|
"JM": {"NA"},
|
||||||
"JO": []string{"AS"},
|
"JO": {"AS"},
|
||||||
"JP": []string{"AS"},
|
"JP": {"AS"},
|
||||||
"KE": []string{"AF"},
|
"KE": {"AF"},
|
||||||
"KG": []string{"AS"},
|
"KG": {"AS"},
|
||||||
"KH": []string{"AS"},
|
"KH": {"AS"},
|
||||||
"KI": []string{"OC"},
|
"KI": {"OC"},
|
||||||
"KM": []string{"AF"},
|
"KM": {"AF"},
|
||||||
"KN": []string{"NA"},
|
"KN": {"NA"},
|
||||||
"KP": []string{"AS"},
|
"KP": {"AS"},
|
||||||
"KR": []string{"AS"},
|
"KR": {"AS"},
|
||||||
"KW": []string{"AS"},
|
"KW": {"AS"},
|
||||||
"KY": []string{"NA"},
|
"KY": {"NA"},
|
||||||
"KZ": []string{"EU", "AS"},
|
"KZ": {"EU", "AS"},
|
||||||
"LA": []string{"AS"},
|
"LA": {"AS"},
|
||||||
"LB": []string{"AS"},
|
"LB": {"AS"},
|
||||||
"LC": []string{"NA"},
|
"LC": {"NA"},
|
||||||
"LI": []string{"EU"},
|
"LI": {"EU"},
|
||||||
"LK": []string{"AS"},
|
"LK": {"AS"},
|
||||||
"LR": []string{"AF"},
|
"LR": {"AF"},
|
||||||
"LS": []string{"AF"},
|
"LS": {"AF"},
|
||||||
"LT": []string{"EU"},
|
"LT": {"EU"},
|
||||||
"LU": []string{"EU"},
|
"LU": {"EU"},
|
||||||
"LV": []string{"EU"},
|
"LV": {"EU"},
|
||||||
"LY": []string{"AF"},
|
"LY": {"AF"},
|
||||||
"MA": []string{"AF"},
|
"MA": {"AF"},
|
||||||
"MC": []string{"EU"},
|
"MC": {"EU"},
|
||||||
"MD": []string{"EU"},
|
"MD": {"EU"},
|
||||||
"ME": []string{"EU"},
|
"ME": {"EU"},
|
||||||
"MF": []string{"NA"},
|
"MF": {"NA"},
|
||||||
"MG": []string{"AF"},
|
"MG": {"AF"},
|
||||||
"MH": []string{"OC"},
|
"MH": {"OC"},
|
||||||
"MK": []string{"EU"},
|
"MK": {"EU"},
|
||||||
"ML": []string{"AF"},
|
"ML": {"AF"},
|
||||||
"MM": []string{"AS"},
|
"MM": {"AS"},
|
||||||
"MN": []string{"AS"},
|
"MN": {"AS"},
|
||||||
"MO": []string{"AS"},
|
"MO": {"AS"},
|
||||||
"MP": []string{"OC"},
|
"MP": {"OC"},
|
||||||
"MQ": []string{"NA"},
|
"MQ": {"NA"},
|
||||||
"MR": []string{"AF"},
|
"MR": {"AF"},
|
||||||
"MS": []string{"NA"},
|
"MS": {"NA"},
|
||||||
"MT": []string{"EU"},
|
"MT": {"EU"},
|
||||||
"MU": []string{"AF"},
|
"MU": {"AF"},
|
||||||
"MV": []string{"AS"},
|
"MV": {"AS"},
|
||||||
"MW": []string{"AF"},
|
"MW": {"AF"},
|
||||||
"MX": []string{"NA"},
|
"MX": {"NA"},
|
||||||
"MY": []string{"AS"},
|
"MY": {"AS"},
|
||||||
"MZ": []string{"AF"},
|
"MZ": {"AF"},
|
||||||
"NA": []string{"AF"},
|
"NA": {"AF"},
|
||||||
"NC": []string{"OC"},
|
"NC": {"OC"},
|
||||||
"NE": []string{"AF"},
|
"NE": {"AF"},
|
||||||
"NF": []string{"OC"},
|
"NF": {"OC"},
|
||||||
"NG": []string{"AF"},
|
"NG": {"AF"},
|
||||||
"NI": []string{"NA"},
|
"NI": {"NA"},
|
||||||
"NL": []string{"EU"},
|
"NL": {"EU"},
|
||||||
"NO": []string{"EU"},
|
"NO": {"EU"},
|
||||||
"NP": []string{"AS"},
|
"NP": {"AS"},
|
||||||
"NR": []string{"OC"},
|
"NR": {"OC"},
|
||||||
"NU": []string{"OC"},
|
"NU": {"OC"},
|
||||||
"NZ": []string{"OC"},
|
"NZ": {"OC"},
|
||||||
"OM": []string{"AS"},
|
"OM": {"AS"},
|
||||||
"PA": []string{"NA"},
|
"PA": {"NA"},
|
||||||
"PE": []string{"SA"},
|
"PE": {"SA"},
|
||||||
"PF": []string{"OC"},
|
"PF": {"OC"},
|
||||||
"PG": []string{"OC"},
|
"PG": {"OC"},
|
||||||
"PH": []string{"AS"},
|
"PH": {"AS"},
|
||||||
"PK": []string{"AS"},
|
"PK": {"AS"},
|
||||||
"PL": []string{"EU"},
|
"PL": {"EU"},
|
||||||
"PM": []string{"NA"},
|
"PM": {"NA"},
|
||||||
"PN": []string{"OC"},
|
"PN": {"OC"},
|
||||||
"PR": []string{"NA"},
|
"PR": {"NA"},
|
||||||
"PS": []string{"AS"},
|
"PS": {"AS"},
|
||||||
"PT": []string{"EU"},
|
"PT": {"EU"},
|
||||||
"PW": []string{"OC"},
|
"PW": {"OC"},
|
||||||
"PY": []string{"SA"},
|
"PY": {"SA"},
|
||||||
"QA": []string{"AS"},
|
"QA": {"AS"},
|
||||||
"RE": []string{"AF"},
|
"RE": {"AF"},
|
||||||
"RO": []string{"EU"},
|
"RO": {"EU"},
|
||||||
"RS": []string{"EU"},
|
"RS": {"EU"},
|
||||||
"RU": []string{"EU", "AS"},
|
"RU": {"EU", "AS"},
|
||||||
"RW": []string{"AF"},
|
"RW": {"AF"},
|
||||||
"SA": []string{"AS"},
|
"SA": {"AS"},
|
||||||
"SB": []string{"OC"},
|
"SB": {"OC"},
|
||||||
"SC": []string{"AF"},
|
"SC": {"AF"},
|
||||||
"SD": []string{"AF"},
|
"SD": {"AF"},
|
||||||
"SE": []string{"EU"},
|
"SE": {"EU"},
|
||||||
"SG": []string{"AS"},
|
"SG": {"AS"},
|
||||||
"SH": []string{"AF"},
|
"SH": {"AF"},
|
||||||
"SI": []string{"EU"},
|
"SI": {"EU"},
|
||||||
"SJ": []string{"EU"},
|
"SJ": {"EU"},
|
||||||
"SK": []string{"EU"},
|
"SK": {"EU"},
|
||||||
"SL": []string{"AF"},
|
"SL": {"AF"},
|
||||||
"SM": []string{"EU"},
|
"SM": {"EU"},
|
||||||
"SN": []string{"AF"},
|
"SN": {"AF"},
|
||||||
"SO": []string{"AF"},
|
"SO": {"AF"},
|
||||||
"SR": []string{"SA"},
|
"SR": {"SA"},
|
||||||
"SS": []string{"AF"},
|
"SS": {"AF"},
|
||||||
"ST": []string{"AF"},
|
"ST": {"AF"},
|
||||||
"SV": []string{"NA"},
|
"SV": {"NA"},
|
||||||
"SX": []string{"NA"},
|
"SX": {"NA"},
|
||||||
"SY": []string{"AS"},
|
"SY": {"AS"},
|
||||||
"SZ": []string{"AF"},
|
"SZ": {"AF"},
|
||||||
"TC": []string{"NA"},
|
"TC": {"NA"},
|
||||||
"TD": []string{"AF"},
|
"TD": {"AF"},
|
||||||
"TF": []string{"AN"},
|
"TF": {"AN"},
|
||||||
"TG": []string{"AF"},
|
"TG": {"AF"},
|
||||||
"TH": []string{"AS"},
|
"TH": {"AS"},
|
||||||
"TJ": []string{"AS"},
|
"TJ": {"AS"},
|
||||||
"TK": []string{"OC"},
|
"TK": {"OC"},
|
||||||
"TL": []string{"AS"},
|
"TL": {"AS"},
|
||||||
"TM": []string{"AS"},
|
"TM": {"AS"},
|
||||||
"TN": []string{"AF"},
|
"TN": {"AF"},
|
||||||
"TO": []string{"OC"},
|
"TO": {"OC"},
|
||||||
"TR": []string{"EU", "AS"},
|
"TR": {"EU", "AS"},
|
||||||
"TT": []string{"NA"},
|
"TT": {"NA"},
|
||||||
"TV": []string{"OC"},
|
"TV": {"OC"},
|
||||||
"TW": []string{"AS"},
|
"TW": {"AS"},
|
||||||
"TZ": []string{"AF"},
|
"TZ": {"AF"},
|
||||||
"UA": []string{"EU"},
|
"UA": {"EU"},
|
||||||
"UG": []string{"AF"},
|
"UG": {"AF"},
|
||||||
"UM": []string{"OC", "NA"},
|
"UM": {"OC", "NA"},
|
||||||
"US": []string{"NA"},
|
"US": {"NA"},
|
||||||
"UY": []string{"SA"},
|
"UY": {"SA"},
|
||||||
"UZ": []string{"AS"},
|
"UZ": {"AS"},
|
||||||
"VA": []string{"EU"},
|
"VA": {"EU"},
|
||||||
"VC": []string{"NA"},
|
"VC": {"NA"},
|
||||||
"VE": []string{"SA"},
|
"VE": {"SA"},
|
||||||
"VG": []string{"NA"},
|
"VG": {"NA"},
|
||||||
"VI": []string{"NA"},
|
"VI": {"NA"},
|
||||||
"VN": []string{"AS"},
|
"VN": {"AS"},
|
||||||
"VU": []string{"OC"},
|
"VU": {"OC"},
|
||||||
"WF": []string{"OC"},
|
"WF": {"OC"},
|
||||||
"WS": []string{"OC"},
|
"WS": {"OC"},
|
||||||
"XD": []string{"AS"},
|
"XD": {"AS"},
|
||||||
"XE": []string{"AS"},
|
"XE": {"AS"},
|
||||||
"XS": []string{"AS"},
|
"XS": {"AS"},
|
||||||
"XX": []string{"OC"},
|
"XX": {"OC"},
|
||||||
"YE": []string{"AS"},
|
"YE": {"AS"},
|
||||||
"YT": []string{"AF"},
|
"YT": {"AF"},
|
||||||
"ZA": []string{"AF"},
|
"ZA": {"AF"},
|
||||||
"ZM": []string{"AF"},
|
"ZM": {"AF"},
|
||||||
"ZW": []string{"AF"},
|
"ZW": {"AF"},
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
4
geoip.go
4
geoip.go
|
@ -153,7 +153,7 @@ func (g *GeoLookup) updateUrl() error {
|
||||||
log.Printf("GeoIP database at %s has not changed", g.url)
|
log.Printf("GeoIP database at %s has not changed", g.url)
|
||||||
return nil
|
return nil
|
||||||
} else if response.StatusCode/100 != 2 {
|
} else if response.StatusCode/100 != 2 {
|
||||||
return fmt.Errorf("Downloading %s returned an error: %s", g.url, response.Status)
|
return fmt.Errorf("downloading %s returned an error: %s", g.url, response.Status)
|
||||||
}
|
}
|
||||||
|
|
||||||
body := response.Body
|
body := response.Body
|
||||||
|
@ -186,7 +186,7 @@ func (g *GeoLookup) updateUrl() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(geoipdata) == 0 {
|
if len(geoipdata) == 0 {
|
||||||
return fmt.Errorf("Did not find MaxMind database in tarball from %s", g.url)
|
return fmt.Errorf("did not find MaxMind database in tarball from %s", g.url)
|
||||||
}
|
}
|
||||||
|
|
||||||
reader, err := maxminddb.FromBytes(geoipdata)
|
reader, err := maxminddb.FromBytes(geoipdata)
|
||||||
|
|
|
@ -98,9 +98,9 @@ func TestGeoLookupCaching(t *testing.T) {
|
||||||
|
|
||||||
func TestGeoLookupContinent(t *testing.T) {
|
func TestGeoLookupContinent(t *testing.T) {
|
||||||
tests := map[string][]string{
|
tests := map[string][]string{
|
||||||
"AU": []string{"OC"},
|
"AU": {"OC"},
|
||||||
"DE": []string{"EU"},
|
"DE": {"EU"},
|
||||||
"RU": []string{"EU", "AS"},
|
"RU": {"EU", "AS"},
|
||||||
"": nil,
|
"": nil,
|
||||||
"INVALID ": nil,
|
"INVALID ": nil,
|
||||||
}
|
}
|
||||||
|
|
24
hub.go
24
hub.go
|
@ -161,7 +161,7 @@ func NewHub(config *goconf.ConfigFile, nats NatsClient, r *mux.Router, version s
|
||||||
case 24:
|
case 24:
|
||||||
case 32:
|
case 32:
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("The sessions block key must be 16, 24 or 32 bytes but is %d bytes", len(blockKey))
|
return nil, fmt.Errorf("the sessions block key must be 16, 24 or 32 bytes but is %d bytes", len(blockKey))
|
||||||
}
|
}
|
||||||
|
|
||||||
internalClientsSecret, _ := config.GetString("clients", "internalsecret")
|
internalClientsSecret, _ := config.GetString("clients", "internalsecret")
|
||||||
|
@ -236,12 +236,12 @@ func NewHub(config *goconf.ConfigFile, nats NatsClient, r *mux.Router, version s
|
||||||
if strings.Contains(option, "/") {
|
if strings.Contains(option, "/") {
|
||||||
_, ipNet, err = net.ParseCIDR(option)
|
_, ipNet, err = net.ParseCIDR(option)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Could not parse CIDR %s: %s", option, err)
|
return nil, fmt.Errorf("could not parse CIDR %s: %s", option, err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
ip = net.ParseIP(option)
|
ip = net.ParseIP(option)
|
||||||
if ip == nil {
|
if ip == nil {
|
||||||
return nil, fmt.Errorf("Could not parse IP %s", option)
|
return nil, fmt.Errorf("could not parse IP %s", option)
|
||||||
}
|
}
|
||||||
|
|
||||||
var mask net.IPMask
|
var mask net.IPMask
|
||||||
|
@ -482,7 +482,7 @@ func (h *Hub) encodeSessionId(data *SessionIdData, sessionType string) (string,
|
||||||
|
|
||||||
func (h *Hub) getDecodeCache(cache_key string) *LruCache {
|
func (h *Hub) getDecodeCache(cache_key string) *LruCache {
|
||||||
hash := fnv.New32a()
|
hash := fnv.New32a()
|
||||||
hash.Write([]byte(cache_key))
|
hash.Write([]byte(cache_key)) // nolint
|
||||||
idx := hash.Sum32() % uint32(len(h.decodeCaches))
|
idx := hash.Sum32() % uint32(len(h.decodeCaches))
|
||||||
return h.decodeCaches[idx]
|
return h.decodeCaches[idx]
|
||||||
}
|
}
|
||||||
|
@ -931,7 +931,7 @@ func (h *Hub) processHelloInternal(client *Client, message *ClientMessage) {
|
||||||
// Validate internal connection.
|
// Validate internal connection.
|
||||||
rnd := message.Hello.Auth.internalParams.Random
|
rnd := message.Hello.Auth.internalParams.Random
|
||||||
mac := hmac.New(sha256.New, h.internalClientsSecret)
|
mac := hmac.New(sha256.New, h.internalClientsSecret)
|
||||||
mac.Write([]byte(rnd))
|
mac.Write([]byte(rnd)) // nolint
|
||||||
check := hex.EncodeToString(mac.Sum(nil))
|
check := hex.EncodeToString(mac.Sum(nil))
|
||||||
if len(rnd) < minTokenRandomLength || check != message.Hello.Auth.internalParams.Token {
|
if len(rnd) < minTokenRandomLength || check != message.Hello.Auth.internalParams.Token {
|
||||||
client.SendMessage(message.NewErrorServerMessage(InvalidToken))
|
client.SendMessage(message.NewErrorServerMessage(InvalidToken))
|
||||||
|
@ -969,7 +969,9 @@ func (h *Hub) disconnectByRoomSessionId(roomSessionId string) {
|
||||||
Reason: "room_session_reconnected",
|
Reason: "room_session_reconnected",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
h.nats.PublishMessage("session."+sessionId, msg)
|
if err := h.nats.PublishMessage("session."+sessionId, msg); err != nil {
|
||||||
|
log.Printf("Could not send reconnect bye to session %s: %s", sessionId, err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,7 +1325,7 @@ func (h *Hub) processMessageMsg(client *Client, message *ClientMessage) {
|
||||||
// client) to start his stream, so we must not block the active
|
// client) to start his stream, so we must not block the active
|
||||||
// goroutine.
|
// goroutine.
|
||||||
go h.processMcuMessage(client, recipient, recipientSession, message, msg, clientData)
|
go h.processMcuMessage(client, recipient, recipientSession, message, msg, clientData)
|
||||||
} else {
|
} else { // nolint
|
||||||
// Client is not connected yet.
|
// Client is not connected yet.
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -1335,7 +1337,9 @@ func (h *Hub) processMessageMsg(client *Client, message *ClientMessage) {
|
||||||
log.Printf("Sending offers to remote clients is not supported yet (client %s)", session.PublicId())
|
log.Printf("Sending offers to remote clients is not supported yet (client %s)", session.PublicId())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h.nats.PublishMessage(subject, response)
|
if err := h.nats.PublishMessage(subject, response); err != nil {
|
||||||
|
log.Printf("Error publishing message to remote session: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1434,7 +1438,9 @@ func (h *Hub) processControlMsg(client *Client, message *ClientMessage) {
|
||||||
if recipient != nil {
|
if recipient != nil {
|
||||||
recipient.SendMessage(response)
|
recipient.SendMessage(response)
|
||||||
} else {
|
} else {
|
||||||
h.nats.PublishMessage(subject, response)
|
if err := h.nats.PublishMessage(subject, response); err != nil {
|
||||||
|
log.Printf("Error publishing message to remote session: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
37
hub_test.go
37
hub_test.go
|
@ -218,7 +218,7 @@ func validateBackendChecksum(t *testing.T, f func(http.ResponseWriter, *http.Req
|
||||||
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
w.Header().Set("Content-Type", "application/json")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(data)
|
w.Write(data) // nolint
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +960,7 @@ func TestClientHelloResumePublicId(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data := "from-1-to-2"
|
data := "from-1-to-2"
|
||||||
client1.SendMessage(recipient2, data)
|
client1.SendMessage(recipient2, data) // nolint
|
||||||
|
|
||||||
var payload string
|
var payload string
|
||||||
var sender *MessageServerMessageSender
|
var sender *MessageServerMessageSender
|
||||||
|
@ -1226,9 +1226,9 @@ func TestClientMessageToSessionId(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data1 := "from-1-to-2"
|
data1 := "from-1-to-2"
|
||||||
client1.SendMessage(recipient2, data1)
|
client1.SendMessage(recipient2, data1) // nolint
|
||||||
data2 := "from-2-to-1"
|
data2 := "from-2-to-1"
|
||||||
client2.SendMessage(recipient1, data2)
|
client2.SendMessage(recipient1, data2) // nolint
|
||||||
|
|
||||||
var payload string
|
var payload string
|
||||||
if err := checkReceiveClientMessage(ctx, client1, "session", hello2.Hello, &payload); err != nil {
|
if err := checkReceiveClientMessage(ctx, client1, "session", hello2.Hello, &payload); err != nil {
|
||||||
|
@ -1286,9 +1286,9 @@ func TestClientMessageToUserId(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data1 := "from-1-to-2"
|
data1 := "from-1-to-2"
|
||||||
client1.SendMessage(recipient2, data1)
|
client1.SendMessage(recipient2, data1) // nolint
|
||||||
data2 := "from-2-to-1"
|
data2 := "from-2-to-1"
|
||||||
client2.SendMessage(recipient1, data2)
|
client2.SendMessage(recipient1, data2) // nolint
|
||||||
|
|
||||||
var payload string
|
var payload string
|
||||||
if err := checkReceiveClientMessage(ctx, client1, "user", hello2.Hello, &payload); err != nil {
|
if err := checkReceiveClientMessage(ctx, client1, "user", hello2.Hello, &payload); err != nil {
|
||||||
|
@ -1361,7 +1361,7 @@ func TestClientMessageToUserIdMultipleSessions(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data1 := "from-1-to-2"
|
data1 := "from-1-to-2"
|
||||||
client1.SendMessage(recipient, data1)
|
client1.SendMessage(recipient, data1) // nolint
|
||||||
|
|
||||||
// Both clients will receive the message as it was sent to the user.
|
// Both clients will receive the message as it was sent to the user.
|
||||||
var payload string
|
var payload string
|
||||||
|
@ -1484,9 +1484,9 @@ func TestClientMessageToRoom(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data1 := "from-1-to-2"
|
data1 := "from-1-to-2"
|
||||||
client1.SendMessage(recipient, data1)
|
client1.SendMessage(recipient, data1) // nolint
|
||||||
data2 := "from-2-to-1"
|
data2 := "from-2-to-1"
|
||||||
client2.SendMessage(recipient, data2)
|
client2.SendMessage(recipient, data2) // nolint
|
||||||
|
|
||||||
var payload string
|
var payload string
|
||||||
if err := checkReceiveClientMessage(ctx, client1, "room", hello2.Hello, &payload); err != nil {
|
if err := checkReceiveClientMessage(ctx, client1, "room", hello2.Hello, &payload); err != nil {
|
||||||
|
@ -1732,9 +1732,8 @@ func TestJoinMultiple(t *testing.T) {
|
||||||
|
|
||||||
func TestGetRealUserIP(t *testing.T) {
|
func TestGetRealUserIP(t *testing.T) {
|
||||||
REMOTE_ATTR := "192.168.1.2"
|
REMOTE_ATTR := "192.168.1.2"
|
||||||
var request *http.Request
|
|
||||||
|
|
||||||
request = &http.Request{
|
request := &http.Request{
|
||||||
RemoteAddr: REMOTE_ATTR,
|
RemoteAddr: REMOTE_ATTR,
|
||||||
}
|
}
|
||||||
if ip := getRealUserIP(request); ip != REMOTE_ATTR {
|
if ip := getRealUserIP(request); ip != REMOTE_ATTR {
|
||||||
|
@ -1815,8 +1814,8 @@ func TestClientMessageToSessionIdWhileDisconnected(t *testing.T) {
|
||||||
if err := json.Unmarshal([]byte(chat_refresh), &data1); err != nil {
|
if err := json.Unmarshal([]byte(chat_refresh), &data1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
client1.SendMessage(recipient2, data1)
|
client1.SendMessage(recipient2, data1) // nolint
|
||||||
client1.SendMessage(recipient2, data1)
|
client1.SendMessage(recipient2, data1) // nolint
|
||||||
|
|
||||||
client2 = NewTestClient(t, server, hub)
|
client2 = NewTestClient(t, server, hub)
|
||||||
defer client2.CloseWithBye()
|
defer client2.CloseWithBye()
|
||||||
|
@ -1909,7 +1908,7 @@ func TestRoomParticipantsListUpdateWhileDisconnected(t *testing.T) {
|
||||||
|
|
||||||
// Simulate request from the backend that somebody joined the call.
|
// Simulate request from the backend that somebody joined the call.
|
||||||
users := []map[string]interface{}{
|
users := []map[string]interface{}{
|
||||||
map[string]interface{}{
|
{
|
||||||
"sessionId": "the-session-id",
|
"sessionId": "the-session-id",
|
||||||
"inCall": 1,
|
"inCall": 1,
|
||||||
},
|
},
|
||||||
|
@ -1943,7 +1942,7 @@ func TestRoomParticipantsListUpdateWhileDisconnected(t *testing.T) {
|
||||||
if err := json.Unmarshal([]byte(chat_refresh), &data1); err != nil {
|
if err := json.Unmarshal([]byte(chat_refresh), &data1); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
client1.SendMessage(recipient2, data1)
|
client1.SendMessage(recipient2, data1) // nolint
|
||||||
|
|
||||||
client2 = NewTestClient(t, server, hub)
|
client2 = NewTestClient(t, server, hub)
|
||||||
defer client2.CloseWithBye()
|
defer client2.CloseWithBye()
|
||||||
|
@ -2294,9 +2293,9 @@ func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data1 := "from-1-to-2"
|
data1 := "from-1-to-2"
|
||||||
client1.SendMessage(recipient2, data1)
|
client1.SendMessage(recipient2, data1) // nolint
|
||||||
data2 := "from-2-to-1"
|
data2 := "from-2-to-1"
|
||||||
client2.SendMessage(recipient1, data2)
|
client2.SendMessage(recipient1, data2) // nolint
|
||||||
|
|
||||||
var payload string
|
var payload string
|
||||||
ctx2, cancel2 := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
ctx2, cancel2 := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||||
|
@ -2400,9 +2399,9 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data1 := "from-1-to-2"
|
data1 := "from-1-to-2"
|
||||||
client1.SendMessage(recipient, data1)
|
client1.SendMessage(recipient, data1) // nolint
|
||||||
data2 := "from-2-to-1"
|
data2 := "from-2-to-1"
|
||||||
client2.SendMessage(recipient, data2)
|
client2.SendMessage(recipient, data2) // nolint
|
||||||
|
|
||||||
var payload string
|
var payload string
|
||||||
ctx2, cancel2 := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
ctx2, cancel2 := context.WithTimeout(context.Background(), 100*time.Millisecond)
|
||||||
|
|
|
@ -166,7 +166,7 @@ type TrickleMsg struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func unexpected(request string) error {
|
func unexpected(request string) error {
|
||||||
return fmt.Errorf("Unexpected response received to '%s' request", request)
|
return fmt.Errorf("unexpected response received to '%s' request", request)
|
||||||
}
|
}
|
||||||
|
|
||||||
type transaction struct {
|
type transaction struct {
|
||||||
|
|
|
@ -36,7 +36,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
ErrNotConnected = fmt.Errorf("Not connected")
|
ErrNotConnected = fmt.Errorf("not connected")
|
||||||
)
|
)
|
||||||
|
|
||||||
type McuListener interface {
|
type McuListener interface {
|
||||||
|
|
38
mcu_janus.go
38
mcu_janus.go
|
@ -60,10 +60,6 @@ var (
|
||||||
streamTypeVideo: videoPublisherUserId,
|
streamTypeVideo: videoPublisherUserId,
|
||||||
streamTypeScreen: screenPublisherUserId,
|
streamTypeScreen: screenPublisherUserId,
|
||||||
}
|
}
|
||||||
userIdToStreamType = map[uint64]string{
|
|
||||||
videoPublisherUserId: streamTypeVideo,
|
|
||||||
screenPublisherUserId: streamTypeScreen,
|
|
||||||
}
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func getPluginValue(data janus.PluginData, pluginName string, key string) interface{} {
|
func getPluginValue(data janus.PluginData, pluginName string, key string) interface{} {
|
||||||
|
@ -209,12 +205,16 @@ func NewMcuJanus(url string, config *goconf.ConfigFile, nats NatsClient) (Mcu, e
|
||||||
|
|
||||||
func (m *mcuJanus) disconnect() {
|
func (m *mcuJanus) disconnect() {
|
||||||
if m.handle != nil {
|
if m.handle != nil {
|
||||||
m.handle.Detach(context.TODO())
|
if _, err := m.handle.Detach(context.TODO()); err != nil {
|
||||||
|
log.Printf("Error detaching handle %d: %s", m.handle.Id, err)
|
||||||
|
}
|
||||||
m.handle = nil
|
m.handle = nil
|
||||||
}
|
}
|
||||||
if m.session != nil {
|
if m.session != nil {
|
||||||
m.closeChan <- true
|
m.closeChan <- true
|
||||||
m.session.Destroy(context.TODO())
|
if _, err := m.session.Destroy(context.TODO()); err != nil {
|
||||||
|
log.Printf("Error destroying session %d: %s", m.session.Id, err)
|
||||||
|
}
|
||||||
m.session = nil
|
m.session = nil
|
||||||
}
|
}
|
||||||
if m.gw != nil {
|
if m.gw != nil {
|
||||||
|
@ -431,7 +431,7 @@ func (m *mcuJanus) sendKeepalive() {
|
||||||
type mcuJanusClient struct {
|
type mcuJanusClient struct {
|
||||||
mcu *mcuJanus
|
mcu *mcuJanus
|
||||||
listener McuListener
|
listener McuListener
|
||||||
mu sync.Mutex
|
mu sync.Mutex // nolint
|
||||||
|
|
||||||
id uint64
|
id uint64
|
||||||
session uint64
|
session uint64
|
||||||
|
@ -626,13 +626,17 @@ func (m *mcuJanus) getOrCreatePublisherHandle(ctx context.Context, id string, st
|
||||||
create_msg["bitrate"] = bitrate
|
create_msg["bitrate"] = bitrate
|
||||||
create_response, err := handle.Request(ctx, create_msg)
|
create_response, err := handle.Request(ctx, create_msg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handle.Detach(ctx)
|
if _, err2 := handle.Detach(ctx); err2 != nil {
|
||||||
|
log.Printf("Error detaching handle %d: %s", handle.Id, err2)
|
||||||
|
}
|
||||||
return nil, 0, 0, err
|
return nil, 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
roomId = getPluginIntValue(create_response.PluginData, pluginVideoRoom, "room")
|
roomId = getPluginIntValue(create_response.PluginData, pluginVideoRoom, "room")
|
||||||
if roomId == 0 {
|
if roomId == 0 {
|
||||||
handle.Detach(ctx)
|
if _, err := handle.Detach(ctx); err != nil {
|
||||||
|
log.Printf("Error detaching handle %d: %s", handle.Id, err)
|
||||||
|
}
|
||||||
return nil, 0, 0, fmt.Errorf("No room id received: %+v", create_response)
|
return nil, 0, 0, fmt.Errorf("No room id received: %+v", create_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,7 +654,9 @@ func (m *mcuJanus) getOrCreatePublisherHandle(ctx context.Context, id string, st
|
||||||
|
|
||||||
response, err := handle.Message(ctx, msg, nil)
|
response, err := handle.Message(ctx, msg, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
handle.Detach(ctx)
|
if _, err2 := handle.Detach(ctx); err2 != nil {
|
||||||
|
log.Printf("Error detaching handle %d: %s", handle.Id, err2)
|
||||||
|
}
|
||||||
return nil, 0, 0, err
|
return nil, 0, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -911,7 +917,11 @@ func (m *mcuJanus) getPublisherRoomId(ctx context.Context, publisher string, str
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return 0, err
|
||||||
}
|
}
|
||||||
defer sub.Unsubscribe()
|
defer func() {
|
||||||
|
if err := sub.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error unsubscribing channel for %s publisher %s: %s", streamType, publisher, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
for roomId == 0 {
|
for roomId == 0 {
|
||||||
var err error
|
var err error
|
||||||
|
@ -1073,7 +1083,11 @@ func (p *mcuJanusSubscriber) joinRoom(ctx context.Context, callback func(error,
|
||||||
callback(err, nil)
|
callback(err, nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer sub.Unsubscribe()
|
defer func() {
|
||||||
|
if err := sub.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error unsubscribing channel for %s publisher %s: %s", p.streamType, p.publisher, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
retry:
|
retry:
|
||||||
join_msg := map[string]interface{}{
|
join_msg := map[string]interface{}{
|
||||||
|
|
19
mcu_proxy.go
19
mcu_proxy.go
|
@ -379,7 +379,7 @@ func (c *mcuProxyConnection) readPump() {
|
||||||
|
|
||||||
conn.SetPongHandler(func(msg string) error {
|
conn.SetPongHandler(func(msg string) error {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
conn.SetReadDeadline(now.Add(pongWait))
|
conn.SetReadDeadline(now.Add(pongWait)) // nolint
|
||||||
if msg == "" {
|
if msg == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -392,7 +392,7 @@ func (c *mcuProxyConnection) readPump() {
|
||||||
})
|
})
|
||||||
|
|
||||||
for {
|
for {
|
||||||
conn.SetReadDeadline(time.Now().Add(pongWait))
|
conn.SetReadDeadline(time.Now().Add(pongWait)) // nolint
|
||||||
_, message, err := conn.ReadMessage()
|
_, message, err := conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(*websocket.CloseError); !ok || websocket.IsUnexpectedCloseError(err,
|
if _, ok := err.(*websocket.CloseError); !ok || websocket.IsUnexpectedCloseError(err,
|
||||||
|
@ -423,7 +423,7 @@ func (c *mcuProxyConnection) sendPing() bool {
|
||||||
|
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
msg := strconv.FormatInt(now.UnixNano(), 10)
|
msg := strconv.FormatInt(now.UnixNano(), 10)
|
||||||
c.conn.SetWriteDeadline(now.Add(writeWait))
|
c.conn.SetWriteDeadline(now.Add(writeWait)) // nolint
|
||||||
if err := c.conn.WriteMessage(websocket.PingMessage, []byte(msg)); err != nil {
|
if err := c.conn.WriteMessage(websocket.PingMessage, []byte(msg)); err != nil {
|
||||||
log.Printf("Could not send ping to proxy at %s: %v", c.url, err)
|
log.Printf("Could not send ping to proxy at %s: %v", c.url, err)
|
||||||
c.scheduleReconnect()
|
c.scheduleReconnect()
|
||||||
|
@ -465,7 +465,7 @@ func (c *mcuProxyConnection) sendClose() error {
|
||||||
return ErrNotConnected
|
return ErrNotConnected
|
||||||
}
|
}
|
||||||
|
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
return c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
return c.conn.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -858,7 +858,7 @@ func (c *mcuProxyConnection) sendMessageLocked(msg *ProxyClientMessage) error {
|
||||||
if c.conn == nil {
|
if c.conn == nil {
|
||||||
return ErrNotConnected
|
return ErrNotConnected
|
||||||
}
|
}
|
||||||
c.conn.SetWriteDeadline(time.Now().Add(writeWait))
|
c.conn.SetWriteDeadline(time.Now().Add(writeWait)) // nolint
|
||||||
return c.conn.WriteJSON(msg)
|
return c.conn.WriteJSON(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -969,11 +969,10 @@ type mcuProxy struct {
|
||||||
tokenId string
|
tokenId string
|
||||||
tokenKey *rsa.PrivateKey
|
tokenKey *rsa.PrivateKey
|
||||||
|
|
||||||
etcdMu sync.Mutex
|
etcdMu sync.Mutex
|
||||||
client atomic.Value
|
client atomic.Value
|
||||||
keyPrefix atomic.Value
|
keyInfos map[string]*ProxyInformationEtcd
|
||||||
keyInfos map[string]*ProxyInformationEtcd
|
urlToKey map[string]string
|
||||||
urlToKey map[string]string
|
|
||||||
|
|
||||||
dialer *websocket.Dialer
|
dialer *websocket.Dialer
|
||||||
connections []*mcuProxyConnection
|
connections []*mcuProxyConnection
|
||||||
|
|
|
@ -39,39 +39,39 @@ func Test_sortConnectionsForCountry(t *testing.T) {
|
||||||
|
|
||||||
testcases := map[string][][]*mcuProxyConnection{
|
testcases := map[string][][]*mcuProxyConnection{
|
||||||
// Direct country match
|
// Direct country match
|
||||||
"DE": [][]*mcuProxyConnection{
|
"DE": {
|
||||||
[]*mcuProxyConnection{conn_at, conn_jp, conn_de},
|
{conn_at, conn_jp, conn_de},
|
||||||
[]*mcuProxyConnection{conn_de, conn_at, conn_jp},
|
{conn_de, conn_at, conn_jp},
|
||||||
},
|
},
|
||||||
// Direct country match
|
// Direct country match
|
||||||
"AT": [][]*mcuProxyConnection{
|
"AT": {
|
||||||
[]*mcuProxyConnection{conn_at, conn_jp, conn_de},
|
{conn_at, conn_jp, conn_de},
|
||||||
[]*mcuProxyConnection{conn_at, conn_de, conn_jp},
|
{conn_at, conn_de, conn_jp},
|
||||||
},
|
},
|
||||||
// Continent match
|
// Continent match
|
||||||
"CH": [][]*mcuProxyConnection{
|
"CH": {
|
||||||
[]*mcuProxyConnection{conn_de, conn_jp, conn_at},
|
{conn_de, conn_jp, conn_at},
|
||||||
[]*mcuProxyConnection{conn_de, conn_at, conn_jp},
|
{conn_de, conn_at, conn_jp},
|
||||||
},
|
},
|
||||||
// Direct country match
|
// Direct country match
|
||||||
"JP": [][]*mcuProxyConnection{
|
"JP": {
|
||||||
[]*mcuProxyConnection{conn_de, conn_jp, conn_at},
|
{conn_de, conn_jp, conn_at},
|
||||||
[]*mcuProxyConnection{conn_jp, conn_de, conn_at},
|
{conn_jp, conn_de, conn_at},
|
||||||
},
|
},
|
||||||
// Continent match
|
// Continent match
|
||||||
"CN": [][]*mcuProxyConnection{
|
"CN": {
|
||||||
[]*mcuProxyConnection{conn_de, conn_jp, conn_at},
|
{conn_de, conn_jp, conn_at},
|
||||||
[]*mcuProxyConnection{conn_jp, conn_de, conn_at},
|
{conn_jp, conn_de, conn_at},
|
||||||
},
|
},
|
||||||
// Partial continent match
|
// Partial continent match
|
||||||
"RU": [][]*mcuProxyConnection{
|
"RU": {
|
||||||
[]*mcuProxyConnection{conn_us, conn_de, conn_jp, conn_at},
|
{conn_us, conn_de, conn_jp, conn_at},
|
||||||
[]*mcuProxyConnection{conn_de, conn_jp, conn_at, conn_us},
|
{conn_de, conn_jp, conn_at, conn_us},
|
||||||
},
|
},
|
||||||
// No match
|
// No match
|
||||||
"AU": [][]*mcuProxyConnection{
|
"AU": {
|
||||||
[]*mcuProxyConnection{conn_us, conn_de, conn_jp, conn_at},
|
{conn_us, conn_de, conn_jp, conn_at},
|
||||||
[]*mcuProxyConnection{conn_us, conn_de, conn_jp, conn_at},
|
{conn_us, conn_de, conn_jp, conn_at},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ package signaling
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"log"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -169,7 +170,11 @@ func (c *LoopbackNatsClient) Request(subject string, data []byte, timeout time.D
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
go replySubscriber.Unsubscribe()
|
go func() {
|
||||||
|
if err := replySubscriber.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error closing reply subscriber %s: %s", reply, err)
|
||||||
|
}
|
||||||
|
}()
|
||||||
}()
|
}()
|
||||||
msg := &nats.Msg{
|
msg := &nats.Msg{
|
||||||
Subject: subject,
|
Subject: subject,
|
||||||
|
|
|
@ -98,7 +98,9 @@ func TestLoopbackNatsClient_Subscribe(t *testing.T) {
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
for i := int32(0); i < max; i++ {
|
for i := int32(0); i < max; i++ {
|
||||||
client.Publish("foo", []byte("hello"))
|
if err := client.Publish("foo", []byte("hello")); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
<-ch
|
<-ch
|
||||||
|
|
||||||
|
|
|
@ -46,7 +46,7 @@ import (
|
||||||
|
|
||||||
"gopkg.in/dgrijalva/jwt-go.v3"
|
"gopkg.in/dgrijalva/jwt-go.v3"
|
||||||
|
|
||||||
"github.com/strukturag/nextcloud-spreed-signaling"
|
signaling "github.com/strukturag/nextcloud-spreed-signaling"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -985,5 +985,5 @@ func (s *ProxyServer) statsHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
w.Header().Set("Content-Type", "application/json; charset=utf-8")
|
||||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||||
w.WriteHeader(http.StatusOK)
|
w.WriteHeader(http.StatusOK)
|
||||||
w.Write(statsData)
|
w.Write(statsData) // nolint
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ import (
|
||||||
|
|
||||||
"gopkg.in/dgrijalva/jwt-go.v3"
|
"gopkg.in/dgrijalva/jwt-go.v3"
|
||||||
|
|
||||||
"github.com/strukturag/nextcloud-spreed-signaling"
|
signaling "github.com/strukturag/nextcloud-spreed-signaling"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -232,7 +232,9 @@ func (t *tokensEtcd) load(config *goconf.ConfigFile, ignoreErrors bool) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokensEtcd) Reload(config *goconf.ConfigFile) {
|
func (t *tokensEtcd) Reload(config *goconf.ConfigFile) {
|
||||||
t.load(config, true)
|
if err := t.load(config, true); err != nil {
|
||||||
|
log.Printf("Error reloading etcd tokens: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokensEtcd) Close() {
|
func (t *tokensEtcd) Close() {
|
||||||
|
|
|
@ -103,7 +103,7 @@ func (t *tokensStatic) load(config *goconf.ConfigFile, ignoreErrors bool) error
|
||||||
log.Printf("No token keys loaded")
|
log.Printf("No token keys loaded")
|
||||||
} else {
|
} else {
|
||||||
var keyIds []string
|
var keyIds []string
|
||||||
for k, _ := range tokenKeys {
|
for k := range tokenKeys {
|
||||||
keyIds = append(keyIds, k)
|
keyIds = append(keyIds, k)
|
||||||
}
|
}
|
||||||
sort.Strings(keyIds)
|
sort.Strings(keyIds)
|
||||||
|
@ -114,7 +114,9 @@ func (t *tokensStatic) load(config *goconf.ConfigFile, ignoreErrors bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokensStatic) Reload(config *goconf.ConfigFile) {
|
func (t *tokensStatic) Reload(config *goconf.ConfigFile) {
|
||||||
t.load(config, true)
|
if err := t.load(config, true); err != nil {
|
||||||
|
log.Printf("Error reloading static tokens: %s", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tokensStatic) Close() {
|
func (t *tokensStatic) Close() {
|
||||||
|
|
42
room.go
42
room.go
|
@ -177,7 +177,9 @@ func (r *Room) unsubscribeBackend() {
|
||||||
}
|
}
|
||||||
|
|
||||||
go func(subscription NatsSubscription) {
|
go func(subscription NatsSubscription) {
|
||||||
subscription.Unsubscribe()
|
if err := subscription.Unsubscribe(); err != nil {
|
||||||
|
log.Printf("Error closing backend subscription for room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
close(r.natsReceiver)
|
close(r.natsReceiver)
|
||||||
}(r.backendSubscription)
|
}(r.backendSubscription)
|
||||||
r.backendSubscription = nil
|
r.backendSubscription = nil
|
||||||
|
@ -330,8 +332,8 @@ func (r *Room) RemoveSession(session Session) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) publish(message *ServerMessage) {
|
func (r *Room) publish(message *ServerMessage) error {
|
||||||
r.nats.PublishMessage(GetSubjectForRoomId(r.id, r.backend), message)
|
return r.nats.PublishMessage(GetSubjectForRoomId(r.id, r.backend), message)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) UpdateProperties(properties *json.RawMessage) {
|
func (r *Room) UpdateProperties(properties *json.RawMessage) {
|
||||||
|
@ -351,7 +353,9 @@ func (r *Room) UpdateProperties(properties *json.RawMessage) {
|
||||||
Properties: r.properties,
|
Properties: r.properties,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish update properties message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) GetRoomSessionData(session Session) *RoomSessionData {
|
func (r *Room) GetRoomSessionData(session Session) *RoomSessionData {
|
||||||
|
@ -377,7 +381,7 @@ func (r *Room) PublishSessionJoined(session Session, sessionData *RoomSessionDat
|
||||||
Target: "room",
|
Target: "room",
|
||||||
Type: "join",
|
Type: "join",
|
||||||
Join: []*EventServerMessageSessionEntry{
|
Join: []*EventServerMessageSessionEntry{
|
||||||
&EventServerMessageSessionEntry{
|
{
|
||||||
SessionId: sessionId,
|
SessionId: sessionId,
|
||||||
UserId: userid,
|
UserId: userid,
|
||||||
User: session.UserData(),
|
User: session.UserData(),
|
||||||
|
@ -385,7 +389,9 @@ func (r *Room) PublishSessionJoined(session Session, sessionData *RoomSessionDat
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish session joined message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
if session.ClientType() == HelloClientTypeInternal {
|
if session.ClientType() == HelloClientTypeInternal {
|
||||||
r.publishUsersChangedWithInternal()
|
r.publishUsersChangedWithInternal()
|
||||||
|
@ -408,7 +414,9 @@ func (r *Room) PublishSessionLeft(session Session) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish session left message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
|
|
||||||
if session.ClientType() == HelloClientTypeInternal {
|
if session.ClientType() == HelloClientTypeInternal {
|
||||||
r.publishUsersChangedWithInternal()
|
r.publishUsersChangedWithInternal()
|
||||||
|
@ -539,7 +547,9 @@ func (r *Room) PublishUsersInCallChanged(changed []map[string]interface{}, users
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish incall message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) PublishUsersChanged(changed []map[string]interface{}, users []map[string]interface{}) {
|
func (r *Room) PublishUsersChanged(changed []map[string]interface{}, users []map[string]interface{}) {
|
||||||
|
@ -558,7 +568,9 @@ func (r *Room) PublishUsersChanged(changed []map[string]interface{}, users []map
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish users changed message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) getParticipantsUpdateMessage(users []map[string]interface{}) *ServerMessage {
|
func (r *Room) getParticipantsUpdateMessage(users []map[string]interface{}) *ServerMessage {
|
||||||
|
@ -603,7 +615,9 @@ func (r *Room) NotifySessionChanged(session Session) {
|
||||||
|
|
||||||
func (r *Room) publishUsersChangedWithInternal() {
|
func (r *Room) publishUsersChangedWithInternal() {
|
||||||
message := r.getParticipantsUpdateMessage(r.users)
|
message := r.getParticipantsUpdateMessage(r.users)
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish users changed message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) publishSessionFlagsChanged(session *VirtualSession) {
|
func (r *Room) publishSessionFlagsChanged(session *VirtualSession) {
|
||||||
|
@ -619,7 +633,9 @@ func (r *Room) publishSessionFlagsChanged(session *VirtualSession) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(message)
|
if err := r.publish(message); err != nil {
|
||||||
|
log.Printf("Could not publish flags changed message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) publishActiveSessions() {
|
func (r *Room) publishActiveSessions() {
|
||||||
|
@ -696,7 +712,9 @@ func (r *Room) publishRoomMessage(message *BackendRoomMessageRequest) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
r.publish(msg)
|
if err := r.publish(msg); err != nil {
|
||||||
|
log.Printf("Could not publish room message in room %s: %s", r.Id(), err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *Room) notifyInternalRoomDeleted() {
|
func (r *Room) notifyInternalRoomDeleted() {
|
||||||
|
|
|
@ -133,8 +133,12 @@ func testRoomSessions(t *testing.T, sessions RoomSessions) {
|
||||||
t.Errorf("Expected session id %s, got %s", s2.PublicId(), sid)
|
t.Errorf("Expected session id %s, got %s", s2.PublicId(), sid)
|
||||||
}
|
}
|
||||||
|
|
||||||
sessions.SetRoomSession(s1, "room-session")
|
if err := sessions.SetRoomSession(s1, "room-session"); err != nil {
|
||||||
sessions.SetRoomSession(s2, "room-session")
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if err := sessions.SetRoomSession(s2, "room-session"); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
sessions.DeleteRoomSession(s1)
|
sessions.DeleteRoomSession(s1)
|
||||||
if sid, err := sessions.GetSessionId("room-session"); err != nil {
|
if sid, err := sessions.GetSessionId("room-session"); err != nil {
|
||||||
t.Errorf("Expected session id %s, got error %s", s2.PublicId(), err)
|
t.Errorf("Expected session id %s, got error %s", s2.PublicId(), err)
|
||||||
|
|
|
@ -74,7 +74,7 @@ def generate_map(filename):
|
||||||
value = []
|
value = []
|
||||||
for continent in continents:
|
for continent in continents:
|
||||||
value.append('"%s"' % (continent))
|
value.append('"%s"' % (continent))
|
||||||
out.write('\t\t"%s": []string{%s},\n' % (country, ', '.join(value)))
|
out.write('\t\t"%s": {%s},\n' % (country, ', '.join(value)))
|
||||||
out.write('\t}\n')
|
out.write('\t}\n')
|
||||||
out.write(')\n')
|
out.write(')\n')
|
||||||
with opentextfile(filename, 'wb') as fp:
|
with opentextfile(filename, 'wb') as fp:
|
||||||
|
|
|
@ -108,8 +108,10 @@ func main() {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := runtimepprof.StartCPUProfile(f); err != nil {
|
||||||
|
log.Fatalf("Error writing CPU profile to %s: %s", *cpuprofile, err)
|
||||||
|
}
|
||||||
log.Printf("Writing CPU profile to %s ...\n", *cpuprofile)
|
log.Printf("Writing CPU profile to %s ...\n", *cpuprofile)
|
||||||
runtimepprof.StartCPUProfile(f)
|
|
||||||
defer runtimepprof.StopCPUProfile()
|
defer runtimepprof.StopCPUProfile()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,7 +124,9 @@ func main() {
|
||||||
defer func() {
|
defer func() {
|
||||||
log.Printf("Writing Memory profile to %s ...\n", *memprofile)
|
log.Printf("Writing Memory profile to %s ...\n", *memprofile)
|
||||||
runtime.GC()
|
runtime.GC()
|
||||||
runtimepprof.WriteHeapProfile(f)
|
if err := runtimepprof.WriteHeapProfile(f); err != nil {
|
||||||
|
log.Printf("Error writing Memory profile to %s: %s", *memprofile, err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -318,20 +322,17 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
for {
|
for sig := range sigChan {
|
||||||
select {
|
switch sig {
|
||||||
case sig := <-sigChan:
|
case os.Interrupt:
|
||||||
switch sig {
|
log.Println("Interrupted")
|
||||||
case os.Interrupt:
|
break loop
|
||||||
log.Println("Interrupted")
|
case syscall.SIGHUP:
|
||||||
break loop
|
log.Printf("Received SIGHUP, reloading %s", *configFlag)
|
||||||
case syscall.SIGHUP:
|
if config, err := goconf.ReadConfigFile(*configFlag); err != nil {
|
||||||
log.Printf("Received SIGHUP, reloading %s", *configFlag)
|
log.Printf("Could not read configuration from %s: %s", *configFlag, err)
|
||||||
if config, err := goconf.ReadConfigFile(*configFlag); err != nil {
|
} else {
|
||||||
log.Printf("Could not read configuration from %s: %s", *configFlag, err)
|
hub.Reload(config)
|
||||||
} else {
|
|
||||||
hub.Reload(config)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,14 +58,6 @@ func getWebsocketUrl(url string) string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPrivateSessionIdData(h *Hub, privateId string) *SessionIdData {
|
|
||||||
decodedPrivate := h.decodeSessionId(privateId, privateSessionName)
|
|
||||||
if decodedPrivate == nil {
|
|
||||||
panic("invalid private session id")
|
|
||||||
}
|
|
||||||
return decodedPrivate
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPubliceSessionIdData(h *Hub, publicId string) *SessionIdData {
|
func getPubliceSessionIdData(h *Hub, publicId string) *SessionIdData {
|
||||||
decodedPublic := h.decodeSessionId(publicId, publicSessionName)
|
decodedPublic := h.decodeSessionId(publicId, publicSessionName)
|
||||||
if decodedPublic == nil {
|
if decodedPublic == nil {
|
||||||
|
@ -74,30 +66,6 @@ func getPubliceSessionIdData(h *Hub, publicId string) *SessionIdData {
|
||||||
return decodedPublic
|
return decodedPublic
|
||||||
}
|
}
|
||||||
|
|
||||||
func privateToPublicSessionId(h *Hub, privateId string) string {
|
|
||||||
decodedPrivate := getPrivateSessionIdData(h, privateId)
|
|
||||||
if decodedPrivate == nil {
|
|
||||||
panic("invalid private session id")
|
|
||||||
}
|
|
||||||
encodedPublic, err := h.encodeSessionId(decodedPrivate, publicSessionName)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return encodedPublic
|
|
||||||
}
|
|
||||||
|
|
||||||
func equalPublicAndPrivateSessionId(h *Hub, publicId, privateId string) bool {
|
|
||||||
decodedPublic := h.decodeSessionId(publicId, publicSessionName)
|
|
||||||
if decodedPublic == nil {
|
|
||||||
panic("invalid public session id")
|
|
||||||
}
|
|
||||||
decodedPrivate := h.decodeSessionId(privateId, privateSessionName)
|
|
||||||
if decodedPrivate == nil {
|
|
||||||
panic("invalid private session id")
|
|
||||||
}
|
|
||||||
return decodedPublic.Sid == decodedPrivate.Sid
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkUnexpectedClose(err error) error {
|
func checkUnexpectedClose(err error) error {
|
||||||
if err != nil && websocket.IsUnexpectedCloseError(err,
|
if err != nil && websocket.IsUnexpectedCloseError(err,
|
||||||
websocket.CloseNormalClosure,
|
websocket.CloseNormalClosure,
|
||||||
|
@ -254,12 +222,12 @@ func NewTestClient(t *testing.T, server *httptest.Server, hub *Hub) *TestClient
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TestClient) CloseWithBye() {
|
func (c *TestClient) CloseWithBye() {
|
||||||
c.SendBye()
|
c.SendBye() // nolint
|
||||||
c.Close()
|
c.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TestClient) Close() {
|
func (c *TestClient) Close() {
|
||||||
c.conn.WriteMessage(websocket.CloseMessage, []byte{})
|
c.conn.WriteMessage(websocket.CloseMessage, []byte{}) // nolint
|
||||||
c.conn.Close()
|
c.conn.Close()
|
||||||
|
|
||||||
// Drain any entries in the channels to terminate the read goroutine.
|
// Drain any entries in the channels to terminate the read goroutine.
|
||||||
|
@ -374,7 +342,7 @@ func (c *TestClient) SendHelloClient(userid string) error {
|
||||||
func (c *TestClient) SendHelloInternal() error {
|
func (c *TestClient) SendHelloInternal() error {
|
||||||
random := newRandomString(48)
|
random := newRandomString(48)
|
||||||
mac := hmac.New(sha256.New, testInternalSecret)
|
mac := hmac.New(sha256.New, testInternalSecret)
|
||||||
mac.Write([]byte(random))
|
mac.Write([]byte(random)) // nolint
|
||||||
token := hex.EncodeToString(mac.Sum(nil))
|
token := hex.EncodeToString(mac.Sum(nil))
|
||||||
backend := c.server.URL
|
backend := c.server.URL
|
||||||
|
|
||||||
|
|
|
@ -205,7 +205,9 @@ func TestVirtualSession(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data := "from-client-to-virtual"
|
data := "from-client-to-virtual"
|
||||||
client.SendMessage(recipient, data)
|
if err := client.SendMessage(recipient, data); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
msg2, err = clientInternal.RunUntilMessage(ctx)
|
msg2, err = clientInternal.RunUntilMessage(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in a new issue