Refactor main to use Cobra command line framework and package restructure

Reorganized the Go package structure, moving the main package to 'cmd'. Upgraded the flag library to Cobra for better management of CLI commands. This included moving the X25519 key generation from a flag to its own standalone Cobra command, which improves user interaction and code modularity. This structural change will benefit future additions and code maintainability.
This commit is contained in:
Senis John 2023-10-14 10:50:50 +08:00
parent edf02307ad
commit b1bfd04895
No known key found for this signature in database
GPG Key ID: 845E9E4727C3E1A4
21 changed files with 158 additions and 103 deletions

View File

@ -122,12 +122,12 @@ jobs:
- name: Build XrayR - name: Build XrayR
run: | run: |
mkdir -p build_assets mkdir -p build_assets
go build -v -o build_assets/XrayR -trimpath -ldflags "-s -w -buildid=" ./main go build -v -o build_assets/XrayR -trimpath -ldflags "-s -w -buildid="
- name: Build Mips softfloat XrayR - name: Build Mips softfloat XrayR
if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle' if: matrix.goarch == 'mips' || matrix.goarch == 'mipsle'
run: | run: |
GOMIPS=softfloat go build -v -o build_assets/XrayR_softfloat -trimpath -ldflags "-s -w -buildid=" ./main GOMIPS=softfloat go build -v -o build_assets/XrayR_softfloat -trimpath -ldflags "-s -w -buildid="
- name: Rename Windows XrayR - name: Rename Windows XrayR
if: matrix.goos == 'windows' if: matrix.goos == 'windows'
run: | run: |
@ -143,12 +143,12 @@ jobs:
command: | command: |
cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md cp ${GITHUB_WORKSPACE}/README.md ./build_assets/README.md
cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE cp ${GITHUB_WORKSPACE}/LICENSE ./build_assets/LICENSE
cp ${GITHUB_WORKSPACE}/main/dns.json ./build_assets/dns.json cp ${GITHUB_WORKSPACE}/release/config/dns.json ./build_assets/dns.json
cp ${GITHUB_WORKSPACE}/main/route.json ./build_assets/route.json cp ${GITHUB_WORKSPACE}/release/config/route.json ./build_assets/route.json
cp ${GITHUB_WORKSPACE}/main/custom_outbound.json ./build_assets/custom_outbound.json cp ${GITHUB_WORKSPACE}/release/config/custom_outbound.json ./build_assets/custom_outbound.json
cp ${GITHUB_WORKSPACE}/main/custom_inbound.json ./build_assets/custom_inbound.json cp ${GITHUB_WORKSPACE}/release/config/custom_inbound.json ./build_assets/custom_inbound.json
cp ${GITHUB_WORKSPACE}/main/rulelist ./build_assets/rulelist cp ${GITHUB_WORKSPACE}/release/config/rulelist ./build_assets/rulelist
cp ${GITHUB_WORKSPACE}/main/config.yml.example ./build_assets/config.yml cp ${GITHUB_WORKSPACE}/release/config/config.yml.example ./build_assets/config.yml
LIST=('geoip geoip geoip' 'domain-list-community dlc geosite') LIST=('geoip geoip geoip' 'domain-list-community dlc geosite')
for i in "${LIST[@]}" for i in "${LIST[@]}"
do do

38
.gitignore vendored
View File

