mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-09-21 15:36:51 +00:00
Reduce rule matching memory allocations
This commit is contained in:
@@ -129,7 +129,7 @@ func (t *DNSTransport) updateDNSServers(routeConfig *router.Config, dnsConfig *n
|
||||
}
|
||||
myResolvers = append(myResolvers, myResolver)
|
||||
}
|
||||
routes[domain.WithTrailingDot()] = myResolvers
|
||||
routes[mDNS.CanonicalName(domain.WithTrailingDot())] = myResolvers
|
||||
}
|
||||
hosts := make(map[string][]netip.Addr)
|
||||
for domain, addresses := range dnsConfig.Hosts {
|
||||
@@ -275,14 +275,25 @@ func (t *DNSTransport) PreferredDomain(domain string) bool {
|
||||
if t.acceptSearchDomain && len(searchDomains) > 0 && mDNS.CountLabel(domain) == 1 {
|
||||
return true
|
||||
}
|
||||
canonicalDomain := mDNS.CanonicalName(domain)
|
||||
for suffix := range routes {
|
||||
if mDNS.IsSubDomain(suffix, domain) {
|
||||
if matchDomainSuffix(canonicalDomain, suffix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func matchDomainSuffix(domain string, suffix string) bool {
|
||||
if suffix == "." || suffix == "" {
|
||||
return true
|
||||
}
|
||||
if !strings.HasSuffix(domain, suffix) {
|
||||
return false
|
||||
}
|
||||
return len(domain) == len(suffix) || domain[len(domain)-len(suffix)-1] == '.'
|
||||
}
|
||||
|
||||
func (t *DNSTransport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg, error) {
|
||||
done := make(chan struct{})
|
||||
var (
|
||||
@@ -375,8 +386,9 @@ func (t *DNSTransport) exchangeOnce(ctx context.Context, message *mDNS.Msg, allo
|
||||
}
|
||||
return
|
||||
}
|
||||
canonicalName := mDNS.CanonicalName(question.Name)
|
||||
for domainSuffix, transports := range routes {
|
||||
if mDNS.IsSubDomain(domainSuffix, question.Name) {
|
||||
if matchDomainSuffix(canonicalName, domainSuffix) {
|
||||
if len(transports) == 0 {
|
||||
callback(&mDNS.Msg{
|
||||
MsgHdr: mDNS.MsgHdr{
|
||||
|
||||
@@ -953,7 +953,7 @@ func (t *Endpoint) PreferredDomain(metadata *adapter.InboundContext, domain stri
|
||||
}
|
||||
}
|
||||
for _, suffix := range t.routeSuffixes.Load() {
|
||||
if mDNS.IsSubDomain(suffix, domain) {
|
||||
if matchDomainSuffix(domain, suffix) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1000,7 +1000,7 @@ func (t *Endpoint) onReconfig(cfg *wgcfg.Config, routerCfg *router.Config, dnsCf
|
||||
}
|
||||
routeSuffixes := make([]string, 0, len(dnsCfg.Routes))
|
||||
for fqdn := range dnsCfg.Routes {
|
||||
routeSuffixes = append(routeSuffixes, fqdn.WithoutTrailingDot())
|
||||
routeSuffixes = append(routeSuffixes, strings.ToLower(fqdn.WithoutTrailingDot()))
|
||||
}
|
||||
t.routeDomains.Store(routeDomains)
|
||||
t.routeSuffixes.Store(routeSuffixes)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package rule
|
||||
|
||||
import "github.com/sagernet/sing-box/adapter"
|
||||
|
||||
type ruleMatchState uint8
|
||||
|
||||
const (
|
||||
@@ -24,3 +26,23 @@ func (g ruleGroupMatch) mergeWith(other ruleGroupMatch) ruleGroupMatch {
|
||||
satisfied: g.satisfied | other.satisfied,
|
||||
}
|
||||
}
|
||||
|
||||
type ruleMatchSnapshot struct {
|
||||
ipCidrMatchSource bool
|
||||
ipCidrAcceptEmpty bool
|
||||
deferredIPCIDRMatchGroups uint8
|
||||
}
|
||||
|
||||
func snapshotRuleMatch(metadata *adapter.InboundContext) ruleMatchSnapshot {
|
||||
return ruleMatchSnapshot{
|
||||
ipCidrMatchSource: metadata.IPCIDRMatchSource,
|
||||
ipCidrAcceptEmpty: metadata.IPCIDRAcceptEmpty,
|
||||
deferredIPCIDRMatchGroups: metadata.DeferredIPCIDRMatchGroups,
|
||||
}
|
||||
}
|
||||
|
||||
func (s ruleMatchSnapshot) restore(metadata *adapter.InboundContext) {
|
||||
metadata.IPCIDRMatchSource = s.ipCidrMatchSource
|
||||
metadata.IPCIDRAcceptEmpty = s.ipCidrAcceptEmpty
|
||||
metadata.DeferredIPCIDRMatchGroups = s.deferredIPCIDRMatchGroups
|
||||
}
|
||||
|
||||
@@ -206,32 +206,32 @@ func (r *abstractLogicalRule) Match(metadata *adapter.InboundContext) bool {
|
||||
matched bool
|
||||
deferredGroups uint8
|
||||
)
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
if r.mode == C.LogicalTypeAnd {
|
||||
matched = true
|
||||
for _, rule := range r.rules {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleCache()
|
||||
if !rule.Match(&nestedMetadata) {
|
||||
metadata.ResetRuleCache()
|
||||
if !rule.Match(metadata) {
|
||||
matched = false
|
||||
deferredGroups = 0
|
||||
break
|
||||
}
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
} else {
|
||||
for _, rule := range r.rules {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleCache()
|
||||
if rule.Match(&nestedMetadata) {
|
||||
metadata.ResetRuleCache()
|
||||
if rule.Match(metadata) {
|
||||
matched = true
|
||||
if nestedMetadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
if metadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
deferredGroups = 0
|
||||
break
|
||||
}
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
if matched {
|
||||
metadata.DeferredIPCIDRMatchGroups |= deferredGroups
|
||||
}
|
||||
|
||||
@@ -52,12 +52,15 @@ func (r *RuleSetItem) Close() error {
|
||||
}
|
||||
|
||||
func (r *RuleSetItem) Match(metadata *adapter.InboundContext) bool {
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
for _, ruleSet := range r.setList {
|
||||
nestedMetadata := r.nestedMetadata(metadata)
|
||||
if ruleSet.Match(&nestedMetadata) {
|
||||
r.prepareNestedMatch(metadata)
|
||||
if ruleSet.Match(metadata) {
|
||||
snapshot.restore(metadata)
|
||||
return true
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -67,17 +70,19 @@ func (r *RuleSetItem) matchWithOuterGroups(metadata *adapter.InboundContext, out
|
||||
matched bool
|
||||
deferredGroups uint8
|
||||
)
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
for _, ruleSet := range r.setList {
|
||||
nestedMetadata := r.nestedMetadata(metadata)
|
||||
r.prepareNestedMatch(metadata)
|
||||
if provider, isProvider := ruleSet.(mergeableRuleProvider); isProvider {
|
||||
branch := provider.mergeableRule()
|
||||
if branch != nil {
|
||||
branchGroups, branchMatched := branch.evaluateForMerge(&nestedMetadata)
|
||||
branchGroups, branchMatched := branch.evaluateForMerge(metadata)
|
||||
if branchMatched {
|
||||
merged := outerGroups.mergeWith(branchGroups)
|
||||
if merged.done() {
|
||||
branchDeferredGroups := nestedMetadata.DeferredIPCIDRMatchGroups &^ uint8(merged.satisfied)
|
||||
branchDeferredGroups := metadata.DeferredIPCIDRMatchGroups &^ uint8(merged.satisfied)
|
||||
if branchDeferredGroups == 0 {
|
||||
snapshot.restore(metadata)
|
||||
metadata.DeferredIPCIDRMatchGroups &^= uint8(merged.satisfied)
|
||||
return true
|
||||
}
|
||||
@@ -88,26 +93,26 @@ func (r *RuleSetItem) matchWithOuterGroups(metadata *adapter.InboundContext, out
|
||||
continue
|
||||
}
|
||||
}
|
||||
if outerDone && ruleSet.Match(&nestedMetadata) {
|
||||
if nestedMetadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
if outerDone && ruleSet.Match(metadata) {
|
||||
if metadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
snapshot.restore(metadata)
|
||||
return true
|
||||
}
|
||||
matched = true
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
if matched {
|
||||
metadata.DeferredIPCIDRMatchGroups |= deferredGroups
|
||||
}
|
||||
return matched
|
||||
}
|
||||
|
||||
func (r *RuleSetItem) nestedMetadata(metadata *adapter.InboundContext) adapter.InboundContext {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleMatchCache()
|
||||
nestedMetadata.IPCIDRMatchSource = r.ipCidrMatchSource
|
||||
nestedMetadata.IPCIDRAcceptEmpty = r.ipCidrAcceptEmpty
|
||||
return nestedMetadata
|
||||
func (r *RuleSetItem) prepareNestedMatch(metadata *adapter.InboundContext) {
|
||||
metadata.ResetRuleMatchCache()
|
||||
metadata.IPCIDRMatchSource = r.ipCidrMatchSource
|
||||
metadata.IPCIDRAcceptEmpty = r.ipCidrAcceptEmpty
|
||||
}
|
||||
|
||||
type mergeableRuleProvider interface {
|
||||
@@ -130,17 +135,19 @@ func matchAnyHeadlessRule(rules []adapter.HeadlessRule, metadata *adapter.Inboun
|
||||
matched bool
|
||||
deferredGroups uint8
|
||||
)
|
||||
snapshot := snapshotRuleMatch(metadata)
|
||||
for _, rule := range rules {
|
||||
nestedMetadata := *metadata
|
||||
nestedMetadata.ResetRuleMatchCache()
|
||||
if rule.Match(&nestedMetadata) {
|
||||
if nestedMetadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
metadata.ResetRuleMatchCache()
|
||||
if rule.Match(metadata) {
|
||||
if metadata.DeferredIPCIDRMatchGroups == 0 {
|
||||
snapshot.restore(metadata)
|
||||
return true
|
||||
}
|
||||
matched = true
|
||||
deferredGroups |= nestedMetadata.DeferredIPCIDRMatchGroups
|
||||
deferredGroups |= metadata.DeferredIPCIDRMatchGroups
|
||||
}
|
||||
}
|
||||
snapshot.restore(metadata)
|
||||
if matched {
|
||||
metadata.DeferredIPCIDRMatchGroups |= deferredGroups
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user