message.go 4.86 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
	b58 "github.com/mr-tron/base58/base58"
9
	ma "github.com/multiformats/go-multiaddr"
Jeromy's avatar
Jeromy committed
10 11
)

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

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

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

29 30 31 32 33 34 35 36
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)
37
	pbp.Id = []byte(s)
38
	c := ConnectionType(p.Connectedness)
39
	pbp.Connection = c
40 41 42
	return pbp
}

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

46 47 48
	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
49
	}
50
	pbp.Id = []byte(p.ID)
Jeromy's avatar
Jeromy committed
51
	return pbp
52 53
}

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

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

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

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

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

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

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

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

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

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

141
// Loggable turns a Message into machine-readable log output
142 143 144 145
func (m *Message) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"message": map[string]string{
			"type": m.Type.String(),
Jeromy's avatar
Jeromy committed
146
			"key":  b58.Encode([]byte(m.GetKey())),
147 148 149
		},
	}
}
150 151

// ConnectionType returns a Message_ConnectionType associated with the
152 153
// network.Connectedness.
func ConnectionType(c network.Connectedness) Message_ConnectionType {
154 155 156
	switch c {
	default:
		return Message_NOT_CONNECTED
157
	case network.NotConnected:
158
		return Message_NOT_CONNECTED
159
	case network.Connected:
160
		return Message_CONNECTED
161
	case network.CanConnect:
162
		return Message_CAN_CONNECT
163
	case network.CannotConnect:
164 165 166 167
		return Message_CANNOT_CONNECT
	}
}

168
// Connectedness returns an network.Connectedness associated with the
169
// Message_ConnectionType.
170
func Connectedness(c Message_ConnectionType) network.Connectedness {
171 172
	switch c {
	default:
173
		return network.NotConnected
174
	case Message_NOT_CONNECTED:
175
		return network.NotConnected
176
	case Message_CONNECTED:
177
		return network.Connected
178
	case Message_CAN_CONNECT:
179
		return network.CanConnect
180
	case Message_CANNOT_CONNECT:
181
		return network.CannotConnect
182 183
	}
}