roster.go
changeset 98 c9cc4eda6dce
parent 72 53f15893a1a7
child 110 7696e6a01709
--- 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
 			}