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 }