--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xmpp/filter.go Sat Sep 07 10:04:44 2013 -0700
@@ -0,0 +1,64 @@
+package xmpp
+
+// Manages the stack of filters that can read and modify stanzas on
+// their way from the remote to the application.
+
+// Receive new filters on filterAdd; those new filters get added to
+// the top of the stack. Receive stanzas at the bottom of the stack on
+// input. Send stanzas out the top of the stack on output.
+func filterMgr(filterAdd <-chan Filter, input <-chan Stanza, output chan<- Stanza) {
+ botFiltIn := output
+ topFiltOut := input
+
+loop:
+ for {
+ select {
+ case stan, ok := <-input:
+ if !ok {
+ break loop
+ }
+ botFiltIn <- stan
+
+ case stan, ok := <-topFiltOut:
+ if !ok {
+ break loop
+ }
+ output <- stan
+
+ case filt := <-filterAdd:
+ newTop := make(chan Stanza)
+ go filt(topFiltOut, newTop)
+ topFiltOut = newTop
+ }
+ }
+ close(botFiltIn)
+}
+
+// Starts the filter chain. Filters will all interpose themselves
+// between srvIn and cliOut.
+func (cl *Client) startFilters(srvIn, cliIn <-chan Stanza) (<-chan Stanza, <-chan Stanza) {
+ cliOut := make(chan Stanza)
+ srvOut := make(chan Stanza)
+ go filterMgr(cl.sendFilterAdd, srvIn, cliOut)
+ go filterMgr(cl.recvFilterAdd, cliIn, srvOut)
+ return cliOut, srvOut
+}
+
+// AddRecvFilter adds a new filter to the top of the stack through which
+// incoming stanzas travel on their way up to the client.
+func (cl *Client) AddRecvFilter(filt Filter) {
+ if filt == nil {
+ return
+ }
+ cl.recvFilterAdd <- filt
+}
+
+// AddSendFilter adds a new filter to the top of the stack through
+// which outgoing stanzas travel on their way down from the client to
+// the network.
+func (cl *Client) AddSendFilter(filt Filter) {
+ if filt == nil {
+ return
+ }
+ cl.sendFilterAdd <- filt
+}