| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- package config
-
- import (
- "bytes"
- "context"
- "encoding/json"
- "errors"
- "fmt"
- "net"
- "strconv"
- "time"
-
- "go.uber.org/zap"
- statsd "gopkg.in/alexcesaro/statsd.v2"
- )
-
- type SecretMode uint8
-
- func (s SecretMode) String() string {
- switch s {
- case SecretModeSimple:
- return "simple"
- case SecretModeSecured:
- return "secured"
- }
- return "tls"
- }
-
- const (
- SecretModeSimple SecretMode = iota
- SecretModeSecured
- SecretModeTLS
- )
-
- const SimpleSecretLength = 16
-
- type OptionType uint8
-
- const (
- OptionTypeDebug OptionType = iota
- OptionTypeVerbose
-
- OptionTypeBindIP
- OptionTypeBindPort
- OptionTypePublicIPv4
- OptionTypePublicIPv4Port
- OptionTypePublicIPv6
- OptionTypePublicIPv6Port
- OptionTypeStatsIP
- OptionTypeStatsPort
-
- OptionTypeStatsdIP
- OptionTypeStatsdPort
- OptionTypeStatsdNetwork
- OptionTypeStatsdPrefix
- OptionTypeStatsdTagsFormat
- OptionTypeStatsdTags
- OptionTypePrometheusPrefix
-
- OptionTypeWriteBufferSize
- OptionTypeReadBufferSize
-
- OptionTypeAntiReplayMaxSize
- OptionTypeAntiReplayEvictionTime
-
- OptionTypeSecret
- OptionTypeAdtag
- )
-
- type BufferSize struct {
- Read int `json:"read"`
- Write int `json:"write"`
- }
-
- type AntiReplay struct {
- MaxSize int `json:"max_size"`
- EvictionTime time.Duration `json:"duration"`
- }
-
- type Stats struct {
- Prefix string `json:"prefix"`
- }
-
- type StatsdStats struct {
- Stats
-
- Addr Addr `json:"addr"`
- Tags map[string]string `json:"tags"`
- TagsFormat statsd.TagFormat `json:"format"`
- }
-
- type PrometheusStats struct {
- Stats
- }
-
- type Addr struct {
- IP net.IP `json:"ip"`
- Port int `json:"port"`
- net string
- }
-
- func (a Addr) Network() string {
- if a.net == "" {
- return "tcp"
- }
- return a.net
- }
-
- func (a Addr) String() string {
- return net.JoinHostPort(a.IP.String(), strconv.Itoa(a.Port))
- }
-
- func (a Addr) MarshalJSON() ([]byte, error) {
- data := map[string]string{
- "network": a.Network(),
- "addr": a.String(),
- }
- return json.Marshal(data)
- }
-
- type Config struct {
- BufferSize BufferSize `json:"buffer_size"`
- AntiReplay AntiReplay `json:"anti_replay"`
-
- ListenAddr Addr `json:"listen_addr"`
- PublicIPv4Addr Addr `json:"public_ipv4_addr"`
- PublicIPv6Addr Addr `json:"public_ipv6_addr"`
- StatsAddr Addr `json:"stats_addr"`
-
- StatsdStats StatsdStats `json:"stats_statsd"`
- PrometheusStats PrometheusStats `json:"stats_prometheus"`
-
- Debug bool `json:"debug"`
- Verbose bool `json:"verbose"`
- SecretMode SecretMode `json:"secret_mode"`
- Secret []byte `json:"secret"`
- AdTag []byte `json:"adtag"`
- }
-
- func (c Config) Printable() interface{} {
- data, err := json.Marshal(c)
- if err != nil {
- panic(err)
- }
-
- rv := map[string]interface{}{}
- if err := json.Unmarshal(data, &rv); err != nil {
- panic(err)
- }
-
- return rv
- }
-
- func (c Config) String() string {
- data, _ := json.Marshal(c)
- return string(data)
- }
-
- type Opt struct {
- Option OptionType
- Value interface{}
- }
-
- var C = Config{}
-
- func Init(options ...Opt) error { // nolint: gocyclo
- for _, opt := range options {
- switch opt.Option {
- case OptionTypeDebug:
- C.Debug = opt.Value.(bool)
- case OptionTypeVerbose:
- C.Verbose = opt.Value.(bool)
- case OptionTypeBindIP:
- C.ListenAddr.IP = opt.Value.(net.IP)
- case OptionTypeBindPort:
- C.ListenAddr.Port = int(opt.Value.(uint16))
- case OptionTypePublicIPv4:
- C.PublicIPv4Addr.IP = opt.Value.(net.IP)
- case OptionTypePublicIPv4Port:
- C.PublicIPv4Addr.Port = int(opt.Value.(uint16))
- case OptionTypePublicIPv6:
- C.PublicIPv6Addr.IP = opt.Value.(net.IP)
- case OptionTypePublicIPv6Port:
- C.PublicIPv6Addr.Port = int(opt.Value.(uint16))
- case OptionTypeStatsIP:
- C.StatsAddr.IP = opt.Value.(net.IP)
- case OptionTypeStatsPort:
- C.StatsAddr.Port = int(opt.Value.(uint16))
- case OptionTypeStatsdIP:
- C.StatsdStats.Addr.IP = opt.Value.(net.IP)
- case OptionTypeStatsdPort:
- C.StatsdStats.Addr.Port = int(opt.Value.(uint16))
- case OptionTypeStatsdNetwork:
- C.StatsdStats.Addr.net = opt.Value.(string)
- case OptionTypeStatsdPrefix:
- C.StatsdStats.Prefix = opt.Value.(string)
- case OptionTypeStatsdTagsFormat:
- value := opt.Value.(string)
- switch value {
- case "datadog":
- C.StatsdStats.TagsFormat = statsd.Datadog
- case "influxdb":
- C.StatsdStats.TagsFormat = statsd.InfluxDB
- default:
- return fmt.Errorf("Incorrect statsd tag %s", value)
- }
- case OptionTypeStatsdTags:
- C.StatsdStats.Tags = opt.Value.(map[string]string)
- case OptionTypePrometheusPrefix:
- C.PrometheusStats.Prefix = opt.Value.(string)
- case OptionTypeWriteBufferSize:
- C.BufferSize.Write = int(opt.Value.(uint32))
- case OptionTypeReadBufferSize:
- C.BufferSize.Read = int(opt.Value.(uint32))
- case OptionTypeAntiReplayMaxSize:
- C.AntiReplay.MaxSize = opt.Value.(int)
- case OptionTypeAntiReplayEvictionTime:
- C.AntiReplay.EvictionTime = opt.Value.(time.Duration)
- case OptionTypeSecret:
- C.Secret = opt.Value.([]byte)
- case OptionTypeAdtag:
- C.AdTag = opt.Value.([]byte)
- default:
- return fmt.Errorf("Unknown tag %v", opt.Option)
- }
- }
-
- switch {
- case len(C.Secret) == 1+SimpleSecretLength && bytes.HasPrefix(C.Secret, []byte{0xdd}):
- C.SecretMode = SecretModeSecured
- C.Secret = bytes.TrimPrefix(C.Secret, []byte{0xdd})
- case len(C.Secret) == SimpleSecretLength:
- C.SecretMode = SecretModeSimple
- default:
- return errors.New("Incorrect secret")
- }
-
- return nil
- }
-
- func InitPublicAddress(ctx context.Context) error {
- if C.PublicIPv4Addr.Port == 0 {
- C.PublicIPv4Addr.Port = C.ListenAddr.Port
- }
- if C.PublicIPv6Addr.Port == 0 {
- C.PublicIPv6Addr.Port = C.ListenAddr.Port
- }
-
- foundAddress := C.PublicIPv4Addr.IP != nil || C.PublicIPv6Addr.IP != nil
- if C.PublicIPv4Addr.IP == nil {
- ip, err := getGlobalIPv4(ctx)
- if err != nil {
- zap.S().Warnw("Cannot resolve public address", "error", err)
- } else {
- C.PublicIPv4Addr.IP = ip
- foundAddress = true
- }
- }
- if C.PublicIPv6Addr.IP == nil {
- ip, err := getGlobalIPv6(ctx)
- if err != nil {
- zap.S().Warnw("Cannot resolve public address", "error", err)
- } else {
- C.PublicIPv6Addr.IP = ip
- foundAddress = true
- }
- }
-
- if !foundAddress {
- return errors.New("Cannot resolve any public address")
- }
-
- return nil
- }
|