func (api *channellingAPI) HandleSessions(session *channelling.Session, sessions *channelling.DataSessionsRequest) (*channelling.DataSessions, error) { switch sessions.Type { case "contact": if !api.config.WithModule("contacts") { return nil, channelling.NewDataError("contacts_not_enabled", "incoming contacts session request with contacts disabled") } userID, err := api.ContactManager.GetContactID(session, sessions.Token) if err != nil { return nil, err } return &channelling.DataSessions{ Type: "Sessions", Users: api.SessionManager.GetUserSessions(session, userID), Sessions: sessions, }, nil case "session": id, err := session.DecodeAttestation(sessions.Token) if err != nil { return nil, channelling.NewDataError("bad_attestation", err.Error()) } session, ok := api.Unicaster.GetSession(id) if !ok { return nil, channelling.NewDataError("no_such_session", "cannot retrieve session") } return &channelling.DataSessions{ Type: "Sessions", Users: []*channelling.DataSession{session.Data()}, Sessions: sessions, }, nil default: return nil, channelling.NewDataError("bad_request", "unknown sessions request type") } }
func (api *channellingAPI) HandleRoom(session *channelling.Session, room *channelling.DataRoom) (*channelling.DataRoom, error) { room, err := api.RoomStatusManager.UpdateRoom(session, room) if err == nil { session.Broadcast(room) } return room, err }
func (api *channellingAPI) HandleAuthentication(session *channelling.Session, st *channelling.SessionToken) (*channelling.DataSelf, error) { if err := api.SessionManager.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) HandleConference(session *channelling.Session, conference *channelling.DataConference) { if room, ok := api.RoomStatusManager.Get(session.Roomid); ok && room.GetType() == channelling.RoomTypeConference { log.Println("Refusing client-side conference update for server-managed conferences.") return } // 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, nil) } } }
func (api *channellingAPI) HandleHello(session *channelling.Session, hello *channelling.DataHello, sender channelling.Sender) (*channelling.DataWelcome, error) { // TODO(longsleep): Filter room id and user agent. session.Update(&channelling.SessionUpdate{Types: []string{"Ua"}, Ua: hello.Ua}) // Compatibily for old clients. roomName := hello.Name if roomName == "" { roomName = hello.Id } room, err := session.JoinRoom(roomName, hello.Type, hello.Credentials, sender) if err != nil { return nil, err } return &channelling.DataWelcome{ Type: "Welcome", Room: room, Users: api.RoomStatusManager.RoomUsers(session), }, nil }
func (api *channellingAPI) HandleChat(session *channelling.Session, chat *channelling.DataChat) { // TODO(longsleep): Limit sent chat messages per incoming connection. msg := chat.Chat to := chat.To if !msg.NoEcho { session.Unicast(session.Id, chat, nil) } msg.Time = time.Now().Format(time.RFC3339) if to == "" { // TODO(longsleep): Check if chat broadcast is allowed. if session.Hello { api.StatsCounter.CountBroadcastChat() session.Broadcast(chat) } } else { if msg.Status != nil { if msg.Status.ContactRequest != nil { if !api.config.WithModule("contacts") { return } if err := api.ContactManager.ContactrequestHandler(session, to, msg.Status.ContactRequest); err != nil { log.Println("Ignoring invalid contact request.", err) return } msg.Status.ContactRequest.Userid = session.Userid() } } else { api.StatsCounter.CountUnicastChat() } session.Unicast(to, chat, nil) if msg.Mid != "" { // Send out delivery confirmation status chat message. session.Unicast(session.Id, &channelling.DataChat{To: to, Type: "Chat", Chat: &channelling.DataChatMessage{Mid: msg.Mid, Status: &channelling.DataChatStatus{State: "sent"}}}, nil) } } }
func (api *channellingAPI) HandleSelf(session *channelling.Session) (*channelling.DataSelf, error) { token, err := api.SessionEncoder.EncodeSessionToken(session) if err != nil { log.Println("Error in OnRegister", err) return nil, err } log.Println("Created new session token", len(token), token) self := &channelling.DataSelf{ Type: "Self", Id: session.Id, Sid: session.Sid, Userid: session.Userid(), Suserid: api.SessionEncoder.EncodeSessionUserID(session), Token: token, Version: api.config.Version, ApiVersion: apiVersion, Turn: api.TurnDataCreator.CreateTurnData(session), Stun: api.config.StunURIs, } api.BusManager.Trigger(channelling.BusManagerSession, session.Id, session.Userid(), nil, nil) return self, nil }
func (api *channellingAPI) HandleLeave(session *channelling.Session) error { session.LeaveRoom() return nil }
func (api *channellingAPI) OnIncoming(sender channelling.Sender, session *channelling.Session, msg *channelling.DataIncoming) (interface{}, error) { var pipeline *channelling.Pipeline switch msg.Type { case "Self": return api.HandleSelf(session) case "Hello": if msg.Hello == nil { return nil, channelling.NewDataError("bad_request", "message did not contain Hello") } return api.HandleHello(session, msg.Hello, sender) case "Offer": if msg.Offer == nil || msg.Offer.Offer == nil { log.Println("Received invalid offer message.", msg) break } if _, ok := msg.Offer.Offer["_token"]; !ok { pipeline = api.PipelineManager.GetPipeline(channelling.PipelineNamespaceCall, sender, session, msg.Offer.To) // Trigger offer event when offer has no token, so this is // not triggered for peerxfer and peerscreenshare offers. api.BusManager.Trigger(channelling.BusManagerOffer, session.Id, msg.Offer.To, nil, pipeline) } session.Unicast(msg.Offer.To, msg.Offer, pipeline) case "Candidate": if msg.Candidate == nil || msg.Candidate.Candidate == nil { log.Println("Received invalid candidate message.", msg) break } pipeline = api.PipelineManager.GetPipeline(channelling.PipelineNamespaceCall, sender, session, msg.Candidate.To) session.Unicast(msg.Candidate.To, msg.Candidate, pipeline) case "Answer": if msg.Answer == nil || msg.Answer.Answer == nil { log.Println("Received invalid answer message.", msg) break } if _, ok := msg.Answer.Answer["_token"]; !ok { pipeline = api.PipelineManager.GetPipeline(channelling.PipelineNamespaceCall, sender, session, msg.Answer.To) // Trigger answer event when answer has no token. so this is // not triggered for peerxfer and peerscreenshare answers. api.BusManager.Trigger(channelling.BusManagerAnswer, session.Id, msg.Answer.To, nil, pipeline) } session.Unicast(msg.Answer.To, msg.Answer, pipeline) case "Users": return api.HandleUsers(session) case "Authentication": if msg.Authentication == nil || msg.Authentication.Authentication == nil { return nil, channelling.NewDataError("bad_request", "message did not contain Authentication") } return api.HandleAuthentication(session, msg.Authentication.Authentication) case "Bye": if msg.Bye == nil { log.Println("Received invalid bye message.", msg) break } pipeline = api.PipelineManager.GetPipeline(channelling.PipelineNamespaceCall, sender, session, msg.Bye.To) api.BusManager.Trigger(channelling.BusManagerBye, session.Id, msg.Bye.To, nil, pipeline) session.Unicast(msg.Bye.To, msg.Bye, pipeline) if pipeline != nil { pipeline.Close() } case "Status": if msg.Status == nil { log.Println("Received invalid status message.", msg) break } //log.Println("Status", msg.Status) session.Update(&channelling.SessionUpdate{Types: []string{"Status"}, Status: msg.Status.Status}) session.BroadcastStatus() case "Chat": if msg.Chat == nil || msg.Chat.Chat == nil { log.Println("Received invalid chat message.", msg) break } api.HandleChat(session, msg.Chat) case "Conference": if msg.Conference == nil { log.Println("Received invalid conference message.", msg) break } api.HandleConference(session, msg.Conference) case "Alive": return msg.Alive, nil case "Sessions": if msg.Sessions == nil || msg.Sessions.Sessions == nil { return nil, channelling.NewDataError("bad_request", "message did not contain Sessions") } return api.HandleSessions(session, msg.Sessions.Sessions) case "Room": if msg.Room == nil { return nil, channelling.NewDataError("bad_request", "message did not contain Room") } return api.HandleRoom(session, msg.Room) case "Leave": if err := api.HandleLeave(session); err != nil { return nil, err } return nil, nil default: log.Println("OnText unhandled message type", msg.Type) } return nil, nil }