2021-06-21 10:32:48 +00:00
|
|
|
package network
|
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
2021-06-23 12:27:00 +00:00
|
|
|
"fmt"
|
2021-06-23 09:17:37 +00:00
|
|
|
"sort"
|
2021-06-21 10:32:48 +00:00
|
|
|
|
|
|
|
"github.com/nspcc-dev/neofs-api-go/pkg/netmap"
|
|
|
|
)
|
|
|
|
|
|
|
|
// AddressGroup represents list of network addresses of the node.
|
|
|
|
//
|
|
|
|
// List is sorted by priority of use.
|
|
|
|
type AddressGroup []Address
|
|
|
|
|
2021-06-21 16:50:00 +00:00
|
|
|
// StringifyGroup returns concatenation of all addresses
|
|
|
|
// from the AddressGroup.
|
|
|
|
//
|
|
|
|
// The result is order-dependent.
|
|
|
|
func StringifyGroup(x AddressGroup) string {
|
|
|
|
var s string
|
|
|
|
|
2021-06-23 09:57:03 +00:00
|
|
|
iterateAllAddresses(x, func(addr Address) {
|
2021-06-21 16:50:00 +00:00
|
|
|
s += addr.String()
|
|
|
|
})
|
|
|
|
|
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2021-06-21 10:32:48 +00:00
|
|
|
// IterateAddresses iterates over all network addresses of the node.
|
|
|
|
//
|
|
|
|
// Breaks iterating on handler's true return.
|
|
|
|
//
|
|
|
|
// Handler should not be nil.
|
|
|
|
func (x AddressGroup) IterateAddresses(f func(Address) bool) {
|
|
|
|
for i := range x {
|
|
|
|
if f(x[i]) {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-06-23 09:57:03 +00:00
|
|
|
// iterateAllAddresses iterates over all network addresses of g
|
|
|
|
// and passes each of them to f.
|
|
|
|
func iterateAllAddresses(g AddressGroup, f func(Address)) {
|
|
|
|
g.IterateAddresses(func(addr Address) bool {
|
|
|
|
f(addr)
|
|
|
|
return false
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2021-06-23 09:17:37 +00:00
|
|
|
// Len returns number of addresses in AddressGroup.
|
|
|
|
func (x AddressGroup) Len() int {
|
|
|
|
return len(x)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Less returns true if i-th address in AddressGroup supports TLS
|
|
|
|
// and j-th one doesn't.
|
|
|
|
func (x AddressGroup) Less(i, j int) bool {
|
|
|
|
return x[i].TLSEnabled() && !x[j].TLSEnabled()
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swap swaps i-th and j-th addresses in AddressGroup.
|
|
|
|
func (x AddressGroup) Swap(i, j int) {
|
|
|
|
x[i], x[j] = x[j], x[i]
|
|
|
|
}
|
|
|
|
|
2021-06-21 10:32:48 +00:00
|
|
|
// MultiAddressIterator is an interface of network address group.
|
|
|
|
type MultiAddressIterator interface {
|
|
|
|
// Must iterate over network addresses and pass each one
|
|
|
|
// to the handler until it returns true.
|
|
|
|
IterateAddresses(func(string) bool)
|
|
|
|
|
|
|
|
// Must return number of addresses in group.
|
|
|
|
NumberOfAddresses() int
|
|
|
|
}
|
|
|
|
|
|
|
|
// FromIterator forms AddressGroup from MultiAddressIterator structure.
|
2021-06-23 09:17:37 +00:00
|
|
|
// The result is sorted with sort.Sort.
|
2021-06-21 10:32:48 +00:00
|
|
|
//
|
|
|
|
// Returns an error in the absence of addresses or if any of the addresses are incorrect.
|
2021-06-23 12:27:00 +00:00
|
|
|
func (x *AddressGroup) FromIterator(iter MultiAddressIterator) error {
|
2021-06-21 10:32:48 +00:00
|
|
|
as := *x
|
|
|
|
|
|
|
|
addrNum := iter.NumberOfAddresses()
|
|
|
|
if addrNum <= 0 {
|
2021-06-23 12:27:00 +00:00
|
|
|
return errors.New("missing network addresses")
|
2021-06-21 10:32:48 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if cap(as) >= addrNum {
|
|
|
|
as = as[:0]
|
|
|
|
} else {
|
|
|
|
as = make(AddressGroup, 0, addrNum)
|
|
|
|
}
|
|
|
|
|
2021-06-23 12:27:00 +00:00
|
|
|
err := iterateParsedAddresses(iter, func(a Address) error {
|
|
|
|
as = append(as, a)
|
|
|
|
return nil
|
|
|
|
})
|
|
|
|
|
|
|
|
if err == nil {
|
|
|
|
sort.Sort(as)
|
|
|
|
*x = as
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
// iterateParsedAddresses parses each address from MultiAddressIterator and passes it to f
|
|
|
|
// until 1st parsing failure or f's error.
|
|
|
|
func iterateParsedAddresses(iter MultiAddressIterator, f func(s Address) error) (err error) {
|
2021-06-21 10:32:48 +00:00
|
|
|
iter.IterateAddresses(func(s string) bool {
|
|
|
|
var a Address
|
|
|
|
|
|
|
|
err = a.FromString(s)
|
2021-06-23 12:27:00 +00:00
|
|
|
if err != nil {
|
|
|
|
err = fmt.Errorf("could not parse address from string: %w", err)
|
|
|
|
return true
|
2021-06-21 10:32:48 +00:00
|
|
|
}
|
|
|
|
|
2021-06-23 12:27:00 +00:00
|
|
|
err = f(a)
|
2021-06-21 10:32:48 +00:00
|
|
|
|
2021-06-23 12:27:00 +00:00
|
|
|
return err != nil
|
|
|
|
})
|
2021-06-21 10:32:48 +00:00
|
|
|
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteToNodeInfo writes AddressGroup to netmap.NodeInfo structure.
|
2021-06-23 09:50:40 +00:00
|
|
|
func WriteToNodeInfo(g AddressGroup, ni *netmap.NodeInfo) {
|
|
|
|
num := g.Len()
|
|
|
|
addrs := make([]string, 0, num)
|
2021-06-21 10:32:48 +00:00
|
|
|
|
2021-06-23 09:57:03 +00:00
|
|
|
iterateAllAddresses(g, func(addr Address) {
|
2021-06-23 09:50:40 +00:00
|
|
|
addrs = append(addrs, addr.String())
|
|
|
|
})
|
2021-06-21 10:32:48 +00:00
|
|
|
|
|
|
|
ni.SetAddresses(addrs...)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Intersects checks if two AddressGroup have
|
|
|
|
// at least one common address.
|
|
|
|
func (x AddressGroup) Intersects(x2 AddressGroup) bool {
|
|
|
|
for i := range x {
|
|
|
|
for j := range x2 {
|
2021-06-23 09:24:01 +00:00
|
|
|
if x[i].equal(x2[j]) {
|
2021-06-21 10:32:48 +00:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|