diff -r 69c5b4382e39 -r bbd4166df95d xmpp/roster.go --- a/xmpp/roster.go Sun Sep 22 17:43:34 2013 -0500 +++ b/xmpp/roster.go Sat Sep 28 13:02:17 2013 -0600 @@ -22,15 +22,9 @@ Group []string } -type rosterCb struct { - id string - cb func() -} - type Roster struct { Extension get chan []RosterItem - callbacks chan rosterCb toServer chan Stanza } @@ -41,24 +35,21 @@ func (r *Roster) rosterMgr(upd <-chan Stanza) { roster := make(map[string]RosterItem) - waits := make(map[string]func()) var snapshot []RosterItem + var get chan<- []RosterItem for { select { + case get <- snapshot: + case stan, ok := <-upd: if !ok { return } - hdr := stan.GetHeader() - if f := waits[hdr.Id]; f != nil { - delete(waits, hdr.Id) - f() - } iq, ok := stan.(*Iq) if !ok { continue } - if iq.Type != "result" { + if iq.Type != "result" && iq.Type != "set" { continue } var rq *RosterQuery @@ -78,9 +69,7 @@ for _, ri := range roster { snapshot = append(snapshot, ri) } - case r.get <- snapshot: - case cb := <-r.callbacks: - waits[cb.id] = cb.cb + get = r.get } } } @@ -119,33 +108,22 @@ r.StanzaHandlers[rName] = reflect.TypeOf(RosterQuery{}) r.RecvFilter, r.SendFilter = r.makeFilters() r.get = make(chan []RosterItem) - r.callbacks = make(chan rosterCb) r.toServer = make(chan Stanza) return &r } // Return the most recent snapshot of the roster status. This is // updated automatically as roster updates are received from the -// server, but especially in response to calls to Update(). +// server. This function may block immediately after the XMPP +// connection has been established, until the first roster update is +// received from the server. func (r *Roster) Get() []RosterItem { return <-r.get } -// Synchronously fetch this entity's roster from the server and cache -// that information. The client can access the roster by watching for -// RosterQuery objects or by calling Get(). -func (r *Roster) Update() { +// Asynchronously fetch this entity's roster from the server. +func (r *Roster) update() { iq := &Iq{Header: Header{Type: "get", Id: NextId(), Nested: []interface{}{RosterQuery{}}}} - waitchan := make(chan int) - done := func() { - close(waitchan) - } - r.waitFor(iq.Id, done) r.toServer <- iq - <-waitchan } - -func (r *Roster) waitFor(id string, cb func()) { - r.callbacks <- rosterCb{id: id, cb: cb} -}