message.go 4.56 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
}

Steven Allen's avatar
Steven Allen committed
28 29
func peerRoutingInfoToPBPeer(p PeerRoutingInfo) Message_Peer {
	var pbp Message_Peer
30 31 32 33 34

	pbp.Addrs = make([][]byte, len(p.Addrs))
	for i, maddr := range p.Addrs {
		pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed.
	}
Steven Allen's avatar
Steven Allen committed
35 36
	pbp.Id = byteString(p.ID)
	pbp.Connection = ConnectionType(p.Connectedness)
37 38 39
	return pbp
}

Steven Allen's avatar
Steven Allen committed
40 41
func peerInfoToPBPeer(p peer.AddrInfo) Message_Peer {
	var pbp Message_Peer
42

43 44 45
	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
46
	}
Steven Allen's avatar
Steven Allen committed
47
	pbp.Id = byteString(p.ID)
Jeromy's avatar
Jeromy committed
48
	return pbp
49 50
}

51
// PBPeerToPeer turns a *Message_Peer into its peer.AddrInfo counterpart
Steven Allen's avatar
Steven Allen committed
52 53 54
func PBPeerToPeerInfo(pbp Message_Peer) peer.AddrInfo {
	return peer.AddrInfo{
		ID:    peer.ID(pbp.Id),
55
		Addrs: pbp.Addresses(),
56 57 58
	}
}

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

69 70 71
// 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
72
// information from the given network.Network.
Steven Allen's avatar
Steven Allen committed
73
func PeerInfosToPBPeers(n network.Network, peers []peer.AddrInfo) []Message_Peer {
74
	pbps := RawPeerInfosToPBPeers(peers)
75
	for i, pbp := range pbps {
76
		c := ConnectionType(n.Connectedness(peers[i].ID))
77
		pbp.Connection = c
78 79 80 81
	}
	return pbps
}

Steven Allen's avatar
Steven Allen committed
82 83
func PeerRoutingInfosToPBPeers(peers []PeerRoutingInfo) []Message_Peer {
	pbpeers := make([]Message_Peer, len(peers))
84 85 86 87 88 89
	for i, p := range peers {
		pbpeers[i] = peerRoutingInfoToPBPeer(p)
	}
	return pbpeers
}

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

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

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

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

120 121 122
// 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
123
func (m *Message) GetClusterLevel() int {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
124 125
	level := m.GetClusterLevelRaw() - 1
	if level < 0 {
126
		return 0
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
127
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
128
	return int(level)
129
}
130

131 132 133
// 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
134 135
func (m *Message) SetClusterLevel(level int) {
	lvl := int32(level)
136
	m.ClusterLevelRaw = lvl + 1
137
}
138

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

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