message.go 4.17 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
// NewMessage constructs a new dht message with given type, key, and level
14
func NewMessage(typ Message_MessageType, key string, level int) *Message {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
15 16 17 18 19 20 21 22
	m := &Message{
		Type: &typ,
		Key:  &key,
	}
	m.SetClusterLevel(level)
	return m
}

23
func peerInfoToPBPeer(p peer.PeerInfo) *Message_Peer {
24
	pbp := new(Message_Peer)
25

26 27 28
	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
29
	}
30 31
	s := string(p.ID)
	pbp.Id = &s
Jeromy's avatar
Jeromy committed
32
	return pbp
33 34
}

35 36 37 38 39
// 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(),
40 41 42
	}
}

43
// RawPeerInfosToPBPeers converts a slice of Peers into a slice of *Message_Peers,
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
44
// ready to go out on the wire.
45
func RawPeerInfosToPBPeers(peers []peer.PeerInfo) []*Message_Peer {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
46
	pbpeers := make([]*Message_Peer, len(peers))
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
47
	for i, p := range peers {
48
		pbpeers[i] = peerInfoToPBPeer(p)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
49 50 51 52
	}
	return pbpeers
}

53 54 55
// 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
56 57 58
// information from the given inet.Network.
func PeerInfosToPBPeers(n inet.Network, peers []peer.PeerInfo) []*Message_Peer {
	pbps := RawPeerInfosToPBPeers(peers)
59
	for i, pbp := range pbps {
60
		c := ConnectionType(n.Connectedness(peers[i].ID))
61 62 63 64 65
		pbp.Connection = &c
	}
	return pbps
}

66 67 68 69 70 71
// 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))
72
	}
73
	return peers
74 75
}

76
// Addresses returns a multiaddr associated with the Message_Peer entry
77
func (m *Message_Peer) Addresses() []ma.Multiaddr {
78
	if m == nil {
79
		return nil
80
	}
81 82 83 84

	var err error
	maddrs := make([]ma.Multiaddr, len(m.Addrs))
	for i, addr := range m.Addrs {
85
		maddrs[i], err = ma.NewMultiaddrBytes(addr)
86
		if err != nil {
87 88
			log.Error("error decoding Multiaddr for peer: %s", m.GetId())
			continue
89 90
		}
	}
91
	return maddrs
92 93
}

94 95 96
// 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
97
func (m *Message) GetClusterLevel() int {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
98 99
	level := m.GetClusterLevelRaw() - 1
	if level < 0 {
100
		return 0
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
101
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
102
	return int(level)
103
}
104

105 106 107
// 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
108 109 110
func (m *Message) SetClusterLevel(level int) {
	lvl := int32(level)
	m.ClusterLevelRaw = &lvl
111
}
112

113
// Loggable turns a Message into machine-readable log output
114 115 116 117 118 119 120
func (m *Message) Loggable() map[string]interface{} {
	return map[string]interface{}{
		"message": map[string]string{
			"type": m.Type.String(),
		},
	}
}
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154

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