diff --git a/common/platform/platform.go b/common/platform/platform.go index fe9acdc7..b827cdc0 100644 --- a/common/platform/platform.go +++ b/common/platform/platform.go @@ -53,8 +53,20 @@ func getExecutableDir() string { return filepath.Dir(exec) } +func getExecuableSubDir(dir string) func() string { + return func() string { + return filepath.Join(getExecutableDir(), dir) + } +} + func GetAssetLocation(file string) string { const name = "v2ray.location.asset" assetPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir) return filepath.Join(assetPath, file) } + +func GetPluginDirectory() string { + const name = "v2ray.location.plugin" + pluginDir := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecuableSubDir("plugins")) + return pluginDir +} diff --git a/main/main.go b/main/main.go index de5bdb40..d6b52cf9 100644 --- a/main/main.go +++ b/main/main.go @@ -22,6 +22,7 @@ var ( version = flag.Bool("version", false, "Show current version of V2Ray.") test = flag.Bool("test", false, "Test config file only, without launching V2Ray server.") format = flag.String("format", "json", "Format of input file.") + plugin = flag.Bool("plugin", false, "True to load plugins.") ) func init() { @@ -82,6 +83,13 @@ func main() { return } + if *plugin { + if err := core.LoadPlugins(); err != nil { + fmt.Println("Failed to load plugins:", err.Error()) + return + } + } + server, err := startV2Ray() if err != nil { fmt.Println(err.Error()) diff --git a/plugin.go b/plugin.go new file mode 100644 index 00000000..dbd9b4c9 --- /dev/null +++ b/plugin.go @@ -0,0 +1,53 @@ +package core + +import ( + "os" + "path/filepath" + "plugin" + "strings" + + "v2ray.com/core/app/log" + "v2ray.com/core/common/platform" +) + +type PluginMetadata struct { + Name string +} + +const GetMetadataFuncName = "GetPluginMetadata" + +type GetMetadataFunc func() PluginMetadata + +func LoadPlugins() error { + pluginPath := platform.GetPluginDirectory() + + dir, err := os.Open(pluginPath) + if err != nil { + return err + } + defer dir.Close() + + files, err := dir.Readdir(-1) + if err != nil { + return err + } + + for _, file := range files { + if !file.IsDir() && strings.HasSuffix(file.Name(), ".so") { + p, err := plugin.Open(filepath.Join(pluginPath, file.Name())) + if err != nil { + return err + } + f, err := p.Lookup(GetMetadataFuncName) + if err != nil { + return err + } + if gmf, ok := f.(GetMetadataFunc); ok { + metadata := gmf() + log.Trace(newError("plugin (", metadata.Name, ") loaded.")) + } + } + } + + return nil +}