This commit is contained in:
RPRX 2020-11-25 19:01:53 +08:00
parent 47d23e9972
commit c7f7c08ead
711 changed files with 82154 additions and 2 deletions

View file

@ -0,0 +1,9 @@
// +build !windows
package ctlcmd
import "syscall"
func getSysProcAttr() *syscall.SysProcAttr {
return nil
}

View file

@ -0,0 +1,11 @@
// +build windows
package ctlcmd
import "syscall"
func getSysProcAttr() *syscall.SysProcAttr {
return &syscall.SysProcAttr{
HideWindow: true,
}
}

View file

@ -0,0 +1,50 @@
package ctlcmd
import (
"io"
"os"
"os/exec"
"strings"
"github.com/xtls/xray-core/v1/common/buf"
"github.com/xtls/xray-core/v1/common/platform"
)
//go:generate go run github.com/xtls/xray-core/v1/common/errors/errorgen
func Run(args []string, input io.Reader) (buf.MultiBuffer, error) {
xctl := platform.GetToolLocation("xctl")
if _, err := os.Stat(xctl); err != nil {
return nil, newError("xctl doesn't exist").Base(err)
}
var errBuffer buf.MultiBufferContainer
var outBuffer buf.MultiBufferContainer
cmd := exec.Command(xctl, args...)
cmd.Stderr = &errBuffer
cmd.Stdout = &outBuffer
cmd.SysProcAttr = getSysProcAttr()
if input != nil {
cmd.Stdin = input
}
if err := cmd.Start(); err != nil {
return nil, newError("failed to start xctl").Base(err)
}
if err := cmd.Wait(); err != nil {
msg := "failed to execute xctl"
if errBuffer.Len() > 0 {
msg += ": \n" + strings.TrimSpace(errBuffer.MultiBuffer.String())
}
return nil, newError(msg).Base(err)
}
// log stderr, info message
if !errBuffer.IsEmpty() {
newError("<xctl message> \n", strings.TrimSpace(errBuffer.MultiBuffer.String())).AtInfo().WriteToLog()
}
return outBuffer.MultiBuffer, nil
}

View file

@ -0,0 +1,9 @@
package ctlcmd
import "github.com/xtls/xray-core/v1/common/errors"
type errPathObjHolder struct{}
func newError(values ...interface{}) *errors.Error {
return errors.New(values...).WithPathObj(errPathObjHolder{})
}

View file

@ -0,0 +1,44 @@
package filesystem
import (
"io"
"os"
"github.com/xtls/xray-core/v1/common/buf"
"github.com/xtls/xray-core/v1/common/platform"
)
type FileReaderFunc func(path string) (io.ReadCloser, error)
var NewFileReader FileReaderFunc = func(path string) (io.ReadCloser, error) {
return os.Open(path)
}
func ReadFile(path string) ([]byte, error) {
reader, err := NewFileReader(path)
if err != nil {
return nil, err
}
defer reader.Close()
return buf.ReadAllToBytes(reader)
}
func ReadAsset(file string) ([]byte, error) {
return ReadFile(platform.GetAssetLocation(file))
}
func CopyFile(dst string, src string) error {
bytes, err := ReadFile(src)
if err != nil {
return err
}
f, err := os.OpenFile(dst, os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
return err
}
defer f.Close()
_, err = f.Write(bytes)
return err
}

44
common/platform/others.go Normal file
View file

@ -0,0 +1,44 @@
// +build !windows
package platform
import (
"os"
"path/filepath"
)
func ExpandEnv(s string) string {
return os.ExpandEnv(s)
}
func LineSeparator() string {
return "\n"
}
func GetToolLocation(file string) string {
const name = "xray.location.tool"
toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir)
return filepath.Join(toolPath, file)
}
// GetAssetLocation search for `file` in certain locations
func GetAssetLocation(file string) string {
const name = "xray.location.asset"
assetPath := NewEnvFlag(name).GetValue(getExecutableDir)
defPath := filepath.Join(assetPath, file)
for _, p := range []string{
defPath,
filepath.Join("/usr/local/share/xray/", file),
filepath.Join("/usr/share/xray/", file),
} {
if _, err := os.Stat(p); os.IsNotExist(err) {
continue
}
// asset found
return p
}
// asset not found, let the caller throw out the error
return defPath
}

