diff --git a/bridge/irc/handlers.go b/bridge/irc/handlers.go index 886e20df..e3900f3a 100644 --- a/bridge/irc/handlers.go +++ b/bridge/irc/handlers.go @@ -113,7 +113,7 @@ func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) { return } else if b.GetBool("nosendjoinpart") { return - } else if b.isUserActive(event.Source.Name) || isKill(event.Last()) { + } else if isActive, _ := b.isUserActive(event.Source.Name); isActive || isKill(event.Last()) { verbosequit := "" quitmsg := "" if len(event.Params) >= 1 { @@ -129,7 +129,7 @@ func (b *Birc) handleJoinPart(client *girc.Client, event girc.Event) { } } if event.Source.Name != b.Nick { - if b.GetBool("nosendjoinpart") || !b.isUserActive(event.Source.Name) { + if isActive, _ := b.isUserActive(event.Source.Name); !isActive || b.GetBool("nosendjoinpart") { return } partmsg := "" @@ -171,7 +171,7 @@ func (b *Birc) handleNick(client *girc.Client, event girc.Event) { if len(event.Params) != 1 { b.Log.Debugf("handleJoinPart: malformed nick change? %#v", event) return - } else if b.isUserActive(event.Source.Name) { + } else if isActive, activeTime := b.isUserActive(event.Source.Name); isActive { msg := config.Message{Username: "system", Text: event.Source.Name + " changed nick to " + event.Params[0], Channel: b.getPseudoChannel(), @@ -181,7 +181,7 @@ func (b *Birc) handleNick(client *girc.Client, event girc.Event) { b.Remote <- msg if b.ActivityTimeout != 0 { // This doesn't count as new activity, but it does preserve the value - b.activeUsers[event.Params[0]] = b.activeUsers[event.Source.Name] + b.markUserActive(event.Params[0], activeTime) } } } @@ -293,7 +293,7 @@ func (b *Birc) handlePrivMsg(client *girc.Client, event girc.Event) { b.Log.Debugf("<= Sending message from %s on %s to gateway", event.Params[0], b.Account) if b.ActivityTimeout > 0 { b.Log.Debugf("<= Updating last-active time for user %s", event.Source.Name) - b.activeUsers[event.Source.Name] = time.Now().Unix() + b.markUserActive(event.Source.Name, time.Now().Unix()) } b.Remote <- rmsg b.cleanActiveMap() diff --git a/bridge/irc/irc.go b/bridge/irc/irc.go index 886ad6a0..db4134fb 100644 --- a/bridge/irc/irc.go +++ b/bridge/irc/irc.go @@ -10,6 +10,7 @@ import ( "sort" "strconv" "strings" + "sync" "time" "github.com/42wim/matterbridge/bridge" @@ -29,6 +30,7 @@ type Birc struct { names map[string][]string activeUsers map[string]int64 activeUsersLastCleaned int64 + activeUsersMutex sync.RWMutex connected chan error Local chan config.Message // local queue for flood control FirstConnection, authDone bool @@ -432,20 +434,24 @@ func (b *Birc) getTLSConfig() (*tls.Config, error) { return tlsConfig, nil } -func (b *Birc) isUserActive(nick string) bool { +func (b *Birc) isUserActive(nick string) (bool, int64) { b.Log.Debugf("checking activity for %s", nick) if b.ActivityTimeout == 0 { - return true - } else if activeTime, ok := b.activeUsers[nick]; ok { - now := time.Now().Unix() - b.Log.Debugf("last activity for %s was %d, currently %d", nick, activeTime, now) - if now < activeTime { - b.Log.Errorf("User %s has active time in the future: %d", nick, activeTime) - return true // err on the side of caution + return true, 0 + } else { + b.activeUsersMutex.RLock() + defer b.activeUsersMutex.RUnlock() + if activeTime, ok := b.activeUsers[nick]; ok { + now := time.Now().Unix() + b.Log.Debugf("last activity for %s was %d, currently %d", nick, activeTime, now) + if now < activeTime { + b.Log.Errorf("User %s has active time in the future: %d", nick, activeTime) + return true, now // err on the side of caution + } + return (now - activeTime) < b.ActivityTimeout, activeTime } - return (now - activeTime) < b.ActivityTimeout } - return false + return false, 0 } func (b *Birc) getPseudoChannel() string { @@ -463,6 +469,8 @@ func (b *Birc) cleanActiveMap() { if b.ActivityTimeout == 0 || (b.activeUsersLastCleaned-now < b.ActivityTimeout) { return } + b.activeUsersMutex.Lock() + defer b.activeUsersMutex.Unlock() for nick, activeTime := range b.activeUsers { if now-activeTime > b.ActivityTimeout { b.Log.Debugf("last activity for %s was %d, currently %d. Deleting.", nick, activeTime, now) @@ -470,3 +478,9 @@ func (b *Birc) cleanActiveMap() { } } } + +func (b *Birc) markUserActive(nick string, activeTime int64) { + b.activeUsersMutex.Lock() + defer b.activeUsersMutex.Unlock() + b.activeUsers[nick] = activeTime +}