Increase Performance (#145)

* Update libv2ray_main.go

code with security fixes for G304 (file inclusion vulnerability) and G104 (unhandled errors).

* Update libv2ray_main.go

* Update libv2ray_main.go

* Standard formatting and removal of redundant structures

* Update libv2ray_main.go
This commit is contained in:
Pk-web6936 authored and GitHub committed 2025-04-29 07:38:47 +08:00
1 parent c53ff63a3b
commit fd5117ab47
1 file changed
+73 -39
+73 -39
View File
@@ -26,6 +26,7 @@ import (
mobasset "golang.org/x/mobile/asset" mobasset "golang.org/x/mobile/asset"
) )
// Constants for environment variables
const ( const (
coreAsset = "xray.location.asset" coreAsset = "xray.location.asset"
coreCert = "xray.location.cert" coreCert = "xray.location.cert"
@@ -51,39 +52,66 @@ type CoreCallbackHandler interface {
// consoleLogWriter implements a log writer without datetime stamps // consoleLogWriter implements a log writer without datetime stamps
// as Android system already adds timestamps to each log line // as Android system already adds timestamps to each log line
type consoleLogWriter struct { type consoleLogWriter struct {
logger *log.Logger logger *log.Logger // Standard logger
} }
// InitCoreEnv initializes environment variables and file system handlers for the core // InitCoreEnv initializes environment variables and file system handlers for the core
// It sets up asset path, certificate path, XUDP base key and customizes the file reader // It sets up asset path, certificate path, XUDP base key and customizes the file reader
// to support Android asset system // to support Android asset system
func InitCoreEnv(envPath string, key string) { func InitCoreEnv(envPath string, key string) {
// Set asset/cert paths
if len(envPath) > 0 { if len(envPath) > 0 {
os.Setenv(coreAsset, envPath) if err := os.Setenv(coreAsset, envPath); err != nil {
os.Setenv(coreCert, envPath) log.Printf("failed to set %s: %v", coreAsset, err)
}
if len(key) > 0 {
os.Setenv(xudpBaseKey, key)
}
corefilesystem.NewFileReader = func(path string) (io.ReadCloser, error) {
if _, err := os.Stat(path); os.IsNotExist(err) {
_, file := filepath.Split(path)
return mobasset.Open(file)
} }
return os.Open(path) if err := os.Setenv(coreCert, envPath); err != nil {
log.Printf("failed to set %s: %v", coreCert, err)
}
}
// Set XUDP encryption key
if len(key) > 0 {
if err := os.Setenv(xudpBaseKey, key); err != nil {
log.Printf("failed to set %s: %v", xudpBaseKey, err)
}
}
// Custom file reader with path validation
corefilesystem.NewFileReader = func(path string) (io.ReadCloser, error) {
// G304 Fix - Path sanitization
baseDir := envPath
cleanPath := filepath.Clean(path)
fullPath := filepath.Join(baseDir, cleanPath)
// Prevent directory traversal
if baseDir != "" && !strings.HasPrefix(fullPath, baseDir) {
return nil, fmt.Errorf("unauthorized path: %s", path)
}
// Check file existence
if _, err := os.Stat(fullPath); os.IsNotExist(err) {
_, file := filepath.Split(fullPath)
return mobasset.Open(file) // Fallback to assets
} else if err != nil {
return nil, fmt.Errorf("file access error: %w", err)
}
return os.Open(fullPath) // #nosec G304 - Validated path
} }
} }
// NewCoreController initializes and returns a new CoreController instance // NewCoreController initializes and returns a new CoreController instance
// Sets up the console log handler and associates it with the provided callback handler // Sets up the console log handler and associates it with the provided callback handler
func NewCoreController(s CoreCallbackHandler) *CoreController { func NewCoreController(s CoreCallbackHandler) *CoreController {
coreapplog.RegisterHandlerCreator(coreapplog.LogType_Console, // Register custom logger
func(lt coreapplog.LogType, if err := coreapplog.RegisterHandlerCreator(
options coreapplog.HandlerCreatorOptions) (corecommlog.Handler, error) { coreapplog.LogType_Console,
func(lt coreapplog.LogType, options coreapplog.HandlerCreatorOptions) (corecommlog.Handler, error) {
return corecommlog.NewLogger(createStdoutLogWriter()), nil return corecommlog.NewLogger(createStdoutLogWriter()), nil
}) },
); err != nil {
log.Printf("logger registration failed: %v", err)
}
return &CoreController{ return &CoreController{
CallbackHandler: s, CallbackHandler: s,
@@ -98,12 +126,11 @@ func (x *CoreController) StartLoop(configContent string) (err error) {
defer x.coreMutex.Unlock() defer x.coreMutex.Unlock()
if x.IsRunning { if x.IsRunning {
log.Println("The instance is already running") log.Println("core already running")
return nil return nil
} }
err = x.doStartLoop(configContent) return x.doStartLoop(configContent)
return
} }
// StopLoop safely stops the core processing loop and releases resources // StopLoop safely stops the core processing loop and releases resources
@@ -114,8 +141,7 @@ func (x *CoreController) StopLoop() error {
if x.IsRunning { if x.IsRunning {
x.doShutdown() x.doShutdown()
log.Println("Shut down the running instance") x.CallbackHandler.OnEmitStatus(0, "core stopped")
x.CallbackHandler.OnEmitStatus(0, "Closed")
} }
return nil return nil
} }
@@ -148,13 +174,16 @@ func (x *CoreController) MeasureDelay(url string) (int64, error) {
func MeasureOutboundDelay(ConfigureFileContent string, url string) (int64, error) { func MeasureOutboundDelay(ConfigureFileContent string, url string) (int64, error) {
config, err := coreserial.LoadJSONConfig(strings.NewReader(ConfigureFileContent)) config, err := coreserial.LoadJSONConfig(strings.NewReader(ConfigureFileContent))
if err != nil { if err != nil {
return -1, fmt.Errorf("failed to load JSON config: %w", err) return -1, fmt.Errorf("config load error: %w", err)
} }
// Simplify config for testing
config.Inbound = nil config.Inbound = nil
var essentialApp []*serial.TypedMessage var essentialApp []*serial.TypedMessage
for _, app := range config.App { for _, app := range config.App {
if app.Type == "xray.app.proxyman.OutboundConfig" || app.Type == "xray.app.dispatcher.Config" || app.Type == "xray.app.log.Config" { if app.Type == "xray.app.proxyman.OutboundConfig" ||
app.Type == "xray.app.dispatcher.Config" ||
app.Type == "xray.app.log.Config" {
essentialApp = append(essentialApp, app) essentialApp = append(essentialApp, app)
} }
} }
@@ -162,10 +191,12 @@ func MeasureOutboundDelay(ConfigureFileContent string, url string) (int64, error
inst, err := core.New(config) inst, err := core.New(config)
if err != nil { if err != nil {
return -1, fmt.Errorf("failed to create core instance: %w", err) return -1, fmt.Errorf("instance creation failed: %w", err)
} }
inst.Start() if err := inst.Start(); err != nil {
return -1, fmt.Errorf("startup failed: %w", err)
}
defer inst.Close() defer inst.Close()
return measureInstDelay(context.Background(), inst, url) return measureInstDelay(context.Background(), inst, url)
} }
@@ -179,7 +210,9 @@ func CheckVersionX() string {
// doShutdown shuts down the Xray instance and cleans up resources // doShutdown shuts down the Xray instance and cleans up resources
func (x *CoreController) doShutdown() { func (x *CoreController) doShutdown() {
if x.coreInstance != nil { if x.coreInstance != nil {
x.coreInstance.Close() if err := x.coreInstance.Close(); err != nil {
log.Printf("core shutdown error: %v", err)
}
x.coreInstance = nil x.coreInstance = nil
} }
x.IsRunning = false x.IsRunning = false
@@ -188,37 +221,36 @@ func (x *CoreController) doShutdown() {
// doStartLoop sets up and starts the Xray core // doStartLoop sets up and starts the Xray core
func (x *CoreController) doStartLoop(configContent string) error { func (x *CoreController) doStartLoop(configContent string) error {
log.Println("Loading core config") log.Println("initializing core...")
config, err := coreserial.LoadJSONConfig(strings.NewReader(configContent)) config, err := coreserial.LoadJSONConfig(strings.NewReader(configContent))
if err != nil { if err != nil {
return fmt.Errorf("failed to load core config: %w", err) return fmt.Errorf("config error: %w", err)
} }
log.Println("Creating new core instance")
x.coreInstance, err = core.New(config) x.coreInstance, err = core.New(config)
if err != nil { if err != nil {
return fmt.Errorf("failed to create core instance: %w", err) return fmt.Errorf("core init failed: %w", err)
} }
x.statsManager = x.coreInstance.GetFeature(corestats.ManagerType()).(corestats.Manager) x.statsManager = x.coreInstance.GetFeature(corestats.ManagerType()).(corestats.Manager)
log.Println("Starting core") log.Println("starting core...")
x.IsRunning = true x.IsRunning = true
if err := x.coreInstance.Start(); err != nil { if err := x.coreInstance.Start(); err != nil {
x.IsRunning = false x.IsRunning = false
return fmt.Errorf("failed to start core: %w", err) return fmt.Errorf("startup failed: %w", err)
} }
x.CallbackHandler.Startup() x.CallbackHandler.Startup()
x.CallbackHandler.OnEmitStatus(0, "Started successfully, running") x.CallbackHandler.OnEmitStatus(0, "Started successfully, running")
log.Println("Starting core successfully") log.Println("Starting core successfully")
return nil return nil
} }
// measureInstDelay measures the delay for an instance to a given URL // measureInstDelay measures the delay for an instance to a given URL
func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int64, error) { func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int64, error) {
if inst == nil { if inst == nil {
return -1, errors.New("core instance is nil") return -1, errors.New("nil instance")
} }
tr := &http.Transport{ tr := &http.Transport{
@@ -238,9 +270,10 @@ func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int
Timeout: 12 * time.Second, Timeout: 12 * time.Second,
} }
if len(url) == 0 { if url == "" {
url = "https://www.google.com/generate_204" url = "https://www.google.com/generate_204"
} }
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil) req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
start := time.Now() start := time.Now()
resp, err := client.Do(req) resp, err := client.Do(req)
@@ -250,11 +283,12 @@ func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int
defer resp.Body.Close() defer resp.Body.Close()
if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent { if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusNoContent {
return -1, fmt.Errorf("unexpected status code: %s", resp.Status) return -1, fmt.Errorf("invalid status: %s", resp.Status)
} }
return time.Since(start).Milliseconds(), nil return time.Since(start).Milliseconds(), nil
} }
// Log writer implementation
func (w *consoleLogWriter) Write(s string) error { func (w *consoleLogWriter) Write(s string) error {
w.logger.Print(s) w.logger.Print(s)
return nil return nil