message.go 5.06 KB
Newer Older
1
package dht_pb
2

Jeromy's avatar
Jeromy committed
3
import (
4
	ma "gx/ipfs/QmYzDkkgAEmrcNzFCiYo6L1dTX4EAG1gZkbtdbd9trL4vd/go-multiaddr"
5

6
	key "github.com/ipfs/go-ipfs/blocks/key"
7 8 9 10
	logging "gx/ipfs/QmNQynaz7qfriSUJkiEZUrm2Wen1u3Kj9goZzWtrPyu7XR/go-log"
	pstore "gx/ipfs/QmQdnfvZQuhdT93LNc5bos52wAmdr3G2p6G8teLJMEN32P/go-libp2p-peerstore"
	peer "gx/ipfs/QmRBqJF7hb8ZSpRcMwUt8hNhydWcxGEhtk81HKq6oUwKvs/go-libp2p-peer"
	inet "gx/ipfs/QmZ8bCZpMWDbFSh6h2zgTYwrhnjrGM5c9WCzw72SU8p63b/go-libp2p/p2p/net"
Jeromy's avatar
Jeromy committed
11 12
)

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

15
type PeerRoutingInfo struct {
Jeromy's avatar
Jeromy committed
16
	pstore.PeerInfo
17 18 19
	inet.Connectedness
}

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

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

Jeromy's avatar
Jeromy committed
44
func peerInfoToPBPeer(p pstore.PeerInfo) *Message_Peer {
45
	pbp := new(Message_Peer)
46

47 48 49
	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
50
	}
51 52
	s := string(p.ID)
	pbp.Id = &s
Jeromy's avatar
Jeromy committed
53
	return pbp
54 55
}

Jeromy's avatar
Jeromy committed
56 57 58
// PBPeerToPeer turns a *Message_Peer into its pstore.PeerInfo counterpart
func PBPeerToPeerInfo(pbp *Message_Peer) pstore.PeerInfo {
	return pstore.PeerInfo{
59 60
		ID:    peer.ID(pbp.GetId()),
		Addrs: pbp.Addresses(),
61 62 63
	}
}

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

74 75 76
// 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
77
// information from the given inet.Network.
Jeromy's avatar
Jeromy committed
78
func PeerInfosToPBPeers(n inet.Network, peers []pstore.PeerInfo) []*Message_Peer {
79
	pbps := RawPeerInfosToPBPeers(peers)
80
	for i, pbp := range pbps {
81
		c := ConnectionType(n.Connectedness(peers[i].ID))
82 83 84 85 86
		pbp.Connection = &c
	}
	return pbps
}

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

Jeromy's avatar
Jeromy committed
95
// PBPeersToPeerInfos converts given []*Message_Peer into []pstore.PeerInfo
96
// Invalid addresses will be silently omitted.
Jeromy's avatar
Jeromy committed
97 98
func PBPeersToPeerInfos(pbps []*Message_Peer) []pstore.PeerInfo {
	peers := make([]pstore.PeerInfo, 0, len(pbps))
99 100
	for _, pbp := range pbps {
		peers = append(peers, PBPeerToPeerInfo(pbp))
101
	}
102
	return peers
103 104
}

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

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

		maddrs = append(maddrs, maddr)
120
	}
121
	return maddrs
122 123
}

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

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

143
// Loggable turns a Message into machine-readable log output
144 145 146 147
func (m *Message) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"message": map[string]string{
			"type": m.Type.String(),
Michael Muré's avatar
Michael Muré committed
148
			"key":  key.Key(m.GetKey()).B58String(),
149 150 151
		},
	}
}
152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185

// ConnectionType returns a Message_ConnectionType associated with the
// inet.Connectedness.
func ConnectionType(c inet.Connectedness) Message_ConnectionType {
	switch c {
	default:
		return Message_NOT_CONNECTED
	case inet.NotConnected:
		return Message_NOT_CONNECTED
	case inet.Connected:
		return Message_CONNECTED
	case inet.CanConnect:
		return Message_CAN_CONNECT
	case inet.CannotConnect:
		return Message_CANNOT_CONNECT
	}
}

// Connectedness returns an inet.Connectedness associated with the
// Message_ConnectionType.
func Connectedness(c Message_ConnectionType) inet.Connectedness {
	switch c {
	default:
		return inet.NotConnected
	case Message_NOT_CONNECTED:
		return inet.NotConnected
	case Message_CONNECTED:
		return inet.Connected
	case Message_CAN_CONNECT:
		return inet.CanConnect
	case Message_CANNOT_CONNECT:
		return inet.CannotConnect
	}
}