github.com/ipfans/trojan-go@v0.11.0/proxy/option.go (about) 1 package proxy 2 3 import ( 4 "bufio" 5 "flag" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "runtime" 10 "strings" 11 12 "github.com/ipfans/trojan-go/common" 13 "github.com/ipfans/trojan-go/constant" 14 "github.com/ipfans/trojan-go/log" 15 "github.com/ipfans/trojan-go/option" 16 ) 17 18 type Option struct { 19 path *string 20 } 21 22 func (o *Option) Name() string { 23 return Name 24 } 25 26 func detectAndReadConfig(file string) ([]byte, bool, error) { 27 isJSON := false 28 switch { 29 case strings.HasSuffix(file, ".json"): 30 isJSON = true 31 case strings.HasSuffix(file, ".yaml"), strings.HasSuffix(file, ".yml"): 32 isJSON = false 33 default: 34 log.Fatalf("unsupported config format: %s. use .yaml or .json instead.", file) 35 } 36 37 data, err := ioutil.ReadFile(file) 38 if err != nil { 39 return nil, false, err 40 } 41 return data, isJSON, nil 42 } 43 44 func (o *Option) Handle() error { 45 defaultConfigPath := []string{ 46 "config.json", 47 "config.yml", 48 "config.yaml", 49 } 50 51 isJSON := false 52 var data []byte 53 var err error 54 55 switch *o.path { 56 case "": 57 log.Warn("no specified config file, use default path to detect config file") 58 for _, file := range defaultConfigPath { 59 log.Warn("try to load config from default path:", file) 60 data, isJSON, err = detectAndReadConfig(file) 61 if err != nil { 62 log.Warn(err) 63 continue 64 } 65 break 66 } 67 default: 68 data, isJSON, err = detectAndReadConfig(*o.path) 69 if err != nil { 70 log.Fatal(err) 71 } 72 } 73 74 if data != nil { 75 log.Info("trojan-go", constant.Version, "initializing") 76 proxy, err := NewProxyFromConfigData(data, isJSON) 77 if err != nil { 78 log.Fatal(err) 79 } 80 err = proxy.Run() 81 if err != nil { 82 log.Fatal(err) 83 } 84 } 85 86 log.Fatal("no valid config") 87 return nil 88 } 89 90 func (o *Option) Priority() int { 91 return -1 92 } 93 94 func init() { 95 option.RegisterHandler(&Option{ 96 path: flag.String("config", "", "Trojan-Go config filename (.yaml/.yml/.json)"), 97 }) 98 option.RegisterHandler(&StdinOption{ 99 format: flag.String("stdin-format", "disabled", "Read from standard input (yaml/json)"), 100 suppressHint: flag.Bool("stdin-suppress-hint", false, "Suppress hint text"), 101 }) 102 } 103 104 type StdinOption struct { 105 format *string 106 suppressHint *bool 107 } 108 109 func (o *StdinOption) Name() string { 110 return Name + "_STDIN" 111 } 112 113 func (o *StdinOption) Handle() error { 114 isJSON, e := o.isFormatJson() 115 if e != nil { 116 return e 117 } 118 119 if o.suppressHint == nil || !*o.suppressHint { 120 fmt.Printf("Trojan-Go %s (%s/%s)\n", constant.Version, runtime.GOOS, runtime.GOARCH) 121 if isJSON { 122 fmt.Println("Reading JSON configuration from stdin.") 123 } else { 124 fmt.Println("Reading YAML configuration from stdin.") 125 } 126 } 127 128 data, e := ioutil.ReadAll(bufio.NewReader(os.Stdin)) 129 if e != nil { 130 log.Fatalf("Failed to read from stdin: %s", e.Error()) 131 } 132 133 proxy, err := NewProxyFromConfigData(data, isJSON) 134 if err != nil { 135 log.Fatal(err) 136 } 137 err = proxy.Run() 138 if err != nil { 139 log.Fatal(err) 140 } 141 142 return nil 143 } 144 145 func (o *StdinOption) Priority() int { 146 return 0 147 } 148 149 func (o *StdinOption) isFormatJson() (isJson bool, e error) { 150 if o.format == nil { 151 return false, common.NewError("format specifier is nil") 152 } 153 if *o.format == "disabled" { 154 return false, common.NewError("reading from stdin is disabled") 155 } 156 return strings.ToLower(*o.format) == "json", nil 157 }