feat: add mrs format domain ruleset

This commit is contained in:
wwqgtxx
2024-07-26 22:30:42 +08:00
parent 0d90a93645
commit 303f6e4567
10 changed files with 301 additions and 26 deletions

View File

@@ -1,6 +1,9 @@
package provider
import (
"errors"
"io"
"github.com/metacubex/mihomo/component/trie"
C "github.com/metacubex/mihomo/constant"
"github.com/metacubex/mihomo/log"
@@ -48,6 +51,25 @@ func (d *domainStrategy) FinishInsert() {
d.domainTrie = nil
}
func (d *domainStrategy) FromMrs(r io.Reader) error {
domainSet, count, err := trie.ReadDomainSetBin(r)
if err != nil {
return err
}
d.count = int(count)
d.domainSet = domainSet
return nil
}
func (d *domainStrategy) WriteMrs(w io.Writer) error {
if d.domainSet == nil {
return errors.New("nil domainSet")
}
return d.domainSet.WriteBin(w, int64(d.count))
}
var _ mrsRuleStrategy = (*domainStrategy)(nil)
func NewDomainStrategy() *domainStrategy {
return &domainStrategy{}
}

View File

@@ -0,0 +1,71 @@
package provider
import (
"io"
"os"
P "github.com/metacubex/mihomo/constant/provider"
"github.com/klauspost/compress/zstd"
)
func ConvertToMrs(buf []byte, behavior P.RuleBehavior, format P.RuleFormat, w io.Writer) (err error) {
strategy := newStrategy(behavior, nil)
strategy, err = rulesParse(buf, strategy, format)
if err != nil {
return err
}
if _strategy, ok := strategy.(mrsRuleStrategy); ok {
var encoder *zstd.Encoder
encoder, err = zstd.NewWriter(w)
if err != nil {
return err
}
defer func() {
zstdErr := encoder.Close()
if err == nil {
err = zstdErr
}
}()
return _strategy.WriteMrs(encoder)
} else {
return ErrInvalidFormat
}
}
func ConvertMain(args []string) {
if len(args) > 3 {
behavior, err := P.ParseBehavior(args[0])
if err != nil {
panic(err)
}
format, err := P.ParseRuleFormat(args[1])
if err != nil {
panic(err)
}
source := args[2]
target := args[3]
sourceFile, err := os.ReadFile(source)
if err != nil {
panic(err)
}
targetFile, err := os.OpenFile(target, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644)
if err != nil {
panic(err)
}
err = ConvertToMrs(sourceFile, behavior, format, targetFile)
if err != nil {
panic(err)
}
err = targetFile.Close()
if err != nil {
panic(err)
}
} else {
panic("Usage: convert-ruleset <behavior> <format> <source file> <target file>")
}
}

View File

@@ -32,28 +32,13 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t
if err := decoder.Decode(mapping, schema); err != nil {
return nil, err
}
var behavior P.RuleBehavior
switch schema.Behavior {
case "domain":
behavior = P.Domain
case "ipcidr":
behavior = P.IPCIDR
case "classical":
behavior = P.Classical
default:
return nil, fmt.Errorf("unsupported behavior type: %s", schema.Behavior)
behavior, err := P.ParseBehavior(schema.Behavior)
if err != nil {
return nil, err
}
var format P.RuleFormat
switch schema.Format {
case "", "yaml":
format = P.YamlRule
case "text":
format = P.TextRule
default:
return nil, fmt.Errorf("unsupported format type: %s", schema.Format)
format, err := P.ParseRuleFormat(schema.Format)
if err != nil {
return nil, err
}
var vehicle P.Vehicle

View File

@@ -4,16 +4,18 @@ import (
"bytes"
"encoding/json"
"errors"
"io"
"runtime"
"strings"
"time"
"gopkg.in/yaml.v3"
"github.com/metacubex/mihomo/common/pool"
"github.com/metacubex/mihomo/component/resource"
C "github.com/metacubex/mihomo/constant"
P "github.com/metacubex/mihomo/constant/provider"
"github.com/klauspost/compress/zstd"
"gopkg.in/yaml.v3"
)
var tunnel P.Tunnel
@@ -52,6 +54,12 @@ type ruleStrategy interface {
FinishInsert()
}
type mrsRuleStrategy interface {
ruleStrategy
FromMrs(r io.Reader) error
WriteMrs(w io.Writer) error
}
func (rp *ruleSetProvider) Type() P.ProviderType {
return P.Rule
}
@@ -152,9 +160,23 @@ func newStrategy(behavior P.RuleBehavior, parse func(tp, payload, target string,
}
var ErrNoPayload = errors.New("file must have a `payload` field")
var ErrInvalidFormat = errors.New("invalid format")
func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStrategy, error) {
strategy.Reset()
if format == P.MrsRule {
if _strategy, ok := strategy.(mrsRuleStrategy); ok {
reader, err := zstd.NewReader(bytes.NewReader(buf))
if err != nil {
return nil, err
}
defer reader.Close()
err = _strategy.FromMrs(reader)
return strategy, err
} else {
return nil, ErrInvalidFormat
}
}
schema := &RulePayload{}
@@ -228,6 +250,8 @@ func rulesParse(buf []byte, strategy ruleStrategy, format P.RuleFormat) (ruleStr
if len(schema.Payload) > 0 {
str = schema.Payload[0]
}
default:
return nil, ErrInvalidFormat
}
if str == "" {