github.com/Uhtred009/v2ray-core-1@v4.31.2+incompatible/main/main.go (about)

     1  package main
     2  
     3  //go:generate go run v2ray.com/core/common/errors/errorgen
     4  
     5  import (
     6  	"flag"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"log"
    10  	"os"
    11  	"os/signal"
    12  	"path"
    13  	"path/filepath"
    14  	"runtime"
    15  	"strings"
    16  	"syscall"
    17  
    18  	"v2ray.com/core"
    19  	"v2ray.com/core/common/cmdarg"
    20  	"v2ray.com/core/common/platform"
    21  	_ "v2ray.com/core/main/distro/all"
    22  )
    23  
    24  var (
    25  	configFiles cmdarg.Arg // "Config file for V2Ray.", the option is customed type, parse in main
    26  	configDir   string
    27  	version     = flag.Bool("version", false, "Show current version of V2Ray.")
    28  	test        = flag.Bool("test", false, "Test config file only, without launching V2Ray server.")
    29  	format      = flag.String("format", "json", "Format of input file.")
    30  
    31  	/* We have to do this here because Golang's Test will also need to parse flag, before
    32  	 * main func in this file is run.
    33  	 */
    34  	_ = func() error {
    35  
    36  		flag.Var(&configFiles, "config", "Config file for V2Ray. Multiple assign is accepted (only json). Latter ones overrides the former ones.")
    37  		flag.Var(&configFiles, "c", "Short alias of -config")
    38  		flag.StringVar(&configDir, "confdir", "", "A dir with multiple json config")
    39  
    40  		return nil
    41  	}()
    42  )
    43  
    44  func fileExists(file string) bool {
    45  	info, err := os.Stat(file)
    46  	return err == nil && !info.IsDir()
    47  }
    48  
    49  func dirExists(file string) bool {
    50  	if file == "" {
    51  		return false
    52  	}
    53  	info, err := os.Stat(file)
    54  	return err == nil && info.IsDir()
    55  }
    56  
    57  func readConfDir(dirPath string) {
    58  	confs, err := ioutil.ReadDir(dirPath)
    59  	if err != nil {
    60  		log.Fatalln(err)
    61  	}
    62  	for _, f := range confs {
    63  		if strings.HasSuffix(f.Name(), ".json") {
    64  			configFiles.Set(path.Join(dirPath, f.Name()))
    65  		}
    66  	}
    67  }
    68  
    69  func getConfigFilePath() (cmdarg.Arg, error) {
    70  	if dirExists(configDir) {
    71  		log.Println("Using confdir from arg:", configDir)
    72  		readConfDir(configDir)
    73  	} else {
    74  		if envConfDir := platform.GetConfDirPath(); dirExists(envConfDir) {
    75  			log.Println("Using confdir from env:", envConfDir)
    76  			readConfDir(envConfDir)
    77  		}
    78  	}
    79  
    80  	if len(configFiles) > 0 {
    81  		return configFiles, nil
    82  	}
    83  
    84  	if workingDir, err := os.Getwd(); err == nil {
    85  		configFile := filepath.Join(workingDir, "config.json")
    86  		if fileExists(configFile) {
    87  			log.Println("Using default config: ", configFile)
    88  			return cmdarg.Arg{configFile}, nil
    89  		}
    90  	}
    91  
    92  	if configFile := platform.GetConfigurationPath(); fileExists(configFile) {
    93  		log.Println("Using config from env: ", configFile)
    94  		return cmdarg.Arg{configFile}, nil
    95  	}
    96  
    97  	log.Println("Using config from STDIN")
    98  	return cmdarg.Arg{"stdin:"}, nil
    99  }
   100  
   101  func GetConfigFormat() string {
   102  	switch strings.ToLower(*format) {
   103  	case "pb", "protobuf":
   104  		return "protobuf"
   105  	default:
   106  		return "json"
   107  	}
   108  }
   109  
   110  func startV2Ray() (core.Server, error) {
   111  	configFiles, err := getConfigFilePath()
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  
   116  	config, err := core.LoadConfig(GetConfigFormat(), configFiles[0], configFiles)
   117  	if err != nil {
   118  		return nil, newError("failed to read config files: [", configFiles.String(), "]").Base(err)
   119  	}
   120  
   121  	server, err := core.New(config)
   122  	if err != nil {
   123  		return nil, newError("failed to create server").Base(err)
   124  	}
   125  
   126  	return server, nil
   127  }
   128  
   129  func printVersion() {
   130  	version := core.VersionStatement()
   131  	for _, s := range version {
   132  		fmt.Println(s)
   133  	}
   134  }
   135  
   136  func main() {
   137  
   138  	flag.Parse()
   139  
   140  	printVersion()
   141  
   142  	if *version {
   143  		return
   144  	}
   145  
   146  	server, err := startV2Ray()
   147  	if err != nil {
   148  		fmt.Println(err)
   149  		// Configuration error. Exit with a special value to prevent systemd from restarting.
   150  		os.Exit(23)
   151  	}
   152  
   153  	if *test {
   154  		fmt.Println("Configuration OK.")
   155  		os.Exit(0)
   156  	}
   157  
   158  	if err := server.Start(); err != nil {
   159  		fmt.Println("Failed to start", err)
   160  		os.Exit(-1)
   161  	}
   162  	defer server.Close()
   163  
   164  	// Explicitly triggering GC to remove garbage from config loading.
   165  	runtime.GC()
   166  
   167  	{
   168  		osSignals := make(chan os.Signal, 1)
   169  		signal.Notify(osSignals, os.Interrupt, syscall.SIGTERM)
   170  		<-osSignals
   171  	}
   172  }