From f7bcfd61a1bf67a3bb31170005b390871338410d Mon Sep 17 00:00:00 2001 From: Lance Cooper Date: Wed, 15 Oct 2014 11:29:39 +0200 Subject: [PATCH] Add server support for responding with Welcome to a Hello. --- doc/CHANNELING-API.txt | 38 ++++++++++++- src/app/spreed-webrtc-server/channeling.go | 11 ++++ .../spreed-webrtc-server/channelling_api.go | 8 +++ .../channelling_api_test.go | 56 ++++++++++++++++++- 4 files changed, 110 insertions(+), 3 deletions(-) diff --git a/doc/CHANNELING-API.txt b/doc/CHANNELING-API.txt index 60606947..968dcafc 100644 --- a/doc/CHANNELING-API.txt +++ b/doc/CHANNELING-API.txt @@ -87,6 +87,16 @@ Sending vs receiving document data encapsulation A : Session attestation token. Only available for incoming data created by other sessions (optional). +Error returns + + Calls providing an Iid which fail will receive an Error document with the + following format: + + { + "Type": "Error", + "Code": "value_identifying_error", + "Message": "A description of the error condition" + } Special purpose documents for channling @@ -151,8 +161,10 @@ Special purpose documents for channling } } - Hello document is to be send by the client after connection was - established. + Hello document is to be send by the client after connection was established. + If an Iid is provided, a Welcome document will be returned if joining the + room with the given Id succeeds. Otherwise an Error document with one of the + error codes listed below will be returned. Keys under Hello: @@ -160,6 +172,28 @@ Special purpose documents for channling Ua : User agent description (string). Id : Room id. The default Room has the empty string Id ("") (string). + Error codes: + + default_room_disabled : Joining the room "" is not allowed by this server. + + Welcome + + { + Type: "Welcome", + Welcome: { + Users: [ + ], + } + } + + Welcome is sent in reply to a successful Hello, and contains all data + needed to set up the initial room connection. + + Keys under Welcome: + + Users: Contains the user list for the room, see the description of + the Users document for more details. + Peer connection documents Offer diff --git a/src/app/spreed-webrtc-server/channeling.go b/src/app/spreed-webrtc-server/channeling.go index 9e040a1a..076180a9 100644 --- a/src/app/spreed-webrtc-server/channeling.go +++ b/src/app/spreed-webrtc-server/channeling.go @@ -21,12 +21,23 @@ package main +type DataError struct { + Type string + Code string + Message string +} + type DataHello struct { Version string Ua string Id string } +type DataWelcome struct { + Type string + Users []*DataSession +} + type DataOffer struct { Type string To string diff --git a/src/app/spreed-webrtc-server/channelling_api.go b/src/app/spreed-webrtc-server/channelling_api.go index f6a9f3fc..12a19a65 100644 --- a/src/app/spreed-webrtc-server/channelling_api.go +++ b/src/app/spreed-webrtc-server/channelling_api.go @@ -85,13 +85,21 @@ func (api *channellingAPI) OnIncoming(c ResponseSender, session *Session, msg *D api.Broadcast(session, session.DataSessionLeft("soft")) } + // NOTE(lcooper): Iid filtered for compatibility's sake. + // Evaluate sending unconditionally when supported by all clients. if api.CanJoinRoom(msg.Hello.Id) { session.Hello = true session.Roomid = msg.Hello.Id api.JoinRoom(session, c) + if msg.Iid != "" { + c.Reply(msg.Iid, &DataWelcome{Type: "Welcome", Users: api.RoomUsers(session)}) + } api.Broadcast(session, session.DataSessionJoined()) } else { session.Hello = false + if msg.Iid != "" { + c.Reply(msg.Iid, &DataError{Type: "Error", Code: "default_room_disabled", Message: "The default room is not enabled"}) + } } case "Offer": // TODO(longsleep): Validate offer diff --git a/src/app/spreed-webrtc-server/channelling_api_test.go b/src/app/spreed-webrtc-server/channelling_api_test.go index ceec4678..25f1c650 100644 --- a/src/app/spreed-webrtc-server/channelling_api_test.go +++ b/src/app/spreed-webrtc-server/channelling_api_test.go @@ -30,12 +30,18 @@ const ( ) type fakeClient struct { + replies map[string]interface{} } func (fake *fakeClient) Send(_ Buffer) { } -func (fake *fakeClient) Reply(_ string, _ interface{}) { +func (fake *fakeClient) Reply(iid string, msg interface{}) { + if fake.replies == nil { + fake.replies = make(map[string]interface{}) + } + + fake.replies[iid] = msg } type fakeRoomManager struct { @@ -132,3 +138,51 @@ func Test_ChannellingAPI_OnIncoming_HelloMessage_DoesNotJoinIfNotPermitted(t *te t.Fatalf("Expected no broadcasts, but got %d", broadcastCount) } } + +func Test_ChannellingAPI_OnIncoming_HelloMessageWithAnIid_RespondsWithAWelcome(t *testing.T) { + iid := "foo" + api, client, session, roomManager := NewTestChannellingAPI() + roomManager.roomUsers = []*DataSession{&DataSession{}} + + api.OnIncoming(client, session, &DataIncoming{Type: "Hello", Iid: iid, Hello: &DataHello{}}) + + msg, ok := client.replies[iid] + if !ok { + t.Fatalf("No response received for Iid %v", iid) + } + + welcome, ok := msg.(*DataWelcome) + if !ok { + t.Fatalf("Expected response message %#v to be a Welcome", msg) + } + + if welcome.Type != "Welcome" { + t.Error("Message did not have the correct type") + } + + if len(welcome.Users) != len(roomManager.roomUsers) { + t.Errorf("Expected to get users %#v, but was %#v", roomManager.roomUsers, welcome.Users) + } +} + +func Test_ChannellingAPI_OnIncoming_HelloMessageWithAnIid_RespondsWithAnErrorIfTheRoomCannotBeJoined(t *testing.T) { + iid := "foo" + api, client, session, roomManager := NewTestChannellingAPI() + roomManager.disallowJoin = true + + api.OnIncoming(client, session, &DataIncoming{Type: "Hello", Iid: iid, Hello: &DataHello{}}) + + msg, ok := client.replies[iid] + if !ok { + t.Fatalf("No response received for Iid %v", iid) + } + + err, ok := msg.(*DataError) + if !ok { + t.Fatalf("Expected response message %#v to be an Error", msg) + } + + if err.Type != "Error" { + t.Error("Message did not have the correct type") + } +}