message.go 4.58 KB
Newer Older
1
package dht_pb
2

Jeromy's avatar
Jeromy committed
3
import (
4 5 6
	"github.com/libp2p/go-libp2p-core/network"
	"github.com/libp2p/go-libp2p-core/peer"

7
	logging "github.com/ipfs/go-log"
8
	ma "github.com/multiformats/go-multiaddr"
Jeromy's avatar
Jeromy committed
9 10
)

Jeromy's avatar
Jeromy committed
11
var log = logging.Logger("dht.pb")
12

13
type PeerRoutingInfo struct {
14 15
	peer.AddrInfo
	network.Connectedness
16 17
}

18
// NewMessage constructs a new dht message with given type, key, and level
19
func NewMessage(typ Message_MessageType, key []byte, level int) *Message {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
20
	m := &Message{
21 22
		Type: typ,
		Key:  key,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
23 24 25 26 27
	}
	m.SetClusterLevel(level)
	return m
}

28 29 30 31 32 33 34 35
func peerRoutingInfoToPBPeer(p PeerRoutingInfo) *Message_Peer {
	pbp := new(Message_Peer)

	pbp.Addrs = make([][]byte, len(p.Addrs))
	for i, maddr := range p.Addrs {
		pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed.
	}
	s := string(p.ID)
36
	pbp.Id = []byte(s)
37
	c := ConnectionType(p.Connectedness)
38
	pbp.Connection = c
39 40 41
	return pbp
}

42
func peerInfoToPBPeer(p peer.AddrInfo) *Message_Peer {
43
	pbp := new(Message_Peer)
44

45 46 47
	pbp.Addrs = make([][]byte, len(p.Addrs))
	for i, maddr := range p.Addrs {
		pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed.
Jeromy's avatar
Jeromy committed
48
	}
49
	pbp.Id = []byte(p.ID)
Jeromy's avatar
Jeromy committed
50
	return pbp
51 52
}

53 54 55
// PBPeerToPeer turns a *Message_Peer into its peer.AddrInfo counterpart
func PBPeerToPeerInfo(pbp *Message_Peer) *peer.AddrInfo {
	return &peer.AddrInfo{
56 57
		ID:    peer.ID(pbp.GetId()),
		Addrs: pbp.Addresses(),
58 59 60
	}
}

61
// RawPeerInfosToPBPeers converts a slice of Peers into a slice of *Message_Peers,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
62
// ready to go out on the wire.
63
func RawPeerInfosToPBPeers(peers []peer.AddrInfo) []*Message_Peer {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
64
	pbpeers := make([]*Message_Peer, len(peers))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
65
	for i, p := range peers {
66
		pbpeers[i] = peerInfoToPBPeer(p)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
67 68 69 70
	}
	return pbpeers
}

71 72 73
// PeersToPBPeers converts given []peer.Peer into a set of []*Message_Peer,
// which can be written to a message and sent out. the key thing this function
// does (in addition to PeersToPBPeers) is set the ConnectionType with
74 75
// information from the given network.Network.
func PeerInfosToPBPeers(n network.Network, peers []peer.AddrInfo) []*Message_Peer {
76
	pbps := RawPeerInfosToPBPeers(peers)
77
	for i, pbp := range pbps {
78
		c := ConnectionType(n.Connectedness(peers[i].ID))
79
		pbp.Connection = c
80 81 82 83
	}
	return pbps
}

84 85 86 87 88 89 90 91
func PeerRoutingInfosToPBPeers(peers []PeerRoutingInfo) []*Message_Peer {
	pbpeers := make([]*Message_Peer, len(peers))
	for i, p := range peers {
		pbpeers[i] = peerRoutingInfoToPBPeer(p)
	}
	return pbpeers
}

92
// PBPeersToPeerInfos converts given []*Message_Peer into []peer.AddrInfo
93
// Invalid addresses will be silently omitted.
94 95
func PBPeersToPeerInfos(pbps []*Message_Peer) []*peer.AddrInfo {
	peers := make([]*peer.AddrInfo, 0, len(pbps))
96 97
	for _, pbp := range pbps {
		peers = append(peers, PBPeerToPeerInfo(pbp))
98
	}
99
	return peers
100 101
}

102
// Addresses returns a multiaddr associated with the Message_Peer entry
103
func (m *Message_Peer) Addresses() []ma.Multiaddr {
104
	if m == nil {
105
		return nil
106
	}
107

108 109 110
	maddrs := make([]ma.Multiaddr, 0, len(m.Addrs))
	for _, addr := range m.Addrs {
		maddr, err := ma.NewMultiaddrBytes(addr)
111
		if err != nil {
Steven Allen's avatar
Steven Allen committed
112
			log.Debugw("error decoding multiaddr for peer", "peer", m.GetId(), "error", err)
113
			continue
114
		}
115 116

		maddrs = append(maddrs, maddr)
117
	}
118
	return maddrs
119 120
}

121 122 123
// GetClusterLevel gets and adjusts the cluster level on the message.
// a +/- 1 adjustment is needed to distinguish a valid first level (1) and
// default "no value" protobuf behavior (0)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
124
func (m *Message) GetClusterLevel() int {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
125 126
	level := m.GetClusterLevelRaw() - 1
	if level < 0 {
127
		return 0
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
128
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
129
	return int(level)
130
}
131

132 133 134
// SetClusterLevel adjusts and sets the cluster level on the message.
// a +/- 1 adjustment is needed to distinguish a valid first level (1) and
// default "no value" protobuf behavior (0)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
135 136
func (m *Message) SetClusterLevel(level int) {
	lvl := int32(level)
137
	m.ClusterLevelRaw = lvl + 1
138
}
139

140
// ConnectionType returns a Message_ConnectionType associated with the
141 142
// network.Connectedness.
func ConnectionType(c network.Connectedness) Message_ConnectionType {
143 144 145
	switch c {
	default:
		return Message_NOT_CONNECTED
146
	case network.NotConnected:
147
		return Message_NOT_CONNECTED
148
	case network.Connected:
149
		return Message_CONNECTED
150
	case network.CanConnect:
151
		return Message_CAN_CONNECT
152
	case network.CannotConnect:
153 154 155 156
		return Message_CANNOT_CONNECT
	}
}

157
// Connectedness returns an network.Connectedness associated with the
158
// Message_ConnectionType.
159
func Connectedness(c Message_ConnectionType) network.Connectedness {
160 161
	switch c {
	default:
162
		return network.NotConnected
163
	case Message_NOT_CONNECTED:
164
		return network.NotConnected
165
	case Message_CONNECTED:
166
		return network.Connected
167
	case Message_CAN_CONNECT:
168
		return network.CanConnect
169
	case Message_CANNOT_CONNECT:
170
		return network.CannotConnect
171 172
	}
}