mirror of
https://github.com/strukturag/nextcloud-spreed-signaling
synced 2024-05-10 01:26:32 +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 (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -220,9 +221,9 @@ func (r *ServerMessage) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Error struct {
|
type Error struct {
|
||||||
Code string `json:"code"`
|
Code string `json:"code"`
|
||||||
Message string `json:"message"`
|
Message string `json:"message"`
|
||||||
Details interface{} `json:"details,omitempty"`
|
Details json.RawMessage `json:"details,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewError(code string, message string) *Error {
|
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 {
|
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{
|
return &Error{
|
||||||
Code: code,
|
Code: code,
|
||||||
Message: message,
|
Message: message,
|
||||||
Details: details,
|
Details: rawDetails,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -511,6 +521,10 @@ type RoomServerMessage struct {
|
||||||
Properties *json.RawMessage `json:"properties,omitempty"`
|
Properties *json.RawMessage `json:"properties,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type RoomErrorDetails struct {
|
||||||
|
Room *RoomServerMessage `json:"room"`
|
||||||
|
}
|
||||||
|
|
||||||
// Type "message"
|
// Type "message"
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
|
@ -417,6 +417,36 @@ func (s *ClientSession) SubscribeEvents() error {
|
||||||
return s.events.RegisterSessionListener(s.publicId, s.backend, s)
|
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 {
|
func (s *ClientSession) SubscribeRoomEvents(roomid string, roomSessionId string) error {
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
defer s.mu.Unlock()
|
defer s.mu.Unlock()
|
||||||
|
|
|
@ -460,6 +460,26 @@ Message format (Server -> Client):
|
||||||
the current room or the properties of a room change.
|
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
|
### Backend validation
|
||||||
|
|
||||||
Rooms are managed by the Nextcloud backend, so the signaling server has to
|
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 session != nil {
|
||||||
if room := h.getRoomForBackend(roomId, session.Backend()); room != nil && room.HasSession(session) {
|
if room := h.getRoomForBackend(roomId, session.Backend()); room != nil && room.HasSession(session) {
|
||||||
// Session already is in that room, no action needed.
|
// 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
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
87
hub_test.go
87
hub_test.go
|
@ -22,6 +22,7 @@
|
||||||
package signaling
|
package signaling
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"crypto/ed25519"
|
"crypto/ed25519"
|
||||||
|
@ -58,6 +59,10 @@ const (
|
||||||
testTimeout = 10 * time.Second
|
testTimeout = 10 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
testRoomProperties = []byte("{\"prop1\":\"value1\"}")
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
clusteredTests = []string{
|
clusteredTests = []string{
|
||||||
"local",
|
"local",
|
||||||
|
@ -403,8 +408,9 @@ func processRoomRequest(t *testing.T, w http.ResponseWriter, r *http.Request, re
|
||||||
response := &BackendClientResponse{
|
response := &BackendClientResponse{
|
||||||
Type: "room",
|
Type: "room",
|
||||||
Room: &BackendClientRoomResponse{
|
Room: &BackendClientRoomResponse{
|
||||||
Version: BackendVersion,
|
Version: BackendVersion,
|
||||||
RoomId: request.Room.RoomId,
|
RoomId: request.Room.RoomId,
|
||||||
|
Properties: (*json.RawMessage)(&testRoomProperties),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
switch request.Room.RoomId {
|
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) {
|
func TestExpectAnonymousJoinRoom(t *testing.T) {
|
||||||
hub, _, _, server := CreateHubForTest(t)
|
hub, _, _, server := CreateHubForTest(t)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue