mirror of
https://github.com/2dust/AndroidLibXrayLite.git
synced 2025-06-28 22:29:51 +00:00
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:
parent
c53ff63a3b
commit
fd5117ab47
1 changed files with 73 additions and 39 deletions
112
libv2ray_main.go
112
libv2ray_main.go
|
@ -26,6 +26,7 @@ import (
|
|||
mobasset "golang.org/x/mobile/asset"
|
||||
)
|
||||
|
||||
// Constants for environment variables
|
||||
const (
|
||||
coreAsset = "xray.location.asset"
|
||||
coreCert = "xray.location.cert"
|
||||
|
@ -51,39 +52,66 @@ type CoreCallbackHandler interface {
|
|||
// consoleLogWriter implements a log writer without datetime stamps
|
||||
// as Android system already adds timestamps to each log line
|
||||
type consoleLogWriter struct {
|
||||
logger *log.Logger
|
||||
logger *log.Logger // Standard logger
|
||||
}
|
||||
|
||||
// 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
|
||||
// to support Android asset system
|
||||
func InitCoreEnv(envPath string, key string) {
|
||||
// Set asset/cert paths
|
||||
if len(envPath) > 0 {
|
||||
os.Setenv(coreAsset, envPath)
|
||||
os.Setenv(coreCert, envPath)
|
||||
}
|
||||
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)
|
||||
if err := os.Setenv(coreAsset, envPath); err != nil {
|
||||
log.Printf("failed to set %s: %v", coreAsset, err)
|
||||
}
|
||||
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
|
||||
// Sets up the console log handler and associates it with the provided callback handler
|
||||
func NewCoreController(s CoreCallbackHandler) *CoreController {
|
||||
coreapplog.RegisterHandlerCreator(coreapplog.LogType_Console,
|
||||
func(lt coreapplog.LogType,
|
||||
options coreapplog.HandlerCreatorOptions) (corecommlog.Handler, error) {
|
||||
// Register custom logger
|
||||
if err := coreapplog.RegisterHandlerCreator(
|
||||
coreapplog.LogType_Console,
|
||||
func(lt coreapplog.LogType, options coreapplog.HandlerCreatorOptions) (corecommlog.Handler, error) {
|
||||
return corecommlog.NewLogger(createStdoutLogWriter()), nil
|
||||
})
|
||||
},
|
||||
); err != nil {
|
||||
log.Printf("logger registration failed: %v", err)
|
||||
}
|
||||
|
||||
return &CoreController{
|
||||
CallbackHandler: s,
|
||||
|
@ -98,12 +126,11 @@ func (x *CoreController) StartLoop(configContent string) (err error) {
|
|||
defer x.coreMutex.Unlock()
|
||||
|
||||
if x.IsRunning {
|
||||
log.Println("The instance is already running")
|
||||
log.Println("core already running")
|
||||
return nil
|
||||
}
|
||||
|
||||
err = x.doStartLoop(configContent)
|
||||
return
|
||||
return x.doStartLoop(configContent)
|
||||
}
|
||||
|
||||
// StopLoop safely stops the core processing loop and releases resources
|
||||
|
@ -114,8 +141,7 @@ func (x *CoreController) StopLoop() error {
|
|||
|
||||
if x.IsRunning {
|
||||
x.doShutdown()
|
||||
log.Println("Shut down the running instance")
|
||||
x.CallbackHandler.OnEmitStatus(0, "Closed")
|
||||
x.CallbackHandler.OnEmitStatus(0, "core stopped")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -148,13 +174,16 @@ func (x *CoreController) MeasureDelay(url string) (int64, error) {
|
|||
func MeasureOutboundDelay(ConfigureFileContent string, url string) (int64, error) {
|
||||
config, err := coreserial.LoadJSONConfig(strings.NewReader(ConfigureFileContent))
|
||||
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
|
||||
var essentialApp []*serial.TypedMessage
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -162,10 +191,12 @@ func MeasureOutboundDelay(ConfigureFileContent string, url string) (int64, error
|
|||
|
||||
inst, err := core.New(config)
|
||||
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()
|
||||
return measureInstDelay(context.Background(), inst, url)
|
||||
}
|
||||
|
@ -179,7 +210,9 @@ func CheckVersionX() string {
|
|||
// doShutdown shuts down the Xray instance and cleans up resources
|
||||
func (x *CoreController) doShutdown() {
|
||||
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.IsRunning = false
|
||||
|
@ -188,37 +221,36 @@ func (x *CoreController) doShutdown() {
|
|||
|
||||
// doStartLoop sets up and starts the Xray core
|
||||
func (x *CoreController) doStartLoop(configContent string) error {
|
||||
log.Println("Loading core config")
|
||||
log.Println("initializing core...")
|
||||
config, err := coreserial.LoadJSONConfig(strings.NewReader(configContent))
|
||||
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)
|
||||
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)
|
||||
|
||||
log.Println("Starting core")
|
||||
log.Println("starting core...")
|
||||
x.IsRunning = true
|
||||
if err := x.coreInstance.Start(); err != nil {
|
||||
x.IsRunning = false
|
||||
return fmt.Errorf("failed to start core: %w", err)
|
||||
return fmt.Errorf("startup failed: %w", err)
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// measureInstDelay measures the delay for an instance to a given URL
|
||||
func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int64, error) {
|
||||
if inst == nil {
|
||||
return -1, errors.New("core instance is nil")
|
||||
return -1, errors.New("nil instance")
|
||||
}
|
||||
|
||||
tr := &http.Transport{
|
||||
|
@ -238,9 +270,10 @@ func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int
|
|||
Timeout: 12 * time.Second,
|
||||
}
|
||||
|
||||
if len(url) == 0 {
|
||||
if url == "" {
|
||||
url = "https://www.google.com/generate_204"
|
||||
}
|
||||
|
||||
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
|
||||
start := time.Now()
|
||||
resp, err := client.Do(req)
|
||||
|
@ -250,11 +283,12 @@ func measureInstDelay(ctx context.Context, inst *core.Instance, url string) (int
|
|||
defer resp.Body.Close()
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// Log writer implementation
|
||||
func (w *consoleLogWriter) Write(s string) error {
|
||||
w.logger.Print(s)
|
||||
return nil
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue