mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-06-08 08:52:27 +02:00
Allow internal clients to set / change the "inCall" flags.
This commit is contained in:
parent
1997a8eecb
commit
2f6e2ba87c
|
@ -423,7 +423,7 @@ func (m *HelloClientMessage) CheckValid() error {
|
|||
}
|
||||
|
||||
const (
|
||||
// Features for all clients.
|
||||
// Features to send to all clients.
|
||||
ServerFeatureMcu = "mcu"
|
||||
ServerFeatureSimulcast = "simulcast"
|
||||
ServerFeatureUpdateSdp = "update-sdp"
|
||||
|
@ -434,8 +434,11 @@ const (
|
|||
ServerFeatureHelloV2 = "hello-v2"
|
||||
ServerFeatureSwitchTo = "switchto"
|
||||
|
||||
// Features for internal clients only.
|
||||
// Features to send to internal clients only.
|
||||
ServerFeatureInternalVirtualSessions = "virtual-sessions"
|
||||
|
||||
// Possible client features from the "hello" request.
|
||||
ClientFeatureInternalInCall = "internal-incall"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -628,6 +631,7 @@ type AddSessionInternalClientMessage struct {
|
|||
UserId string `json:"userid,omitempty"`
|
||||
User *json.RawMessage `json:"user,omitempty"`
|
||||
Flags uint32 `json:"flags,omitempty"`
|
||||
InCall *int `json:"incall,omitempty"`
|
||||
|
||||
Options *AddSessionOptions `json:"options,omitempty"`
|
||||
}
|
||||
|
@ -639,7 +643,8 @@ func (m *AddSessionInternalClientMessage) CheckValid() error {
|
|||
type UpdateSessionInternalClientMessage struct {
|
||||
CommonSessionInternalClientMessage
|
||||
|
||||
Flags *uint32 `json:"flags,omitempty"`
|
||||
Flags *uint32 `json:"flags,omitempty"`
|
||||
InCall *int `json:"incall,omitempty"`
|
||||
}
|
||||
|
||||
func (m *UpdateSessionInternalClientMessage) CheckValid() error {
|
||||
|
@ -656,6 +661,14 @@ func (m *RemoveSessionInternalClientMessage) CheckValid() error {
|
|||
return m.CommonSessionInternalClientMessage.CheckValid()
|
||||
}
|
||||
|
||||
type InCallInternalClientMessage struct {
|
||||
InCall int `json:"incall"`
|
||||
}
|
||||
|
||||
func (m *InCallInternalClientMessage) CheckValid() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
type InternalClientMessage struct {
|
||||
Type string `json:"type"`
|
||||
|
||||
|
@ -664,6 +677,8 @@ type InternalClientMessage struct {
|
|||
UpdateSession *UpdateSessionInternalClientMessage `json:"updatesession,omitempty"`
|
||||
|
||||
RemoveSession *RemoveSessionInternalClientMessage `json:"removesession,omitempty"`
|
||||
|
||||
InCall *InCallInternalClientMessage `json:"incall,omitempty"`
|
||||
}
|
||||
|
||||
func (m *InternalClientMessage) CheckValid() error {
|
||||
|
@ -686,6 +701,12 @@ func (m *InternalClientMessage) CheckValid() error {
|
|||
} else if err := m.RemoveSession.CheckValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
case "incall":
|
||||
if m.InCall == nil {
|
||||
return fmt.Errorf("incall missing")
|
||||
} else if err := m.InCall.CheckValid(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ var (
|
|||
|
||||
type ClientSession struct {
|
||||
roomJoinTime int64
|
||||
inCall uint32
|
||||
|
||||
hub *Hub
|
||||
events AsyncEvents
|
||||
|
@ -106,6 +107,9 @@ func NewClientSession(hub *Hub, privateId string, publicId string, data *Session
|
|||
if s.clientType == HelloClientTypeInternal {
|
||||
s.backendUrl = hello.Auth.internalParams.Backend
|
||||
s.parsedBackendUrl = hello.Auth.internalParams.parsedBackend
|
||||
if !s.HasFeature(ClientFeatureInternalInCall) {
|
||||
s.SetInCall(FlagInCall | FlagWithAudio)
|
||||
}
|
||||
} else {
|
||||
s.backendUrl = hello.Auth.Url
|
||||
s.parsedBackendUrl = hello.Auth.parsedUrl
|
||||
|
@ -155,6 +159,28 @@ func (s *ClientSession) ClientType() string {
|
|||
return s.clientType
|
||||
}
|
||||
|
||||
// GetInCall is only used for internal clients.
|
||||
func (s *ClientSession) GetInCall() int {
|
||||
return int(atomic.LoadUint32(&s.inCall))
|
||||
}
|
||||
|
||||
func (s *ClientSession) SetInCall(inCall int) bool {
|
||||
if inCall < 0 {
|
||||
inCall = 0
|
||||
}
|
||||
|
||||
for {
|
||||
old := atomic.LoadUint32(&s.inCall)
|
||||
if old == uint32(inCall) {
|
||||
return false
|
||||
}
|
||||
|
||||
if atomic.CompareAndSwapUint32(&s.inCall, old, uint32(inCall)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ClientSession) GetFeatures() []string {
|
||||
return s.features
|
||||
}
|
||||
|
|
|
@ -238,7 +238,7 @@ func TestBandwidth_Backend(t *testing.T) {
|
|||
params := TestBackendClientAuthParams{
|
||||
UserId: testDefaultUserId,
|
||||
}
|
||||
if err := client.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", params); err != nil {
|
||||
if err := client.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
22
hub.go
22
hub.go
|
@ -1797,7 +1797,7 @@ func (h *Hub) processInternalMsg(client *Client, message *ClientMessage) {
|
|||
request := NewBackendClientRoomRequest(room.Id(), msg.UserId, publicSessionId)
|
||||
request.Room.ActorId = msg.Options.ActorId
|
||||
request.Room.ActorType = msg.Options.ActorType
|
||||
request.Room.InCall = FlagInCall | FlagWithPhone
|
||||
request.Room.InCall = sess.GetInCall()
|
||||
|
||||
var response BackendClientResponse
|
||||
if err := h.backend.PerformJSONRequest(ctx, session.ParsedBackendUrl(), request, &response); err != nil {
|
||||
|
@ -1856,18 +1856,23 @@ func (h *Hub) processInternalMsg(client *Client, message *ClientMessage) {
|
|||
sess := h.sessions[sid]
|
||||
h.mu.Unlock()
|
||||
if sess != nil {
|
||||
update := false
|
||||
var changed SessionChangeFlag
|
||||
if virtualSession, ok := sess.(*VirtualSession); ok {
|
||||
if msg.Flags != nil {
|
||||
if virtualSession.SetFlags(*msg.Flags) {
|
||||
update = true
|
||||
changed |= SessionChangeFlags
|
||||
}
|
||||
}
|
||||
if msg.InCall != nil {
|
||||
if virtualSession.SetInCall(*msg.InCall) {
|
||||
changed |= SessionChangeInCall
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.Printf("Ignore update request for non-virtual session %s", sess.PublicId())
|
||||
}
|
||||
if update {
|
||||
room.NotifySessionChanged(sess)
|
||||
if changed != 0 {
|
||||
room.NotifySessionChanged(sess, changed)
|
||||
}
|
||||
}
|
||||
case "removesession":
|
||||
|
@ -1898,6 +1903,13 @@ func (h *Hub) processInternalMsg(client *Client, message *ClientMessage) {
|
|||
sess.Close()
|
||||
}
|
||||
}
|
||||
case "incall":
|
||||
msg := msg.InCall
|
||||
if session.SetInCall(msg.InCall) {
|
||||
if room := session.GetRoom(); room != nil {
|
||||
room.NotifySessionChanged(session, SessionChangeInCall)
|
||||
}
|
||||
}
|
||||
default:
|
||||
log.Printf("Ignore unsupported internal message %+v from %s", msg, session.PublicId())
|
||||
return
|
||||
|
|
20
hub_test.go
20
hub_test.go
|
@ -848,7 +848,7 @@ func TestExpectClientHelloUnsupportedVersion(t *testing.T) {
|
|||
params := TestBackendClientAuthParams{
|
||||
UserId: testDefaultUserId,
|
||||
}
|
||||
if err := client.SendHelloParams(server.URL, "0.0", "", params); err != nil {
|
||||
if err := client.SendHelloParams(server.URL, "0.0", "", nil, params); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1254,7 +1254,7 @@ func TestClientHelloSessionLimit(t *testing.T) {
|
|||
params1 := TestBackendClientAuthParams{
|
||||
UserId: testDefaultUserId,
|
||||
}
|
||||
if err := client.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", params1); err != nil {
|
||||
if err := client.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", nil, params1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1279,7 +1279,7 @@ func TestClientHelloSessionLimit(t *testing.T) {
|
|||
params2 := TestBackendClientAuthParams{
|
||||
UserId: testDefaultUserId + "2",
|
||||
}
|
||||
if err := client2.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", params2); err != nil {
|
||||
if err := client2.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", nil, params2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1295,7 +1295,7 @@ func TestClientHelloSessionLimit(t *testing.T) {
|
|||
}
|
||||
|
||||
// The client can connect to a different backend.
|
||||
if err := client2.SendHelloParams(server1.URL+"/two", HelloVersionV1, "client", params2); err != nil {
|
||||
if err := client2.SendHelloParams(server1.URL+"/two", HelloVersionV1, "client", nil, params2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1322,7 +1322,7 @@ func TestClientHelloSessionLimit(t *testing.T) {
|
|||
params3 := TestBackendClientAuthParams{
|
||||
UserId: testDefaultUserId + "3",
|
||||
}
|
||||
if err := client3.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", params3); err != nil {
|
||||
if err := client3.SendHelloParams(server1.URL+"/one", HelloVersionV1, "client", nil, params3); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -1926,7 +1926,7 @@ func TestClientHelloClient_V3Api(t *testing.T) {
|
|||
}
|
||||
// The "/api/v1/signaling/" URL will be changed to use "v3" as the "signaling-v3"
|
||||
// feature is returned by the capabilities endpoint.
|
||||
if err := client.SendHelloParams(server.URL+"/ocs/v2.php/apps/spreed/api/v1/signaling/backend", HelloVersionV1, "client", params); err != nil {
|
||||
if err := client.SendHelloParams(server.URL+"/ocs/v2.php/apps/spreed/api/v1/signaling/backend", HelloVersionV1, "client", nil, params); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
@ -4269,7 +4269,7 @@ func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
|
|||
params1 := TestBackendClientAuthParams{
|
||||
UserId: "user1",
|
||||
}
|
||||
if err := client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", params1); err != nil {
|
||||
if err := client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hello1, err := client1.RunUntilHello(ctx)
|
||||
|
@ -4283,7 +4283,7 @@ func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
|
|||
params2 := TestBackendClientAuthParams{
|
||||
UserId: "user2",
|
||||
}
|
||||
if err := client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", params2); err != nil {
|
||||
if err := client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hello2, err := client2.RunUntilHello(ctx)
|
||||
|
@ -4339,7 +4339,7 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
|
|||
params1 := TestBackendClientAuthParams{
|
||||
UserId: "user1",
|
||||
}
|
||||
if err := client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", params1); err != nil {
|
||||
if err := client1.SendHelloParams(server.URL+"/one", HelloVersionV1, "client", nil, params1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hello1, err := client1.RunUntilHello(ctx)
|
||||
|
@ -4353,7 +4353,7 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
|
|||
params2 := TestBackendClientAuthParams{
|
||||
UserId: "user2",
|
||||
}
|
||||
if err := client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", params2); err != nil {
|
||||
if err := client2.SendHelloParams(server.URL+"/two", HelloVersionV1, "client", nil, params2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
hello2, err := client2.RunUntilHello(ctx)
|
||||
|
|
60
room.go
60
room.go
|
@ -44,6 +44,13 @@ const (
|
|||
FlagWithPhone = 8
|
||||
)
|
||||
|
||||
type SessionChangeFlag int
|
||||
|
||||
const (
|
||||
SessionChangeFlags SessionChangeFlag = 1
|
||||
SessionChangeInCall SessionChangeFlag = 2
|
||||
)
|
||||
|
||||
var (
|
||||
updateActiveSessionsInterval = 10 * time.Second
|
||||
)
|
||||
|
@ -571,7 +578,7 @@ func (r *Room) addInternalSessions(users []map[string]interface{}) []map[string]
|
|||
}
|
||||
for session := range r.internalSessions {
|
||||
users = append(users, map[string]interface{}{
|
||||
"inCall": FlagInCall | FlagWithAudio,
|
||||
"inCall": session.(*ClientSession).GetInCall(),
|
||||
"sessionId": session.PublicId(),
|
||||
"lastPing": now,
|
||||
"internal": true,
|
||||
|
@ -579,7 +586,7 @@ func (r *Room) addInternalSessions(users []map[string]interface{}) []map[string]
|
|||
}
|
||||
for session := range r.virtualSessions {
|
||||
users = append(users, map[string]interface{}{
|
||||
"inCall": FlagInCall | FlagWithPhone,
|
||||
"inCall": session.GetInCall(),
|
||||
"sessionId": session.PublicId(),
|
||||
"lastPing": now,
|
||||
"virtual": true,
|
||||
|
@ -816,18 +823,51 @@ func (r *Room) NotifySessionResumed(session *ClientSession) {
|
|||
session.SendMessage(message)
|
||||
}
|
||||
|
||||
func (r *Room) NotifySessionChanged(session Session) {
|
||||
if session.ClientType() != HelloClientTypeVirtual {
|
||||
func (r *Room) NotifySessionChanged(session Session, flags SessionChangeFlag) {
|
||||
if flags&SessionChangeFlags != 0 && session.ClientType() == HelloClientTypeVirtual {
|
||||
// Only notify if a virtual session has changed.
|
||||
return
|
||||
if virtual, ok := session.(*VirtualSession); ok {
|
||||
r.publishSessionFlagsChanged(virtual)
|
||||
}
|
||||
}
|
||||
|
||||
virtual, ok := session.(*VirtualSession)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
if flags&SessionChangeInCall != 0 {
|
||||
joinLeave := 0
|
||||
if clientSession, ok := session.(*ClientSession); ok {
|
||||
if clientSession.GetInCall()&FlagInCall != 0 {
|
||||
joinLeave = 1
|
||||
} else {
|
||||
joinLeave = 2
|
||||
}
|
||||
} else if virtual, ok := session.(*VirtualSession); ok {
|
||||
if virtual.GetInCall()&FlagInCall != 0 {
|
||||
joinLeave = 1
|
||||
} else {
|
||||
joinLeave = 2
|
||||
}
|
||||
}
|
||||
|
||||
r.publishSessionFlagsChanged(virtual)
|
||||
if joinLeave != 0 {
|
||||
if joinLeave == 1 {
|
||||
r.mu.Lock()
|
||||
if !r.inCallSessions[session] {
|
||||
r.inCallSessions[session] = true
|
||||
log.Printf("Session %s joined call %s", session.PublicId(), r.id)
|
||||
}
|
||||
r.mu.Unlock()
|
||||
} else if joinLeave == 2 {
|
||||
r.mu.Lock()
|
||||
delete(r.inCallSessions, session)
|
||||
r.mu.Unlock()
|
||||
if clientSession, ok := session.(*ClientSession); ok {
|
||||
clientSession.LeaveCall()
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Check if we could send a smaller update message with only the changed session.
|
||||
r.publishUsersChangedWithInternal()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Room) publishUsersChangedWithInternal() {
|
||||
|
|
|
@ -385,7 +385,7 @@ func (c *TestClient) SendHelloV1(userid string) error {
|
|||
params := TestBackendClientAuthParams{
|
||||
UserId: userid,
|
||||
}
|
||||
return c.SendHelloParams(c.server.URL, HelloVersionV1, "", params)
|
||||
return c.SendHelloParams(c.server.URL, HelloVersionV1, "", nil, params)
|
||||
}
|
||||
|
||||
func (c *TestClient) SendHelloV2(userid string) error {
|
||||
|
@ -434,7 +434,7 @@ func (c *TestClient) SendHelloV2WithTimes(userid string, issuedAt time.Time, exp
|
|||
params := HelloV2AuthParams{
|
||||
Token: tokenString,
|
||||
}
|
||||
return c.SendHelloParams(c.server.URL, HelloVersionV2, "", params)
|
||||
return c.SendHelloParams(c.server.URL, HelloVersionV2, "", nil, params)
|
||||
}
|
||||
|
||||
func (c *TestClient) SendHelloResume(resumeId string) error {
|
||||
|
@ -453,10 +453,14 @@ func (c *TestClient) SendHelloClient(userid string) error {
|
|||
params := TestBackendClientAuthParams{
|
||||
UserId: userid,
|
||||
}
|
||||
return c.SendHelloParams(c.server.URL, HelloVersionV1, "client", params)
|
||||
return c.SendHelloParams(c.server.URL, HelloVersionV1, "client", nil, params)
|
||||
}
|
||||
|
||||
func (c *TestClient) SendHelloInternal() error {
|
||||
return c.SendHelloInternalWithFeatures(nil)
|
||||
}
|
||||
|
||||
func (c *TestClient) SendHelloInternalWithFeatures(features []string) error {
|
||||
random := newRandomString(48)
|
||||
mac := hmac.New(sha256.New, testInternalSecret)
|
||||
mac.Write([]byte(random)) // nolint
|
||||
|
@ -468,10 +472,10 @@ func (c *TestClient) SendHelloInternal() error {
|
|||
Token: token,
|
||||
Backend: backend,
|
||||
}
|
||||
return c.SendHelloParams("", HelloVersionV1, "internal", params)
|
||||
return c.SendHelloParams("", HelloVersionV1, "internal", features, params)
|
||||
}
|
||||
|
||||
func (c *TestClient) SendHelloParams(url string, version string, clientType string, params interface{}) error {
|
||||
func (c *TestClient) SendHelloParams(url string, version string, clientType string, features []string, params interface{}) error {
|
||||
data, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
c.t.Fatal(err)
|
||||
|
@ -481,7 +485,8 @@ func (c *TestClient) SendHelloParams(url string, version string, clientType stri
|
|||
Id: "1234",
|
||||
Type: "hello",
|
||||
Hello: &HelloClientMessage{
|
||||
Version: version,
|
||||
Version: version,
|
||||
Features: features,
|
||||
Auth: HelloClientMessageAuth{
|
||||
Type: clientType,
|
||||
Url: url,
|
||||
|
|
|
@ -38,6 +38,8 @@ const (
|
|||
)
|
||||
|
||||
type VirtualSession struct {
|
||||
inCall uint32
|
||||
|
||||
hub *Hub
|
||||
session *ClientSession
|
||||
privateId string
|
||||
|
@ -75,6 +77,12 @@ func NewVirtualSession(session *ClientSession, privateId string, publicId string
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if msg.InCall != nil {
|
||||
result.SetInCall(*msg.InCall)
|
||||
} else if !session.HasFeature(ClientFeatureInternalInCall) {
|
||||
result.SetInCall(FlagInCall | FlagWithPhone)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
|
@ -90,6 +98,27 @@ func (s *VirtualSession) ClientType() string {
|
|||
return HelloClientTypeVirtual
|
||||
}
|
||||
|
||||
func (s *VirtualSession) GetInCall() int {
|
||||
return int(atomic.LoadUint32(&s.inCall))
|
||||
}
|
||||
|
||||
func (s *VirtualSession) SetInCall(inCall int) bool {
|
||||
if inCall < 0 {
|
||||
inCall = 0
|
||||
}
|
||||
|
||||
for {
|
||||
old := atomic.LoadUint32(&s.inCall)
|
||||
if old == uint32(inCall) {
|
||||
return false
|
||||
}
|
||||
|
||||
if atomic.CompareAndSwapUint32(&s.inCall, old, uint32(inCall)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *VirtualSession) Data() *SessionIdData {
|
||||
return s.data
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -143,8 +144,8 @@ func TestVirtualSession(t *testing.T) {
|
|||
t.Errorf("Expected session id %s, got %+v", sessionId, updateMsg.Users[0])
|
||||
} else if virtual, ok := updateMsg.Users[0]["virtual"].(bool); !ok || !virtual {
|
||||
t.Errorf("Expected virtual user, got %+v", updateMsg.Users[0])
|
||||
} else if inCall, ok := updateMsg.Users[0]["inCall"].(float64); !ok || inCall == 0 {
|
||||
t.Errorf("Expected user in call, got %+v", updateMsg.Users[0])
|
||||
} else if inCall, ok := updateMsg.Users[0]["inCall"].(float64); !ok || inCall != (FlagInCall|FlagWithPhone) {
|
||||
t.Errorf("Expected user in call with phone, got %+v", updateMsg.Users[0])
|
||||
}
|
||||
|
||||
msg3, err := client.RunUntilMessage(ctx)
|
||||
|
@ -313,6 +314,260 @@ func TestVirtualSession(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func checkHasEntryWithInCall(message *RoomEventServerMessage, sessionId string, entryType string, inCall int) error {
|
||||
found := false
|
||||
for _, entry := range message.Users {
|
||||
if sid, ok := entry["sessionId"].(string); ok && sid == sessionId {
|
||||
if value, ok := entry[entryType].(bool); !ok || !value {
|
||||
return fmt.Errorf("Expected %s user, got %+v", entryType, entry)
|
||||
}
|
||||
|
||||
if value, ok := entry["inCall"].(float64); !ok || int(value) != inCall {
|
||||
return fmt.Errorf("Expected in call %d, got %+v", inCall, entry)
|
||||
}
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return fmt.Errorf("No user with session id %s found, got %+v", sessionId, message)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestVirtualSessionCustomInCall(t *testing.T) {
|
||||
hub, _, _, server := CreateHubForTest(t)
|
||||
|
||||
roomId := "the-room-id"
|
||||
emptyProperties := json.RawMessage("{}")
|
||||
backend := &Backend{
|
||||
id: "compat",
|
||||
compat: true,
|
||||
}
|
||||
room, err := hub.createRoom(roomId, &emptyProperties, backend)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create room: %s", err)
|
||||
}
|
||||
defer room.Close()
|
||||
|
||||
clientInternal := NewTestClient(t, server, hub)
|
||||
defer clientInternal.CloseWithBye()
|
||||
features := []string{
|
||||
ClientFeatureInternalInCall,
|
||||
}
|
||||
if err := clientInternal.SendHelloInternalWithFeatures(features); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
client := NewTestClient(t, server, hub)
|
||||
defer client.CloseWithBye()
|
||||
if err := client.SendHello(testDefaultUserId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||
defer cancel()
|
||||
|
||||
helloInternal, err := clientInternal.RunUntilHello(ctx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else {
|
||||
if helloInternal.Hello.UserId != "" {
|
||||
t.Errorf("Expected empty user id, got %+v", helloInternal.Hello)
|
||||
}
|
||||
if helloInternal.Hello.SessionId == "" {
|
||||
t.Errorf("Expected session id, got %+v", helloInternal.Hello)
|
||||
}
|
||||
if helloInternal.Hello.ResumeId == "" {
|
||||
t.Errorf("Expected resume id, got %+v", helloInternal.Hello)
|
||||
}
|
||||
}
|
||||
if room, err := clientInternal.JoinRoomWithRoomSession(ctx, roomId, ""); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if room.Room.RoomId != roomId {
|
||||
t.Fatalf("Expected room %s, got %s", roomId, room.Room.RoomId)
|
||||
}
|
||||
|
||||
hello, err := client.RunUntilHello(ctx)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if room, err := client.JoinRoom(ctx, roomId); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if room.Room.RoomId != roomId {
|
||||
t.Fatalf("Expected room %s, got %s", roomId, room.Room.RoomId)
|
||||
}
|
||||
|
||||
if _, additional, err := clientInternal.RunUntilJoinedAndReturn(ctx, helloInternal.Hello, hello.Hello); err != nil {
|
||||
t.Error(err)
|
||||
} else if len(additional) != 1 {
|
||||
t.Errorf("expected one additional message, got %+v", additional)
|
||||
} else if additional[0].Type != "event" {
|
||||
t.Errorf("expected event message, got %+v", additional[0])
|
||||
} else if additional[0].Event.Target != "participants" {
|
||||
t.Errorf("expected event participants message, got %+v", additional[0])
|
||||
} else if additional[0].Event.Type != "update" {
|
||||
t.Errorf("expected event participants update message, got %+v", additional[0])
|
||||
} else if additional[0].Event.Update.Users[0]["sessionId"].(string) != helloInternal.Hello.SessionId {
|
||||
t.Errorf("expected event update message for internal session, got %+v", additional[0])
|
||||
} else if additional[0].Event.Update.Users[0]["inCall"].(float64) != 0 {
|
||||
t.Errorf("expected event update message with session not in call, got %+v", additional[0])
|
||||
}
|
||||
if err := client.RunUntilJoined(ctx, helloInternal.Hello, hello.Hello); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
internalSessionId := "session1"
|
||||
userId := "user1"
|
||||
msgAdd := &ClientMessage{
|
||||
Type: "internal",
|
||||
Internal: &InternalClientMessage{
|
||||
Type: "addsession",
|
||||
AddSession: &AddSessionInternalClientMessage{
|
||||
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
|
||||
SessionId: internalSessionId,
|
||||
RoomId: roomId,
|
||||
},
|
||||
UserId: userId,
|
||||
Flags: FLAG_MUTED_SPEAKING,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := clientInternal.WriteJSON(msgAdd); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
msg1, err := client.RunUntilMessage(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// The public session id will be generated by the server, so don't check for it.
|
||||
if err := client.checkMessageJoinedSession(msg1, "", userId); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
sessionId := msg1.Event.Join[0].SessionId
|
||||
session := hub.GetSessionByPublicId(sessionId)
|
||||
if session == nil {
|
||||
t.Fatalf("Could not get virtual session %s", sessionId)
|
||||
}
|
||||
if session.ClientType() != HelloClientTypeVirtual {
|
||||
t.Errorf("Expected client type %s, got %s", HelloClientTypeVirtual, session.ClientType())
|
||||
}
|
||||
if sid := session.(*VirtualSession).SessionId(); sid != internalSessionId {
|
||||
t.Errorf("Expected internal session id %s, got %s", internalSessionId, sid)
|
||||
}
|
||||
|
||||
// Also a participants update event will be triggered for the virtual user.
|
||||
msg2, err := client.RunUntilMessage(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
updateMsg, err := checkMessageParticipantsInCall(msg2)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if updateMsg.RoomId != roomId {
|
||||
t.Errorf("Expected room %s, got %s", roomId, updateMsg.RoomId)
|
||||
} else if len(updateMsg.Users) != 2 {
|
||||
t.Errorf("Expected two users, got %+v", updateMsg.Users)
|
||||
}
|
||||
|
||||
if err := checkHasEntryWithInCall(updateMsg, sessionId, "virtual", 0); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := checkHasEntryWithInCall(updateMsg, helloInternal.Hello.SessionId, "internal", 0); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
msg3, err := client.RunUntilMessage(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
flagsMsg, err := checkMessageParticipantFlags(msg3)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if flagsMsg.RoomId != roomId {
|
||||
t.Errorf("Expected room %s, got %s", roomId, flagsMsg.RoomId)
|
||||
} else if flagsMsg.SessionId != sessionId {
|
||||
t.Errorf("Expected session id %s, got %s", sessionId, flagsMsg.SessionId)
|
||||
} else if flagsMsg.Flags != FLAG_MUTED_SPEAKING {
|
||||
t.Errorf("Expected flags %d, got %+v", FLAG_MUTED_SPEAKING, flagsMsg.Flags)
|
||||
}
|
||||
|
||||
// The internal session can change its "inCall" flags
|
||||
msgInCall := &ClientMessage{
|
||||
Type: "internal",
|
||||
Internal: &InternalClientMessage{
|
||||
Type: "incall",
|
||||
InCall: &InCallInternalClientMessage{
|
||||
InCall: FlagInCall | FlagWithAudio,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := clientInternal.WriteJSON(msgInCall); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
msg4, err := client.RunUntilMessage(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
updateMsg2, err := checkMessageParticipantsInCall(msg4)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if updateMsg2.RoomId != roomId {
|
||||
t.Errorf("Expected room %s, got %s", roomId, updateMsg2.RoomId)
|
||||
} else if len(updateMsg2.Users) != 2 {
|
||||
t.Errorf("Expected two users, got %+v", updateMsg2.Users)
|
||||
}
|
||||
if err := checkHasEntryWithInCall(updateMsg2, sessionId, "virtual", 0); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := checkHasEntryWithInCall(updateMsg2, helloInternal.Hello.SessionId, "internal", FlagInCall|FlagWithAudio); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
// The internal session can change the "inCall" flags of a virtual session
|
||||
newInCall := FlagInCall | FlagWithPhone
|
||||
msgInCall2 := &ClientMessage{
|
||||
Type: "internal",
|
||||
Internal: &InternalClientMessage{
|
||||
Type: "updatesession",
|
||||
UpdateSession: &UpdateSessionInternalClientMessage{
|
||||
CommonSessionInternalClientMessage: CommonSessionInternalClientMessage{
|
||||
SessionId: internalSessionId,
|
||||
RoomId: roomId,
|
||||
},
|
||||
InCall: &newInCall,
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := clientInternal.WriteJSON(msgInCall2); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
msg5, err := client.RunUntilMessage(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
updateMsg3, err := checkMessageParticipantsInCall(msg5)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
} else if updateMsg3.RoomId != roomId {
|
||||
t.Errorf("Expected room %s, got %s", roomId, updateMsg3.RoomId)
|
||||
} else if len(updateMsg3.Users) != 2 {
|
||||
t.Errorf("Expected two users, got %+v", updateMsg3.Users)
|
||||
}
|
||||
if err := checkHasEntryWithInCall(updateMsg3, sessionId, "virtual", newInCall); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if err := checkHasEntryWithInCall(updateMsg3, helloInternal.Hello.SessionId, "internal", FlagInCall|FlagWithAudio); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVirtualSessionCleanup(t *testing.T) {
|
||||
hub, _, _, server := CreateHubForTest(t)
|
||||
|
||||
|
@ -427,8 +682,8 @@ func TestVirtualSessionCleanup(t *testing.T) {
|
|||
t.Errorf("Expected session id %s, got %+v", sessionId, updateMsg.Users[0])
|
||||
} else if virtual, ok := updateMsg.Users[0]["virtual"].(bool); !ok || !virtual {
|
||||
t.Errorf("Expected virtual user, got %+v", updateMsg.Users[0])
|
||||
} else if inCall, ok := updateMsg.Users[0]["inCall"].(float64); !ok || inCall == 0 {
|
||||
t.Errorf("Expected user in call, got %+v", updateMsg.Users[0])
|
||||
} else if inCall, ok := updateMsg.Users[0]["inCall"].(float64); !ok || inCall != (FlagInCall|FlagWithPhone) {
|
||||
t.Errorf("Expected user in call with phone, got %+v", updateMsg.Users[0])
|
||||
}
|
||||
|
||||
msg3, err := client.RunUntilMessage(ctx)
|
||||
|
|
Loading…
Reference in a new issue