mirror of
https://github.com/matrix-org/dendrite.git
synced 2025-12-06 14:33:10 -06:00
Move cache to the ServerACLs struct, store a pointer to the regexes
This commit is contained in:
parent
bed7dc70c0
commit
4f9cd554b9
|
|
@ -20,7 +20,6 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
|
@ -42,18 +41,21 @@ type ServerACLDatabase interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type ServerACLs struct {
|
type ServerACLs struct {
|
||||||
acls map[string]*serverACL // room ID -> ACL
|
acls map[string]*serverACL // room ID -> ACL
|
||||||
aclsMutex sync.RWMutex // protects the above
|
aclsMutex sync.RWMutex // protects the above
|
||||||
compileRegexFunc func(orig string) (*regexp.Regexp, error)
|
aclRegexCache map[string]**regexp.Regexp // Cache from "serverName" -> pointer to a regex
|
||||||
|
aclRegexCacheMutex sync.RWMutex // protects the above
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewServerACLs(db ServerACLDatabase) *ServerACLs {
|
func NewServerACLs(db ServerACLDatabase) *ServerACLs {
|
||||||
ctx := context.TODO()
|
ctx := context.TODO()
|
||||||
acls := &ServerACLs{
|
acls := &ServerACLs{
|
||||||
acls: make(map[string]*serverACL),
|
acls: make(map[string]*serverACL),
|
||||||
|
// Be generous when creating the cache, as in reality
|
||||||
|
// there are hundreds of servers in an ACL.
|
||||||
|
aclRegexCache: make(map[string]**regexp.Regexp, 100),
|
||||||
}
|
}
|
||||||
// temporary regex function to use on start up
|
|
||||||
acls.compileRegexFunc = cachedCompileACLRegex()
|
|
||||||
// Look up all of the rooms that the current state server knows about.
|
// Look up all of the rooms that the current state server knows about.
|
||||||
rooms, err := db.GetKnownRooms(ctx)
|
rooms, err := db.GetKnownRooms(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -72,14 +74,6 @@ func NewServerACLs(db ServerACLDatabase) *ServerACLs {
|
||||||
acls.OnServerACLUpdate(event)
|
acls.OnServerACLUpdate(event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// All regexes are built, replace the function to use.
|
|
||||||
acls.compileRegexFunc = compileACLRegex
|
|
||||||
|
|
||||||
// Force a GC, as we potentially allocated hundreds of regexes
|
|
||||||
// which can now be GCed, since we replaced the regex function
|
|
||||||
// containing the cache.
|
|
||||||
runtime.GC()
|
|
||||||
|
|
||||||
return acls
|
return acls
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,8 +85,8 @@ type ServerACL struct {
|
||||||
|
|
||||||
type serverACL struct {
|
type serverACL struct {
|
||||||
ServerACL
|
ServerACL
|
||||||
allowedRegexes []*regexp.Regexp
|
allowedRegexes []**regexp.Regexp
|
||||||
deniedRegexes []*regexp.Regexp
|
deniedRegexes []**regexp.Regexp
|
||||||
}
|
}
|
||||||
|
|
||||||
func compileACLRegex(orig string) (*regexp.Regexp, error) {
|
func compileACLRegex(orig string) (*regexp.Regexp, error) {
|
||||||
|
|
@ -103,22 +97,22 @@ func compileACLRegex(orig string) (*regexp.Regexp, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// cachedCompileACLRegex is a wrapper around compileACLRegex with added caching
|
// cachedCompileACLRegex is a wrapper around compileACLRegex with added caching
|
||||||
func cachedCompileACLRegex() func(string) (*regexp.Regexp, error) {
|
func (s *ServerACLs) cachedCompileACLRegex(orig string) (**regexp.Regexp, error) {
|
||||||
// Be generous when creating the cache, as in reality
|
s.aclRegexCacheMutex.RLock()
|
||||||
// there are hundreds of servers in an ACL.
|
re, ok := s.aclRegexCache[orig]
|
||||||
cache := make(map[string]*regexp.Regexp, 100)
|
if ok {
|
||||||
return func(orig string) (*regexp.Regexp, error) {
|
s.aclRegexCacheMutex.RUnlock()
|
||||||
re, ok := cache[orig]
|
|
||||||
if ok {
|
|
||||||
return re, nil
|
|
||||||
}
|
|
||||||
re, err := compileACLRegex(orig)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
cache[orig] = re
|
|
||||||
return re, nil
|
return re, nil
|
||||||
}
|
}
|
||||||
|
s.aclRegexCacheMutex.RUnlock()
|
||||||
|
compiled, err := compileACLRegex(orig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
s.aclRegexCacheMutex.Lock()
|
||||||
|
defer s.aclRegexCacheMutex.Unlock()
|
||||||
|
s.aclRegexCache[orig] = &compiled
|
||||||
|
return &compiled, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ServerACLs) OnServerACLUpdate(strippedEvent tables.StrippedEvent) {
|
func (s *ServerACLs) OnServerACLUpdate(strippedEvent tables.StrippedEvent) {
|
||||||
|
|
@ -132,14 +126,14 @@ func (s *ServerACLs) OnServerACLUpdate(strippedEvent tables.StrippedEvent) {
|
||||||
// special characters and then replace * and ? with their regex counterparts.
|
// special characters and then replace * and ? with their regex counterparts.
|
||||||
// https://matrix.org/docs/spec/client_server/r0.6.1#m-room-server-acl
|
// https://matrix.org/docs/spec/client_server/r0.6.1#m-room-server-acl
|
||||||
for _, orig := range acls.Allowed {
|
for _, orig := range acls.Allowed {
|
||||||
if expr, err := s.compileRegexFunc(orig); err != nil {
|
if expr, err := s.cachedCompileACLRegex(orig); err != nil {
|
||||||
logrus.WithError(err).Errorf("Failed to compile allowed regex")
|
logrus.WithError(err).Errorf("Failed to compile allowed regex")
|
||||||
} else {
|
} else {
|
||||||
acls.allowedRegexes = append(acls.allowedRegexes, expr)
|
acls.allowedRegexes = append(acls.allowedRegexes, expr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, orig := range acls.Denied {
|
for _, orig := range acls.Denied {
|
||||||
if expr, err := s.compileRegexFunc(orig); err != nil {
|
if expr, err := s.cachedCompileACLRegex(orig); err != nil {
|
||||||
logrus.WithError(err).Errorf("Failed to compile denied regex")
|
logrus.WithError(err).Errorf("Failed to compile denied regex")
|
||||||
} else {
|
} else {
|
||||||
acls.deniedRegexes = append(acls.deniedRegexes, expr)
|
acls.deniedRegexes = append(acls.deniedRegexes, expr)
|
||||||
|
|
@ -187,14 +181,14 @@ func (s *ServerACLs) IsServerBannedFromRoom(serverName spec.ServerName, roomID s
|
||||||
// Check if the hostname matches one of the denied regexes. If it does then
|
// Check if the hostname matches one of the denied regexes. If it does then
|
||||||
// the server is banned from the room.
|
// the server is banned from the room.
|
||||||
for _, expr := range acls.deniedRegexes {
|
for _, expr := range acls.deniedRegexes {
|
||||||
if expr.MatchString(string(serverName)) {
|
if (*expr).MatchString(string(serverName)) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if the hostname matches one of the allowed regexes. If it does then
|
// Check if the hostname matches one of the allowed regexes. If it does then
|
||||||
// the server is NOT banned from the room.
|
// the server is NOT banned from the room.
|
||||||
for _, expr := range acls.allowedRegexes {
|
for _, expr := range acls.allowedRegexes {
|
||||||
if expr.MatchString(string(serverName)) {
|
if (*expr).MatchString(string(serverName)) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,8 @@ func TestOpenACLsWithBlacklist(t *testing.T) {
|
||||||
ServerACL: ServerACL{
|
ServerACL: ServerACL{
|
||||||
AllowIPLiterals: true,
|
AllowIPLiterals: true,
|
||||||
},
|
},
|
||||||
allowedRegexes: []*regexp.Regexp{allowRegex},
|
allowedRegexes: []**regexp.Regexp{&allowRegex},
|
||||||
deniedRegexes: []*regexp.Regexp{denyRegex},
|
deniedRegexes: []**regexp.Regexp{&denyRegex},
|
||||||
}
|
}
|
||||||
|
|
||||||
if acls.IsServerBannedFromRoom("1.2.3.4", roomID) {
|
if acls.IsServerBannedFromRoom("1.2.3.4", roomID) {
|
||||||
|
|
@ -83,8 +83,8 @@ func TestDefaultACLsWithWhitelist(t *testing.T) {
|
||||||
ServerACL: ServerACL{
|
ServerACL: ServerACL{
|
||||||
AllowIPLiterals: false,
|
AllowIPLiterals: false,
|
||||||
},
|
},
|
||||||
allowedRegexes: []*regexp.Regexp{allowRegex},
|
allowedRegexes: []**regexp.Regexp{&allowRegex},
|
||||||
deniedRegexes: []*regexp.Regexp{},
|
deniedRegexes: []**regexp.Regexp{},
|
||||||
}
|
}
|
||||||
|
|
||||||
if !acls.IsServerBannedFromRoom("1.2.3.4", roomID) {
|
if !acls.IsServerBannedFromRoom("1.2.3.4", roomID) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue