xmpp/filter.go
changeset 126 367e76b3028e
parent 121 ebb86cbdd218
child 133 c4e0b897db83
equal deleted inserted replaced
125:f464f14e39a7 126:367e76b3028e
       
     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 }