roster.go
changeset 38 2839fece923e
parent 37 fbda8e925fdf
child 39 4a06f7ccfa84
equal deleted inserted replaced
37:fbda8e925fdf 38:2839fece923e
     4 
     4 
     5 package xmpp
     5 package xmpp
     6 
     6 
     7 import (
     7 import (
     8 	"fmt"
     8 	"fmt"
     9 	"io"
       
    10 	"os"
     9 	"os"
    11 	"xml"
    10 	"xml"
    12 )
    11 )
    13 
    12 
    14 // This file contains support for roster management, RFC 3921, Section 7.
    13 // This file contains support for roster management, RFC 3921, Section 7.
    15 
       
    16 type RosterIq struct {
       
    17 	Iq
       
    18 	Query RosterQuery
       
    19 }
       
    20 var _ ExtendedStanza = &RosterIq{}
       
    21 
    14 
    22 // Roster query/result
    15 // Roster query/result
    23 type RosterQuery struct {
    16 type RosterQuery struct {
    24 	// Should always be NsRoster, "query"
    17 	// Should always be NsRoster, "query"
    25 	XMLName xml.Name
    18 	XMLName xml.Name
    34 	Subscription string `xml:"attr"`
    27 	Subscription string `xml:"attr"`
    35 	Name string `xml:"attr"`
    28 	Name string `xml:"attr"`
    36 	Group []string
    29 	Group []string
    37 }
    30 }
    38 
    31 
    39 func (riq *RosterIq) MarshalXML() ([]byte, os.Error) {
       
    40 	return marshalXML(riq)
       
    41 }
       
    42 
       
    43 func (riq *RosterIq) InnerMarshal(w io.Writer) os.Error {
       
    44 	return xml.Marshal(w, riq.Query)
       
    45 }
       
    46 
       
    47 // Implicitly becomes part of NewClient's extStanza arg.
    32 // Implicitly becomes part of NewClient's extStanza arg.
    48 func rosterStanza(name *xml.Name) ExtendedStanza {
    33 func newRosterQuery(name *xml.Name) interface{} {
    49 	return &RosterIq{}
    34 	return &RosterQuery{}
    50 }
    35 }
    51 
    36 
    52 // Synchronously fetch this entity's roster from the server and cache
    37 // Synchronously fetch this entity's roster from the server and cache
    53 // that information.
    38 // that information.
    54 func (cl *Client) fetchRoster() os.Error {
    39 func (cl *Client) fetchRoster() os.Error {
    55 	iq := &RosterIq{Iq: Iq{From: cl.Jid.String(), Id: <- cl.Id,
    40 	iq := &Iq{From: cl.Jid.String(), Id: <- cl.Id, Type: "get",
    56 		Type: "get"}, Query: RosterQuery{XMLName:
    41 		Nested: RosterQuery{XMLName: xml.Name{Local: "query",
    57 			xml.Name{Local: "query", Space: NsRoster}}}
    42 			Space: NsRoster}}}
    58 	ch := make(chan os.Error)
    43 	ch := make(chan os.Error)
    59 	f := func(st Stanza) bool {
    44 	f := func(st Stanza) bool {
    60 		iq, ok := st.(*RosterIq)
       
    61 		if !ok {
       
    62 			ch <- os.NewError(fmt.Sprintf(
       
    63 				"Roster query result not iq: %v", st))
       
    64 			return false
       
    65 		}
       
    66 		if iq.Type == "error" {
    45 		if iq.Type == "error" {
    67 			ch <- iq.Error
    46 			ch <- iq.Error
    68 			return false
    47 			return false
    69 		}
    48 		}
    70 		q := iq.Query
    49 		rq, ok := st.XNested().(*RosterQuery)
    71 		cl.roster = make(map[string] *RosterItem, len(q.Item))
    50 		if !ok {
    72 		for _, item := range(q.Item) {
    51 			ch <- os.NewError(fmt.Sprintf(
       
    52 				"Roster query result not query: %v", st))
       
    53 			return false
       
    54 		}
       
    55 		cl.roster = make(map[string] *RosterItem, len(rq.Item))
       
    56 		for _, item := range(rq.Item) {
    73 			cl.roster[item.Jid] = &item
    57 			cl.roster[item.Jid] = &item
    74 		}
    58 		}
    75 		ch <- nil
    59 		ch <- nil
    76 		return false
    60 		return false
    77 	}
    61 	}