message.go 4.78 KB
Newer Older
1
package dht_pb
2

Jeromy's avatar
Jeromy committed
3
import (
4
	ma "github.com/jbenet/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr"
5

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
6
	inet "github.com/jbenet/go-ipfs/p2p/net"
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
7
	peer "github.com/jbenet/go-ipfs/p2p/peer"
8
	eventlog "github.com/jbenet/go-ipfs/thirdparty/eventlog"
Jeromy's avatar
Jeromy committed
9 10
)

11 12
var log = eventlog.Logger("dht.pb")

13 14 15 16 17
type PeerRoutingInfo struct {
	peer.PeerInfo
	inet.Connectedness
}

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

28 29 30 31 32 33 34 35 36 37 38 39 40 41
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
}

42
func peerInfoToPBPeer(p peer.PeerInfo) *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 50
	s := string(p.ID)
	pbp.Id = &s
Jeromy's avatar
Jeromy committed
51
	return pbp
52 53
}

54 55 56 57 58
// PBPeerToPeer turns a *Message_Peer into its peer.PeerInfo counterpart
func PBPeerToPeerInfo(pbp *Message_Peer) peer.PeerInfo {
	return peer.PeerInfo{
		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.PeerInfo) []*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 77
// information from the given inet.Network.
func PeerInfosToPBPeers(n inet.Network, peers []peer.PeerInfo) []*Message_Peer {
	pbps := RawPeerInfosToPBPeers(peers)
78
	for i, pbp := range pbps {
79
		c := ConnectionType(n.Connectedness(peers[i].ID))
80 81 82 83 84
		pbp.Connection = &c
	}
	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 94 95 96 97 98
// PBPeersToPeerInfos converts given []*Message_Peer into []peer.PeerInfo
// Invalid addresses will be silently omitted.
func PBPeersToPeerInfos(pbps []*Message_Peer) []peer.PeerInfo {
	peers := make([]peer.PeerInfo, 0, len(pbps))
	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

	var err error
	maddrs := make([]ma.Multiaddr, len(m.Addrs))
	for i, addr := range m.Addrs {
112
		maddrs[i], err = ma.NewMultiaddrBytes(addr)
113
		if err != nil {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
114
			log.Debugf("error decoding Multiaddr for peer: %s", m.GetId())
115
			continue
116 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 137
func (m *Message) SetClusterLevel(level int) {
	lvl := int32(level)
	m.ClusterLevelRaw = &lvl
138
}
139

140
// Loggable turns a Message into machine-readable log output
141 142 143 144 145 146 147
func (m *Message) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"message": map[string]string{
			"type": m.Type.String(),
		},
	}
}
148 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

// 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
	}
}