Only allow subscribing if both users are in the same room and call.
Previously it was possible to subscribe any stream if the session id of the publisher was known.
This commit is contained in:
parent
4530b91434
commit
b398591447
40
hub.go
40
hub.go
|
@ -1367,7 +1367,7 @@ func (h *Hub) processMessageMsg(client *Client, message *ClientMessage) {
|
||||||
if clientData != nil && clientData.Type == "sendoffer" {
|
if clientData != nil && clientData.Type == "sendoffer" {
|
||||||
if !isAllowedToSend(session, clientData) {
|
if !isAllowedToSend(session, clientData) {
|
||||||
log.Printf("Session %s is not allowed to send offer for %s, ignoring", session.PublicId(), clientData.RoomType)
|
log.Printf("Session %s is not allowed to send offer for %s, ignoring", session.PublicId(), clientData.RoomType)
|
||||||
sendNotAllowed(session, message)
|
sendNotAllowed(session, message, "Not allowed to send offer")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1652,8 +1652,8 @@ func isAllowedToSend(session *ClientSession, data *MessageClientMessageData) boo
|
||||||
return session.HasPermission(permission)
|
return session.HasPermission(permission)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendNotAllowed(session *ClientSession, message *ClientMessage) {
|
func sendNotAllowed(session *ClientSession, message *ClientMessage, reason string) {
|
||||||
response := message.NewErrorServerMessage(NewError("not_allowed", "Not allowed to publish."))
|
response := message.NewErrorServerMessage(NewError("not_allowed", reason))
|
||||||
session.SendMessage(response)
|
session.SendMessage(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1667,6 +1667,28 @@ func sendMcuProcessingFailed(session *ClientSession, message *ClientMessage) {
|
||||||
session.SendMessage(response)
|
session.SendMessage(response)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (h *Hub) isInSameCall(senderSession *ClientSession, recipientSessionId string) bool {
|
||||||
|
senderRoom := senderSession.GetRoom()
|
||||||
|
if senderRoom == nil || !senderRoom.IsSessionInCall(senderSession) {
|
||||||
|
// Sender is not in a room or not in the call.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
recipientSession := h.GetSessionByPublicId(recipientSessionId)
|
||||||
|
if recipientSession == nil {
|
||||||
|
// Recipient session does not exist.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
recipientRoom := recipientSession.GetRoom()
|
||||||
|
if recipientRoom == nil || !senderRoom.IsEqual(recipientRoom) || !recipientRoom.IsSessionInCall(recipientSession) {
|
||||||
|
// Recipient is not in a room, a different room or not in the call.
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSession, client_message *ClientMessage, message *MessageClientMessage, data *MessageClientMessageData) {
|
func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSession, client_message *ClientMessage, message *MessageClientMessage, data *MessageClientMessageData) {
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), h.mcuTimeout)
|
ctx, cancel := context.WithTimeout(context.Background(), h.mcuTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
@ -1681,6 +1703,14 @@ func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSes
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A user is only allowed to subscribe a stream if she is in the same room
|
||||||
|
// as the other user and both have their "inCall" flag set.
|
||||||
|
if !h.isInSameCall(senderSession, message.Recipient.SessionId) {
|
||||||
|
log.Printf("Session %s is not in the same call as session %s, not requesting offer", session.PublicId(), message.Recipient.SessionId)
|
||||||
|
sendNotAllowed(senderSession, client_message, "Not allowed to request offer.")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
clientType = "subscriber"
|
clientType = "subscriber"
|
||||||
mc, err = session.GetOrCreateSubscriber(ctx, h.mcu, message.Recipient.SessionId, data.RoomType)
|
mc, err = session.GetOrCreateSubscriber(ctx, h.mcu, message.Recipient.SessionId, data.RoomType)
|
||||||
case "sendoffer":
|
case "sendoffer":
|
||||||
|
@ -1690,7 +1720,7 @@ func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSes
|
||||||
case "offer":
|
case "offer":
|
||||||
if !isAllowedToSend(session, data) {
|
if !isAllowedToSend(session, data) {
|
||||||
log.Printf("Session %s is not allowed to offer %s, ignoring", session.PublicId(), data.RoomType)
|
log.Printf("Session %s is not allowed to offer %s, ignoring", session.PublicId(), data.RoomType)
|
||||||
sendNotAllowed(senderSession, client_message)
|
sendNotAllowed(senderSession, client_message, "Not allowed to publish.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1708,7 +1738,7 @@ func (h *Hub) processMcuMessage(senderSession *ClientSession, session *ClientSes
|
||||||
if session.PublicId() == message.Recipient.SessionId {
|
if session.PublicId() == message.Recipient.SessionId {
|
||||||
if !isAllowedToSend(session, data) {
|
if !isAllowedToSend(session, data) {
|
||||||
log.Printf("Session %s is not allowed to send candidate for %s, ignoring", session.PublicId(), data.RoomType)
|
log.Printf("Session %s is not allowed to send candidate for %s, ignoring", session.PublicId(), data.RoomType)
|
||||||
sendNotAllowed(senderSession, client_message)
|
sendNotAllowed(senderSession, client_message, "Not allowed to send candidate.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
197
hub_test.go
197
hub_test.go
|
@ -2449,6 +2449,191 @@ func TestClientSendOfferPermissions(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestClientRequestOfferNotInRoom(t *testing.T) {
|
||||||
|
hub, _, _, server, shutdown := CreateHubForTest(t)
|
||||||
|
defer shutdown()
|
||||||
|
|
||||||
|
mcu, err := NewTestMCU()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if err := mcu.Start(); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
defer mcu.Stop()
|
||||||
|
|
||||||
|
hub.SetMcu(mcu)
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(context.Background(), testTimeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
client1 := NewTestClient(t, server, hub)
|
||||||
|
defer client1.CloseWithBye()
|
||||||
|
|
||||||
|
if err := client1.SendHello(testDefaultUserId + "1"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hello1, err := client1.RunUntilHello(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
client2 := NewTestClient(t, server, hub)
|
||||||
|
defer client2.CloseWithBye()
|
||||||
|
|
||||||
|
if err := client2.SendHello(testDefaultUserId + "2"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hello2, err := client2.RunUntilHello(ctx)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join room by id.
|
||||||
|
roomId := "test-room"
|
||||||
|
if room, err := client1.JoinRoomWithRoomSession(ctx, roomId, "roomsession1"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else if room.Room.RoomId != roomId {
|
||||||
|
t.Fatalf("Expected room %s, got %s", roomId, room.Room.RoomId)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will receive a "joined" event.
|
||||||
|
if err := client1.RunUntilJoined(ctx, hello1.Hello); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client 2 may not request an offer (he is not in the room yet).
|
||||||
|
if err := client2.SendMessage(MessageClientMessageRecipient{
|
||||||
|
Type: "session",
|
||||||
|
SessionId: hello1.Hello.SessionId,
|
||||||
|
}, MessageClientMessageData{
|
||||||
|
Type: "requestoffer",
|
||||||
|
Sid: "12345",
|
||||||
|
RoomType: "screen",
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg, err := client2.RunUntilMessage(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if err := checkMessageError(msg, "not_allowed"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if room, err := client2.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We will receive a "joined" event.
|
||||||
|
if err := client1.RunUntilJoined(ctx, hello2.Hello); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if err := client2.RunUntilJoined(ctx, hello1.Hello, hello2.Hello); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client 2 may not request an offer (he is not in the call yet).
|
||||||
|
if err := client2.SendMessage(MessageClientMessageRecipient{
|
||||||
|
Type: "session",
|
||||||
|
SessionId: hello1.Hello.SessionId,
|
||||||
|
}, MessageClientMessageData{
|
||||||
|
Type: "requestoffer",
|
||||||
|
Sid: "12345",
|
||||||
|
RoomType: "screen",
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg, err := client2.RunUntilMessage(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if err := checkMessageError(msg, "not_allowed"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate request from the backend that somebody joined the call.
|
||||||
|
users1 := []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"sessionId": hello2.Hello.SessionId,
|
||||||
|
"inCall": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
room := hub.getRoom(roomId)
|
||||||
|
if room == nil {
|
||||||
|
t.Fatalf("Could not find room %s", roomId)
|
||||||
|
}
|
||||||
|
room.PublishUsersInCallChanged(users1, users1)
|
||||||
|
if err := checkReceiveClientEvent(ctx, client1, "update", nil); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if err := checkReceiveClientEvent(ctx, client2, "update", nil); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client 2 may not request an offer (recipient is not in the call yet).
|
||||||
|
if err := client2.SendMessage(MessageClientMessageRecipient{
|
||||||
|
Type: "session",
|
||||||
|
SessionId: hello1.Hello.SessionId,
|
||||||
|
}, MessageClientMessageData{
|
||||||
|
Type: "requestoffer",
|
||||||
|
Sid: "12345",
|
||||||
|
RoomType: "screen",
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg, err := client2.RunUntilMessage(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
if err := checkMessageError(msg, "not_allowed"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate request from the backend that somebody joined the call.
|
||||||
|
users2 := []map[string]interface{}{
|
||||||
|
{
|
||||||
|
"sessionId": hello1.Hello.SessionId,
|
||||||
|
"inCall": 1,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
room.PublishUsersInCallChanged(users2, users2)
|
||||||
|
if err := checkReceiveClientEvent(ctx, client1, "update", nil); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
if err := checkReceiveClientEvent(ctx, client2, "update", nil); err != nil {
|
||||||
|
t.Error(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Client 2 may request an offer now (both are in the same room and call).
|
||||||
|
if err := client2.SendMessage(MessageClientMessageRecipient{
|
||||||
|
Type: "session",
|
||||||
|
SessionId: hello1.Hello.SessionId,
|
||||||
|
}, MessageClientMessageData{
|
||||||
|
Type: "requestoffer",
|
||||||
|
Sid: "12345",
|
||||||
|
RoomType: "screen",
|
||||||
|
}); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if msg, err := client2.RunUntilMessage(ctx); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
} else {
|
||||||
|
// We check for "client_not_found" as the testing MCU doesn't support publishing/subscribing.
|
||||||
|
if err := checkMessageError(msg, "client_not_found"); err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
|
func TestNoSendBetweenSessionsOnDifferentBackends(t *testing.T) {
|
||||||
// Clients can't send messages to sessions connected from other backends.
|
// Clients can't send messages to sessions connected from other backends.
|
||||||
hub, _, _, server, shutdown := CreateHubWithMultipleBackendsForTest(t)
|
hub, _, _, server, shutdown := CreateHubWithMultipleBackendsForTest(t)
|
||||||
|
@ -2585,15 +2770,19 @@ func TestNoSameRoomOnDifferentBackends(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
hub.ru.RLock()
|
hub.ru.RLock()
|
||||||
roomCount := 0
|
var rooms []*Room
|
||||||
for _, room := range hub.rooms {
|
for _, room := range hub.rooms {
|
||||||
defer room.Close()
|
defer room.Close()
|
||||||
roomCount++
|
rooms = append(rooms, room)
|
||||||
}
|
}
|
||||||
hub.ru.RUnlock()
|
hub.ru.RUnlock()
|
||||||
|
|
||||||
if roomCount != 2 {
|
if len(rooms) != 2 {
|
||||||
t.Errorf("Expected 2 rooms, got %d", roomCount)
|
t.Errorf("Expected 2 rooms, got %+v", rooms)
|
||||||
|
}
|
||||||
|
|
||||||
|
if rooms[0].IsEqual(rooms[1]) {
|
||||||
|
t.Errorf("Rooms should be different: %+v", rooms)
|
||||||
}
|
}
|
||||||
|
|
||||||
recipient := MessageClientMessageRecipient{
|
recipient := MessageClientMessageRecipient{
|
||||||
|
|
29
room.go
29
room.go
|
@ -159,6 +159,28 @@ func (r *Room) Backend() *Backend {
|
||||||
return r.backend
|
return r.backend
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Room) IsEqual(other *Room) bool {
|
||||||
|
if r == other {
|
||||||
|
return true
|
||||||
|
} else if other == nil {
|
||||||
|
return false
|
||||||
|
} else if r.Id() != other.Id() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
b1 := r.Backend()
|
||||||
|
b2 := other.Backend()
|
||||||
|
if b1 == b2 {
|
||||||
|
return true
|
||||||
|
} else if b1 == nil && b2 != nil {
|
||||||
|
return false
|
||||||
|
} else if b1 != nil && b2 == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return b1.Id() == b2.Id()
|
||||||
|
}
|
||||||
|
|
||||||
func (r *Room) run() {
|
func (r *Room) run() {
|
||||||
ticker := time.NewTicker(updateActiveSessionsInterval)
|
ticker := time.NewTicker(updateActiveSessionsInterval)
|
||||||
loop:
|
loop:
|
||||||
|
@ -320,6 +342,13 @@ func (r *Room) HasSession(session Session) bool {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Room) IsSessionInCall(session Session) bool {
|
||||||
|
r.mu.RLock()
|
||||||
|
_, result := r.inCallSessions[session]
|
||||||
|
r.mu.RUnlock()
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// Returns "true" if there are still clients in the room.
|
// Returns "true" if there are still clients in the room.
|
||||||
func (r *Room) RemoveSession(session Session) bool {
|
func (r *Room) RemoveSession(session Session) bool {
|
||||||
r.mu.Lock()
|
r.mu.Lock()
|
||||||
|
|
Loading…
Reference in New Issue