addrinfo.go 2.6 KB
Newer Older
1 2 3 4 5
package peer

import (
	"fmt"

tavit ohanian's avatar
tavit ohanian committed
6
	ma "gitlab.dms3.io/mf/go-multiaddr"
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
)

// AddrInfo is a small struct used to pass around a peer with
// a set of addresses (and later, keys?).
type AddrInfo struct {
	ID    ID
	Addrs []ma.Multiaddr
}

var _ fmt.Stringer = AddrInfo{}

func (pi AddrInfo) String() string {
	return fmt.Sprintf("{%v: %v}", pi.ID, pi.Addrs)
}

22
var ErrInvalidAddr = fmt.Errorf("invalid dms3 multiaddr")
23

24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
// AddrInfosFromP2pAddrs converts a set of Multiaddrs to a set of AddrInfos.
func AddrInfosFromP2pAddrs(maddrs ...ma.Multiaddr) ([]AddrInfo, error) {
	m := make(map[ID][]ma.Multiaddr)
	for _, maddr := range maddrs {
		transport, id := SplitAddr(maddr)
		if id == "" {
			return nil, ErrInvalidAddr
		}
		if transport == nil {
			if _, ok := m[id]; !ok {
				m[id] = nil
			}
		} else {
			m[id] = append(m[id], transport)
		}
	}
	ais := make([]AddrInfo, 0, len(m))
	for id, maddrs := range m {
		ais = append(ais, AddrInfo{ID: id, Addrs: maddrs})
	}
	return ais, nil
}

47
// SplitAddr splits a dms3 Multiaddr into a transport multiaddr and a peer ID.
48
//
49 50
// * Returns a nil transport if the address only contains a /dms3 part.
// * Returns a empty peer ID if the address doesn't contain a /dms3 part.
51
func SplitAddr(m ma.Multiaddr) (transport ma.Multiaddr, id ID) {
52
	if m == nil {
53
		return nil, ""
54 55
	}

Steven Allen's avatar
Steven Allen committed
56
	transport, p2ppart := ma.SplitLast(m)
57
	if p2ppart == nil || p2ppart.Protocol().Code != ma.P_DMS3 {
58
		return m, ""
59
	}
60 61 62 63
	id = ID(p2ppart.RawValue()) // already validated by the multiaddr library.
	return transport, id
}

64 65
// AddrInfoFromString builds an AddrInfo from the string representation of a Multiaddr
func AddrInfoFromString(s string) (*AddrInfo, error) {
Marten Seemann's avatar
Marten Seemann committed
66
	a, err := ma.NewMultiaddr(s)
67 68 69 70 71 72 73
	if err != nil {
		return nil, err
	}

	return AddrInfoFromP2pAddr(a)
}

74 75 76 77 78
// AddrInfoFromP2pAddr converts a Multiaddr to an AddrInfo.
func AddrInfoFromP2pAddr(m ma.Multiaddr) (*AddrInfo, error) {
	transport, id := SplitAddr(m)
	if id == "" {
		return nil, ErrInvalidAddr
79
	}
Steven Allen's avatar
Steven Allen committed
80 81 82
	info := &AddrInfo{ID: id}
	if transport != nil {
		info.Addrs = []ma.Multiaddr{transport}
83
	}
Steven Allen's avatar
Steven Allen committed
84
	return info, nil
85 86
}

Vasco Santos's avatar
Vasco Santos committed
87
// AddrInfoToP2pAddrs converts an AddrInfo to a list of Multiaddrs.
88 89
func AddrInfoToP2pAddrs(pi *AddrInfo) ([]ma.Multiaddr, error) {
	var addrs []ma.Multiaddr
90
	p2ppart, err := ma.NewComponent("dms3", IDB58Encode(pi.ID))
Steven Allen's avatar
Steven Allen committed
91 92 93
	if err != nil {
		return nil, err
	}
Steven Allen's avatar
Steven Allen committed
94 95 96
	if len(pi.Addrs) == 0 {
		return []ma.Multiaddr{p2ppart}, nil
	}
97
	for _, addr := range pi.Addrs {
Steven Allen's avatar
Steven Allen committed
98
		addrs = append(addrs, addr.Encapsulate(p2ppart))
99 100 101 102 103 104 105 106 107 108
	}
	return addrs, nil
}

func (pi *AddrInfo) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"peerID": pi.ID.Pretty(),
		"addrs":  pi.Addrs,
	}
}