|
1 package xmpp |
|
2 |
|
3 // Manages the stack of filters that can read and modify stanzas on |
|
4 // their way from the remote to the application. |
|
5 |
|
6 // Receive new filters on filterAdd; those new filters get added to |
|
7 // the top of the stack. Receive stanzas at the bottom of the stack on |
|
8 // input. Send stanzas out the top of the stack on output. |
|
9 func filterMgr(filterAdd <-chan Filter, input <-chan Stanza, output chan<- Stanza) { |
|
10 botFiltIn := output |
|
11 topFiltOut := input |
|
12 |
|
13 loop: |
|
14 for { |
|
15 select { |
|
16 case stan, ok := <-input: |
|
17 if !ok { |
|
18 break loop |
|
19 } |
|
20 botFiltIn <- stan |
|
21 |
|
22 case stan, ok := <-topFiltOut: |
|
23 if !ok { |
|
24 break loop |
|
25 } |
|
26 output <- stan |
|
27 |
|
28 case filt := <-filterAdd: |
|
29 newTop := make(chan Stanza) |
|
30 go filt(topFiltOut, newTop) |
|
31 topFiltOut = newTop |
|
32 } |
|
33 } |
|
34 close(botFiltIn) |
|
35 } |
|
36 |
|
37 // Starts the filter chain. Filters will all interpose themselves |
|
38 // between srvIn and cliOut. |
|
39 func (cl *Client) startFilters(srvIn, cliIn <-chan Stanza) (<-chan Stanza, <-chan Stanza) { |
|
40 cliOut := make(chan Stanza) |
|
41 srvOut := make(chan Stanza) |
|
42 go filterMgr(cl.sendFilterAdd, srvIn, cliOut) |
|
43 go filterMgr(cl.recvFilterAdd, cliIn, srvOut) |
|
44 return cliOut, srvOut |
|
45 } |
|
46 |
|
47 // AddRecvFilter adds a new filter to the top of the stack through which |
|
48 // incoming stanzas travel on their way up to the client. |
|
49 func (cl *Client) AddRecvFilter(filt Filter) { |
|
50 if filt == nil { |
|
51 return |
|
52 } |
|
53 cl.recvFilterAdd <- filt |
|
54 } |
|
55 |
|
56 // AddSendFilter adds a new filter to the top of the stack through |
|
57 // which outgoing stanzas travel on their way down from the client to |
|
58 // the network. |
|
59 func (cl *Client) AddSendFilter(filt Filter) { |
|
60 if filt == nil { |
|
61 return |
|
62 } |
|
63 cl.sendFilterAdd <- filt |
|
64 } |