diff -r 569833f08780 -r 9fe022261dcc roster.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/roster.go Fri Dec 30 21:49:00 2011 -0700 @@ -0,0 +1,91 @@ +// Copyright 2011 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package xmpp + +import ( + "fmt" + "io" + "os" + "xml" +) + +// This file contains support for roster management, RFC 3921, Section 7. + +type RosterIq struct { + Iq + Query RosterQuery +} +var _ ExtendedStanza = &RosterIq{} + +// Roster query/result +type RosterQuery struct { + // Should always be NsRoster, "query" + XMLName xml.Name + Item []RosterItem +} + +// See RFC 3921, Section 7.1. +type RosterItem struct { + // Should always be "item" + XMLName xml.Name + Jid string `xml:"attr"` + Subscription string `xml:"attr"` + Name string `xml:"attr"` + Group []string +} + +func (riq *RosterIq) InnerMarshal(w io.Writer) os.Error { + return xml.Marshal(w, riq.Query) +} + +// Implicitly becomes part of NewClient's extStanza arg. +func rosterStanza(name *xml.Name) ExtendedStanza { + return &RosterIq{} +} + +// Synchronously fetch this entity's roster from the server and cache +// that information. +func (cl *Client) fetchRoster() os.Error { + iq := &RosterIq{Iq: Iq{From: cl.Jid.String(), Id: <- cl.Id, + Type: "get"}, Query: RosterQuery{XMLName: + xml.Name{Local: "query", Space: NsRoster}}} + ch := make(chan os.Error) + f := func(st Stanza) bool { + iq, ok := st.(*RosterIq) + if !ok { + ch <- os.NewError(fmt.Sprintf( + "Roster query result not iq: %v", st)) + return false + } + if iq.Type == "error" { + ch <- iq.Error + return false + } + q := iq.Query + cl.roster = make(map[string] *RosterItem, len(q.Item)) + for _, item := range(q.Item) { + cl.roster[item.Jid] = &item + } + ch <- nil + return false + } + cl.HandleStanza(iq.Id, f) + cl.Out <- iq + // Wait for f to complete. + return <- ch +} + +// BUG(cjyar) The roster isn't actually updated when things change. + +// Returns the current roster of other entities which this one has a +// relationship with. Changes to the roster will be signaled by an +// appropriate Iq appearing on Client.In. See RFC 3921, Section 7.4. +func (cl *Client) Roster() map[string] *RosterItem { + r := make(map[string] *RosterItem) + for key, val := range(cl.roster) { + r[key] = val + } + return r +}