You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
4.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package config
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "flag"
  6. "fmt"
  7. "io/ioutil"
  8. "net"
  9. "os"
  10. "path/filepath"
  11. "strings"
  12. . "github.com/tendermint/tendermint/common"
  13. )
  14. //-----------------------------------------------------------------------------j
  15. // Configuration types
  16. type ConfigType struct {
  17. Network string
  18. LAddr string
  19. SeedNode string
  20. DB DBConfig
  21. Alert AlertConfig
  22. SMTP SMTPConfig
  23. RPC RPCConfig
  24. }
  25. type DBConfig struct {
  26. Backend string
  27. Dir string
  28. }
  29. type AlertConfig struct {
  30. MinInterval int
  31. TwilioSid string
  32. TwilioToken string
  33. TwilioFrom string
  34. TwilioTo string
  35. EmailRecipients []string
  36. }
  37. type SMTPConfig struct {
  38. User string
  39. Password string
  40. Host string
  41. Port uint
  42. }
  43. type RPCConfig struct {
  44. HTTPLAddr string
  45. }
  46. func (cfg *ConfigType) validate() error {
  47. if cfg.Network == "" {
  48. cfg.Network = defaultConfig.Network
  49. }
  50. if cfg.LAddr == "" {
  51. cfg.LAddr = defaultConfig.LAddr
  52. }
  53. if cfg.SeedNode == "" {
  54. cfg.SeedNode = defaultConfig.SeedNode
  55. }
  56. if cfg.DB.Backend == "" {
  57. return errors.New("DB.Backend must be set")
  58. }
  59. if cfg.RPC.HTTPLAddr == "" {
  60. fmt.Println("Set RPC.HTTPLAddr to \"0.0.0.0:8888\" in your config.json to enable the RPC API server.")
  61. } else {
  62. _, port, err := net.SplitHostPort(cfg.RPC.HTTPLAddr)
  63. if err != nil {
  64. return errors.New(Fmt("RPC.HTTPLAddr is invalid. %v", err))
  65. }
  66. if port == "" || port == "0" {
  67. return errors.New("RPC.HTTPLAddr is invalid. Port number must be defined")
  68. }
  69. }
  70. return nil
  71. }
  72. func (cfg *ConfigType) bytes() []byte {
  73. configBytes, err := json.MarshalIndent(cfg, "", "\t")
  74. if err != nil {
  75. panic(err)
  76. }
  77. return configBytes
  78. }
  79. func (cfg *ConfigType) write(configFile string) {
  80. if strings.Index(configFile, "/") != -1 {
  81. err := os.MkdirAll(filepath.Dir(configFile), 0700)
  82. if err != nil {
  83. panic(err)
  84. }
  85. }
  86. err := ioutil.WriteFile(configFile, cfg.bytes(), 0600)
  87. if err != nil {
  88. panic(err)
  89. }
  90. }
  91. //-----------------------------------------------------------------------------
  92. var rootDir string
  93. var defaultConfig ConfigType
  94. func init() {
  95. // Get RootDir
  96. rootDir = os.Getenv("TMROOT")
  97. if rootDir == "" {
  98. rootDir = os.Getenv("HOME") + "/.tendermint"
  99. }
  100. // Compute defaultConfig
  101. defaultConfig = ConfigType{
  102. Network: "tendermint_testnet0",
  103. LAddr: "0.0.0.0:0",
  104. SeedNode: "",
  105. DB: DBConfig{
  106. Backend: "leveldb",
  107. Dir: DataDir(),
  108. },
  109. Alert: AlertConfig{},
  110. SMTP: SMTPConfig{},
  111. RPC: RPCConfig{
  112. HTTPLAddr: "0.0.0.0:0",
  113. },
  114. }
  115. }
  116. func ConfigFile() string { return rootDir + "/config.json" }
  117. func GenesisFile() string { return rootDir + "/genesis.json" }
  118. func AddrBookFile() string { return rootDir + "/addrbook.json" }
  119. func PrivValidatorFile() string { return rootDir + "/priv_validator.json" }
  120. func DataDir() string { return rootDir + "/data" }
  121. // The actual global config singleton object.
  122. var Config ConfigType
  123. func parseFlags(flags *flag.FlagSet, args []string) (printHelp bool) {
  124. flags.BoolVar(&printHelp, "help", false, "Print this help message.")
  125. flags.StringVar(&Config.LAddr, "laddr", Config.LAddr, "Listen address. (0.0.0.0:0 means any interface, any port)")
  126. flags.StringVar(&Config.SeedNode, "seed", Config.SeedNode, "Address of seed node")
  127. flags.StringVar(&Config.RPC.HTTPLAddr, "rpc_http_laddr", Config.RPC.HTTPLAddr, "RPC listen address. (0.0.0.0:0 means any interface, any port)")
  128. flags.Parse(args)
  129. return
  130. }
  131. func ParseFlags(args []string) {
  132. configFile := ConfigFile()
  133. // try to read configuration from file. if missing, write default
  134. configBytes, err := ioutil.ReadFile(configFile)
  135. if err != nil {
  136. defaultConfig.write(configFile)
  137. fmt.Println("Config file written to config.json. Please edit & run again")
  138. os.Exit(1)
  139. return
  140. }
  141. // try to parse configuration. on error, die
  142. Config = ConfigType{}
  143. err = json.Unmarshal(configBytes, &Config)
  144. if err != nil {
  145. Exit(Fmt("Invalid configuration file %s:\n%v\n", configFile, err))
  146. }
  147. err = Config.validate()
  148. if err != nil {
  149. Exit(Fmt("Invalid configuration file %s:\n%v\n", configFile, err))
  150. }
  151. // try to parse arg flags, which can override file configuration.
  152. flags := flag.NewFlagSet("main", flag.ExitOnError)
  153. printHelp := parseFlags(flags, args)
  154. if printHelp {
  155. flags.PrintDefaults()
  156. os.Exit(0)
  157. }
  158. }