From cccea70db10bb329eb12e119be175c69cda0bfe0 Mon Sep 17 00:00:00 2001 From: fumiama Date: Thu, 14 Oct 2021 16:26:01 +0800 Subject: [PATCH] =?UTF-8?q?=E2=9C=8F=EF=B8=8F=20=E5=88=86=E7=A6=BB=20dyloa?= =?UTF-8?q?der?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dyloader/hook.go | 16 --- dyloader/plugin/plugin_dlopen.go | 57 ---------- dyloader/plugin/plugin_stubs.go | 22 ---- dyloader/plugin/plugin_unix.go | 89 --------------- dyloader/plugin/plugin_win.go | 83 -------------- dyloader/scan.go | 189 ------------------------------- main.go | 4 +- 7 files changed, 2 insertions(+), 458 deletions(-) delete mode 100644 dyloader/hook.go delete mode 100644 dyloader/plugin/plugin_dlopen.go delete mode 100644 dyloader/plugin/plugin_stubs.go delete mode 100644 dyloader/plugin/plugin_unix.go delete mode 100644 dyloader/plugin/plugin_win.go delete mode 100644 dyloader/scan.go diff --git a/dyloader/hook.go b/dyloader/hook.go deleted file mode 100644 index 6b562dd5..00000000 --- a/dyloader/hook.go +++ /dev/null @@ -1,16 +0,0 @@ -package dyloader - -import zero "github.com/wdvxdr1123/ZeroBot" - -func sendGroupMessage(ctx *zero.Ctx, groupID int64, message interface{}) int64 { - return ctx.SendGroupMessage(groupID, message) -} -func sendPrivateMessage(ctx *zero.Ctx, userID int64, message interface{}) int64 { - return ctx.SendPrivateMessage(userID, message) -} -func getMessage(ctx *zero.Ctx, messageID int64) zero.Message { - return ctx.GetMessage(messageID) -} -func parse(ctx *zero.Ctx, model interface{}) (err error) { - return ctx.Parse(model) -} diff --git a/dyloader/plugin/plugin_dlopen.go b/dyloader/plugin/plugin_dlopen.go deleted file mode 100644 index 069b4e82..00000000 --- a/dyloader/plugin/plugin_dlopen.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build linux,cgo darwin,cgo freebsd,cgo -// +build linux,cgo darwin,cgo freebsd,cgo - -package plugin - -/* -#cgo linux LDFLAGS: -ldl -#include -#include -#include -#include -#include -static int pluginClose(void* handle, char** err) { - int res = dlclose(handle); - if (res != 0) { - *err = (char*)dlerror(); - } - return res; -} -*/ -import "C" - -import ( - "errors" - "sync" - "unsafe" -) - -func unload(pg *Plugin) error { - filepath := pg.pluginpath - - pluginsMu.Lock() - p := plugins[filepath] - if p != nil { - delete(plugins, filepath) - } - pluginsMu.Unlock() - if p != nil { - var cErr *C.char - res := C.pluginClose(unsafe.Pointer(p), &cErr) - if res != 0 { - return errors.New(`plugin.Close("` + filepath + `"): ` + C.GoString(cErr)) - } - } - return nil -} - -//go:linkname pluginsMu plugin.pluginsMu -//go:linkname plugins plugin.plugins -var ( - pluginsMu sync.Mutex - plugins map[string]*Plugin -) diff --git a/dyloader/plugin/plugin_stubs.go b/dyloader/plugin/plugin_stubs.go deleted file mode 100644 index 9e0265d4..00000000 --- a/dyloader/plugin/plugin_stubs.go +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -//go:build !linux,!freebsd,!darwin !cgo -// +build !linux,!freebsd,!darwin !cgo - -package plugin - -import "errors" - -func lookup(p *Plugin, symName string) (Symbol, error) { - return nil, errors.New("plugin: not implemented") -} - -func open(name string) (*Plugin, error) { - return nil, errors.New("plugin: not implemented") -} - -func unload(name string) error { - return nil, errors.New("plugin: not implemented") -} diff --git a/dyloader/plugin/plugin_unix.go b/dyloader/plugin/plugin_unix.go deleted file mode 100644 index 28171fae..00000000 --- a/dyloader/plugin/plugin_unix.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package plugin implements loading and symbol resolution of Go plugins. -// -// A plugin is a Go main package with exported functions and variables that -// has been built with: -// -// go build -buildmode=plugin -// -// When a plugin is first opened, the init functions of all packages not -// already part of the program are called. The main function is not run. -// A plugin is only initialized once, and cannot be closed. -// -// Currently plugins are only supported on Linux, FreeBSD, and macOS. -// Please report any issues. - -//go:build linux,cgo darwin,cgo freebsd,cgo -// +build linux,cgo darwin,cgo freebsd,cgo - -package plugin - -import ( - pl "plugin" - "unsafe" -) - -// Plugin is a loaded Go plugin. -type Plugin struct { - pluginpath string - err string // set if plugin failed to load - loaded chan struct{} // closed when loaded - syms map[string]interface{} -} - -// Open opens a Go plugin. -// If a path has already been opened, then the existing *Plugin is returned. -// It is safe for concurrent use by multiple goroutines. -func Open(path string) (*Plugin, error) { - p, err := pl.Open(path) - return (*Plugin)(unsafe.Pointer(p)), err -} - -// Lookup searches for a symbol named symName in plugin p. -// A symbol is any exported variable or function. -// It reports an error if the symbol is not found. -// It is safe for concurrent use by multiple goroutines. -func (p *Plugin) Lookup(symName string) (Symbol, error) { - return (*pl.Plugin)(unsafe.Pointer(p)).Lookup(symName) -} - -// Close closes a Go plugin. -// If a path is noth opened, it is ignored. -// It is safe for concurrent use by multiple goroutines. -func Close(p *Plugin) error { - return unload(p) -} - -// A Symbol is a pointer to a variable or function. -// -// For example, a plugin defined as -// -// package main -// -// import "fmt" -// -// var V int -// -// func F() { fmt.Printf("Hello, number %d\n", V) } -// -// may be loaded with the Open function and then the exported package -// symbols V and F can be accessed -// -// p, err := plugin.Open("plugin_name.so") -// if err != nil { -// panic(err) -// } -// v, err := p.Lookup("V") -// if err != nil { -// panic(err) -// } -// f, err := p.Lookup("F") -// if err != nil { -// panic(err) -// } -// *v.(*int) = 7 -// f.(func())() // prints "Hello, number 7" -type Symbol interface{} diff --git a/dyloader/plugin/plugin_win.go b/dyloader/plugin/plugin_win.go deleted file mode 100644 index e95f52d0..00000000 --- a/dyloader/plugin/plugin_win.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2016 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package plugin implements loading and symbol resolution of Go plugins. -// -// A plugin is a Go main package with exported functions and variables that -// has been built with: -// -// go build -buildmode=plugin -// -// When a plugin is first opened, the init functions of all packages not -// already part of the program are called. The main function is not run. -// A plugin is only initialized once, and cannot be closed. -// -// Currently plugins are only supported on Linux, FreeBSD, and macOS. -// Please report any issues. - -//go:build windows,cgo -// +build windows,cgo - -package plugin - -// Plugin is a loaded Go plugin. -type Plugin struct { - pluginpath string - err string // set if plugin failed to load - loaded chan struct{} // closed when loaded - syms map[string]interface{} -} - -// Open opens a Go plugin. -// If a path has already been opened, then the existing *Plugin is returned. -// It is safe for concurrent use by multiple goroutines. -func Open(path string) (*Plugin, error) { - return open(path) -} - -// Lookup searches for a symbol named symName in plugin p. -// A symbol is any exported variable or function. -// It reports an error if the symbol is not found. -// It is safe for concurrent use by multiple goroutines. -func (p *Plugin) Lookup(symName string) (Symbol, error) { - return lookup(p, symName) -} - -// Close closes a Go plugin. -// If a path is noth opened, it is ignored. -// It is safe for concurrent use by multiple goroutines. -func Close(p *Plugin) error { - return unload(p) -} - -// A Symbol is a pointer to a variable or function. -// -// For example, a plugin defined as -// -// package main -// -// import "fmt" -// -// var V int -// -// func F() { fmt.Printf("Hello, number %d\n", V) } -// -// may be loaded with the Open function and then the exported package -// symbols V and F can be accessed -// -// p, err := plugin.Open("plugin_name.so") -// if err != nil { -// panic(err) -// } -// v, err := p.Lookup("V") -// if err != nil { -// panic(err) -// } -// f, err := p.Lookup("F") -// if err != nil { -// panic(err) -// } -// *v.(*int) = 7 -// f.(func())() // prints "Hello, number 7" -type Symbol interface{} diff --git a/dyloader/scan.go b/dyloader/scan.go deleted file mode 100644 index d693e5ee..00000000 --- a/dyloader/scan.go +++ /dev/null @@ -1,189 +0,0 @@ -// Package dyloader 动态插件加载器 -package dyloader - -import ( - "io/fs" - "path/filepath" - "strings" - "sync" - "time" - _ "unsafe" - - "github.com/sirupsen/logrus" - zero "github.com/wdvxdr1123/ZeroBot" - "github.com/wdvxdr1123/ZeroBot/extension" - "github.com/wdvxdr1123/ZeroBot/message" - - "github.com/FloatTech/ZeroBot-Plugin/control" - "github.com/FloatTech/ZeroBot-Plugin/dyloader/plugin" -) - -var typeIsSo bool -var visited bool - -//go:linkname matcherList github.com/wdvxdr1123/ZeroBot.matcherList -//go:linkname matcherLock github.com/wdvxdr1123/ZeroBot.matcherLock -//go:linkname defaultEngine github.com/wdvxdr1123/ZeroBot.defaultEngine -var ( - // matcherList 所有主匹配器列表 - matcherList []*zero.Matcher - // Matcher 修改读写锁 - matcherLock sync.RWMutex - // defaultEngine zero 的默认 engine - defaultEngine *zero.Engine -) - -var ( - pluginsMu sync.Mutex - plugins = make(map[string]*plugin.Plugin) -) - -func init() { - zero.OnCommand("刷新插件", zero.SuperUserPermission).SetBlock(true).FirstPriority(). - Handle(func(ctx *zero.Ctx) { - err := scan() - if err != nil { - ctx.SendChain(message.Text("Error: " + err.Error())) - } else { - ctx.SendChain(message.Text("成功!")) - } - }) - zero.OnCommand("加载插件", zero.SuperUserPermission).SetBlock(true).FirstPriority(). - Handle(func(ctx *zero.Ctx) { - model := extension.CommandModel{} - _ = ctx.Parse(&model) - _, ok := control.Lookup(model.Args) - if !ok { - t := ".dll" - if typeIsSo { - t = ".so" - } - target := model.Args + t - logrus.Debugln("[dyloader]target:", target) - path := "plugins/" + target - err := open(path, target) - if err != nil { - ctx.SendChain(message.Text("Error: " + err.Error())) - } else { - ctx.SendChain(message.Text("成功!")) - } - } - }) - zero.OnCommand("卸载插件", zero.SuperUserPermission).SetBlock(true).FirstPriority(). - Handle(func(ctx *zero.Ctx) { - model := extension.CommandModel{} - _ = ctx.Parse(&model) - _, ok := control.Lookup(model.Args) - if ok { - t := ".dll" - if typeIsSo { - t = ".so" - } - target := model.Args + t - logrus.Debugln("[dyloader]target:", target) - pluginsMu.Lock() - p, ok := plugins[target] - pluginsMu.Unlock() - if ok { - err := plugin.Close(p) - control.Delete(model.Args) - pluginsMu.Lock() - delete(plugins, target) - pluginsMu.Unlock() - if err != nil { - ctx.SendChain(message.Text("Error: " + err.Error())) - } else { - ctx.SendChain(message.Text("成功!")) - } - } else { - ctx.SendChain(message.Text("没有这个插件!")) - } - } - }) - go func() { - time.Sleep(time.Second * 2) - _ = scan() - }() -} - -func scan() error { - return filepath.WalkDir("plugins/", load) -} - -func open(path, target string) error { - pluginsMu.Lock() - _, ok := plugins[target] - pluginsMu.Unlock() - if !ok { - p, err := plugin.Open(path) - var initfunc, hookfunc, ishooked plugin.Symbol - if err == nil { - ishooked, err = p.Lookup("IsHooked") - if err == nil { - if !*ishooked.(*bool) { - hookfunc, err = p.Lookup("Hook") - if err == nil { - logrus.Debugf("[dyloader]reg: %x, del: %x\n", control.Register, control.Delete) - logrus.Debugf("[dyloader]matlist: %p, matlock: %p\n", &matcherList, &matcherLock) - hookfunc.(func(interface{}, interface{}, interface{}, - interface{}, interface{}, interface{}, - interface{}, interface{}, - interface{}, interface{}, interface{}, - interface{}, - interface{}, interface{}, interface{}, - ))( - &zero.BotConfig, &zero.APICallers, zero.New, - &matcherList, &matcherLock, defaultEngine, - control.Register, control.Delete, - sendGroupMessage, sendPrivateMessage, getMessage, - parse, - message.CustomNode, message.ParseMessage, message.ParseMessageFromArray, - ) - } else { - _ = plugin.Close(p) - return err - } - } - initfunc, err = p.Lookup("Inita") - if err == nil { - initfunc.(func())() - logrus.Infoln("[dyloader]加载插件", path, "成功") - pluginsMu.Lock() - plugins[target] = p - pluginsMu.Unlock() - return nil - } - } - _ = plugin.Close(p) - } - if err != nil { - logrus.Errorln("[dyloader]加载插件", path, "错误:", err) - } - return err - } - return nil -} - -func load(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - if d.IsDir() { - return nil - } - n := d.Name() - if !visited { - if strings.HasSuffix(n, ".so") { - typeIsSo = true - visited = true - } else if strings.HasSuffix(n, ".dll") { - visited = true - } - } - if strings.HasSuffix(n, ".so") || strings.HasSuffix(n, ".dll") { - target := path[strings.LastIndex(path, "/")+1:] - logrus.Debugln("[dyloader]target:", target) - return open(path, target) - } - return nil -} diff --git a/main.go b/main.go index e781e469..cbaca315 100644 --- a/main.go +++ b/main.go @@ -48,7 +48,7 @@ import ( _ "github.com/FloatTech/ZeroBot-Plugin/plugin_setutime" // 来份涩图 // 以下为内置依赖,勿动 - // _ "github.com/FloatTech/ZeroBot-Plugin/dyloader" + // _ "github.com/FloatTech/ZeroBot-Plugin-Dynamic/dyloader" "github.com/sirupsen/logrus" zero "github.com/wdvxdr1123/ZeroBot" "github.com/wdvxdr1123/ZeroBot/driver" @@ -57,7 +57,7 @@ import ( var ( contents = []string{ "* OneBot + ZeroBot + Golang", - "* Version 1.1.6 - 2021-10-09 12:50:23 +0800 CST", + "* Version 1.1.7 - 2021-10-09 12:50:23 +0800 CST", "* Copyright © 2020 - 2021 Kanri, DawnNights, Fumiama, Suika", "* Project: https://github.com/FloatTech/ZeroBot-Plugin", }