Protect XMPP filters from concurrent access.

This commit is contained in:
Matt Goodall 2012-07-10 17:20:16 +01:00
parent 15a35ce4ff
commit c31efeffe5
1 changed files with 19 additions and 5 deletions

View File

@ -3,6 +3,7 @@ package xmpp
import ( import (
"fmt" "fmt"
"log" "log"
"sync"
) )
// Handles XMPP conversations over a Stream. Use NewClientXMPP and/or // Handles XMPP conversations over a Stream. Use NewClientXMPP and/or
@ -18,6 +19,7 @@ type XMPP struct {
out chan interface{} out chan interface{}
// Incoming stanza filters. // Incoming stanza filters.
filterLock sync.Mutex
nextFilterId FilterId nextFilterId FilterId
filters map[FilterId]filter filters map[FilterId]filter
} }
@ -71,20 +73,36 @@ func (fid FilterId) Error() string {
} }
func (x *XMPP) AddFilter(fn FilterFn) (FilterId, chan interface{}) { func (x *XMPP) AddFilter(fn FilterFn) (FilterId, chan interface{}) {
ch := make(chan interface{})
// Protect against concurrent access.
x.filterLock.Lock()
defer x.filterLock.Lock()
// Create filter chan and add to map.
filterId := x.nextFilterId filterId := x.nextFilterId
x.nextFilterId ++ x.nextFilterId ++
ch := make(chan interface{})
x.filters[filterId] = filter{fn, ch} x.filters[filterId] = filter{fn, ch}
return filterId, ch return filterId, ch
} }
func (x *XMPP) RemoveFilter(id FilterId) error { func (x *XMPP) RemoveFilter(id FilterId) error {
// Protect against concurrent access.
x.filterLock.Lock()
defer x.filterLock.Lock()
// Find filter.
filter, ok := x.filters[id] filter, ok := x.filters[id]
if !ok { if !ok {
return id return id
} }
// Close filter channel and remove from map.
close(filter.ch) close(filter.ch)
delete(x.filters, id) delete(x.filters, id)
return nil return nil
} }
@ -157,7 +175,3 @@ func (x *XMPP) receiver() {
} }
} }
} }
// BUG(matt): filter id generation is not re-entrant.
// BUG(matt): filters map is not re-entrant.