equal
deleted
inserted
replaced
6 |
6 |
7 // This file contains support for roster management, RFC 3921, Section 7. |
7 // This file contains support for roster management, RFC 3921, Section 7. |
8 |
8 |
9 import ( |
9 import ( |
10 "encoding/xml" |
10 "encoding/xml" |
|
11 "reflect" |
11 ) |
12 ) |
12 |
13 |
13 // Roster query/result |
14 // Roster query/result |
14 type RosterQuery struct { |
15 type RosterQuery struct { |
15 XMLName xml.Name `xml:"jabber:iq:roster query"` |
16 XMLName xml.Name `xml:"jabber:iq:roster query"` |
30 cb func() |
31 cb func() |
31 } |
32 } |
32 |
33 |
33 type Roster struct { |
34 type Roster struct { |
34 Extension |
35 Extension |
35 get chan []RosterItem |
36 get chan []RosterItem |
36 callbacks chan rosterCb |
37 callbacks chan rosterCb |
37 toServer chan Stanza |
38 toServer chan Stanza |
38 } |
39 } |
39 |
40 |
40 type rosterClient struct { |
41 type rosterClient struct { |
41 rosterChan <-chan []RosterItem |
42 rosterChan <-chan []RosterItem |
42 rosterUpdate chan<- RosterItem |
43 rosterUpdate chan<- RosterItem |
43 } |
|
44 |
|
45 // Implicitly becomes part of NewClient's extStanza arg. |
|
46 func newRosterQuery(name *xml.Name) interface{} { |
|
47 return &RosterQuery{} |
|
48 } |
44 } |
49 |
45 |
50 func (r *Roster) rosterMgr(upd <-chan Stanza) { |
46 func (r *Roster) rosterMgr(upd <-chan Stanza) { |
51 roster := make(map[string]RosterItem) |
47 roster := make(map[string]RosterItem) |
52 waits := make(map[string]func()) |
48 waits := make(map[string]func()) |
53 var snapshot []RosterItem |
49 var snapshot []RosterItem |
54 for { |
50 for { |
55 select { |
51 select { |
56 case stan, ok := <- upd: |
52 case stan, ok := <-upd: |
57 if !ok { |
53 if !ok { |
58 return |
54 return |
59 } |
55 } |
60 hdr := stan.GetHeader() |
56 hdr := stan.GetHeader() |
61 if f := waits[hdr.Id] ; f != nil { |
57 if f := waits[hdr.Id]; f != nil { |
62 delete(waits, hdr.Id) |
58 delete(waits, hdr.Id) |
63 f() |
59 f() |
64 } |
60 } |
65 iq, ok := stan.(*Iq) |
61 iq, ok := stan.(*Iq) |
66 if iq.Type != "set" { |
62 if iq.Type != "set" { |
82 snapshot = []RosterItem{} |
78 snapshot = []RosterItem{} |
83 for _, ri := range roster { |
79 for _, ri := range roster { |
84 snapshot = append(snapshot, ri) |
80 snapshot = append(snapshot, ri) |
85 } |
81 } |
86 case r.get <- snapshot: |
82 case r.get <- snapshot: |
87 case cb := <- r.callbacks: |
83 case cb := <-r.callbacks: |
88 waits[cb.id] = cb.cb |
84 waits[cb.id] = cb.cb |
89 } |
85 } |
90 } |
86 } |
91 } |
87 } |
92 |
88 |
102 } |
98 } |
103 send := func(in <-chan Stanza, out chan<- Stanza) { |
99 send := func(in <-chan Stanza, out chan<- Stanza) { |
104 defer close(out) |
100 defer close(out) |
105 for { |
101 for { |
106 select { |
102 select { |
107 case stan, ok := <- in: |
103 case stan, ok := <-in: |
108 if !ok { |
104 if !ok { |
109 return |
105 return |
110 } |
106 } |
111 out <- stan |
107 out <- stan |
112 case stan := <- r.toServer: |
108 case stan := <-r.toServer: |
113 out <- stan |
109 out <- stan |
114 } |
110 } |
115 } |
111 } |
116 } |
112 } |
117 return recv, send |
113 return recv, send |
118 } |
114 } |
119 |
115 |
120 func newRosterExt() *Roster { |
116 func newRosterExt() *Roster { |
121 r := Roster{} |
117 r := Roster{} |
122 r.StanzaHandlers = make(map[string]func(*xml.Name) interface{}) |
118 r.StanzaHandlers = make(map[xml.Name]reflect.Type) |
123 r.StanzaHandlers[NsRoster] = newRosterQuery |
119 rName := xml.Name{Space: NsRoster, Local: "query"} |
|
120 r.StanzaHandlers[rName] = reflect.TypeOf(RosterQuery{}) |
124 r.RecvFilter, r.SendFilter = r.makeFilters() |
121 r.RecvFilter, r.SendFilter = r.makeFilters() |
125 r.get = make(chan []RosterItem) |
122 r.get = make(chan []RosterItem) |
126 r.callbacks = make(chan rosterCb) |
123 r.callbacks = make(chan rosterCb) |
127 r.toServer = make(chan Stanza) |
124 r.toServer = make(chan Stanza) |
128 return &r |
125 return &r |