mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2026-03-14 14:35:44 +01:00
Merge 3d2893ea63 into 791ad0e294
This commit is contained in:
commit
6c50345f13
15 changed files with 636 additions and 825 deletions
|
|
@ -26,6 +26,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"maps"
|
||||
"net"
|
||||
"net/url"
|
||||
"slices"
|
||||
|
|
@ -1177,13 +1178,62 @@ type InternalServerMessage struct {
|
|||
|
||||
// Type "event"
|
||||
|
||||
type UserData = StringMap
|
||||
|
||||
func (d UserData) Clone() UserData {
|
||||
return maps.Clone(d)
|
||||
}
|
||||
|
||||
func (d UserData) SessionId() (PublicSessionId, bool) {
|
||||
return GetStringMapString[PublicSessionId](StringMap(d), "sessionId")
|
||||
}
|
||||
|
||||
type UserDataMap map[PublicSessionId]UserData
|
||||
|
||||
func (m UserDataMap) Users() UserDataList {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
return slices.Collect(maps.Values(m))
|
||||
}
|
||||
|
||||
type UserDataList []UserData
|
||||
|
||||
func (l UserDataList) Clone() UserDataList {
|
||||
if len(l) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
clone := make(UserDataList, len(l))
|
||||
for idx, u := range l {
|
||||
clone[idx] = u.Clone()
|
||||
}
|
||||
return clone
|
||||
}
|
||||
|
||||
func (l UserDataList) Map() UserDataMap {
|
||||
if len(l) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
result := make(UserDataMap, len(l))
|
||||
for _, d := range l {
|
||||
sid, found := d.SessionId()
|
||||
if found {
|
||||
result[sid] = d
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type RoomEventServerMessage struct {
|
||||
RoomId string `json:"roomid"`
|
||||
Properties json.RawMessage `json:"properties,omitempty"`
|
||||
// TODO(jojo): Change "InCall" to "int" when #914 has landed in NC Talk.
|
||||
InCall json.RawMessage `json:"incall,omitempty"`
|
||||
Changed []StringMap `json:"changed,omitempty"`
|
||||
Users []StringMap `json:"users,omitempty"`
|
||||
Changed UserDataList `json:"changed,omitempty"`
|
||||
Users UserDataList `json:"users,omitempty"`
|
||||
|
||||
All bool `json:"all,omitempty"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1144,9 +1144,9 @@ func easyjson6128dd2DecodeGithubComStrukturagNextcloudSpreedSignalingApi8(in *jl
|
|||
in.Delim('[')
|
||||
if out.Changed == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Changed = make([]StringMap, 0, 8)
|
||||
out.Changed = make(UserDataList, 0, 8)
|
||||
} else {
|
||||
out.Changed = []StringMap{}
|
||||
out.Changed = UserDataList{}
|
||||
}
|
||||
} else {
|
||||
out.Changed = (out.Changed)[:0]
|
||||
|
|
@ -1191,9 +1191,9 @@ func easyjson6128dd2DecodeGithubComStrukturagNextcloudSpreedSignalingApi8(in *jl
|
|||
in.Delim('[')
|
||||
if out.Users == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Users = make([]StringMap, 0, 8)
|
||||
out.Users = make(UserDataList, 0, 8)
|
||||
} else {
|
||||
out.Users = []StringMap{}
|
||||
out.Users = UserDataList{}
|
||||
}
|
||||
} else {
|
||||
out.Users = (out.Users)[:0]
|
||||
|
|
@ -1741,9 +1741,9 @@ func easyjson6128dd2DecodeGithubComStrukturagNextcloudSpreedSignalingApi13(in *j
|
|||
in.Delim('[')
|
||||
if out.Changed == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Changed = make([]StringMap, 0, 8)
|
||||
out.Changed = make(UserDataList, 0, 8)
|
||||
} else {
|
||||
out.Changed = []StringMap{}
|
||||
out.Changed = UserDataList{}
|
||||
}
|
||||
} else {
|
||||
out.Changed = (out.Changed)[:0]
|
||||
|
|
@ -1788,9 +1788,9 @@ func easyjson6128dd2DecodeGithubComStrukturagNextcloudSpreedSignalingApi13(in *j
|
|||
in.Delim('[')
|
||||
if out.Users == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Users = make([]StringMap, 0, 8)
|
||||
out.Users = make(UserDataList, 0, 8)
|
||||
} else {
|
||||
out.Users = []StringMap{}
|
||||
out.Users = UserDataList{}
|
||||
}
|
||||
} else {
|
||||
out.Users = (out.Users)[:0]
|
||||
|
|
|
|||
|
|
@ -603,3 +603,77 @@ func TestNoFilterSDPCandidates(t *testing.T) {
|
|||
assert.Equal(mock.MockSdpOfferAudioOnlyNoFilter, strings.ReplaceAll(string(encoded), "\r\n", "\n"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserData(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
|
||||
type s struct {
|
||||
value any
|
||||
}
|
||||
|
||||
d := UserData{
|
||||
"foo": "bar",
|
||||
"baz": &s{
|
||||
value: 1234,
|
||||
},
|
||||
}
|
||||
|
||||
// Clone is *not* a deep copy.
|
||||
d2 := d.Clone()
|
||||
assert.Equal(d, d2)
|
||||
|
||||
d["baz"].(*s).value = 2345
|
||||
assert.Equal(UserData{
|
||||
"foo": "bar",
|
||||
"baz": &s{
|
||||
value: 2345,
|
||||
},
|
||||
}, d2)
|
||||
|
||||
delete(d2, "foo")
|
||||
assert.Equal(UserData{
|
||||
"baz": &s{
|
||||
value: 2345,
|
||||
},
|
||||
}, d2)
|
||||
|
||||
sid, found := d2.SessionId()
|
||||
assert.False(found, "expected no session id, got %s", sid)
|
||||
|
||||
d2["sessionid"] = "not-found"
|
||||
sid, found = d2.SessionId()
|
||||
assert.False(found, "expected no session id, got %s", sid)
|
||||
|
||||
d2["sessionId"] = "session-id"
|
||||
if sid, found = d2.SessionId(); assert.True(found) {
|
||||
assert.EqualValues("session-id", sid)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserDataList(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert := assert.New(t)
|
||||
|
||||
l := UserDataList{
|
||||
{
|
||||
"foo": "bar",
|
||||
},
|
||||
}
|
||||
|
||||
// Clone is a deep clone.
|
||||
l2 := l.Clone()
|
||||
assert.Equal(l, l2)
|
||||
|
||||
l[0]["bar"] = "baz"
|
||||
assert.NotEqual(l, l2)
|
||||
|
||||
m := l.Map()
|
||||
assert.Empty(m)
|
||||
|
||||
l[0]["sessionId"] = "session-id"
|
||||
if m := l.Map(); assert.Len(m, 1) {
|
||||
l3 := m.Users()
|
||||
assert.Equal(l, l3)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1688,7 +1688,9 @@ sent as `POST` request with proper checksum headers as described above.
|
|||
|
||||
### New users invited to room
|
||||
|
||||
This can be used to notify users that they are now invited to a room.
|
||||
This can be used to notify users that they are now invited to a room. Only
|
||||
sessions currently connected to the room (in addition to the invited users)
|
||||
will receive an event that they need to update the participant list.
|
||||
|
||||
Message format (Backend -> Server)
|
||||
|
||||
|
|
@ -1698,9 +1700,6 @@ Message format (Backend -> Server)
|
|||
"userids": [
|
||||
...list of user ids that are now invited to the room...
|
||||
],
|
||||
"alluserids": [
|
||||
...list of all user ids that invited to the room...
|
||||
],
|
||||
"properties": [
|
||||
...additional room properties...
|
||||
]
|
||||
|
|
@ -1711,6 +1710,8 @@ Message format (Backend -> Server)
|
|||
### Users no longer invited to room
|
||||
|
||||
This can be used to notify users that they are no longer invited to a room.
|
||||
Only sessions currently connected to the room (in addition to the disinvited
|
||||
users) will receive an event that they need to update the participant list.
|
||||
|
||||
Message format (Backend -> Server)
|
||||
|
||||
|
|
@ -1719,9 +1720,6 @@ Message format (Backend -> Server)
|
|||
"disinvite" {
|
||||
"userids": [
|
||||
...list of user ids that are no longer invited to the room...
|
||||
],
|
||||
"alluserids": [
|
||||
...list of all user ids that still invited to the room...
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1730,16 +1728,14 @@ Message format (Backend -> Server)
|
|||
### Room updated
|
||||
|
||||
This can be used to notify about changes to a room. The room properties are the
|
||||
same as described in section "Join room" above.
|
||||
same as described in section "Join room" above. Only sessions currently
|
||||
connected to the room will receive an event about the update.
|
||||
|
||||
Message format (Backend -> Server)
|
||||
|
||||
{
|
||||
"type": "update"
|
||||
"update" {
|
||||
"userids": [
|
||||
...list of user ids that are invited to the room...
|
||||
],
|
||||
"properties": [
|
||||
...additional room properties...
|
||||
]
|
||||
|
|
@ -1749,18 +1745,15 @@ Message format (Backend -> Server)
|
|||
|
||||
### Room deleted
|
||||
|
||||
This can be used to notify about a deleted room. All sessions currently
|
||||
connected to the room will leave the room.
|
||||
This can be used to notify about a deleted room. Only sessions currently
|
||||
connected to the room will get notified about the deletion and also leave
|
||||
the room.
|
||||
|
||||
Message format (Backend -> Server)
|
||||
|
||||
{
|
||||
"type": "delete"
|
||||
"delete" {
|
||||
"userids": [
|
||||
...list of user ids that were invited to the room...
|
||||
]
|
||||
}
|
||||
"delete" {}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1775,9 +1768,6 @@ Message format (Backend -> Server)
|
|||
"participants" {
|
||||
"changed": [
|
||||
...list of users that were changed...
|
||||
],
|
||||
"users": [
|
||||
...list of users in the room...
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -1795,9 +1785,6 @@ Message format (Backend -> Server)
|
|||
"incall": new-incall-state,
|
||||
"changed": [
|
||||
...list of users that were changed...
|
||||
],
|
||||
"users": [
|
||||
...list of users in the room...
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -380,27 +380,20 @@ func (b *BackendServer) sendRoomDisinvite(roomid string, backend *talk.Backend,
|
|||
defer cancel()
|
||||
var wg sync.WaitGroup
|
||||
for _, sessionid := range sessionids {
|
||||
if sessionid == sessionIdNotInMeeting {
|
||||
// Ignore entries that are no longer in the meeting.
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(sessionid api.RoomSessionId) {
|
||||
defer wg.Done()
|
||||
if sid, err := b.lookupByRoomSessionId(ctx, sessionid, nil); err != nil {
|
||||
b.logger.Printf("Could not lookup by room session %s: %s", sessionid, err)
|
||||
} else if sid != "" {
|
||||
if err := b.events.PublishSessionMessage(sid, backend, msg); err != nil {
|
||||
b.logger.Printf("Could not publish room disinvite for session %s: %s", sid, err)
|
||||
}
|
||||
b.asyncLookupByRoomSessionId(ctx, sessionid, &wg, func(sid api.PublicSessionId) {
|
||||
if sid == "" {
|
||||
return
|
||||
}
|
||||
}(sessionid)
|
||||
|
||||
if err := b.events.PublishSessionMessage(sid, backend, msg); err != nil {
|
||||
b.logger.Printf("Could not publish room disinvite for session %s: %s", sid, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (b *BackendServer) sendRoomUpdate(roomid string, backend *talk.Backend, notified_userids []string, all_userids []string, properties json.RawMessage) {
|
||||
func (b *BackendServer) sendRoomUpdate(roomid string, backend *talk.Backend, properties json.RawMessage) {
|
||||
msg := &events.AsyncMessage{
|
||||
Type: "message",
|
||||
Message: &api.ServerMessage{
|
||||
|
|
@ -415,34 +408,17 @@ func (b *BackendServer) sendRoomUpdate(roomid string, backend *talk.Backend, not
|
|||
},
|
||||
},
|
||||
}
|
||||
notified := make(map[string]bool)
|
||||
for _, userid := range notified_userids {
|
||||
notified[userid] = true
|
||||
}
|
||||
// Only send to users not notified otherwise.
|
||||
for _, userid := range all_userids {
|
||||
if notified[userid] {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := b.events.PublishUserMessage(userid, backend, msg); err != nil {
|
||||
b.logger.Printf("Could not publish room update for user %s in backend %s: %s", userid, backend.Id(), err)
|
||||
}
|
||||
if err := b.events.PublishRoomMessage(roomid, backend, msg); err != nil {
|
||||
b.logger.Printf("Could not publish room update for %s in backend %s: %s", roomid, backend.Id(), err)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *BackendServer) lookupByRoomSessionId(ctx context.Context, roomSessionId api.RoomSessionId, cache *container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId]) (api.PublicSessionId, error) {
|
||||
func (b *BackendServer) lookupByRoomSessionId(ctx context.Context, roomSessionId api.RoomSessionId) (api.PublicSessionId, error) {
|
||||
if roomSessionId == sessionIdNotInMeeting {
|
||||
b.logger.Printf("Trying to lookup empty room session id: %s", roomSessionId)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
if cache != nil {
|
||||
if result, found := cache.Get(roomSessionId); found {
|
||||
return result, nil
|
||||
}
|
||||
}
|
||||
|
||||
sid, err := b.roomSessions.LookupSessionId(ctx, roomSessionId, "")
|
||||
if err == ErrNoSuchRoomSession {
|
||||
return "", nil
|
||||
|
|
@ -450,54 +426,43 @@ func (b *BackendServer) lookupByRoomSessionId(ctx context.Context, roomSessionId
|
|||
return "", err
|
||||
}
|
||||
|
||||
if cache != nil {
|
||||
cache.Set(roomSessionId, sid)
|
||||
}
|
||||
return sid, nil
|
||||
}
|
||||
|
||||
func (b *BackendServer) fixupUserSessions(ctx context.Context, cache *container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId], users []api.StringMap) []api.StringMap {
|
||||
func (b *BackendServer) fixupUserSessions(ctx context.Context, users api.UserDataList) api.UserDataList {
|
||||
if len(users) == 0 {
|
||||
return users
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
for _, user := range users {
|
||||
roomSessionId, found := api.GetStringMapString[api.RoomSessionId](user, "sessionId")
|
||||
roomSessionId, found := user.SessionId()
|
||||
if !found {
|
||||
b.logger.Printf("User %+v has invalid room session id, ignoring", user)
|
||||
delete(user, "sessionId")
|
||||
continue
|
||||
}
|
||||
|
||||
if roomSessionId == sessionIdNotInMeeting {
|
||||
if api.RoomSessionId(roomSessionId) == sessionIdNotInMeeting {
|
||||
b.logger.Printf("User %+v is not in the meeting, ignoring", user)
|
||||
delete(user, "sessionId")
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(roomSessionId api.RoomSessionId, u api.StringMap) {
|
||||
defer wg.Done()
|
||||
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId, cache); err != nil {
|
||||
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
|
||||
delete(u, "sessionId")
|
||||
} else if sessionId != "" {
|
||||
u["sessionId"] = sessionId
|
||||
b.asyncLookupByRoomSessionId(ctx, api.RoomSessionId(roomSessionId), &wg, func(sessionId api.PublicSessionId) {
|
||||
if sessionId == "" {
|
||||
delete(user, "sessionId")
|
||||
} else {
|
||||
// sessionId == ""
|
||||
delete(u, "sessionId")
|
||||
user["sessionId"] = sessionId
|
||||
}
|
||||
}(roomSessionId, user)
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
result := make([]api.StringMap, 0, len(users))
|
||||
for _, user := range users {
|
||||
if _, found := user["sessionId"]; found {
|
||||
result = append(result, user)
|
||||
}
|
||||
}
|
||||
result := slices.DeleteFunc(users, func(user api.UserData) bool {
|
||||
_, found := user["sessionId"]
|
||||
return !found
|
||||
})
|
||||
return result
|
||||
}
|
||||
|
||||
|
|
@ -508,13 +473,10 @@ func (b *BackendServer) sendRoomIncall(roomid string, backend *talk.Backend, req
|
|||
ctx := log.NewLoggerContext(context.Background(), b.logger)
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
var cache container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId]
|
||||
// Convert (Nextcloud) session ids to signaling session ids.
|
||||
request.InCall.Users = b.fixupUserSessions(ctx, &cache, request.InCall.Users)
|
||||
// Entries in "Changed" are most likely already fetched through the "Users" list.
|
||||
request.InCall.Changed = b.fixupUserSessions(ctx, &cache, request.InCall.Changed)
|
||||
|
||||
if len(request.InCall.Users) == 0 && len(request.InCall.Changed) == 0 {
|
||||
// Convert (Nextcloud) session ids to signaling session ids.
|
||||
request.InCall.Changed = b.fixupUserSessions(ctx, request.InCall.Changed)
|
||||
if len(request.InCall.Changed) == 0 {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
@ -532,11 +494,9 @@ func (b *BackendServer) sendRoomParticipantsUpdate(ctx context.Context, roomid s
|
|||
// Convert (Nextcloud) session ids to signaling session ids.
|
||||
ctx, cancel := context.WithTimeout(ctx, timeout)
|
||||
defer cancel()
|
||||
var cache container.ConcurrentMap[api.RoomSessionId, api.PublicSessionId]
|
||||
request.Participants.Users = b.fixupUserSessions(ctx, &cache, request.Participants.Users)
|
||||
request.Participants.Changed = b.fixupUserSessions(ctx, &cache, request.Participants.Changed)
|
||||
|
||||
if len(request.Participants.Users) == 0 && len(request.Participants.Changed) == 0 {
|
||||
request.Participants.Changed = b.fixupUserSessions(ctx, request.Participants.Changed)
|
||||
if len(request.Participants.Changed) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -548,7 +508,7 @@ loop:
|
|||
continue
|
||||
}
|
||||
|
||||
sessionId, found := api.GetStringMapString[api.PublicSessionId](user, "sessionId")
|
||||
sessionId, found := user.SessionId()
|
||||
if !found {
|
||||
b.logger.Printf("User entry has no session id: %+v", user)
|
||||
continue
|
||||
|
|
@ -598,6 +558,24 @@ func (b *BackendServer) sendRoomMessage(roomid string, backend *talk.Backend, re
|
|||
return b.events.PublishBackendRoomMessage(roomid, backend, message)
|
||||
}
|
||||
|
||||
func (b *BackendServer) asyncLookupByRoomSessionId(ctx context.Context, roomSessionId api.RoomSessionId, wg *sync.WaitGroup, callback func(sessionId api.PublicSessionId)) {
|
||||
if roomSessionId == sessionIdNotInMeeting {
|
||||
return
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId); err != nil {
|
||||
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
|
||||
callback("")
|
||||
} else {
|
||||
callback(sessionId)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (b *BackendServer) sendRoomSwitchTo(ctx context.Context, roomid string, backend *talk.Backend, request *talk.BackendServerRoomRequest) error {
|
||||
timeout := time.Second
|
||||
|
||||
|
|
@ -621,21 +599,15 @@ func (b *BackendServer) sendRoomSwitchTo(ctx context.Context, roomid string, bac
|
|||
|
||||
var internalSessionsList talk.BackendRoomSwitchToPublicSessionsList
|
||||
for _, roomSessionId := range sessionsList {
|
||||
if roomSessionId == sessionIdNotInMeeting {
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(roomSessionId api.RoomSessionId) {
|
||||
defer wg.Done()
|
||||
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId, nil); err != nil {
|
||||
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
|
||||
} else if sessionId != "" {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
internalSessionsList = append(internalSessionsList, sessionId)
|
||||
b.asyncLookupByRoomSessionId(ctx, roomSessionId, &wg, func(sessionId api.PublicSessionId) {
|
||||
if sessionId == "" {
|
||||
return
|
||||
}
|
||||
}(roomSessionId)
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
internalSessionsList = append(internalSessionsList, sessionId)
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
|
|
@ -659,21 +631,15 @@ func (b *BackendServer) sendRoomSwitchTo(ctx context.Context, roomid string, bac
|
|||
|
||||
internalSessionsMap := make(talk.BackendRoomSwitchToPublicSessionsMap)
|
||||
for roomSessionId, details := range sessionsMap {
|
||||
if roomSessionId == sessionIdNotInMeeting {
|
||||
continue
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func(roomSessionId api.RoomSessionId, details json.RawMessage) {
|
||||
defer wg.Done()
|
||||
if sessionId, err := b.lookupByRoomSessionId(ctx, roomSessionId, nil); err != nil {
|
||||
b.logger.Printf("Could not lookup by room session %s: %s", roomSessionId, err)
|
||||
} else if sessionId != "" {
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
internalSessionsMap[sessionId] = details
|
||||
b.asyncLookupByRoomSessionId(ctx, roomSessionId, &wg, func(sessionId api.PublicSessionId) {
|
||||
if sessionId == "" {
|
||||
return
|
||||
}
|
||||
}(roomSessionId, details)
|
||||
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
internalSessionsMap[sessionId] = details
|
||||
})
|
||||
}
|
||||
wg.Wait()
|
||||
|
||||
|
|
@ -918,24 +884,24 @@ func (b *BackendServer) roomHandler(ctx context.Context, w http.ResponseWriter,
|
|||
switch request.Type {
|
||||
case "invite":
|
||||
b.sendRoomInvite(roomid, backend, request.Invite.UserIds, request.Invite.Properties)
|
||||
b.sendRoomUpdate(roomid, backend, request.Invite.UserIds, request.Invite.AllUserIds, request.Invite.Properties)
|
||||
b.sendRoomUpdate(roomid, backend, request.Invite.Properties)
|
||||
case "disinvite":
|
||||
b.sendRoomUpdate(roomid, backend, request.Disinvite.Properties)
|
||||
b.sendRoomDisinvite(roomid, backend, api.DisinviteReasonDisinvited, request.Disinvite.UserIds, request.Disinvite.SessionIds)
|
||||
b.sendRoomUpdate(roomid, backend, request.Disinvite.UserIds, request.Disinvite.AllUserIds, request.Disinvite.Properties)
|
||||
case "update":
|
||||
message := &events.AsyncMessage{
|
||||
Type: "room",
|
||||
Room: &request,
|
||||
}
|
||||
err = b.events.PublishBackendRoomMessage(roomid, backend, message)
|
||||
b.sendRoomUpdate(roomid, backend, nil, request.Update.UserIds, request.Update.Properties)
|
||||
b.sendRoomUpdate(roomid, backend, request.Update.Properties)
|
||||
case "delete":
|
||||
// Notify the backend about the room deletion.
|
||||
message := &events.AsyncMessage{
|
||||
Type: "room",
|
||||
Room: &request,
|
||||
}
|
||||
err = b.events.PublishBackendRoomMessage(roomid, backend, message)
|
||||
b.sendRoomDisinvite(roomid, backend, api.DisinviteReasonDeleted, request.Delete.UserIds, nil)
|
||||
case "incall":
|
||||
err = b.sendRoomIncall(roomid, backend, &request)
|
||||
case "participants":
|
||||
|
|
|
|||
|
|
@ -249,34 +249,44 @@ func performBackendRequest(requestUrl string, body []byte) (*http.Response, erro
|
|||
return client.Do(request)
|
||||
}
|
||||
|
||||
func expectRoomlistEvent(t *testing.T, ch events.AsyncChannel, msgType string) (*api.EventServerMessage, bool) {
|
||||
func expectAsyncMessage(t *testing.T, ch events.AsyncChannel) (*events.AsyncMessage, bool) {
|
||||
assert := assert.New(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
|
||||
defer cancel()
|
||||
select {
|
||||
case natsMsg := <-ch:
|
||||
var message events.AsyncMessage
|
||||
if !assert.NoError(nats.Decode(natsMsg, &message)) ||
|
||||
!assert.Equal("message", message.Type, "invalid message type, got %+v", message) ||
|
||||
!assert.NotNil(message.Message, "message missing, got %+v", message) {
|
||||
if !assert.NoError(nats.Decode(natsMsg, &message)) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
msg := message.Message
|
||||
if !assert.Equal("event", msg.Type, "invalid message type, got %+v", msg) ||
|
||||
!assert.NotNil(msg.Event, "event missing, got %+v", msg) ||
|
||||
!assert.Equal("roomlist", msg.Event.Target, "invalid event target, got %+v", msg.Event) ||
|
||||
!assert.Equal(msgType, msg.Event.Type, "invalid event type, got %+v", msg.Event) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return msg.Event, true
|
||||
return &message, true
|
||||
case <-ctx.Done():
|
||||
assert.NoError(ctx.Err())
|
||||
return nil, false
|
||||
}
|
||||
}
|
||||
|
||||
func expectRoomlistEvent(t *testing.T, ch events.AsyncChannel, msgType string) (*api.EventServerMessage, bool) {
|
||||
assert := assert.New(t)
|
||||
message, ok := expectAsyncMessage(t, ch)
|
||||
if !ok ||
|
||||
!assert.Equal("message", message.Type, "invalid message type, got %+v", message) ||
|
||||
!assert.NotNil(message.Message, "message missing, got %+v", message) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
msg := message.Message
|
||||
if !assert.Equal("event", msg.Type, "invalid message type, got %+v", msg) ||
|
||||
!assert.NotNil(msg.Event, "event missing, got %+v", msg) ||
|
||||
!assert.Equal("roomlist", msg.Event.Target, "invalid event target, got %+v", msg.Event) ||
|
||||
!assert.Equal(msgType, msg.Event.Type, "invalid event type, got %+v", msg.Event) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
return msg.Event, true
|
||||
}
|
||||
|
||||
func TestBackendServer_NoAuth(t *testing.T) {
|
||||
t.Parallel()
|
||||
require := require.New(t)
|
||||
|
|
@ -336,9 +346,6 @@ func TestBackendServer_OldCompatAuth(t *testing.T) {
|
|||
UserIds: []string{
|
||||
userid,
|
||||
},
|
||||
AllUserIds: []string{
|
||||
userid,
|
||||
},
|
||||
Properties: roomProperties,
|
||||
},
|
||||
}
|
||||
|
|
@ -447,9 +454,6 @@ func RunTestBackendServer_RoomInvite(ctx context.Context, t *testing.T) {
|
|||
UserIds: []string{
|
||||
userid,
|
||||
},
|
||||
AllUserIds: []string{
|
||||
userid,
|
||||
},
|
||||
Properties: roomProperties,
|
||||
},
|
||||
}
|
||||
|
|
@ -525,9 +529,8 @@ func RunTestBackendServer_RoomDisinvite(ctx context.Context, t *testing.T) {
|
|||
testDefaultUserId,
|
||||
},
|
||||
SessionIds: []api.RoomSessionId{
|
||||
api.RoomSessionId(fmt.Sprintf("%s-%s"+roomId, hello.Hello.SessionId)),
|
||||
api.RoomSessionId(fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId)),
|
||||
},
|
||||
AllUserIds: []string{},
|
||||
Properties: roomProperties,
|
||||
},
|
||||
}
|
||||
|
|
@ -547,11 +550,21 @@ func RunTestBackendServer_RoomDisinvite(ctx context.Context, t *testing.T) {
|
|||
assert.Empty(string(event.Disinvite.Properties))
|
||||
}
|
||||
|
||||
if message, ok := client.RunUntilRoomlistDisinvite(ctx); ok {
|
||||
if message, ok := client.RunUntilRoomlistUpdate(ctx); ok {
|
||||
assert.Equal(roomId, message.RoomId)
|
||||
}
|
||||
|
||||
client.RunUntilClosed(ctx)
|
||||
if message, ok := client.RunUntilRoomlistDisinvite(ctx); ok {
|
||||
assert.Equal(roomId, message.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDisinvited, message.Reason)
|
||||
}
|
||||
if message, ok := client.RunUntilMessageOrClosed(ctx); ok && message != nil {
|
||||
// The client might receive a second disinvite message as both the userid and the session id were disinvited.
|
||||
if message, ok := checkMessageRoomlistDisinvite(t, message); ok {
|
||||
assert.Equal(roomId, message.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDisinvited, message.Reason)
|
||||
}
|
||||
client.RunUntilClosed(ctx)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBackendServer_RoomDisinviteDifferentRooms(t *testing.T) {
|
||||
|
|
@ -585,9 +598,8 @@ func TestBackendServer_RoomDisinviteDifferentRooms(t *testing.T) {
|
|||
testDefaultUserId,
|
||||
},
|
||||
SessionIds: []api.RoomSessionId{
|
||||
api.RoomSessionId(fmt.Sprintf("%s-%s"+roomId1, hello1.Hello.SessionId)),
|
||||
api.RoomSessionId(fmt.Sprintf("%s-%s", roomId1, hello1.Hello.SessionId)),
|
||||
},
|
||||
AllUserIds: []string{},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -600,22 +612,30 @@ func TestBackendServer_RoomDisinviteDifferentRooms(t *testing.T) {
|
|||
assert.NoError(err)
|
||||
assert.Equal(http.StatusOK, res.StatusCode, "Expected successful request, got %s", string(body))
|
||||
|
||||
if message, ok := client1.RunUntilRoomlistDisinvite(ctx); ok {
|
||||
if message, ok := client1.RunUntilRoomlistUpdate(ctx); ok {
|
||||
assert.Equal(roomId1, message.RoomId)
|
||||
}
|
||||
|
||||
client1.RunUntilClosed(ctx)
|
||||
if message, ok := client1.RunUntilRoomlistDisinvite(ctx); ok {
|
||||
assert.Equal(roomId1, message.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDisinvited, message.Reason)
|
||||
}
|
||||
if message, ok := client1.RunUntilMessageOrClosed(ctx); ok && message != nil {
|
||||
// The client might receive a second disinvite message as both the userid and the session id were disinvited.
|
||||
if message, ok := checkMessageRoomlistDisinvite(t, message); ok {
|
||||
assert.Equal(roomId1, message.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDisinvited, message.Reason)
|
||||
}
|
||||
client1.RunUntilClosed(ctx)
|
||||
}
|
||||
|
||||
if message, ok := client2.RunUntilRoomlistDisinvite(ctx); ok {
|
||||
assert.Equal(roomId1, message.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDisinvited, message.Reason)
|
||||
}
|
||||
|
||||
msg = &talk.BackendServerRoomRequest{
|
||||
Type: "update",
|
||||
Update: &talk.BackendRoomUpdateRequest{
|
||||
UserIds: []string{
|
||||
testDefaultUserId,
|
||||
},
|
||||
Properties: testRoomProperties,
|
||||
},
|
||||
}
|
||||
|
|
@ -634,6 +654,62 @@ func TestBackendServer_RoomDisinviteDifferentRooms(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestBackendServer_RoomDisinviteClustered(t *testing.T) {
|
||||
t.Parallel()
|
||||
logger := logtest.NewLoggerForTest(t)
|
||||
ctx := log.NewLoggerContext(t.Context(), logger)
|
||||
require := require.New(t)
|
||||
assert := assert.New(t)
|
||||
_, _, hub1, hub2, server1, server2 := CreateBackendServerWithClusteringForTest(t)
|
||||
|
||||
ctx, cancel := context.WithTimeout(ctx, testTimeout)
|
||||
defer cancel()
|
||||
|
||||
client1, hello1 := NewTestClientWithHello(ctx, t, server1, hub1, testDefaultUserId+"1")
|
||||
defer client1.CloseWithBye()
|
||||
client2, hello2 := NewTestClientWithHello(ctx, t, server2, hub2, testDefaultUserId+"2")
|
||||
defer client2.CloseWithBye()
|
||||
|
||||
// Join room by id.
|
||||
roomId := "test-room1"
|
||||
MustSucceed2(t, client1.JoinRoom, ctx, roomId)
|
||||
MustSucceed2(t, client2.JoinRoom, ctx, roomId)
|
||||
WaitForUsersJoined(ctx, t, client1, hello1, client2, hello2)
|
||||
|
||||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "disinvite",
|
||||
Disinvite: &talk.BackendRoomDisinviteRequest{
|
||||
SessionIds: []api.RoomSessionId{
|
||||
api.RoomSessionId(fmt.Sprintf("%s-%s", roomId, hello2.Hello.SessionId)),
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
require.NoError(err)
|
||||
res, err := performBackendRequest(server1.URL+"/api/v1/room/"+roomId, data)
|
||||
require.NoError(err)
|
||||
defer res.Body.Close()
|
||||
body, err := io.ReadAll(res.Body)
|
||||
assert.NoError(err)
|
||||
assert.Equal(http.StatusOK, res.StatusCode, "Expected successful request, got %s", string(body))
|
||||
|
||||
if message, ok := client1.RunUntilRoomlistUpdate(ctx); ok {
|
||||
assert.Equal(roomId, message.RoomId)
|
||||
}
|
||||
|
||||
if message, ok := client2.RunUntilRoomlistUpdate(ctx); ok {
|
||||
assert.Equal(roomId, message.RoomId)
|
||||
}
|
||||
if message, ok := client2.RunUntilRoomlistDisinvite(ctx); ok {
|
||||
assert.Equal(roomId, message.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDisinvited, message.Reason)
|
||||
}
|
||||
client2.RunUntilClosed(ctx)
|
||||
|
||||
client1.RunUntilLeft(ctx, hello2.Hello)
|
||||
}
|
||||
|
||||
func TestBackendServer_RoomUpdate(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, backend := range eventstest.EventBackendsForTest {
|
||||
|
|
@ -662,24 +738,20 @@ func RunTestBackendServer_RoomUpdate(ctx context.Context, t *testing.T) {
|
|||
require.NoError(err, "Could not create room")
|
||||
defer room.Close()
|
||||
|
||||
userid := "test-userid"
|
||||
roomProperties := json.RawMessage("{\"foo\":\"bar\"}")
|
||||
|
||||
eventsChan := make(events.AsyncChannel, 1)
|
||||
listener := &channelEventListener{
|
||||
ch: eventsChan,
|
||||
}
|
||||
require.NoError(asyncEvents.RegisterUserListener(userid, backend, listener))
|
||||
require.NoError(asyncEvents.RegisterRoomListener(roomId, backend, listener))
|
||||
defer func() {
|
||||
assert.NoError(asyncEvents.UnregisterUserListener(userid, backend, listener))
|
||||
assert.NoError(asyncEvents.UnregisterRoomListener(roomId, backend, listener))
|
||||
}()
|
||||
|
||||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "update",
|
||||
Update: &talk.BackendRoomUpdateRequest{
|
||||
UserIds: []string{
|
||||
userid,
|
||||
},
|
||||
Properties: roomProperties,
|
||||
},
|
||||
}
|
||||
|
|
@ -733,23 +805,18 @@ func RunTestBackendServer_RoomDelete(ctx context.Context, t *testing.T) {
|
|||
_, err = hub.CreateRoom(roomId, emptyProperties, backend)
|
||||
require.NoError(err)
|
||||
|
||||
userid := "test-userid"
|
||||
eventsChan := make(events.AsyncChannel, 1)
|
||||
listener := &channelEventListener{
|
||||
ch: eventsChan,
|
||||
}
|
||||
require.NoError(asyncEvents.RegisterUserListener(userid, backend, listener))
|
||||
require.NoError(asyncEvents.RegisterBackendRoomListener(roomId, backend, listener))
|
||||
defer func() {
|
||||
assert.NoError(asyncEvents.UnregisterUserListener(userid, backend, listener))
|
||||
assert.NoError(asyncEvents.UnregisterBackendRoomListener(roomId, backend, listener))
|
||||
}()
|
||||
|
||||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "delete",
|
||||
Delete: &talk.BackendRoomDeleteRequest{
|
||||
UserIds: []string{
|
||||
userid,
|
||||
},
|
||||
},
|
||||
Type: "delete",
|
||||
Delete: &talk.BackendRoomDeleteRequest{},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
|
|
@ -761,11 +828,12 @@ func RunTestBackendServer_RoomDelete(ctx context.Context, t *testing.T) {
|
|||
assert.NoError(err)
|
||||
assert.Equal(http.StatusOK, res.StatusCode, "Expected successful request, got %s", string(body))
|
||||
|
||||
// A deleted room is signalled as a "disinvite" event.
|
||||
if event, ok := expectRoomlistEvent(t, eventsChan, "disinvite"); ok && assert.NotNil(event.Disinvite) {
|
||||
assert.Equal(roomId, event.Disinvite.RoomId)
|
||||
assert.Empty(event.Disinvite.Properties)
|
||||
assert.Equal("deleted", event.Disinvite.Reason)
|
||||
// A deleted room is signalled as a backend room event.
|
||||
if message, ok := expectAsyncMessage(t, eventsChan); ok {
|
||||
assert.Equal("room", message.Type)
|
||||
if assert.NotNil(message.Room) {
|
||||
assert.Equal("delete", message.Room.Type)
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Use event to wait for asynchronous messages.
|
||||
|
|
@ -832,17 +900,7 @@ func TestBackendServer_ParticipantsUpdatePermissions(t *testing.T) {
|
|||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "participants",
|
||||
Participants: &talk.BackendRoomParticipantsRequest{
|
||||
Changed: []api.StringMap{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_MEDIA},
|
||||
},
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello2.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_SCREEN},
|
||||
},
|
||||
},
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_MEDIA},
|
||||
|
|
@ -910,13 +968,7 @@ func TestBackendServer_ParticipantsUpdateEmptyPermissions(t *testing.T) {
|
|||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "participants",
|
||||
Participants: &talk.BackendRoomParticipantsRequest{
|
||||
Changed: []api.StringMap{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId),
|
||||
"permissions": []api.Permission{},
|
||||
},
|
||||
},
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId),
|
||||
"permissions": []api.Permission{},
|
||||
|
|
@ -979,17 +1031,7 @@ func TestBackendServer_ParticipantsUpdateTimeout(t *testing.T) {
|
|||
Type: "incall",
|
||||
InCall: &talk.BackendRoomInCallRequest{
|
||||
InCall: json.RawMessage("7"),
|
||||
Changed: []api.StringMap{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId),
|
||||
"inCall": 7,
|
||||
},
|
||||
{
|
||||
"sessionId": "unknown-room-session-id",
|
||||
"inCall": 3,
|
||||
},
|
||||
},
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId),
|
||||
"inCall": 7,
|
||||
|
|
@ -1026,17 +1068,7 @@ func TestBackendServer_ParticipantsUpdateTimeout(t *testing.T) {
|
|||
Type: "incall",
|
||||
InCall: &talk.BackendRoomInCallRequest{
|
||||
InCall: json.RawMessage("7"),
|
||||
Changed: []api.StringMap{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId),
|
||||
"inCall": 7,
|
||||
},
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello2.Hello.SessionId),
|
||||
"inCall": 3,
|
||||
},
|
||||
},
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello1.Hello.SessionId),
|
||||
"inCall": 7,
|
||||
|
|
|
|||
|
|
@ -650,7 +650,7 @@ func (c *FederationClient) joinRoom() error {
|
|||
})
|
||||
}
|
||||
|
||||
func (c *FederationClient) updateActor(u api.StringMap, actorIdKey, actorTypeKey string, localCloudUrl string, remoteCloudUrl string) (changed bool) {
|
||||
func (c *FederationClient) updateActor(u api.UserData, actorIdKey, actorTypeKey string, localCloudUrl string, remoteCloudUrl string) (changed bool) {
|
||||
if actorType, found := api.GetStringMapEntry[string](u, actorTypeKey); found {
|
||||
if actorId, found := api.GetStringMapEntry[string](u, actorIdKey); found {
|
||||
switch actorType {
|
||||
|
|
@ -726,7 +726,7 @@ func (c *FederationClient) updateComment(comment api.StringMap, localCloudUrl st
|
|||
return changed
|
||||
}
|
||||
|
||||
func (c *FederationClient) updateEventUsers(users []api.StringMap, localSessionId api.PublicSessionId, remoteSessionId api.PublicSessionId) {
|
||||
func (c *FederationClient) updateEventUsers(users api.UserDataList, localSessionId api.PublicSessionId, remoteSessionId api.PublicSessionId) {
|
||||
localCloudUrl := "@" + getCloudUrl(c.session.BackendUrl())
|
||||
remoteCloudUrl := "@" + getCloudUrl(c.federation.Load().NextcloudUrl)
|
||||
checkSessionId := true
|
||||
|
|
|
|||
|
|
@ -359,21 +359,25 @@ func Test_Federation(t *testing.T) {
|
|||
"actorType": "federated_users",
|
||||
},
|
||||
}
|
||||
room.PublishUsersInCallChanged(users, users)
|
||||
room.PublishUsersInCallChanged(users)
|
||||
var event *api.EventServerMessage
|
||||
// For the local user, it's a federated user on server 2 that joined.
|
||||
if checkReceiveClientEvent(ctx, t, client1, "update", &event) {
|
||||
assert.EqualValues(remoteSessionId, event.Update.Users[0]["sessionId"])
|
||||
assert.Equal("remoteUser@"+strings.TrimPrefix(server2.URL, "http://"), event.Update.Users[0]["actorId"])
|
||||
assert.Equal("federated_users", event.Update.Users[0]["actorType"])
|
||||
assert.Equal(roomId, event.Update.RoomId)
|
||||
if assert.Len(event.Update.Users, 1) {
|
||||
assert.EqualValues(remoteSessionId, event.Update.Users[0]["sessionId"])
|
||||
assert.Equal("remoteUser@"+strings.TrimPrefix(server2.URL, "http://"), event.Update.Users[0]["actorId"])
|
||||
assert.Equal("federated_users", event.Update.Users[0]["actorType"])
|
||||
}
|
||||
}
|
||||
// For the federated user, it's a local user that joined.
|
||||
if checkReceiveClientEvent(ctx, t, client2, "update", &event) {
|
||||
assert.EqualValues(hello2.Hello.SessionId, event.Update.Users[0]["sessionId"])
|
||||
assert.Equal("remoteUser", event.Update.Users[0]["actorId"])
|
||||
assert.Equal("users", event.Update.Users[0]["actorType"])
|
||||
assert.Equal(federatedRoomId, event.Update.RoomId)
|
||||
if assert.Len(event.Update.Users, 1) {
|
||||
assert.EqualValues(hello2.Hello.SessionId, event.Update.Users[0]["sessionId"])
|
||||
assert.Equal("remoteUser", event.Update.Users[0]["actorId"])
|
||||
assert.Equal("users", event.Update.Users[0]["actorType"])
|
||||
}
|
||||
}
|
||||
|
||||
// Simulate request from the backend that a local user joined the call.
|
||||
|
|
@ -385,20 +389,42 @@ func Test_Federation(t *testing.T) {
|
|||
"actorType": "users",
|
||||
},
|
||||
}
|
||||
room.PublishUsersInCallChanged(users, users)
|
||||
room.PublishUsersInCallChanged(users)
|
||||
// For the local user, it's a local user that joined.
|
||||
if checkReceiveClientEvent(ctx, t, client1, "update", &event) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, event.Update.Users[0]["sessionId"])
|
||||
assert.Equal("localUser", event.Update.Users[0]["actorId"])
|
||||
assert.Equal("users", event.Update.Users[0]["actorType"])
|
||||
assert.Equal(roomId, event.Update.RoomId)
|
||||
if assert.Len(event.Update.Users, 2) {
|
||||
users := event.Update.Users.Map()
|
||||
if user := users[hello1.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello1.Hello.SessionId, event) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, user["sessionId"])
|
||||
assert.Equal("localUser", user["actorId"])
|
||||
assert.Equal("users", user["actorType"])
|
||||
}
|
||||
|
||||
if user := users[remoteSessionId]; assert.NotNil(user, "expected %s, got %+v", remoteSessionId, event) {
|
||||
assert.EqualValues(remoteSessionId, user["sessionId"])
|
||||
assert.Equal("remoteUser@"+strings.TrimPrefix(server2.URL, "http://"), user["actorId"])
|
||||
assert.Equal("federated_users", user["actorType"])
|
||||
}
|
||||
}
|
||||
}
|
||||
// For the federated user, it's a federated user on server 1 that joined.
|
||||
if checkReceiveClientEvent(ctx, t, client2, "update", &event) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, event.Update.Users[0]["sessionId"])
|
||||
assert.Equal("localUser@"+strings.TrimPrefix(server1.URL, "http://"), event.Update.Users[0]["actorId"])
|
||||
assert.Equal("federated_users", event.Update.Users[0]["actorType"])
|
||||
assert.Equal(federatedRoomId, event.Update.RoomId)
|
||||
if assert.Len(event.Update.Users, 2) {
|
||||
users := event.Update.Users.Map()
|
||||
if user := users[hello1.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello1.Hello.SessionId, event) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, user["sessionId"])
|
||||
assert.Equal("localUser@"+strings.TrimPrefix(server1.URL, "http://"), user["actorId"])
|
||||
assert.Equal("federated_users", user["actorType"])
|
||||
}
|
||||
|
||||
if user := users[hello2.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello2.Hello.SessionId, event) {
|
||||
assert.EqualValues(hello2.Hello.SessionId, user["sessionId"])
|
||||
assert.Equal("remoteUser", user["actorId"])
|
||||
assert.Equal("users", user["actorType"])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Joining another "direct" session will trigger correct events.
|
||||
|
|
|
|||
|
|
@ -3101,8 +3101,26 @@ func (h *Hub) processRoomDeleted(message *talk.BackendServerRoomRequest) {
|
|||
}
|
||||
|
||||
sessions := room.Close()
|
||||
if len(sessions) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
msg := &api.ServerMessage{
|
||||
Type: "event",
|
||||
Event: &api.EventServerMessage{
|
||||
Target: "roomlist",
|
||||
Type: "disinvite",
|
||||
Disinvite: &api.RoomDisinviteEventServerMessage{
|
||||
RoomEventServerMessage: api.RoomEventServerMessage{
|
||||
RoomId: message.RoomId,
|
||||
},
|
||||
Reason: api.DisinviteReasonDeleted,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, session := range sessions {
|
||||
// The session is no longer in the room
|
||||
session.SendMessage(msg)
|
||||
session.LeaveRoom(true)
|
||||
switch sess := session.(type) {
|
||||
case *ClientSession:
|
||||
|
|
@ -3135,7 +3153,7 @@ func (h *Hub) processRoomInCallChanged(message *talk.BackendServerRoomRequest) {
|
|||
|
||||
room.PublishUsersInCallChangedAll(flags)
|
||||
} else {
|
||||
room.PublishUsersInCallChanged(message.InCall.Changed, message.InCall.Users)
|
||||
room.PublishUsersInCallChanged(message.InCall.Changed)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -3145,7 +3163,7 @@ func (h *Hub) processRoomParticipants(message *talk.BackendServerRoomRequest) {
|
|||
return
|
||||
}
|
||||
|
||||
room.PublishUsersChanged(message.Participants.Changed, message.Participants.Users)
|
||||
room.PublishUsersChanged(message.Participants.Changed)
|
||||
}
|
||||
|
||||
func (h *Hub) GetStats() api.StringMap {
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ func Test_JanusSubscriberNoSuchRoom(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users1, users1)
|
||||
room.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -275,7 +275,7 @@ func test_JanusSubscriberAlreadyJoined(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users1, users1)
|
||||
room.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -390,7 +390,7 @@ func Test_JanusSubscriberTimeout(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users1, users1)
|
||||
room.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -498,7 +498,7 @@ func Test_JanusSubscriberCloseEmptyStreams(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users1, users1)
|
||||
room.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -612,7 +612,7 @@ func Test_JanusSubscriberRoomDestroyed(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users1, users1)
|
||||
room.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -726,7 +726,7 @@ func Test_JanusSubscriberUpdateOffer(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users1, users1)
|
||||
room.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
|
|||
|
|
@ -1820,7 +1820,7 @@ func TestClientHelloResumeProxy(t *testing.T) { // nolint:paralleltest
|
|||
"inCall": 1,
|
||||
},
|
||||
}
|
||||
room.PublishUsersInCallChanged(users, users)
|
||||
room.PublishUsersInCallChanged(users)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
})
|
||||
})
|
||||
|
|
@ -2447,7 +2447,7 @@ func TestClientMessageToCall(t *testing.T) {
|
|||
}
|
||||
room1 := hub1.getRoom(roomId)
|
||||
require.NotNil(room1, "Could not find room %s", roomId)
|
||||
room1.PublishUsersInCallChanged(users, users)
|
||||
room1.PublishUsersInCallChanged(users)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -2484,7 +2484,7 @@ func TestClientMessageToCall(t *testing.T) {
|
|||
}
|
||||
room2 := hub2.getRoom(roomId)
|
||||
require.NotNil(room2, "Could not find room %s", roomId)
|
||||
room2.PublishUsersInCallChanged(users, users)
|
||||
room2.PublishUsersInCallChanged(users)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -2552,7 +2552,7 @@ func TestClientControlToCall(t *testing.T) {
|
|||
}
|
||||
room1 := hub1.getRoom(roomId)
|
||||
require.NotNil(room1, "Could not find room %s", roomId)
|
||||
room1.PublishUsersInCallChanged(users, users)
|
||||
room1.PublishUsersInCallChanged(users)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -2589,7 +2589,7 @@ func TestClientControlToCall(t *testing.T) {
|
|||
}
|
||||
room2 := hub2.getRoom(roomId)
|
||||
require.NotNil(room2, "Could not find room %s", roomId)
|
||||
room2.PublishUsersInCallChanged(users, users)
|
||||
room2.PublishUsersInCallChanged(users)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -3239,13 +3239,13 @@ func TestRoomParticipantsListUpdateWhileDisconnected(t *testing.T) {
|
|||
}
|
||||
room := hub.getRoom(roomId)
|
||||
require.NotNil(room, "Could not find room %s", roomId)
|
||||
room.PublishUsersInCallChanged(users, users)
|
||||
room.PublishUsersInCallChanged(users)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
client2.Close()
|
||||
assert.NoError(client2.WaitForClientRemoved(ctx))
|
||||
|
||||
room.PublishUsersInCallChanged(users, users)
|
||||
room.PublishUsersInCallChanged(users)
|
||||
|
||||
// Give asynchronous events some time to be processed.
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
|
@ -3579,13 +3579,7 @@ func TestClientSendOfferPermissionsAudioVideo(t *testing.T) {
|
|||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "participants",
|
||||
Participants: &talk.BackendRoomParticipantsRequest{
|
||||
Changed: []api.StringMap{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_AUDIO},
|
||||
},
|
||||
},
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_AUDIO},
|
||||
|
|
@ -3676,13 +3670,7 @@ func TestClientSendOfferPermissionsAudioVideoMedia(t *testing.T) {
|
|||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "participants",
|
||||
Participants: &talk.BackendRoomParticipantsRequest{
|
||||
Changed: []api.StringMap{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_MEDIA, api.PERMISSION_MAY_CONTROL},
|
||||
},
|
||||
},
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": fmt.Sprintf("%s-%s", roomId, hello.Hello.SessionId),
|
||||
"permissions": []api.Permission{api.PERMISSION_MAY_PUBLISH_MEDIA, api.PERMISSION_MAY_CONTROL},
|
||||
|
|
@ -3822,7 +3810,7 @@ func TestClientRequestOfferNotInRoom(t *testing.T) {
|
|||
}
|
||||
room2 := hub2.getRoom(roomId)
|
||||
require.NotNil(room2, "Could not find room %s", roomId)
|
||||
room2.PublishUsersInCallChanged(users1, users1)
|
||||
room2.PublishUsersInCallChanged(users1)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -3848,7 +3836,7 @@ func TestClientRequestOfferNotInRoom(t *testing.T) {
|
|||
}
|
||||
room1 := hub1.getRoom(roomId)
|
||||
require.NotNil(room1, "Could not find room %s", roomId)
|
||||
room1.PublishUsersInCallChanged(users2, users2)
|
||||
room1.PublishUsersInCallChanged(users2)
|
||||
checkReceiveClientEvent(ctx, t, client1, "update", nil)
|
||||
checkReceiveClientEvent(ctx, t, client2, "update", nil)
|
||||
|
||||
|
|
@ -4676,7 +4664,7 @@ func TestDuplicateVirtualSessions(t *testing.T) {
|
|||
Type: "incall",
|
||||
InCall: &talk.BackendRoomInCallRequest{
|
||||
InCall: []byte("0"),
|
||||
Users: []api.StringMap{
|
||||
Changed: api.UserDataList{
|
||||
{
|
||||
"sessionId": virtualSession.PublicId(),
|
||||
"participantPermissions": 246,
|
||||
|
|
@ -4706,20 +4694,27 @@ func TestDuplicateVirtualSessions(t *testing.T) {
|
|||
if msg, ok := client1.RunUntilMessage(ctx); ok {
|
||||
if msg, ok := checkMessageParticipantsInCall(t, msg); ok {
|
||||
if assert.Len(msg.Users, 3) {
|
||||
assert.Equal(true, msg.Users[0]["virtual"], "%+v", msg)
|
||||
assert.EqualValues(virtualSession.PublicId(), msg.Users[0]["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithPhone, msg.Users[0]["inCall"], "%+v", msg)
|
||||
assert.EqualValues(246, msg.Users[0]["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(4, msg.Users[0]["participantType"], "%+v", msg)
|
||||
users := msg.Users.Map()
|
||||
if user := users[virtualSession.PublicId()]; assert.NotNil(user, "expected %s, got %+v", virtualSession.PublicId(), msg) {
|
||||
assert.Equal(true, user["virtual"], "%+v", msg)
|
||||
assert.EqualValues(virtualSession.PublicId(), user["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithPhone, user["inCall"], "%+v", msg)
|
||||
assert.EqualValues(246, user["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(4, user["participantType"], "%+v", msg)
|
||||
}
|
||||
|
||||
assert.EqualValues(hello1.Hello.SessionId, msg.Users[1]["sessionId"], "%+v", msg)
|
||||
assert.Nil(msg.Users[1]["inCall"], "%+v", msg)
|
||||
assert.EqualValues(254, msg.Users[1]["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(1, msg.Users[1]["participantType"], "%+v", msg)
|
||||
if user := users[hello1.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello1.Hello.SessionId, msg) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, user["sessionId"], "%+v", msg)
|
||||
assert.Nil(user["inCall"], "%+v", msg)
|
||||
assert.EqualValues(254, user["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(1, user["participantType"], "%+v", msg)
|
||||
}
|
||||
|
||||
assert.Equal(true, msg.Users[2]["internal"], "%+v", msg)
|
||||
assert.EqualValues(hello2.Hello.SessionId, msg.Users[2]["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithAudio, msg.Users[2]["inCall"], "%+v", msg)
|
||||
if user := users[hello2.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello2.Hello.SessionId, msg) {
|
||||
assert.Equal(true, user["internal"], "%+v", msg)
|
||||
assert.EqualValues(hello2.Hello.SessionId, user["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithAudio, user["inCall"], "%+v", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4727,20 +4722,27 @@ func TestDuplicateVirtualSessions(t *testing.T) {
|
|||
if msg, ok := client2.RunUntilMessage(ctx); ok {
|
||||
if msg, ok := checkMessageParticipantsInCall(t, msg); ok {
|
||||
if assert.Len(msg.Users, 3) {
|
||||
assert.Equal(true, msg.Users[0]["virtual"], "%+v", msg)
|
||||
assert.EqualValues(virtualSession.PublicId(), msg.Users[0]["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithPhone, msg.Users[0]["inCall"], "%+v", msg)
|
||||
assert.EqualValues(246, msg.Users[0]["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(4, msg.Users[0]["participantType"], "%+v", msg)
|
||||
users := msg.Users.Map()
|
||||
if user := users[virtualSession.PublicId()]; assert.NotNil(user, "expected %s, got %+v", virtualSession.PublicId(), msg) {
|
||||
assert.Equal(true, user["virtual"], "%+v", msg)
|
||||
assert.EqualValues(virtualSession.PublicId(), user["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithPhone, user["inCall"], "%+v", msg)
|
||||
assert.EqualValues(246, user["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(4, user["participantType"], "%+v", msg)
|
||||
}
|
||||
|
||||
assert.EqualValues(hello1.Hello.SessionId, msg.Users[1]["sessionId"], "%+v", msg)
|
||||
assert.Nil(msg.Users[1]["inCall"], "%+v", msg)
|
||||
assert.EqualValues(254, msg.Users[1]["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(1, msg.Users[1]["participantType"], "%+v", msg)
|
||||
if user := users[hello1.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello1.Hello.SessionId, msg) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, user["sessionId"], "%+v", msg)
|
||||
assert.Nil(user["inCall"], "%+v", msg)
|
||||
assert.EqualValues(254, user["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(1, user["participantType"], "%+v", msg)
|
||||
}
|
||||
|
||||
assert.Equal(true, msg.Users[2]["internal"], "%+v", msg)
|
||||
assert.EqualValues(hello2.Hello.SessionId, msg.Users[2]["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithAudio, msg.Users[2]["inCall"], "%+v", msg)
|
||||
if user := users[hello2.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello2.Hello.SessionId, msg) {
|
||||
assert.Equal(true, user["internal"], "%+v", msg)
|
||||
assert.EqualValues(hello2.Hello.SessionId, user["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithAudio, user["inCall"], "%+v", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -4761,20 +4763,27 @@ func TestDuplicateVirtualSessions(t *testing.T) {
|
|||
if msg, ok := client3.RunUntilMessage(ctx); ok {
|
||||
if msg, ok := checkMessageParticipantsInCall(t, msg); ok {
|
||||
if assert.Len(msg.Users, 3) {
|
||||
assert.Equal(true, msg.Users[0]["virtual"], "%+v", msg)
|
||||
assert.EqualValues(virtualSession.PublicId(), msg.Users[0]["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithPhone, msg.Users[0]["inCall"], "%+v", msg)
|
||||
assert.EqualValues(246, msg.Users[0]["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(4, msg.Users[0]["participantType"], "%+v", msg)
|
||||
users := msg.Users.Map()
|
||||
if user := users[virtualSession.PublicId()]; assert.NotNil(user, "expected %s, got %+v", virtualSession.PublicId(), msg) {
|
||||
assert.Equal(true, user["virtual"], "%+v", msg)
|
||||
assert.EqualValues(virtualSession.PublicId(), user["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithPhone, user["inCall"], "%+v", msg)
|
||||
assert.EqualValues(246, user["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(4, user["participantType"], "%+v", msg)
|
||||
}
|
||||
|
||||
assert.EqualValues(hello1.Hello.SessionId, msg.Users[1]["sessionId"], "%+v", msg)
|
||||
assert.Nil(msg.Users[1]["inCall"], "%+v", msg)
|
||||
assert.EqualValues(254, msg.Users[1]["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(1, msg.Users[1]["participantType"], "%+v", msg)
|
||||
if user := users[hello1.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello1.Hello.SessionId, msg) {
|
||||
assert.EqualValues(hello1.Hello.SessionId, user["sessionId"], "%+v", msg)
|
||||
assert.Nil(user["inCall"], "%+v", msg)
|
||||
assert.EqualValues(254, user["participantPermissions"], "%+v", msg)
|
||||
assert.EqualValues(1, user["participantType"], "%+v", msg)
|
||||
}
|
||||
|
||||
assert.Equal(true, msg.Users[2]["internal"], "%+v", msg)
|
||||
assert.EqualValues(hello2.Hello.SessionId, msg.Users[2]["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithAudio, msg.Users[2]["inCall"], "%+v", msg)
|
||||
if user := users[hello2.Hello.SessionId]; assert.NotNil(user, "expected %s, got %+v", hello2.Hello.SessionId, msg) {
|
||||
assert.Equal(true, user["internal"], "%+v", msg)
|
||||
assert.EqualValues(hello2.Hello.SessionId, user["sessionId"], "%+v", msg)
|
||||
assert.EqualValues(FlagInCall|FlagWithAudio, user["inCall"], "%+v", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,8 @@ type Room struct {
|
|||
statsRoomSessionsCurrent *prometheus.GaugeVec
|
||||
|
||||
// Users currently in the room
|
||||
users []api.StringMap
|
||||
// +checklocks:mu
|
||||
users api.UserDataMap
|
||||
|
||||
// Timestamps of last backend requests for the different types.
|
||||
lastRoomRequests map[string]int64
|
||||
|
|
@ -136,6 +137,7 @@ func NewRoom(roomId string, properties json.RawMessage, hub *Hub, asyncEvents ev
|
|||
"backend": backend.Id(),
|
||||
"room": roomId,
|
||||
}),
|
||||
users: make(api.UserDataMap),
|
||||
|
||||
lastRoomRequests: make(map[string]int64),
|
||||
|
||||
|
|
@ -503,18 +505,9 @@ func (r *Room) RemoveSession(session Session) bool {
|
|||
sid := session.PublicId()
|
||||
r.statsRoomSessionsCurrent.With(prometheus.Labels{"clienttype": string(session.ClientType())}).Dec()
|
||||
delete(r.sessions, sid)
|
||||
delete(r.users, sid)
|
||||
if virtualSession, ok := session.(*VirtualSession); ok {
|
||||
delete(r.virtualSessions, virtualSession)
|
||||
// Handle case where virtual session was also sent by Nextcloud.
|
||||
users := make([]api.StringMap, 0, len(r.users))
|
||||
for _, u := range r.users {
|
||||
if value, found := api.GetStringMapString[api.PublicSessionId](u, "sessionId"); !found || value != sid {
|
||||
users = append(users, u)
|
||||
}
|
||||
}
|
||||
if len(users) != len(r.users) {
|
||||
r.users = users
|
||||
}
|
||||
}
|
||||
if clientSession, ok := session.(*ClientSession); ok {
|
||||
delete(r.internalSessions, clientSession)
|
||||
|
|
@ -683,7 +676,7 @@ func (r *Room) getClusteredInternalSessionsRLocked() (internal map[api.PublicSes
|
|||
return
|
||||
}
|
||||
|
||||
func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
||||
func (r *Room) addInternalSessions(users api.UserDataList) api.UserDataList {
|
||||
now := time.Now().Unix()
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
|
@ -700,7 +693,7 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
|||
|
||||
skipSession := make(map[api.PublicSessionId]bool)
|
||||
for _, user := range users {
|
||||
sessionid, found := api.GetStringMapString[api.PublicSessionId](user, "sessionId")
|
||||
sessionid, found := user.SessionId()
|
||||
if !found || sessionid == "" {
|
||||
continue
|
||||
}
|
||||
|
|
@ -725,7 +718,7 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
|||
}
|
||||
}
|
||||
for session := range r.internalSessions {
|
||||
u := api.StringMap{
|
||||
u := api.UserData{
|
||||
"inCall": session.GetInCall(),
|
||||
"sessionId": session.PublicId(),
|
||||
"lastPing": now,
|
||||
|
|
@ -737,7 +730,7 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
|||
users = append(users, u)
|
||||
}
|
||||
for _, session := range clusteredInternalSessions {
|
||||
u := api.StringMap{
|
||||
u := api.UserData{
|
||||
"inCall": session.GetInCall(),
|
||||
"sessionId": session.GetSessionId(),
|
||||
"lastPing": now,
|
||||
|
|
@ -754,7 +747,7 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
|||
continue
|
||||
}
|
||||
skipSession[sid] = true
|
||||
users = append(users, api.StringMap{
|
||||
users = append(users, api.UserData{
|
||||
"inCall": session.GetInCall(),
|
||||
"sessionId": sid,
|
||||
"lastPing": now,
|
||||
|
|
@ -766,7 +759,7 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
|||
continue
|
||||
}
|
||||
|
||||
users = append(users, api.StringMap{
|
||||
users = append(users, api.UserData{
|
||||
"inCall": session.GetInCall(),
|
||||
"sessionId": sid,
|
||||
"lastPing": now,
|
||||
|
|
@ -776,7 +769,7 @@ func (r *Room) addInternalSessions(users []api.StringMap) []api.StringMap {
|
|||
return users
|
||||
}
|
||||
|
||||
func (r *Room) filterPermissions(users []api.StringMap) []api.StringMap {
|
||||
func (r *Room) filterPermissions(users api.UserDataList) api.UserDataList {
|
||||
for _, user := range users {
|
||||
delete(user, "permissions")
|
||||
}
|
||||
|
|
@ -803,9 +796,25 @@ func IsInCall(value any) (bool, bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Room) PublishUsersInCallChanged(changed []api.StringMap, users []api.StringMap) {
|
||||
r.users = users
|
||||
func (r *Room) addUser(sessionId api.PublicSessionId, user api.UserData) {
|
||||
r.mu.Lock()
|
||||
defer r.mu.Unlock()
|
||||
|
||||
r.users[sessionId] = user
|
||||
}
|
||||
|
||||
func (r *Room) PublishUsersInCallChanged(changed api.UserDataList) {
|
||||
for _, user := range changed {
|
||||
sessionId, found := user.SessionId()
|
||||
if !found {
|
||||
// TODO: Do we still need this fallback?
|
||||
sessionId, found = api.GetStringMapString[api.PublicSessionId](user, "sessionid")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
r.addUser(sessionId, user)
|
||||
inCallInterface, found := user["inCall"]
|
||||
if !found {
|
||||
continue
|
||||
|
|
@ -815,14 +824,6 @@ func (r *Room) PublishUsersInCallChanged(changed []api.StringMap, users []api.St
|
|||
continue
|
||||
}
|
||||
|
||||
sessionId, found := api.GetStringMapString[api.PublicSessionId](user, "sessionId")
|
||||
if !found {
|
||||
sessionId, found = api.GetStringMapString[api.PublicSessionId](user, "sessionid")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
session := r.hub.GetSessionByPublicId(sessionId)
|
||||
if session == nil {
|
||||
continue
|
||||
|
|
@ -846,7 +847,8 @@ func (r *Room) PublishUsersInCallChanged(changed []api.StringMap, users []api.St
|
|||
}
|
||||
|
||||
changed = r.filterPermissions(changed)
|
||||
users = r.filterPermissions(users)
|
||||
// TODO: Do we still need the whole list of users to send to all participants?
|
||||
users := r.filterPermissions(r.getUsers())
|
||||
|
||||
message := &api.ServerMessage{
|
||||
Type: "event",
|
||||
|
|
@ -953,9 +955,10 @@ func (r *Room) PublishUsersInCallChangedAll(inCall int) {
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Room) PublishUsersChanged(changed []api.StringMap, users []api.StringMap) {
|
||||
func (r *Room) PublishUsersChanged(changed api.UserDataList) {
|
||||
changed = r.filterPermissions(changed)
|
||||
users = r.filterPermissions(users)
|
||||
// TODO: Do we still need the whole list of users to send to all participants?
|
||||
users := r.filterPermissions(r.getUsers())
|
||||
|
||||
message := &api.ServerMessage{
|
||||
Type: "event",
|
||||
|
|
@ -974,8 +977,15 @@ func (r *Room) PublishUsersChanged(changed []api.StringMap, users []api.StringMa
|
|||
}
|
||||
}
|
||||
|
||||
func (r *Room) getParticipantsUpdateMessage(users []api.StringMap) *api.ServerMessage {
|
||||
users = r.filterPermissions(users)
|
||||
func (r *Room) getUsers() api.UserDataList {
|
||||
r.mu.RLock()
|
||||
defer r.mu.RUnlock()
|
||||
|
||||
return r.users.Users().Clone()
|
||||
}
|
||||
|
||||
func (r *Room) getParticipantsUpdateMessage() *api.ServerMessage {
|
||||
users := r.filterPermissions(r.getUsers())
|
||||
|
||||
message := &api.ServerMessage{
|
||||
Type: "event",
|
||||
|
|
@ -992,7 +1002,7 @@ func (r *Room) getParticipantsUpdateMessage(users []api.StringMap) *api.ServerMe
|
|||
}
|
||||
|
||||
func (r *Room) NotifySessionResumed(session *ClientSession) {
|
||||
message := r.getParticipantsUpdateMessage(r.users)
|
||||
message := r.getParticipantsUpdateMessage()
|
||||
if len(message.Event.Update.Users) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
@ -1043,7 +1053,7 @@ func (r *Room) NotifySessionChanged(session Session, flags SessionChangeFlag) {
|
|||
}
|
||||
|
||||
func (r *Room) publishUsersChangedWithInternal() {
|
||||
message := r.getParticipantsUpdateMessage(r.users)
|
||||
message := r.getParticipantsUpdateMessage()
|
||||
if len(message.Event.Update.Users) == 0 {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ import (
|
|||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/api"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/log"
|
||||
logtest "github.com/strukturag/nextcloud-spreed-signaling/log/test"
|
||||
"github.com/strukturag/nextcloud-spreed-signaling/talk"
|
||||
|
|
@ -111,9 +112,6 @@ func TestRoom_Update(t *testing.T) {
|
|||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "update",
|
||||
Update: &talk.BackendRoomUpdateRequest{
|
||||
UserIds: []string{
|
||||
testDefaultUserId,
|
||||
},
|
||||
Properties: roomProperties,
|
||||
},
|
||||
}
|
||||
|
|
@ -203,12 +201,8 @@ func TestRoom_Delete(t *testing.T) {
|
|||
|
||||
// Simulate backend request from Nextcloud to update the room.
|
||||
msg := &talk.BackendServerRoomRequest{
|
||||
Type: "delete",
|
||||
Delete: &talk.BackendRoomDeleteRequest{
|
||||
UserIds: []string{
|
||||
testDefaultUserId,
|
||||
},
|
||||
},
|
||||
Type: "delete",
|
||||
Delete: &talk.BackendRoomDeleteRequest{},
|
||||
}
|
||||
|
||||
data, err := json.Marshal(msg)
|
||||
|
|
@ -227,16 +221,27 @@ func TestRoom_Delete(t *testing.T) {
|
|||
// Ordering should be "leave room", "disinvited".
|
||||
checkMessageRoomId(t, message1, "")
|
||||
if message2, ok := client.RunUntilMessage(ctx); ok {
|
||||
checkMessageRoomlistDisinvite(t, message2)
|
||||
if msg, ok := checkMessageRoomlistDisinvite(t, message2); ok {
|
||||
assert.Equal(roomId, msg.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDeleted, msg.Reason)
|
||||
}
|
||||
}
|
||||
if !client.RunUntilClosed(ctx) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// Ordering should be "disinvited", "leave room".
|
||||
checkMessageRoomlistDisinvite(t, message1)
|
||||
if msg, ok := checkMessageRoomlistDisinvite(t, message1); ok {
|
||||
assert.Equal(roomId, msg.RoomId)
|
||||
assert.Equal(api.DisinviteReasonDeleted, msg.Reason)
|
||||
}
|
||||
// The connection should get closed after the "disinvited".
|
||||
// However due to the asynchronous processing, the "leave room" message might be received before.
|
||||
if message2, ok := client.RunUntilMessageOrClosed(ctx); ok && message2 != nil {
|
||||
checkMessageRoomId(t, message2, "")
|
||||
client.RunUntilClosed(ctx)
|
||||
if !client.RunUntilClosed(ctx) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
22
talk/api.go
22
talk/api.go
|
|
@ -110,42 +110,32 @@ type BackendServerRoomRequest struct {
|
|||
}
|
||||
|
||||
type BackendRoomInviteRequest struct {
|
||||
UserIds []string `json:"userids,omitempty"`
|
||||
// TODO(jojo): We should get rid of "AllUserIds" and find a better way to
|
||||
// notify existing users the room has changed and they need to update it.
|
||||
AllUserIds []string `json:"alluserids,omitempty"`
|
||||
UserIds []string `json:"userids,omitempty"`
|
||||
Properties json.RawMessage `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
type BackendRoomDisinviteRequest struct {
|
||||
UserIds []string `json:"userids,omitempty"`
|
||||
SessionIds []api.RoomSessionId `json:"sessionids,omitempty"`
|
||||
// TODO(jojo): We should get rid of "AllUserIds" and find a better way to
|
||||
// notify existing users the room has changed and they need to update it.
|
||||
AllUserIds []string `json:"alluserids,omitempty"`
|
||||
Properties json.RawMessage `json:"properties,omitempty"`
|
||||
Properties json.RawMessage `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
type BackendRoomUpdateRequest struct {
|
||||
UserIds []string `json:"userids,omitempty"`
|
||||
Properties json.RawMessage `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
type BackendRoomDeleteRequest struct {
|
||||
UserIds []string `json:"userids,omitempty"`
|
||||
}
|
||||
|
||||
type BackendRoomInCallRequest struct {
|
||||
// TODO(jojo): Change "InCall" to "int" when #914 has landed in NC Talk.
|
||||
InCall json.RawMessage `json:"incall,omitempty"`
|
||||
All bool `json:"all,omitempty"`
|
||||
Changed []api.StringMap `json:"changed,omitempty"`
|
||||
Users []api.StringMap `json:"users,omitempty"`
|
||||
InCall json.RawMessage `json:"incall,omitempty"`
|
||||
All bool `json:"all,omitempty"`
|
||||
Changed api.UserDataList `json:"changed,omitempty"`
|
||||
}
|
||||
|
||||
type BackendRoomParticipantsRequest struct {
|
||||
Changed []api.StringMap `json:"changed,omitempty"`
|
||||
Users []api.StringMap `json:"users,omitempty"`
|
||||
Changed api.UserDataList `json:"changed,omitempty"`
|
||||
}
|
||||
|
||||
type BackendRoomMessageRequest struct {
|
||||
|
|
|
|||
|
|
@ -2021,33 +2021,6 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk13(in
|
|||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
switch key {
|
||||
case "userids":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.UserIds = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.UserIds == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.UserIds = make([]string, 0, 4)
|
||||
} else {
|
||||
out.UserIds = []string{}
|
||||
}
|
||||
} else {
|
||||
out.UserIds = (out.UserIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v25 string
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v25 = string(in.String())
|
||||
}
|
||||
out.UserIds = append(out.UserIds, v25)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "properties":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
|
|
@ -2070,29 +2043,10 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk13(out
|
|||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
if len(in.UserIds) != 0 {
|
||||
const prefix string = ",\"userids\":"
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v26, v27 := range in.UserIds {
|
||||
if v26 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v27))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if len(in.Properties) != 0 {
|
||||
const prefix string = ",\"properties\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
out.Raw((in.Properties).MarshalJSON())
|
||||
}
|
||||
out.RawByte('}')
|
||||
|
|
@ -2271,13 +2225,13 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk15(in
|
|||
out.SessionsList = (out.SessionsList)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v28 api.PublicSessionId
|
||||
var v25 api.PublicSessionId
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v28 = api.PublicSessionId(in.String())
|
||||
v25 = api.PublicSessionId(in.String())
|
||||
}
|
||||
out.SessionsList = append(out.SessionsList, v28)
|
||||
out.SessionsList = append(out.SessionsList, v25)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -2295,15 +2249,15 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk15(in
|
|||
for !in.IsDelim('}') {
|
||||
key := api.PublicSessionId(in.String())
|
||||
in.WantColon()
|
||||
var v29 json.RawMessage
|
||||
var v26 json.RawMessage
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
if data := in.Raw(); in.Ok() {
|
||||
in.AddError((v29).UnmarshalJSON(data))
|
||||
in.AddError((v26).UnmarshalJSON(data))
|
||||
}
|
||||
}
|
||||
(out.SessionsMap)[key] = v29
|
||||
(out.SessionsMap)[key] = v26
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
|
|
@ -2337,11 +2291,11 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk15(out
|
|||
out.RawString(prefix)
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v30, v31 := range in.SessionsList {
|
||||
if v30 > 0 {
|
||||
for v27, v28 := range in.SessionsList {
|
||||
if v27 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v31))
|
||||
out.String(string(v28))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
|
@ -2351,16 +2305,16 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk15(out
|
|||
out.RawString(prefix)
|
||||
{
|
||||
out.RawByte('{')
|
||||
v32First := true
|
||||
for v32Name, v32Value := range in.SessionsMap {
|
||||
if v32First {
|
||||
v32First = false
|
||||
v29First := true
|
||||
for v29Name, v29Value := range in.SessionsMap {
|
||||
if v29First {
|
||||
v29First = false
|
||||
} else {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v32Name))
|
||||
out.String(string(v29Name))
|
||||
out.RawByte(':')
|
||||
out.Raw((v32Value).MarshalJSON())
|
||||
out.Raw((v29Value).MarshalJSON())
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
|
|
@ -2413,88 +2367,41 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk16(in
|
|||
in.Delim('[')
|
||||
if out.Changed == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Changed = make([]api.StringMap, 0, 8)
|
||||
out.Changed = make(api.UserDataList, 0, 8)
|
||||
} else {
|
||||
out.Changed = []api.StringMap{}
|
||||
out.Changed = api.UserDataList{}
|
||||
}
|
||||
} else {
|
||||
out.Changed = (out.Changed)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v33 api.StringMap
|
||||
var v30 api.StringMap
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
in.Delim('{')
|
||||
if !in.IsDelim('}') {
|
||||
v33 = make(api.StringMap)
|
||||
v30 = make(api.StringMap)
|
||||
} else {
|
||||
v33 = nil
|
||||
v30 = nil
|
||||
}
|
||||
for !in.IsDelim('}') {
|
||||
key := string(in.String())
|
||||
in.WantColon()
|
||||
var v34 interface{}
|
||||
if m, ok := v34.(easyjson.Unmarshaler); ok {
|
||||
var v31 interface{}
|
||||
if m, ok := v31.(easyjson.Unmarshaler); ok {
|
||||
m.UnmarshalEasyJSON(in)
|
||||
} else if m, ok := v34.(json.Unmarshaler); ok {
|
||||
} else if m, ok := v31.(json.Unmarshaler); ok {
|
||||
_ = m.UnmarshalJSON(in.Raw())
|
||||
} else {
|
||||
v34 = in.Interface()
|
||||
v31 = in.Interface()
|
||||
}
|
||||
(v33)[key] = v34
|
||||
(v30)[key] = v31
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
}
|
||||
out.Changed = append(out.Changed, v33)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "users":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.Users = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.Users == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Users = make([]api.StringMap, 0, 8)
|
||||
} else {
|
||||
out.Users = []api.StringMap{}
|
||||
}
|
||||
} else {
|
||||
out.Users = (out.Users)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v35 api.StringMap
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
in.Delim('{')
|
||||
if !in.IsDelim('}') {
|
||||
v35 = make(api.StringMap)
|
||||
} else {
|
||||
v35 = nil
|
||||
}
|
||||
for !in.IsDelim('}') {
|
||||
key := string(in.String())
|
||||
in.WantColon()
|
||||
var v36 interface{}
|
||||
if m, ok := v36.(easyjson.Unmarshaler); ok {
|
||||
m.UnmarshalEasyJSON(in)
|
||||
} else if m, ok := v36.(json.Unmarshaler); ok {
|
||||
_ = m.UnmarshalJSON(in.Raw())
|
||||
} else {
|
||||
v36 = in.Interface()
|
||||
}
|
||||
(v35)[key] = v36
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
}
|
||||
out.Users = append(out.Users, v35)
|
||||
out.Changed = append(out.Changed, v30)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -2519,70 +2426,29 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk16(out
|
|||
out.RawString(prefix[1:])
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v37, v38 := range in.Changed {
|
||||
if v37 > 0 {
|
||||
for v32, v33 := range in.Changed {
|
||||
if v32 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
if v38 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
|
||||
if v33 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
|
||||
out.RawString(`null`)
|
||||
} else {
|
||||
out.RawByte('{')
|
||||
v39First := true
|
||||
for v39Name, v39Value := range v38 {
|
||||
if v39First {
|
||||
v39First = false
|
||||
v34First := true
|
||||
for v34Name, v34Value := range v33 {
|
||||
if v34First {
|
||||
v34First = false
|
||||
} else {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v39Name))
|
||||
out.String(string(v34Name))
|
||||
out.RawByte(':')
|
||||
if m, ok := v39Value.(easyjson.Marshaler); ok {
|
||||
if m, ok := v34Value.(easyjson.Marshaler); ok {
|
||||
m.MarshalEasyJSON(out)
|
||||
} else if m, ok := v39Value.(json.Marshaler); ok {
|
||||
} else if m, ok := v34Value.(json.Marshaler); ok {
|
||||
out.Raw(m.MarshalJSON())
|
||||
} else {
|
||||
out.Raw(json.Marshal(v39Value))
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if len(in.Users) != 0 {
|
||||
const prefix string = ",\"users\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v40, v41 := range in.Users {
|
||||
if v40 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
if v41 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
|
||||
out.RawString(`null`)
|
||||
} else {
|
||||
out.RawByte('{')
|
||||
v42First := true
|
||||
for v42Name, v42Value := range v41 {
|
||||
if v42First {
|
||||
v42First = false
|
||||
} else {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v42Name))
|
||||
out.RawByte(':')
|
||||
if m, ok := v42Value.(easyjson.Marshaler); ok {
|
||||
m.MarshalEasyJSON(out)
|
||||
} else if m, ok := v42Value.(json.Marshaler); ok {
|
||||
out.Raw(m.MarshalJSON())
|
||||
} else {
|
||||
out.Raw(json.Marshal(v42Value))
|
||||
out.Raw(json.Marshal(v34Value))
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
|
|
@ -2715,40 +2581,13 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk18(in
|
|||
out.UserIds = (out.UserIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v43 string
|
||||
var v35 string
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v43 = string(in.String())
|
||||
v35 = string(in.String())
|
||||
}
|
||||
out.UserIds = append(out.UserIds, v43)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "alluserids":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.AllUserIds = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.AllUserIds == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.AllUserIds = make([]string, 0, 4)
|
||||
} else {
|
||||
out.AllUserIds = []string{}
|
||||
}
|
||||
} else {
|
||||
out.AllUserIds = (out.AllUserIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v44 string
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v44 = string(in.String())
|
||||
}
|
||||
out.AllUserIds = append(out.AllUserIds, v44)
|
||||
out.UserIds = append(out.UserIds, v35)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -2781,30 +2620,11 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk18(out
|
|||
out.RawString(prefix[1:])
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v45, v46 := range in.UserIds {
|
||||
if v45 > 0 {
|
||||
for v36, v37 := range in.UserIds {
|
||||
if v36 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v46))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if len(in.AllUserIds) != 0 {
|
||||
const prefix string = ",\"alluserids\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v47, v48 := range in.AllUserIds {
|
||||
if v47 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v48))
|
||||
out.String(string(v37))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
|
@ -2881,88 +2701,41 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk19(in
|
|||
in.Delim('[')
|
||||
if out.Changed == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Changed = make([]api.StringMap, 0, 8)
|
||||
out.Changed = make(api.UserDataList, 0, 8)
|
||||
} else {
|
||||
out.Changed = []api.StringMap{}
|
||||
out.Changed = api.UserDataList{}
|
||||
}
|
||||
} else {
|
||||
out.Changed = (out.Changed)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v49 api.StringMap
|
||||
var v38 api.StringMap
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
in.Delim('{')
|
||||
if !in.IsDelim('}') {
|
||||
v49 = make(api.StringMap)
|
||||
v38 = make(api.StringMap)
|
||||
} else {
|
||||
v49 = nil
|
||||
v38 = nil
|
||||
}
|
||||
for !in.IsDelim('}') {
|
||||
key := string(in.String())
|
||||
in.WantColon()
|
||||
var v50 interface{}
|
||||
if m, ok := v50.(easyjson.Unmarshaler); ok {
|
||||
var v39 interface{}
|
||||
if m, ok := v39.(easyjson.Unmarshaler); ok {
|
||||
m.UnmarshalEasyJSON(in)
|
||||
} else if m, ok := v50.(json.Unmarshaler); ok {
|
||||
} else if m, ok := v39.(json.Unmarshaler); ok {
|
||||
_ = m.UnmarshalJSON(in.Raw())
|
||||
} else {
|
||||
v50 = in.Interface()
|
||||
v39 = in.Interface()
|
||||
}
|
||||
(v49)[key] = v50
|
||||
(v38)[key] = v39
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
}
|
||||
out.Changed = append(out.Changed, v49)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "users":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.Users = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.Users == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.Users = make([]api.StringMap, 0, 8)
|
||||
} else {
|
||||
out.Users = []api.StringMap{}
|
||||
}
|
||||
} else {
|
||||
out.Users = (out.Users)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v51 api.StringMap
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
in.Delim('{')
|
||||
if !in.IsDelim('}') {
|
||||
v51 = make(api.StringMap)
|
||||
} else {
|
||||
v51 = nil
|
||||
}
|
||||
for !in.IsDelim('}') {
|
||||
key := string(in.String())
|
||||
in.WantColon()
|
||||
var v52 interface{}
|
||||
if m, ok := v52.(easyjson.Unmarshaler); ok {
|
||||
m.UnmarshalEasyJSON(in)
|
||||
} else if m, ok := v52.(json.Unmarshaler); ok {
|
||||
_ = m.UnmarshalJSON(in.Raw())
|
||||
} else {
|
||||
v52 = in.Interface()
|
||||
}
|
||||
(v51)[key] = v52
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim('}')
|
||||
}
|
||||
out.Users = append(out.Users, v51)
|
||||
out.Changed = append(out.Changed, v38)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -3007,70 +2780,29 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk19(out
|
|||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v53, v54 := range in.Changed {
|
||||
if v53 > 0 {
|
||||
for v40, v41 := range in.Changed {
|
||||
if v40 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
if v54 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
|
||||
if v41 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
|
||||
out.RawString(`null`)
|
||||
} else {
|
||||
out.RawByte('{')
|
||||
v55First := true
|
||||
for v55Name, v55Value := range v54 {
|
||||
if v55First {
|
||||
v55First = false
|
||||
v42First := true
|
||||
for v42Name, v42Value := range v41 {
|
||||
if v42First {
|
||||
v42First = false
|
||||
} else {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v55Name))
|
||||
out.String(string(v42Name))
|
||||
out.RawByte(':')
|
||||
if m, ok := v55Value.(easyjson.Marshaler); ok {
|
||||
if m, ok := v42Value.(easyjson.Marshaler); ok {
|
||||
m.MarshalEasyJSON(out)
|
||||
} else if m, ok := v55Value.(json.Marshaler); ok {
|
||||
} else if m, ok := v42Value.(json.Marshaler); ok {
|
||||
out.Raw(m.MarshalJSON())
|
||||
} else {
|
||||
out.Raw(json.Marshal(v55Value))
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if len(in.Users) != 0 {
|
||||
const prefix string = ",\"users\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v56, v57 := range in.Users {
|
||||
if v56 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
if v57 == nil && (out.Flags&jwriter.NilMapAsEmpty) == 0 {
|
||||
out.RawString(`null`)
|
||||
} else {
|
||||
out.RawByte('{')
|
||||
v58First := true
|
||||
for v58Name, v58Value := range v57 {
|
||||
if v58First {
|
||||
v58First = false
|
||||
} else {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v58Name))
|
||||
out.RawByte(':')
|
||||
if m, ok := v58Value.(easyjson.Marshaler); ok {
|
||||
m.MarshalEasyJSON(out)
|
||||
} else if m, ok := v58Value.(json.Marshaler); ok {
|
||||
out.Raw(m.MarshalJSON())
|
||||
} else {
|
||||
out.Raw(json.Marshal(v58Value))
|
||||
out.Raw(json.Marshal(v42Value))
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
|
|
@ -3135,13 +2867,13 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk20(in
|
|||
out.UserIds = (out.UserIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v59 string
|
||||
var v43 string
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v59 = string(in.String())
|
||||
v43 = string(in.String())
|
||||
}
|
||||
out.UserIds = append(out.UserIds, v59)
|
||||
out.UserIds = append(out.UserIds, v43)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -3162,40 +2894,13 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk20(in
|
|||
out.SessionIds = (out.SessionIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v60 api.RoomSessionId
|
||||
var v44 api.RoomSessionId
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v60 = api.RoomSessionId(in.String())
|
||||
v44 = api.RoomSessionId(in.String())
|
||||
}
|
||||
out.SessionIds = append(out.SessionIds, v60)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
case "alluserids":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.AllUserIds = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.AllUserIds == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.AllUserIds = make([]string, 0, 4)
|
||||
} else {
|
||||
out.AllUserIds = []string{}
|
||||
}
|
||||
} else {
|
||||
out.AllUserIds = (out.AllUserIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v61 string
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v61 = string(in.String())
|
||||
}
|
||||
out.AllUserIds = append(out.AllUserIds, v61)
|
||||
out.SessionIds = append(out.SessionIds, v44)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -3228,11 +2933,11 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk20(out
|
|||
out.RawString(prefix[1:])
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v62, v63 := range in.UserIds {
|
||||
if v62 > 0 {
|
||||
for v45, v46 := range in.UserIds {
|
||||
if v45 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v63))
|
||||
out.String(string(v46))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
|
@ -3247,30 +2952,11 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk20(out
|
|||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v64, v65 := range in.SessionIds {
|
||||
if v64 > 0 {
|
||||
for v47, v48 := range in.SessionIds {
|
||||
if v47 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v65))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
if len(in.AllUserIds) != 0 {
|
||||
const prefix string = ",\"alluserids\":"
|
||||
if first {
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
} else {
|
||||
out.RawString(prefix)
|
||||
}
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v66, v67 := range in.AllUserIds {
|
||||
if v66 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v67))
|
||||
out.String(string(v48))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
|
@ -3569,33 +3255,6 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk24(in
|
|||
key := in.UnsafeFieldName(false)
|
||||
in.WantColon()
|
||||
switch key {
|
||||
case "userids":
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
out.UserIds = nil
|
||||
} else {
|
||||
in.Delim('[')
|
||||
if out.UserIds == nil {
|
||||
if !in.IsDelim(']') {
|
||||
out.UserIds = make([]string, 0, 4)
|
||||
} else {
|
||||
out.UserIds = []string{}
|
||||
}
|
||||
} else {
|
||||
out.UserIds = (out.UserIds)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v68 string
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v68 = string(in.String())
|
||||
}
|
||||
out.UserIds = append(out.UserIds, v68)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
}
|
||||
default:
|
||||
in.SkipRecursive()
|
||||
}
|
||||
|
|
@ -3610,21 +3269,6 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk24(out
|
|||
out.RawByte('{')
|
||||
first := true
|
||||
_ = first
|
||||
if len(in.UserIds) != 0 {
|
||||
const prefix string = ",\"userids\":"
|
||||
first = false
|
||||
out.RawString(prefix[1:])
|
||||
{
|
||||
out.RawByte('[')
|
||||
for v69, v70 := range in.UserIds {
|
||||
if v69 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v70))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
}
|
||||
out.RawByte('}')
|
||||
}
|
||||
|
||||
|
|
@ -3996,13 +3640,13 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk28(in
|
|||
*out.Permissions = (*out.Permissions)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v71 api.Permission
|
||||
var v49 api.Permission
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
v71 = api.Permission(in.String())
|
||||
v49 = api.Permission(in.String())
|
||||
}
|
||||
*out.Permissions = append(*out.Permissions, v71)
|
||||
*out.Permissions = append(*out.Permissions, v49)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -4049,11 +3693,11 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk28(out
|
|||
out.RawString("null")
|
||||
} else {
|
||||
out.RawByte('[')
|
||||
for v72, v73 := range *in.Permissions {
|
||||
if v72 > 0 {
|
||||
for v50, v51 := range *in.Permissions {
|
||||
if v50 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
out.String(string(v73))
|
||||
out.String(string(v51))
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
|
@ -4645,13 +4289,13 @@ func easyjsonC1cedd36DecodeGithubComStrukturagNextcloudSpreedSignalingTalk33(in
|
|||
out.Entries = (out.Entries)[:0]
|
||||
}
|
||||
for !in.IsDelim(']') {
|
||||
var v74 BackendPingEntry
|
||||
var v52 BackendPingEntry
|
||||
if in.IsNull() {
|
||||
in.Skip()
|
||||
} else {
|
||||
(v74).UnmarshalEasyJSON(in)
|
||||
(v52).UnmarshalEasyJSON(in)
|
||||
}
|
||||
out.Entries = append(out.Entries, v74)
|
||||
out.Entries = append(out.Entries, v52)
|
||||
in.WantComma()
|
||||
}
|
||||
in.Delim(']')
|
||||
|
|
@ -4687,11 +4331,11 @@ func easyjsonC1cedd36EncodeGithubComStrukturagNextcloudSpreedSignalingTalk33(out
|
|||
out.RawString("null")
|
||||
} else {
|
||||
out.RawByte('[')
|
||||
for v75, v76 := range in.Entries {
|
||||
if v75 > 0 {
|
||||
for v53, v54 := range in.Entries {
|
||||
if v53 > 0 {
|
||||
out.RawByte(',')
|
||||
}
|
||||
(v76).MarshalEasyJSON(out)
|
||||
(v54).MarshalEasyJSON(out)
|
||||
}
|
||||
out.RawByte(']')
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue