mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-06-08 08:52:27 +02:00
Return response if session tries to join room again.
This commit is contained in:
parent
92690f4613
commit
35135433c2
|
@ -24,6 +24,7 @@ package signaling
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
|
@ -222,7 +223,7 @@ func (r *ServerMessage) String() string {
|
|||
type Error struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
Details interface{} `json:"details,omitempty"`
|
||||
Details json.RawMessage `json:"details,omitempty"`
|
||||
}
|
||||
|
||||
func NewError(code string, message string) *Error {
|
||||
|
@ -230,10 +231,19 @@ func NewError(code string, message string) *Error {
|
|||
}
|
||||
|
||||
func NewErrorDetail(code string, message string, details interface{}) *Error {
|
||||
var rawDetails json.RawMessage
|
||||
if details != nil {
|
||||
var err error
|
||||
if rawDetails, err = json.Marshal(details); err != nil {
|
||||
log.Printf("Could not marshal details %+v for error %s with %s: %s", details, code, message, err)
|
||||
return NewError("internal_error", "Could not marshal error details")
|
||||
}
|
||||
}
|
||||
|
||||
return &Error{
|
||||
Code: code,
|
||||
Message: message,
|
||||
Details: details,
|
||||
Details: rawDetails,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,6 +521,10 @@ type RoomServerMessage struct {
|
|||
Properties *json.RawMessage `json:"properties,omitempty"`
|
||||
}
|
||||
|
||||
type RoomErrorDetails struct {
|
||||
Room *RoomServerMessage `json:"room"`
|
||||
}
|
||||
|
||||
// Type "message"
|
||||
|
||||
const (
|
||||
|
|
|
@ -417,6 +417,36 @@ func (s *ClientSession) SubscribeEvents() error {
|
|||
return s.events.RegisterSessionListener(s.publicId, s.backend, s)
|
||||
}
|
||||
|
||||
func (s *ClientSession) UpdateRoomSessionId(roomSessionId string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
||||
if s.roomSessionId == roomSessionId {
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := s.hub.roomSessions.SetRoomSession(s, roomSessionId); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if roomSessionId != "" {
|
||||
if room := s.GetRoom(); room != nil {
|
||||
log.Printf("Session %s updated room session id to %s in room %s", s.PublicId(), roomSessionId, room.Id())
|
||||
} else {
|
||||
log.Printf("Session %s updated room session id to %s in unknown room", s.PublicId(), roomSessionId)
|
||||
}
|
||||
} else {
|
||||
if room := s.GetRoom(); room != nil {
|
||||
log.Printf("Session %s cleared room session id in room %s", s.PublicId(), room.Id())
|
||||
} else {
|
||||
log.Printf("Session %s cleared room session id in unknown room", s.PublicId())
|
||||
}
|
||||
}
|
||||
|
||||
s.roomSessionId = roomSessionId
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ClientSession) SubscribeRoomEvents(roomid string, roomSessionId string) error {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
|
|
|
@ -460,6 +460,26 @@ Message format (Server -> Client):
|
|||
the current room or the properties of a room change.
|
||||
|
||||
|
||||
Message format (Server -> Client if already joined before):
|
||||
|
||||
{
|
||||
"id": "unique-request-id-from-request",
|
||||
"type": "error",
|
||||
"error": {
|
||||
"code": "already_joined",
|
||||
"message": "Human readable error message",
|
||||
"details": {
|
||||
"roomid": "the-room-id",
|
||||
"properties": {
|
||||
...additional room properties...
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- Sent if a client tried to join a room it is already in.
|
||||
|
||||
|
||||
### Backend validation
|
||||
|
||||
Rooms are managed by the Nextcloud backend, so the signaling server has to
|
||||
|
|
18
hub.go
18
hub.go
|
@ -1256,6 +1256,24 @@ func (h *Hub) processRoom(client *Client, message *ClientMessage) {
|
|||
if session != nil {
|
||||
if room := h.getRoomForBackend(roomId, session.Backend()); room != nil && room.HasSession(session) {
|
||||
// Session already is in that room, no action needed.
|
||||
roomSessionId := message.Room.SessionId
|
||||
if roomSessionId == "" {
|
||||
// TODO(jojo): Better make the session id required in the request.
|
||||
log.Printf("User did not send a room session id, assuming session %s", session.PublicId())
|
||||
roomSessionId = session.PublicId()
|
||||
}
|
||||
|
||||
if err := session.UpdateRoomSessionId(roomSessionId); err != nil {
|
||||
log.Printf("Error updating room session id for session %s: %s", session.PublicId(), err)
|
||||
}
|
||||
session.SendMessage(message.NewErrorServerMessage(
|
||||
NewErrorDetail("already_joined", "Already joined this room.", &RoomErrorDetails{
|
||||
Room: &RoomServerMessage{
|
||||
RoomId: room.id,
|
||||
Properties: room.properties,
|
||||
},
|
||||
}),
|
||||
))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
83
hub_test.go
83
hub_test.go
|
@ -22,6 +22,7 @@
|
|||
package signaling
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/ecdsa"
|
||||
"crypto/ed25519"
|
||||
|
@ -58,6 +59,10 @@ const (
|
|||
testTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
var (
|
||||
testRoomProperties = []byte("{\"prop1\":\"value1\"}")
|
||||
)
|
||||
|
||||
var (
|
||||
clusteredTests = []string{
|
||||
"local",
|
||||
|
@ -405,6 +410,7 @@ func processRoomRequest(t *testing.T, w http.ResponseWriter, r *http.Request, re
|
|||
Room: &BackendClientRoomResponse{
|
||||
Version: BackendVersion,
|
||||
RoomId: request.Room.RoomId,
|
||||
Properties: (*json.RawMessage)(&testRoomProperties),
|
||||
},
|
||||
}
|
||||
switch request.Room.RoomId {
|
||||
|
@ -2628,6 +2634,83 @@ func TestJoinRoom(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestJoinRoomTwice(t *testing.T) {
|
||||
hub, _, _, server := CreateHubForTest(t)
|
||||
|
||||
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()
|
||||
|
||||
hello, err := client.RunUntilHello(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Join room by id.
|
||||
roomId := "test-room"
|
||||
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)
|
||||
} else if !bytes.Equal(testRoomProperties, *room.Room.Properties) {
|
||||
t.Fatalf("Expected room properties %s, got %s", string(testRoomProperties), string(*room.Room.Properties))
|
||||
}
|
||||
|
||||
// We will receive a "joined" event.
|
||||
if err := client.RunUntilJoined(ctx, hello.Hello); err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
||||
msg := &ClientMessage{
|
||||
Id: "ABCD",
|
||||
Type: "room",
|
||||
Room: &RoomClientMessage{
|
||||
RoomId: roomId,
|
||||
SessionId: roomId + "-" + client.publicId + "-2",
|
||||
},
|
||||
}
|
||||
if err := client.WriteJSON(msg); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
message, err := client.RunUntilMessage(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if err := checkUnexpectedClose(err); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if msg.Id != message.Id {
|
||||
t.Errorf("expected message id %s, got %s", msg.Id, message.Id)
|
||||
} else if err := checkMessageType(message, "error"); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if expected := "already_joined"; message.Error.Code != expected {
|
||||
t.Errorf("expected error %s, got %s", expected, message.Error.Code)
|
||||
} else if message.Error.Details == nil {
|
||||
t.Fatal("expected error details")
|
||||
}
|
||||
|
||||
var roomMsg RoomErrorDetails
|
||||
if err := json.Unmarshal(message.Error.Details, &roomMsg); err != nil {
|
||||
t.Fatal(err)
|
||||
} else if roomMsg.Room == nil {
|
||||
t.Fatalf("expected room details, got %+v", message)
|
||||
}
|
||||
|
||||
if roomMsg.Room.RoomId != roomId {
|
||||
t.Fatalf("Expected room %s, got %+v", roomId, roomMsg.Room)
|
||||
} else if !bytes.Equal(testRoomProperties, *roomMsg.Room.Properties) {
|
||||
t.Fatalf("Expected room properties %s, got %s", string(testRoomProperties), string(*roomMsg.Room.Properties))
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpectAnonymousJoinRoom(t *testing.T) {
|
||||
hub, _, _, server := CreateHubForTest(t)
|
||||
|
||||
|
|
Loading…
Reference in a new issue