From 55c7c4edb377652992e6b503131558ed3256272c Mon Sep 17 00:00:00 2001 From: Skyxim Date: Sun, 5 Jun 2022 17:28:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=B0=9D=E8=AF=95=E5=AE=9E=E7=8E=B0?= =?UTF-8?q?=E8=84=9A=E6=9C=ACrule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/js/js.go | 23 +++++++++--- constant/rule.go | 3 ++ rule/common/script.go | 68 +++++++++++++++++++++++++++++++++++ rule/ruleparser/ruleparser.go | 2 ++ 4 files changed, 91 insertions(+), 5 deletions(-) create mode 100644 rule/common/script.go diff --git a/component/js/js.go b/component/js/js.go index 669ac915..91748422 100644 --- a/component/js/js.go +++ b/component/js/js.go @@ -3,17 +3,22 @@ package js import ( + "github.com/Dreamacro/clash/log" "github.com/dop251/goja" "github.com/dop251/goja_nodejs/console" "github.com/dop251/goja_nodejs/eventloop" "github.com/dop251/goja_nodejs/require" ) +func init() { + logPrinter := console.RequireWithPrinter(&JsLog{}) + require.RegisterNativeModule("console", logPrinter) +} + func preSetting(rt *goja.Runtime) { registry := new(require.Registry) registry.Enable(rt) - logPrinter := console.RequireWithPrinter(&JsLog{}) - require.RegisterNativeModule("console", logPrinter) + console.Enable(rt) eventloop.EnableConsole(true) } @@ -33,12 +38,20 @@ func compiler(name, code string) (*goja.Program, error) { } func run(loop *eventloop.EventLoop, program *goja.Program, args map[string]any, callback func(any, error)) { - loop.RunOnLoop(func(runtime *goja.Runtime) { + loop.Run(func(runtime *goja.Runtime) { for k, v := range args { - runtime.Set(k, v) + runtime.SetFieldNameMapper(goja.TagFieldNameMapper("json", true)) + err := runtime.Set(k, v) + if err != nil { + log.Errorln("Args to script failed, %s", err.Error()) + } } v, err := runtime.RunProgram(program) - callback(v, err) + if v == nil { + callback(nil, err) + } else { + callback(v.Export(), err) + } }) } diff --git a/constant/rule.go b/constant/rule.go index 2cc60cdd..535f0264 100644 --- a/constant/rule.go +++ b/constant/rule.go @@ -14,6 +14,7 @@ const ( SrcPort DstPort Process + Script ProcessPath RuleSet Network @@ -61,6 +62,8 @@ func (rt RuleType) String() string { return "RuleSet" case Network: return "Network" + case Script: + return "Script" case Uid: return "Uid" case INTYPE: diff --git a/rule/common/script.go b/rule/common/script.go new file mode 100644 index 00000000..7b19569f --- /dev/null +++ b/rule/common/script.go @@ -0,0 +1,68 @@ +package common + +import ( + "github.com/Dreamacro/clash/component/js" + C "github.com/Dreamacro/clash/constant" + "github.com/gofrs/uuid" +) + +type Script struct { + *Base + adapter string + name string +} + +func (s *Script) RuleType() C.RuleType { + return C.Script +} + +func (s *Script) Match(metadata *C.Metadata) bool { + res := false + js.Run(s.name, map[string]any{ + "metadata": metadata, + }, func(a any, err error) { + if err != nil { + res = false + } + + r, ok := a.(bool) + if !ok { + res = false + } + + res = r + }) + + return res +} + +func (s *Script) Adapter() string { + return s.adapter +} + +func (s *Script) Payload() string { + return s.adapter +} + +func (s *Script) ShouldResolveIP() bool { + return true +} + +func NewScript(script string, adapter string) (*Script, error) { + name, err := uuid.NewV4() + if err != nil { + return nil, err + } + + if err := js.NewJS(name.String(), script); err != nil { + return nil, err + } + + return &Script{ + Base: &Base{}, + adapter: adapter, + name: name.String(), + }, nil +} + +var _ C.Rule = (*Script)(nil) diff --git a/rule/ruleparser/ruleparser.go b/rule/ruleparser/ruleparser.go index 55f63f82..cd7c0a70 100644 --- a/rule/ruleparser/ruleparser.go +++ b/rule/ruleparser/ruleparser.go @@ -43,6 +43,8 @@ func ParseSameRule(tp, payload, target string, params []string) (parsed C.Rule, parsed, parseErr = RC.NewUid(payload, target) case "IN-TYPE": parsed, parseErr = RC.NewInType(payload, target) + case "SCRIPT": + parsed, parseErr = RC.NewScript(payload, target) default: parseErr = fmt.Errorf("unsupported rule type %s", tp) }