@ -1,18 +1,20 @@
main/main .idea
main/XrayR *.iml
main/XrayR* out
main/mytest gen
main/access.logo *.exe
main/error.log *.exe~
api/chooseparser.go.bak *.dll
common/Inboundbuilder/.lego/ *.so
common/legocmd/.lego/ *.dylib
.vscode/launch.json *.test
main/.lego *.out
main/cert go.work
main/config.yml main
./vscode XrayR
.idea/* XrayR*
.DS_Store access.log
*.bak error.log
go.work* .lego
cert
config.yml

View File

@ -4,7 +4,7 @@ WORKDIR /app
COPY . . COPY . .
ENV CGO_ENABLED=0 ENV CGO_ENABLED=0
RUN go mod download RUN go mod download
RUN go build -v -o XrayR -trimpath -ldflags "-s -w -buildid=" ./main RUN go build -v -o XrayR -trimpath -ldflags "-s -w -buildid="
# Release # Release
FROM alpine FROM alpine

View File

@ -1,7 +1,6 @@
package main package cmd
import ( import (
"flag"
"fmt" "fmt"
"log" "log"
"os" "os"
@ -13,37 +12,37 @@ import (
"time" "time"
"github.com/fsnotify/fsnotify" "github.com/fsnotify/fsnotify"
"github.com/spf13/cobra"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/XrayR-project/XrayR/common"
"github.com/XrayR-project/XrayR/panel" "github.com/XrayR-project/XrayR/panel"
) )
var ( var (
configFile = flag.String("config", "", "Config file for XrayR.") cfgFile string
printVersion = flag.Bool("version", false, "show version") rootCmd = &cobra.Command{
x25519 = flag.Bool("x25519", false, "Generate key pair for x25519 key exchange") Use: "XrayR",
Run: func(cmd *cobra.Command, args []string) {
if err := run(); err != nil {
log.Fatal(err)
}
},
}
) )
var ( func init() {
version = "0.9.1" rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "Config file for XrayR.")
codename = "XrayR"
intro = "A Xray backend that supports many panels"
)
func showVersion() {
fmt.Printf("%s %s (%s) \n", codename, version, intro)
} }
func getConfig() *viper.Viper { func getConfig() *viper.Viper {
config := viper.New() config := viper.New()
// Set custom path and name // Set custom path and name
if *configFile != "" { if cfgFile != "" {
configName := path.Base(*configFile) configName := path.Base(cfgFile)
configFileExt := path.Ext(*configFile) configFileExt := path.Ext(cfgFile)
configNameOnly := strings.TrimSuffix(configName, configFileExt) configNameOnly := strings.TrimSuffix(configName, configFileExt)
configPath := path.Dir(*configFile) configPath := path.Dir(cfgFile)
config.SetConfigName(configNameOnly) config.SetConfigName(configNameOnly)
config.SetConfigType(strings.TrimPrefix(configFileExt, ".")) config.SetConfigType(strings.TrimPrefix(configFileExt, "."))
config.AddConfigPath(configPath) config.AddConfigPath(configPath)
@ -67,21 +66,13 @@ func getConfig() *viper.Viper {
return config return config
} }
func main() { func run() error {
flag.Parse()
showVersion() showVersion()
if *printVersion {
return
}
if *x25519 {
common.X25519()
return
}
config := getConfig() config := getConfig()
panelConfig := &panel.Config{} panelConfig := &panel.Config{}
if err := config.Unmarshal(panelConfig); err != nil { if err := config.Unmarshal(panelConfig); err != nil {
log.Panicf("Parse config file %v failed: %s \n", configFile, err) return fmt.Errorf("Parse config file %v failed: %s \n", cfgFile, err)
} }
p := panel.New(panelConfig) p := panel.New(panelConfig)
lastTime := time.Now() lastTime := time.Now()
@ -94,7 +85,7 @@ func main() {
// Delete old instance and trigger GC // Delete old instance and trigger GC
runtime.GC() runtime.GC()
if err := config.Unmarshal(panelConfig); err != nil { if err := config.Unmarshal(panelConfig); err != nil {
log.Panicf("Parse config file %v failed: %s \n", configFile, err) log.Panicf("Parse config file %v failed: %s \n", cfgFile, err)
} }
p.Start() p.Start()
lastTime = time.Now() lastTime = time.Now()
@ -106,9 +97,13 @@ func main() {
// Explicitly triggering GC to remove garbage from config loading. // Explicitly triggering GC to remove garbage from config loading.
runtime.GC() runtime.GC()
// Running backend // Running backend
{
osSignals := make(chan os.Signal, 1) osSignals := make(chan os.Signal, 1)
signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM) signal.Notify(osSignals, os.Interrupt, os.Kill, syscall.SIGTERM)
<-osSignals <-osSignals
}
return nil
}
func Execute() error {
return rootCmd.Execute()
} }

27
cmd/version.go Normal file
View File

@ -0,0 +1,27 @@
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var (
version = "0.9.1"
codename = "XrayR"
intro = "A Xray backend that supports many panels"
)
func init() {
rootCmd.AddCommand(&cobra.Command{
Use: "version",
Short: "Print current version of XrayR",
Run: func(cmd *cobra.Command, args []string) {
showVersion()
},
})
}
func showVersion() {
fmt.Printf("%s %s (%s) \n", codename, version, intro)
}

48
cmd/x25519.go Normal file
View File

@ -0,0 +1,48 @@
package cmd
import (
"crypto/rand"
"encoding/base64"
"fmt"
"github.com/spf13/cobra"
"golang.org/x/crypto/curve25519"
)
func init() {
rootCmd.AddCommand(&cobra.Command{
Use: "x25519",
Short: "Generate key pair for x25519 key exchange",
Run: func(cmd *cobra.Command, args []string) {
if err := x25519(); err != nil {
fmt.Println(err)
}
},
})
}
func x25519() error {
var publicKey []byte
privateKey := make([]byte, curve25519.ScalarSize)
if _, err := rand.Read(privateKey); err != nil {
return err
}
// Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html.
privateKey[0] &= 248
privateKey[31] &= 127
privateKey[31] |= 64
publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
if err != nil {
return err
}
output := fmt.Sprintf("Private key: %v\nPublic key: %v",
base64.RawURLEncoding.EncodeToString(privateKey),
base64.RawURLEncoding.EncodeToString(publicKey))
fmt.Println(output)
return nil
}

View File

@ -1,36 +1,2 @@
// Package common contains common utilities that are shared among other packages. // Package common contains common utilities that are shared among other packages.
package common package common
import (
"crypto/rand"
"encoding/base64"
"fmt"
"golang.org/x/crypto/curve25519"
)
func X25519() {
var publicKey []byte
privateKey := make([]byte, curve25519.ScalarSize)
if _, err := rand.Read(privateKey); err != nil {
fmt.Println(err)
return
}
// Modify random bytes using algorithm described at:
// https://cr.yp.to/ecdh.html.
privateKey[0] &= 248
privateKey[31] &= 127
privateKey[31] |= 64
publicKey, err := curve25519.X25519(privateKey, curve25519.Basepoint)
if err != nil {
fmt.Println(err)
return
}
output := fmt.Sprintf("Private key: %v\nPublic key: %v",
base64.RawURLEncoding.EncodeToString(privateKey),
base64.RawURLEncoding.EncodeToString(publicKey))
fmt.Println(output)
}

2
go.mod
View File

@ -21,6 +21,7 @@ require (
github.com/sagernet/sing v0.2.13 github.com/sagernet/sing v0.2.13
github.com/sagernet/sing-shadowsocks v0.2.5 github.com/sagernet/sing-shadowsocks v0.2.5
github.com/shirou/gopsutil/v3 v3.23.9 github.com/shirou/gopsutil/v3 v3.23.9
github.com/spf13/cobra v1.1.1
github.com/spf13/viper v1.17.0 github.com/spf13/viper v1.17.0
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/xtls/xray-core v1.8.4 github.com/xtls/xray-core v1.8.4
@ -112,6 +113,7 @@ require (
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect github.com/infobloxopen/infoblox-go-client v1.1.1 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect github.com/json-iterator/go v1.1.12 // indirect

2
go.sum
View File

@ -468,6 +468,7 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df h1:MZf03xP9WdakyXhOWuAD5uPK3wHh96wCsqe3hCMKh8E=
github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4= github.com/iij/doapi v0.0.0-20190504054126-0bbf12d6d7df/go.mod h1:QMZY7/J/KSQEhKWFeDesPjMj+wCHReeknARU3wqlyN4=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU= github.com/infobloxopen/infoblox-go-client v1.1.1 h1:728A6LbLjptj/7kZjHyIxQnm768PWHfGFm0HH8FnbtU=
github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI= github.com/infobloxopen/infoblox-go-client v1.1.1/go.mod h1:BXiw7S2b9qJoM8MS40vfgCNB2NLHGusk1DtO16BD9zI=
@ -834,6 +835,7 @@ github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkU
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA= github.com/spf13/cast v1.5.1 h1:R+kOtfhWQE6TVQzY+4D7wJLBgkdVasCEFxSUBYBYIlA=
github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48= github.com/spf13/cast v1.5.1/go.mod h1:b9PdjNptOpzXr7Rq1q9gJML/2cdGQAo69NKzQ10KN48=
github.com/spf13/cobra v1.1.1 h1:KfztREH0tPxJJ+geloSLaAkaPkr4ki2Er5quFV1TDo4=
github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI= github.com/spf13/cobra v1.1.1/go.mod h1:WnodtKOvamDL/PwE2M4iKs8aMDBZ5Q5klgD3qfVJQMI=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=

13
main.go Normal file
View File

@ -0,0 +1,13 @@
package main
import (
"log"
"github.com/XrayR-project/XrayR/cmd"
)
func main() {
if err := cmd.Execute(); err != nil {
log.Fatal(err)
}
}

View File

@ -23,7 +23,7 @@ import (
"github.com/XrayR-project/XrayR/api/proxypanel" "github.com/XrayR-project/XrayR/api/proxypanel"
"github.com/XrayR-project/XrayR/api/sspanel" "github.com/XrayR-project/XrayR/api/sspanel"
"github.com/XrayR-project/XrayR/api/v2raysocks" "github.com/XrayR-project/XrayR/api/v2raysocks"
_ "github.com/XrayR-project/XrayR/main/distro/all" _ "github.com/XrayR-project/XrayR/cmd/distro/all"
"github.com/XrayR-project/XrayR/service" "github.com/XrayR-project/XrayR/service"
"github.com/XrayR-project/XrayR/service/controller" "github.com/XrayR-project/XrayR/service/controller"
) )

View File

@ -56,11 +56,11 @@ Nodes:
EnableREALITY: false # Enable REALITY EnableREALITY: false # Enable REALITY
REALITYConfigs: REALITYConfigs:
Show: true # Show REALITY debug Show: true # Show REALITY debug
Dest: www.smzdm.com:443 # Required, Same as fallback Dest: www.amazon.com:443 # Required, Same as fallback
ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment. ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment.
- www.smzdm.com - www.amazon.com
PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR -x25519' to generate. PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR x25519' to generate.
MinClientVer: # Optional, minimum version of Xray client, format is x.y.z. MinClientVer: # Optional, minimum version of Xray client, format is x.y.z.
MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z. MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z.
MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds. MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds.
@ -119,11 +119,11 @@ Nodes:
# EnableREALITY: true # Enable REALITY # EnableREALITY: true # Enable REALITY
# REALITYConfigs: # REALITYConfigs:
# Show: true # Show REALITY debug # Show: true # Show REALITY debug
# Dest: www.smzdm.com:443 # Required, Same as fallback # Dest: www.amazon.com:443 # Required, Same as fallback
# ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable # ProxyProtocolVer: 0 # Send PROXY protocol version, 0 for disable
# ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment. # ServerNames: # Required, list of available serverNames for the client, * wildcard is not supported at the moment.
# - www.smzdm.com # - www.amazon.com
# PrivateKey: YOUR_PRIVATE_KEY # Required, execute './xray x25519' to generate. # PrivateKey: YOUR_PRIVATE_KEY # Required, execute './XrayR x25519' to generate.
# MinClientVer: # Optional, minimum version of Xray client, format is x.y.z. # MinClientVer: # Optional, minimum version of Xray client, format is x.y.z.
# MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z. # MaxClientVer: # Optional, maximum version of Xray client, format is x.y.z.
# MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds. # MaxTimeDiff: 0 # Optional, maximum allowed time difference, unit is in milliseconds.

View File

@ -13,8 +13,8 @@ import (
"github.com/XrayR-project/XrayR/api" "github.com/XrayR-project/XrayR/api"
"github.com/XrayR-project/XrayR/api/sspanel" "github.com/XrayR-project/XrayR/api/sspanel"
_ "github.com/XrayR-project/XrayR/cmd/distro/all"
"github.com/XrayR-project/XrayR/common/mylego" "github.com/XrayR-project/XrayR/common/mylego"
_ "github.com/XrayR-project/XrayR/main/distro/all"
. "github.com/XrayR-project/XrayR/service/controller" . "github.com/XrayR-project/XrayR/service/controller"
) )