60 cl.Out <- iq |
60 cl.Out <- iq |
61 // Wait for f to complete. |
61 // Wait for f to complete. |
62 return <- ch |
62 return <- ch |
63 } |
63 } |
64 |
64 |
65 // BUG(cjyar) The roster isn't actually updated when things change. |
|
66 |
|
67 // Returns the current roster of other entities which this one has a |
65 // Returns the current roster of other entities which this one has a |
68 // relationship with. Changes to the roster will be signaled by an |
66 // relationship with. Changes to the roster will be signaled by an |
69 // appropriate Iq appearing on Client.In. See RFC 3921, Section 7.4. |
67 // appropriate Iq appearing on Client.In. See RFC 3921, Section 7.4. |
70 func (cl *Client) Roster() map[string] *RosterItem { |
68 func (cl *Client) Roster() map[string] *RosterItem { |
71 r := make(map[string] *RosterItem) |
69 r := make(map[string] *RosterItem) |
72 for key, val := range(cl.roster) { |
70 for key, val := range(cl.roster) { |
73 r[key] = val |
71 r[key] = val |
74 } |
72 } |
75 return r |
73 return r |
76 } |
74 } |
|
75 |
|
76 // The roster filter updates the Client's representation of the |
|
77 // roster, but it lets the relevant stanzas through. |
|
78 func (cl *Client) startRosterFilter() { |
|
79 out := make(chan Stanza) |
|
80 in := cl.AddFilter(out) |
|
81 go func(inSave <-chan Stanza, outSave chan<- Stanza) { |
|
82 defer close(out) |
|
83 in := inSave |
|
84 var out chan<- Stanza |
|
85 var st Stanza |
|
86 var ok bool |
|
87 for { |
|
88 select { |
|
89 case st, ok = <- in: |
|
90 if !ok { |
|
91 break |
|
92 } |
|
93 cl.maybeUpdateRoster(st) |
|
94 in = nil |
|
95 out = outSave |
|
96 case out <- st: |
|
97 out = nil |
|
98 in = inSave |
|
99 } |
|
100 } |
|
101 }(in, out) |
|
102 } |
|
103 |
|
104 func (cl *Client) maybeUpdateRoster(st Stanza) { |
|
105 rq, ok := st.GetNested().(*RosterQuery) |
|
106 if st.GetName() == "iq" && st.GetType() == "set" && ok { |
|
107 for _, item := range(rq.Item) { |
|
108 cl.roster[item.Jid] = &item |
|
109 } |
|
110 } |
|
111 } |