diff -r 9d7e8333948b -r ebb86cbdd218 filter.go --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/filter.go Mon Sep 02 20:38:02 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 +}