filter.go
author Chris Jones <christian.jones@sri.com>
Mon, 02 Sep 2013 20:46:23 -0700
changeset 125 f464f14e39a7
parent 121 ebb86cbdd218
permissions -rw-r--r--
Renamed examples to example, since there's only one program there.

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
}