|
|
@ -31,9 +31,9 @@ const ( |
|
|
|
) |
|
|
|
) |
|
|
|
|
|
|
|
|
|
|
|
type ChannellingAPI interface { |
|
|
|
type ChannellingAPI interface { |
|
|
|
OnConnect(Client, *Session) |
|
|
|
OnConnect(Client, *Session) (interface{}, error) |
|
|
|
OnDisconnect(Client, *Session) |
|
|
|
OnDisconnect(Client, *Session) |
|
|
|
OnIncoming(ResponseSender, *Session, *DataIncoming) |
|
|
|
OnIncoming(Sender, *Session, *DataIncoming) (interface{}, error) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
type channellingAPI struct { |
|
|
|
type channellingAPI struct { |
|
|
@ -60,169 +60,113 @@ func NewChannellingAPI(config *Config, roomStatus RoomStatusManager, sessionEnco |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) OnConnect(client Client, session *Session) { |
|
|
|
func (api *channellingAPI) OnConnect(client Client, session *Session) (interface{}, error) { |
|
|
|
api.Unicaster.OnConnect(client, session) |
|
|
|
api.Unicaster.OnConnect(client, session) |
|
|
|
api.SendSelf(client, session) |
|
|
|
return api.HandleSelf(session) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) OnDisconnect(client Client, session *Session) { |
|
|
|
func (api *channellingAPI) OnDisconnect(client Client, session *Session) { |
|
|
|
api.Unicaster.OnDisconnect(client, session) |
|
|
|
api.Unicaster.OnDisconnect(client, session) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) OnIncoming(c ResponseSender, session *Session, msg *DataIncoming) { |
|
|
|
func (api *channellingAPI) OnIncoming(sender Sender, session *Session, msg *DataIncoming) (interface{}, error) { |
|
|
|
switch msg.Type { |
|
|
|
switch msg.Type { |
|
|
|
case "Self": |
|
|
|
case "Self": |
|
|
|
api.SendSelf(c, session) |
|
|
|
return api.HandleSelf(session) |
|
|
|
case "Hello": |
|
|
|
case "Hello": |
|
|
|
//log.Println("Hello", msg.Hello, c.Index())
|
|
|
|
if msg.Hello == nil { |
|
|
|
// TODO(longsleep): Filter room id and user agent.
|
|
|
|
return nil, NewDataError("bad_request", "message did not contain Hello") |
|
|
|
session.Update(&SessionUpdate{Types: []string{"Ua"}, Ua: msg.Hello.Ua}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
room, err := session.JoinRoom(msg.Hello.Id, msg.Hello.Credentials, c) |
|
|
|
|
|
|
|
// NOTE(lcooper): Iid filtered for compatibility's sake.
|
|
|
|
|
|
|
|
// Evaluate sending unconditionally when supported by all clients.
|
|
|
|
|
|
|
|
if msg.Iid != "" { |
|
|
|
|
|
|
|
if err == nil { |
|
|
|
|
|
|
|
c.Reply(msg.Iid, &DataWelcome{ |
|
|
|
|
|
|
|
Type: "Welcome", |
|
|
|
|
|
|
|
Room: room, |
|
|
|
|
|
|
|
Users: api.RoomUsers(session), |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
c.Reply(msg.Iid, err) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return api.HandleHello(session, msg.Hello, sender) |
|
|
|
case "Offer": |
|
|
|
case "Offer": |
|
|
|
|
|
|
|
if msg.Offer == nil { |
|
|
|
|
|
|
|
log.Println("Received invalid offer message.", msg) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO(longsleep): Validate offer
|
|
|
|
// TODO(longsleep): Validate offer
|
|
|
|
session.Unicast(msg.Offer.To, msg.Offer) |
|
|
|
session.Unicast(msg.Offer.To, msg.Offer) |
|
|
|
case "Candidate": |
|
|
|
case "Candidate": |
|
|
|
|
|
|
|
if msg.Candidate == nil { |
|
|
|
|
|
|
|
log.Println("Received invalid candidate message.", msg) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO(longsleep): Validate candidate
|
|
|
|
// TODO(longsleep): Validate candidate
|
|
|
|
session.Unicast(msg.Candidate.To, msg.Candidate) |
|
|
|
session.Unicast(msg.Candidate.To, msg.Candidate) |
|
|
|
case "Answer": |
|
|
|
case "Answer": |
|
|
|
|
|
|
|
if msg.Answer == nil { |
|
|
|
|
|
|
|
log.Println("Received invalid answer message.", msg) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO(longsleep): Validate Answer
|
|
|
|
// TODO(longsleep): Validate Answer
|
|
|
|
session.Unicast(msg.Answer.To, msg.Answer) |
|
|
|
session.Unicast(msg.Answer.To, msg.Answer) |
|
|
|
case "Users": |
|
|
|
case "Users": |
|
|
|
if session.Hello { |
|
|
|
return api.HandleUsers(session) |
|
|
|
sessions := &DataSessions{Type: "Users", Users: api.RoomUsers(session)} |
|
|
|
|
|
|
|
c.Reply(msg.Iid, sessions) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case "Authentication": |
|
|
|
case "Authentication": |
|
|
|
st := msg.Authentication.Authentication |
|
|
|
if msg.Authentication == nil || msg.Authentication.Authentication == nil { |
|
|
|
if st == nil { |
|
|
|
return nil, NewDataError("bad_request", "message did not contain Authentication") |
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if err := api.Authenticate(session, st, ""); err == nil { |
|
|
|
return api.HandleAuthentication(session, msg.Authentication.Authentication) |
|
|
|
log.Println("Authentication success", session.Userid()) |
|
|
|
|
|
|
|
api.SendSelf(c, session) |
|
|
|
|
|
|
|
session.BroadcastStatus() |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
log.Println("Authentication failed", err, st.Userid, st.Nonce) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case "Bye": |
|
|
|
case "Bye": |
|
|
|
|
|
|
|
if msg.Bye == nil { |
|
|
|
|
|
|
|
log.Println("Received invalid bye message.", msg) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
session.Unicast(msg.Bye.To, msg.Bye) |
|
|
|
session.Unicast(msg.Bye.To, msg.Bye) |
|
|
|
case "Status": |
|
|
|
case "Status": |
|
|
|
|
|
|
|
if msg.Status == nil { |
|
|
|
|
|
|
|
log.Println("Received invalid status message.", msg) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//log.Println("Status", msg.Status)
|
|
|
|
//log.Println("Status", msg.Status)
|
|
|
|
session.Update(&SessionUpdate{Types: []string{"Status"}, Status: msg.Status.Status}) |
|
|
|
session.Update(&SessionUpdate{Types: []string{"Status"}, Status: msg.Status.Status}) |
|
|
|
session.BroadcastStatus() |
|
|
|
session.BroadcastStatus() |
|
|
|
case "Chat": |
|
|
|
case "Chat": |
|
|
|
// TODO(longsleep): Limit sent chat messages per incoming connection.
|
|
|
|
if msg.Chat == nil || msg.Chat.Chat == nil { |
|
|
|
if !msg.Chat.Chat.NoEcho { |
|
|
|
log.Println("Received invalid chat message.", msg) |
|
|
|
session.Unicast(session.Id, msg.Chat) |
|
|
|
break |
|
|
|
} |
|
|
|
|
|
|
|
msg.Chat.Chat.Time = time.Now().Format(time.RFC3339) |
|
|
|
|
|
|
|
if msg.Chat.To == "" { |
|
|
|
|
|
|
|
// TODO(longsleep): Check if chat broadcast is allowed.
|
|
|
|
|
|
|
|
if session.Hello { |
|
|
|
|
|
|
|
api.CountBroadcastChat() |
|
|
|
|
|
|
|
session.Broadcast(msg.Chat) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if msg.Chat.Chat.Status != nil && msg.Chat.Chat.Status.ContactRequest != nil { |
|
|
|
|
|
|
|
if !api.Config.WithModule("contacts") { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if err := api.contactrequestHandler(session, msg.Chat.To, msg.Chat.Chat.Status.ContactRequest); err != nil { |
|
|
|
|
|
|
|
log.Println("Ignoring invalid contact request.", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
msg.Chat.Chat.Status.ContactRequest.Userid = session.Userid() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if msg.Chat.Chat.Status == nil { |
|
|
|
|
|
|
|
api.CountUnicastChat() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
session.Unicast(msg.Chat.To, msg.Chat) |
|
|
|
|
|
|
|
if msg.Chat.Chat.Mid != "" { |
|
|
|
|
|
|
|
// Send out delivery confirmation status chat message.
|
|
|
|
|
|
|
|
session.Unicast(session.Id, &DataChat{To: msg.Chat.To, Type: "Chat", Chat: &DataChatMessage{Mid: msg.Chat.Chat.Mid, Status: &DataChatStatus{State: "sent"}}}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api.HandleChat(session, msg.Chat.To, msg.Chat.Chat) |
|
|
|
case "Conference": |
|
|
|
case "Conference": |
|
|
|
// Check conference maximum size.
|
|
|
|
if msg.Conference == nil { |
|
|
|
if len(msg.Conference.Conference) > maxConferenceSize { |
|
|
|
log.Println("Received invalid conference message.", msg) |
|
|
|
log.Println("Refusing to create conference above limit.", len(msg.Conference.Conference)) |
|
|
|
break |
|
|
|
} else { |
|
|
|
|
|
|
|
// Send conference update to anyone.
|
|
|
|
|
|
|
|
for _, id := range msg.Conference.Conference { |
|
|
|
|
|
|
|
if id != session.Id { |
|
|
|
|
|
|
|
session.Unicast(id, msg.Conference) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
api.HandleConference(session, msg.Conference) |
|
|
|
case "Alive": |
|
|
|
case "Alive": |
|
|
|
c.Reply(msg.Iid, msg.Alive) |
|
|
|
return msg.Alive, nil |
|
|
|
case "Sessions": |
|
|
|
case "Sessions": |
|
|
|
var users []*DataSession |
|
|
|
if msg.Sessions == nil || msg.Sessions.Sessions == nil { |
|
|
|
switch msg.Sessions.Sessions.Type { |
|
|
|
return nil, NewDataError("bad_request", "message did not contain Sessions") |
|
|
|
case "contact": |
|
|
|
|
|
|
|
if api.Config.WithModule("contacts") { |
|
|
|
|
|
|
|
if userID, err := api.getContactID(session, msg.Sessions.Sessions.Token); err == nil { |
|
|
|
|
|
|
|
users = api.GetUserSessions(session, userID) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
log.Printf(err.Error()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
log.Printf("Incoming contacts session request with contacts disabled") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case "session": |
|
|
|
|
|
|
|
id, err := session.attestation.Decode(msg.Sessions.Sessions.Token) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
log.Printf("Failed to decode incoming attestation", err, msg.Sessions.Sessions.Token) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
session, ok := api.GetSession(id) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
log.Printf("Cannot retrieve session for id %s", id) |
|
|
|
|
|
|
|
break |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
users = make([]*DataSession, 1, 1) |
|
|
|
|
|
|
|
users[0] = session.Data() |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
log.Printf("Unkown incoming sessions request type %s", msg.Sessions.Sessions.Type) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// TODO(lcooper): We ought to reply with a *DataError here if failed.
|
|
|
|
return api.HandleSessions(session, msg.Sessions.Sessions) |
|
|
|
if users != nil { |
|
|
|
|
|
|
|
c.Reply(msg.Iid, &DataSessions{Type: "Sessions", Users: users, Sessions: msg.Sessions.Sessions}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
case "Room": |
|
|
|
case "Room": |
|
|
|
if room, err := api.UpdateRoom(session, msg.Room); err == nil { |
|
|
|
if msg.Room == nil { |
|
|
|
session.Broadcast(room) |
|
|
|
return nil, NewDataError("bad_request", "message did not contain Room") |
|
|
|
c.Reply(msg.Iid, room) |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
c.Reply(msg.Iid, err) |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return api.HandleRoom(session, msg.Room) |
|
|
|
default: |
|
|
|
default: |
|
|
|
log.Println("OnText unhandled message type", msg.Type) |
|
|
|
log.Println("OnText unhandled message type", msg.Type) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return nil, nil |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) SendSelf(c Responder, session *Session) { |
|
|
|
func (api *channellingAPI) HandleSelf(session *Session) (*DataSelf, error) { |
|
|
|
token, err := api.EncodeSessionToken(session) |
|
|
|
token, err := api.EncodeSessionToken(session) |
|
|
|
if err != nil { |
|
|
|
if err != nil { |
|
|
|
log.Println("Error in OnRegister", err) |
|
|
|
log.Println("Error in OnRegister", err) |
|
|
|
return |
|
|
|
return nil, err |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
log.Println("Created new session token", len(token), token) |
|
|
|
log.Println("Created new session token", len(token), token) |
|
|
@ -237,5 +181,138 @@ func (api *channellingAPI) SendSelf(c Responder, session *Session) { |
|
|
|
Turn: api.CreateTurnData(session), |
|
|
|
Turn: api.CreateTurnData(session), |
|
|
|
Stun: api.StunURIs, |
|
|
|
Stun: api.StunURIs, |
|
|
|
} |
|
|
|
} |
|
|
|
c.Reply("", self) |
|
|
|
|
|
|
|
|
|
|
|
return self, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleHello(session *Session, hello *DataHello, sender Sender) (*DataWelcome, error) { |
|
|
|
|
|
|
|
// TODO(longsleep): Filter room id and user agent.
|
|
|
|
|
|
|
|
session.Update(&SessionUpdate{Types: []string{"Ua"}, Ua: hello.Ua}) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
room, err := session.JoinRoom(hello.Id, hello.Credentials, sender) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return &DataWelcome{ |
|
|
|
|
|
|
|
Type: "Welcome", |
|
|
|
|
|
|
|
Room: room, |
|
|
|
|
|
|
|
Users: api.RoomUsers(session), |
|
|
|
|
|
|
|
}, nil |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleUsers(session *Session) (sessions *DataSessions, err error) { |
|
|
|
|
|
|
|
if session.Hello { |
|
|
|
|
|
|
|
sessions = &DataSessions{Type: "Users", Users: api.RoomUsers(session)} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
err = NewDataError("not_in_room", "Cannot list users without a current room") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleAuthentication(session *Session, st *SessionToken) (*DataSelf, error) { |
|
|
|
|
|
|
|
if err := api.Authenticate(session, st, ""); err != nil { |
|
|
|
|
|
|
|
log.Println("Authentication failed", err, st.Userid, st.Nonce) |
|
|
|
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
log.Println("Authentication success", session.Userid()) |
|
|
|
|
|
|
|
self, err := api.HandleSelf(session) |
|
|
|
|
|
|
|
if err == nil { |
|
|
|
|
|
|
|
session.BroadcastStatus() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return self, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleChat(session *Session, to string, chat *DataChatMessage) { |
|
|
|
|
|
|
|
// TODO(longsleep): Limit sent chat messages per incoming connection.
|
|
|
|
|
|
|
|
if !chat.NoEcho { |
|
|
|
|
|
|
|
session.Unicast(session.Id, chat) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
chat.Time = time.Now().Format(time.RFC3339) |
|
|
|
|
|
|
|
if to == "" { |
|
|
|
|
|
|
|
// TODO(longsleep): Check if chat broadcast is allowed.
|
|
|
|
|
|
|
|
if session.Hello { |
|
|
|
|
|
|
|
api.CountBroadcastChat() |
|
|
|
|
|
|
|
session.Broadcast(chat) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if chat.Status != nil { |
|
|
|
|
|
|
|
if chat.Status.ContactRequest != nil { |
|
|
|
|
|
|
|
if !api.Config.WithModule("contacts") { |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if err := api.contactrequestHandler(session, to, chat.Status.ContactRequest); err != nil { |
|
|
|
|
|
|
|
log.Println("Ignoring invalid contact request.", err) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
chat.Status.ContactRequest.Userid = session.Userid() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
api.CountUnicastChat() |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
session.Unicast(to, chat) |
|
|
|
|
|
|
|
if chat.Mid != "" { |
|
|
|
|
|
|
|
// Send out delivery confirmation status chat message.
|
|
|
|
|
|
|
|
session.Unicast(session.Id, &DataChat{To: to, Type: "Chat", Chat: &DataChatMessage{Mid: chat.Mid, Status: &DataChatStatus{State: "sent"}}}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleConference(session *Session, conference *DataConference) { |
|
|
|
|
|
|
|
// Check conference maximum size.
|
|
|
|
|
|
|
|
if len(conference.Conference) > maxConferenceSize { |
|
|
|
|
|
|
|
log.Println("Refusing to create conference above limit.", len(conference.Conference)) |
|
|
|
|
|
|
|
return |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send conference update to anyone.
|
|
|
|
|
|
|
|
for _, id := range conference.Conference { |
|
|
|
|
|
|
|
if id != session.Id { |
|
|
|
|
|
|
|
session.Unicast(id, conference) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleSessions(session *Session, sessions *DataSessionsRequest) (*DataSessions, error) { |
|
|
|
|
|
|
|
switch sessions.Type { |
|
|
|
|
|
|
|
case "contact": |
|
|
|
|
|
|
|
if !api.Config.WithModule("contacts") { |
|
|
|
|
|
|
|
return nil, NewDataError("contacts_not_enabled", "incoming contacts session request with contacts disabled") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
userID, err := api.getContactID(session, sessions.Token) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, err |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return &DataSessions{ |
|
|
|
|
|
|
|
Type: "Sessions", |
|
|
|
|
|
|
|
Users: api.GetUserSessions(session, userID), |
|
|
|
|
|
|
|
Sessions: sessions, |
|
|
|
|
|
|
|
}, nil |
|
|
|
|
|
|
|
case "session": |
|
|
|
|
|
|
|
id, err := session.attestation.Decode(sessions.Token) |
|
|
|
|
|
|
|
if err != nil { |
|
|
|
|
|
|
|
return nil, NewDataError("bad_attestation", err.Error()) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
session, ok := api.GetSession(id) |
|
|
|
|
|
|
|
if !ok { |
|
|
|
|
|
|
|
return nil, NewDataError("no_such_session", "cannot retrieve session") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return &DataSessions{ |
|
|
|
|
|
|
|
Type: "Sessions", |
|
|
|
|
|
|
|
Users: []*DataSession{session.Data()}, |
|
|
|
|
|
|
|
Sessions: sessions, |
|
|
|
|
|
|
|
}, nil |
|
|
|
|
|
|
|
default: |
|
|
|
|
|
|
|
return nil, NewDataError("bad_request", "unknown sessions request type") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
func (api *channellingAPI) HandleRoom(session *Session, room *DataRoom) (*DataRoom, error) { |
|
|
|
|
|
|
|
room, err := api.UpdateRoom(session, room) |
|
|
|
|
|
|
|
if err == nil { |
|
|
|
|
|
|
|
session.Broadcast(room) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
return room, err |
|
|
|
} |
|
|
|
} |
|
|
|