diff -r d2ec96c80efe -r c9cc4eda6dce roster.go --- a/roster.go Mon Jan 23 21:54:41 2012 -0700 +++ b/roster.go Sun Dec 16 13:03:03 2012 -0700 @@ -5,9 +5,8 @@ package xmpp import ( + "encoding/xml" "fmt" - "os" - "xml" ) // This file contains support for roster management, RFC 3921, Section 7. @@ -17,15 +16,15 @@ // Roster query/result type RosterQuery struct { XMLName xml.Name `xml:"jabber:iq:roster query"` - Item []RosterItem + Item []RosterItem `xml:"item"` } // See RFC 3921, Section 7.1. type RosterItem struct { - XMLName xml.Name `xml:"item"` - Jid string `xml:"attr"` - Subscription string `xml:"attr"` - Name string `xml:"attr"` + XMLName xml.Name `xml:"jabber:iq:roster item"` + Jid string `xml:"jid,attr"` + Subscription string `xml:"subscription,attr"` + Name string `xml:"name,attr"` Group []string } @@ -46,28 +45,33 @@ // Synchronously fetch this entity's roster from the server and cache // that information. This is called once from a fairly deep call stack // as part of XMPP negotiation. -func fetchRoster(client *Client) os.Error { +func fetchRoster(client *Client) error { rosterUpdate := rosterClients[client.Uid].rosterUpdate iq := &Iq{From: client.Jid.String(), Id: <-Id, Type: "get", Nested: []interface{}{RosterQuery{}}} - ch := make(chan os.Error) + ch := make(chan error) f := func(st Stanza) bool { defer close(ch) + iq, ok := st.(*Iq) + if !ok { + ch <- fmt.Errorf("response to iq wasn't iq: %s", st) + return false + } if iq.Type == "error" { ch <- iq.Error return false } var rq *RosterQuery - for _, ele := range st.GetNested() { + for _, ele := range iq.Nested { if q, ok := ele.(*RosterQuery); ok { rq = q break } } if rq == nil { - ch <- os.NewError(fmt.Sprintf( - "Roster query result not query: %v", st)) + ch <- fmt.Errorf( + "Roster query result not query: %v", st) return false } for _, item := range rq.Item { @@ -105,22 +109,27 @@ } func maybeUpdateRoster(client *Client, st Stanza) { + iq, ok := st.(*Iq) + if !ok { + return + } + rosterUpdate := rosterClients[client.Uid].rosterUpdate var rq *RosterQuery - for _, ele := range st.GetNested() { + for _, ele := range iq.Nested { if q, ok := ele.(*RosterQuery); ok { rq = q break } } - if st.GetName() == "iq" && st.GetType() == "set" && rq != nil { + if iq.Type == "set" && rq != nil { for _, item := range rq.Item { rosterUpdate <- item } // Send a reply. - iq := &Iq{To: st.GetFrom(), Id: st.GetId(), Type: "result"} - client.Out <- iq + reply := &Iq{To: iq.From, Id: iq.Id, Type: "result"} + client.Out <- reply } } @@ -131,7 +140,7 @@ select { case newIt := <-rosterUpdate: if newIt.Subscription == "remove" { - roster[newIt.Jid] = RosterItem{}, false + delete(roster, newIt.Jid) } else { roster[newIt.Jid] = newIt }