github.com/nspcc-dev/neo-go@v0.105.2-0.20240517133400-6be757af3eba/pkg/config/application_config.go (about) 1 package config 2 3 import ( 4 "fmt" 5 "sort" 6 "strconv" 7 "strings" 8 9 "github.com/nspcc-dev/neo-go/pkg/core/storage/dbconfig" 10 ) 11 12 // ApplicationConfiguration config specific to the node. 13 type ApplicationConfiguration struct { 14 Ledger `yaml:",inline"` 15 16 DBConfiguration dbconfig.DBConfiguration `yaml:"DBConfiguration"` 17 18 LogLevel string `yaml:"LogLevel"` 19 LogPath string `yaml:"LogPath"` 20 21 P2P P2P `yaml:"P2P"` 22 23 Pprof BasicService `yaml:"Pprof"` 24 Prometheus BasicService `yaml:"Prometheus"` 25 26 Relay bool `yaml:"Relay"` 27 Consensus Consensus `yaml:"Consensus"` 28 RPC RPC `yaml:"RPC"` 29 Oracle OracleConfiguration `yaml:"Oracle"` 30 P2PNotary P2PNotary `yaml:"P2PNotary"` 31 StateRoot StateRoot `yaml:"StateRoot"` 32 } 33 34 // EqualsButServices returns true when the o is the same as a except for services 35 // (Oracle, P2PNotary, Pprof, Prometheus, RPC and StateRoot sections) 36 // and LogLevel field. 37 func (a *ApplicationConfiguration) EqualsButServices(o *ApplicationConfiguration) bool { 38 if len(a.P2P.Addresses) != len(o.P2P.Addresses) { 39 return false 40 } 41 aCp := make([]string, len(a.P2P.Addresses)) 42 oCp := make([]string, len(o.P2P.Addresses)) 43 copy(aCp, a.P2P.Addresses) 44 copy(oCp, o.P2P.Addresses) 45 sort.Strings(aCp) 46 sort.Strings(oCp) 47 for i := range aCp { 48 if aCp[i] != oCp[i] { 49 return false 50 } 51 } 52 if a.P2P.AttemptConnPeers != o.P2P.AttemptConnPeers || 53 a.P2P.BroadcastFactor != o.P2P.BroadcastFactor || 54 a.DBConfiguration != o.DBConfiguration || 55 a.P2P.DialTimeout != o.P2P.DialTimeout || 56 a.P2P.ExtensiblePoolSize != o.P2P.ExtensiblePoolSize || 57 a.LogPath != o.LogPath || 58 a.P2P.MaxPeers != o.P2P.MaxPeers || 59 a.P2P.MinPeers != o.P2P.MinPeers || 60 a.P2P.PingInterval != o.P2P.PingInterval || 61 a.P2P.PingTimeout != o.P2P.PingTimeout || 62 a.P2P.ProtoTickInterval != o.P2P.ProtoTickInterval || 63 a.Relay != o.Relay { 64 return false 65 } 66 return true 67 } 68 69 // AnnounceableAddress is a pair of node address in the form of "[host]:[port]" 70 // with optional corresponding announced port to be used in version exchange. 71 type AnnounceableAddress struct { 72 Address string 73 AnnouncedPort uint16 74 } 75 76 // GetAddresses parses returns the list of AnnounceableAddress containing information 77 // gathered from Addresses. 78 func (a *ApplicationConfiguration) GetAddresses() ([]AnnounceableAddress, error) { 79 addrs := make([]AnnounceableAddress, 0, len(a.P2P.Addresses)) 80 for i, addrStr := range a.P2P.Addresses { 81 if len(addrStr) == 0 { 82 return nil, fmt.Errorf("address #%d is empty", i) 83 } 84 lastCln := strings.LastIndex(addrStr, ":") 85 if lastCln == -1 { 86 addrs = append(addrs, AnnounceableAddress{ 87 Address: addrStr, // Plain IPv4 address without port. 88 }) 89 continue 90 } 91 lastPort, err := strconv.ParseUint(addrStr[lastCln+1:], 10, 16) 92 if err != nil { 93 addrs = append(addrs, AnnounceableAddress{ 94 Address: addrStr, // Still may be a valid IPv4 of the form "X.Y.Z.Q:" or plain IPv6 "A:B::", keep it. 95 }) 96 continue 97 } 98 penultimateCln := strings.LastIndex(addrStr[:lastCln], ":") 99 if penultimateCln == -1 { 100 addrs = append(addrs, AnnounceableAddress{ 101 Address: addrStr, // IPv4 address with port "X.Y.Z.Q:123" 102 }) 103 continue 104 } 105 isV6 := strings.Count(addrStr, ":") > 2 106 hasBracket := strings.Contains(addrStr, "]") 107 if penultimateCln == lastCln-1 { 108 if isV6 && !hasBracket { 109 addrs = append(addrs, AnnounceableAddress{ 110 Address: addrStr, // Plain IPv6 of the form "A:B::123" 111 }) 112 } else { 113 addrs = append(addrs, AnnounceableAddress{ 114 Address: addrStr[:lastCln], // IPv4 with empty port and non-empty announced port "X.Y.Z.Q::123" or IPv6 with non-empty announced port "[A:B::]::123". 115 AnnouncedPort: uint16(lastPort), 116 }) 117 } 118 continue 119 } 120 _, err = strconv.ParseUint(addrStr[penultimateCln+1:lastCln], 10, 16) 121 if err != nil { 122 if isV6 { 123 addrs = append(addrs, AnnounceableAddress{ 124 Address: addrStr, // Still may be a valid plain IPv6 of the form "A::B:123" or IPv6 with single port [A:B::]:123, keep it. 125 }) 126 continue 127 } 128 return nil, fmt.Errorf("failed to parse port from %s: %w", addrStr, err) // Some garbage. 129 } 130 if isV6 && !hasBracket { 131 addrs = append(addrs, AnnounceableAddress{ 132 Address: addrStr, // Plain IPv6 of the form "A::1:1" 133 }) 134 } else { 135 addrs = append(addrs, AnnounceableAddress{ 136 Address: addrStr[:lastCln], // IPv4 with both ports or IPv6 with both ports specified. 137 AnnouncedPort: uint16(lastPort), 138 }) 139 } 140 } 141 if len(addrs) == 0 { 142 addrs = append(addrs, AnnounceableAddress{ 143 Address: ":0", 144 }) 145 } 146 return addrs, nil 147 }