equal
deleted
inserted
replaced
46 // that information. This is called once from a fairly deep call stack |
46 // that information. This is called once from a fairly deep call stack |
47 // as part of XMPP negotiation. |
47 // as part of XMPP negotiation. |
48 func fetchRoster(client *Client) error { |
48 func fetchRoster(client *Client) error { |
49 rosterUpdate := rosterClients[client.Uid].rosterUpdate |
49 rosterUpdate := rosterClients[client.Uid].rosterUpdate |
50 |
50 |
51 iq := &Iq{From: client.Jid.String(), Id: <-Id, Type: "get", |
51 iq := &Iq{Stanza: Stanza{From: client.Jid.String(), Type: "get", |
52 Nested: []interface{}{RosterQuery{}}} |
52 Id: <-Id, Nested: []interface{}{RosterQuery{}}}} |
53 ch := make(chan error) |
53 ch := make(chan error) |
54 f := func(st Stanza) bool { |
54 f := func(v interface{}) bool { |
55 defer close(ch) |
55 defer close(ch) |
56 iq, ok := st.(*Iq) |
56 iq, ok := v.(*Iq) |
57 if !ok { |
57 if !ok { |
58 ch <- fmt.Errorf("response to iq wasn't iq: %s", st) |
58 ch <- fmt.Errorf("response to iq wasn't iq: %s", v) |
59 return false |
59 return false |
60 } |
60 } |
61 if iq.Type == "error" { |
61 if iq.Type == "error" { |
62 ch <- iq.Error |
62 ch <- iq.Error |
63 return false |
63 return false |
69 break |
69 break |
70 } |
70 } |
71 } |
71 } |
72 if rq == nil { |
72 if rq == nil { |
73 ch <- fmt.Errorf( |
73 ch <- fmt.Errorf( |
74 "Roster query result not query: %v", st) |
74 "Roster query result not query: %v", v) |
75 return false |
75 return false |
76 } |
76 } |
77 for _, item := range rq.Item { |
77 for _, item := range rq.Item { |
78 rosterUpdate <- item |
78 rosterUpdate <- item |
79 } |
79 } |
89 // The roster filter updates the Client's representation of the |
89 // The roster filter updates the Client's representation of the |
90 // roster, but it lets the relevant stanzas through. This also starts |
90 // roster, but it lets the relevant stanzas through. This also starts |
91 // the roster feeder, which is the goroutine that provides data on |
91 // the roster feeder, which is the goroutine that provides data on |
92 // client.Roster. |
92 // client.Roster. |
93 func startRosterFilter(client *Client) { |
93 func startRosterFilter(client *Client) { |
94 out := make(chan Stanza) |
94 out := make(chan interface{}) |
95 in := client.AddFilter(out) |
95 in := client.AddFilter(out) |
96 go func(in <-chan Stanza, out chan<- Stanza) { |
96 go func(in <-chan interface{}, out chan<- interface{}) { |
97 defer close(out) |
97 defer close(out) |
98 for st := range in { |
98 for st := range in { |
99 maybeUpdateRoster(client, st) |
99 maybeUpdateRoster(client, st) |
100 out <- st |
100 out <- st |
101 } |
101 } |
106 rosterClients[client.Uid] = rosterClient{rosterChan: rosterCh, |
106 rosterClients[client.Uid] = rosterClient{rosterChan: rosterCh, |
107 rosterUpdate: rosterUpdate} |
107 rosterUpdate: rosterUpdate} |
108 go feedRoster(rosterCh, rosterUpdate) |
108 go feedRoster(rosterCh, rosterUpdate) |
109 } |
109 } |
110 |
110 |
111 func maybeUpdateRoster(client *Client, st Stanza) { |
111 func maybeUpdateRoster(client *Client, st interface{}) { |
112 iq, ok := st.(*Iq) |
112 iq, ok := st.(*Iq) |
113 if !ok { |
113 if !ok { |
114 return |
114 return |
115 } |
115 } |
116 |
116 |
126 if iq.Type == "set" && rq != nil { |
126 if iq.Type == "set" && rq != nil { |
127 for _, item := range rq.Item { |
127 for _, item := range rq.Item { |
128 rosterUpdate <- item |
128 rosterUpdate <- item |
129 } |
129 } |
130 // Send a reply. |
130 // Send a reply. |
131 reply := &Iq{To: iq.From, Id: iq.Id, Type: "result"} |
131 reply := &Iq{Stanza: Stanza{To: iq.From, Id: iq.Id, |
|
132 Type: "result"}} |
132 client.Out <- reply |
133 client.Out <- reply |
133 } |
134 } |
134 } |
135 } |
135 |
136 |
136 func feedRoster(rosterCh chan<- []RosterItem, rosterUpdate <-chan RosterItem) { |
137 func feedRoster(rosterCh chan<- []RosterItem, rosterUpdate <-chan RosterItem) { |