// evictUser evicts given user's sessions from the topic and clears user's cached data, if requested func (t *Topic) evictUser(uid types.Uid, clear bool, ignore *Session) { now := time.Now().UTC().Round(time.Millisecond) note := NoErrEvicted("", t.original, now) if clear { // Delete per-user data delete(t.perUser, uid) } else { // Clear online status pud := t.perUser[uid] pud.online = 0 t.perUser[uid] = pud } // Notify topic subscribers that the user has left the topic if t.cat == TopicCat_Grp { t.presPubChange(uid.UserId(), "off") } // Detach all user's sessions for sess, _ := range t.sessions { if sess.uid == uid { delete(t.sessions, sess) sess.detach <- t.name if sess != ignore { sess.QueueOut(note) } } } }
// Announce to a single user on 'me' topic func (t *Topic) presAnnounceToUser(uid types.Uid, what string, seq int, skip *Session) { if pud, ok := t.perUser[uid]; ok { update := &MsgServerPres{Topic: "me", What: what, Src: t.original, SeqId: seq} if pud.modeGiven&pud.modeWant&types.ModePres != 0 { globals.hub.route <- &ServerComMessage{Pres: update, rcptto: uid.UserId(), sessSkip: skip} } } }
func (t *Topic) makeInvite(notify, target, from types.Uid, act types.InviteAction, modeWant, modeGiven types.AccessMode, info interface{}) *ServerComMessage { // FIXME(gene): this is a workaround for gorethink's broken way of marshalling json inv, err := json.Marshal(MsgInvitation{ Topic: t.name, User: target.UserId(), Action: act.String(), Acs: MsgAccessMode{modeWant.String(), modeGiven.String()}, Info: info}) if err != nil { log.Println(err) } converted := map[string]interface{}{} err = json.Unmarshal(inv, &converted) if err != nil { log.Println(err) } // endof workaround msg := &ServerComMessage{Data: &MsgServerData{ Topic: "me", From: from.UserId(), Timestamp: time.Now().UTC().Round(time.Millisecond), Content: converted}, rcptto: notify.UserId()} log.Printf("Invite generated: %#+v", msg.Data) return msg }
// Authenticate func (s *Session) login(msg *ClientComMessage) { var uid types.Uid var err error if !s.uid.IsZero() { s.QueueOut(ErrAlreadyAuthenticated(msg.Login.Id, "", msg.timestamp)) return } else if msg.Login.Scheme == "" || msg.Login.Scheme == "basic" { uid, err = store.Users.Login(msg.Login.Scheme, msg.Login.Secret) if err != nil { // DB error log.Println(err) s.QueueOut(ErrUnknown(msg.Login.Id, "", msg.timestamp)) return } else if uid.IsZero() { // Invalid login or password s.QueueOut(ErrAuthFailed(msg.Login.Id, "", msg.timestamp)) return } } else { s.QueueOut(ErrAuthUnknownScheme(msg.Login.Id, "", msg.timestamp)) return } s.uid = uid s.userAgent = msg.Login.UserAgent s.QueueOut(&ServerComMessage{Ctrl: &MsgServerCtrl{ Id: msg.Login.Id, Code: http.StatusOK, Text: http.StatusText(http.StatusOK), Timestamp: msg.timestamp, Params: map[string]interface{}{"uid": uid.UserId()}}}) }
// User subscribed to a new topic. Let all user's other sessions know. // Case 11 func (t *Topic) presTopicSubscribed(user types.Uid, skip *Session) { t.presAnnounceToUser(user, "on", 0, skip) log.Printf("Pres 11: from '%s' (src: %s) [subbed/on]", t.name, user.UserId()) }
// Announce topic disappearance just to the affected user // Case 4.b func (t *Topic) presTopicGone(user types.Uid) { t.presAnnounceToUser(user, "gone", 0, nil) log.Printf("Pres 4.b: from '%s' (src: %s) [gone]", t.name, user.UserId()) }
// Publish announcement to topic // Cases 4.a, 7 func (t *Topic) presPubChange(src types.Uid, what string) { // Announce to topic subscribers. 4.a, 7 t.presAnnounceToTopic(src.UserId(), what, 0, nil) //log.Printf("Pres 4.a,7: from '%s' (src: %s) [%s]", t.name, src, what) }