View file

@ -0,0 +1,86 @@
package platform // import "github.com/xtls/xray-core/v1/common/platform"
import (
"os"
"path/filepath"
"strconv"
"strings"
)
type EnvFlag struct {
Name string
AltName string
}
func NewEnvFlag(name string) EnvFlag {
return EnvFlag{
Name: name,
AltName: NormalizeEnvName(name),
}
}
func (f EnvFlag) GetValue(defaultValue func() string) string {
if v, found := os.LookupEnv(f.Name); found {
return v
}
if len(f.AltName) > 0 {
if v, found := os.LookupEnv(f.AltName); found {
return v
}
}
return defaultValue()
}
func (f EnvFlag) GetValueAsInt(defaultValue int) int {
useDefaultValue := false
s := f.GetValue(func() string {
useDefaultValue = true
return ""
})
if useDefaultValue {
return defaultValue
}
v, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return defaultValue
}
return int(v)
}
func NormalizeEnvName(name string) string {
return strings.ReplaceAll(strings.ToUpper(strings.TrimSpace(name)), ".", "_")
}
func getExecutableDir() string {
exec, err := os.Executable()
if err != nil {
return ""
}
return filepath.Dir(exec)
}
func getExecutableSubDir(dir string) func() string {
return func() string {
return filepath.Join(getExecutableDir(), dir)
}
}
func GetPluginDirectory() string {
const name = "xray.location.plugin"
pluginDir := NewEnvFlag(name).GetValue(getExecutableSubDir("plugins"))
return pluginDir
}
func GetConfigurationPath() string {
const name = "xray.location.config"
configPath := NewEnvFlag(name).GetValue(getExecutableDir)
return filepath.Join(configPath, "config.json")
}
// GetConfDirPath reads "xray.location.confdir"
func GetConfDirPath() string {
const name = "xray.location.confdir"
configPath := NewEnvFlag(name).GetValue(func() string { return "" })
return configPath
}

View file

@ -0,0 +1,65 @@
package platform_test
import (
"os"
"path/filepath"
"runtime"
"testing"
"github.com/xtls/xray-core/v1/common"
. "github.com/xtls/xray-core/v1/common/platform"
)
func TestNormalizeEnvName(t *testing.T) {
cases := []struct {
input string
output string
}{
{
input: "a",
output: "A",
},
{
input: "a.a",
output: "A_A",
},
{
input: "A.A.B",
output: "A_A_B",
},
}
for _, test := range cases {
if v := NormalizeEnvName(test.input); v != test.output {
t.Error("unexpected output: ", v, " want ", test.output)
}
}
}
func TestEnvFlag(t *testing.T) {
if v := (EnvFlag{
Name: "xxxxx.y",
}.GetValueAsInt(10)); v != 10 {
t.Error("env value: ", v)
}
}
func TestGetAssetLocation(t *testing.T) {
exec, err := os.Executable()
common.Must(err)
loc := GetAssetLocation("t")
if filepath.Dir(loc) != filepath.Dir(exec) {
t.Error("asset dir: ", loc, " not in ", exec)
}
os.Setenv("xray.location.asset", "/xray")
if runtime.GOOS == "windows" {
if v := GetAssetLocation("t"); v != "\\xray\\t" {
t.Error("asset loc: ", v)
}
} else {
if v := GetAssetLocation("t"); v != "/xray/t" {
t.Error("asset loc: ", v)
}
}
}

View file

@ -0,0 +1,27 @@
// +build windows
package platform
import "path/filepath"
func ExpandEnv(s string) string {
// TODO
return s
}
func LineSeparator() string {
return "\r\n"
}
func GetToolLocation(file string) string {
const name = "xray.location.tool"
toolPath := EnvFlag{Name: name, AltName: NormalizeEnvName(name)}.GetValue(getExecutableDir)
return filepath.Join(toolPath, file+".exe")
}
// GetAssetLocation search for `file` in the excutable dir
func GetAssetLocation(file string) string {
const name = "xray.location.asset"
assetPath := NewEnvFlag(name).GetValue(getExecutableDir)
return filepath.Join(assetPath, file)
}