github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/routing/dht/pb/message.go (about) 1 package dht_pb 2 3 import ( 4 ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 5 6 key "github.com/ipfs/go-ipfs/blocks/key" 7 inet "github.com/ipfs/go-ipfs/p2p/net" 8 peer "github.com/ipfs/go-ipfs/p2p/peer" 9 eventlog "github.com/ipfs/go-ipfs/thirdparty/eventlog" 10 ) 11 12 var log = eventlog.Logger("dht.pb") 13 14 type PeerRoutingInfo struct { 15 peer.PeerInfo 16 inet.Connectedness 17 } 18 19 // NewMessage constructs a new dht message with given type, key, and level 20 func NewMessage(typ Message_MessageType, key string, level int) *Message { 21 m := &Message{ 22 Type: &typ, 23 Key: &key, 24 } 25 m.SetClusterLevel(level) 26 return m 27 } 28 29 func peerRoutingInfoToPBPeer(p PeerRoutingInfo) *Message_Peer { 30 pbp := new(Message_Peer) 31 32 pbp.Addrs = make([][]byte, len(p.Addrs)) 33 for i, maddr := range p.Addrs { 34 pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed. 35 } 36 s := string(p.ID) 37 pbp.Id = &s 38 c := ConnectionType(p.Connectedness) 39 pbp.Connection = &c 40 return pbp 41 } 42 43 func peerInfoToPBPeer(p peer.PeerInfo) *Message_Peer { 44 pbp := new(Message_Peer) 45 46 pbp.Addrs = make([][]byte, len(p.Addrs)) 47 for i, maddr := range p.Addrs { 48 pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed. 49 } 50 s := string(p.ID) 51 pbp.Id = &s 52 return pbp 53 } 54 55 // PBPeerToPeer turns a *Message_Peer into its peer.PeerInfo counterpart 56 func PBPeerToPeerInfo(pbp *Message_Peer) peer.PeerInfo { 57 return peer.PeerInfo{ 58 ID: peer.ID(pbp.GetId()), 59 Addrs: pbp.Addresses(), 60 } 61 } 62 63 // RawPeerInfosToPBPeers converts a slice of Peers into a slice of *Message_Peers, 64 // ready to go out on the wire. 65 func RawPeerInfosToPBPeers(peers []peer.PeerInfo) []*Message_Peer { 66 pbpeers := make([]*Message_Peer, len(peers)) 67 for i, p := range peers { 68 pbpeers[i] = peerInfoToPBPeer(p) 69 } 70 return pbpeers 71 } 72 73 // PeersToPBPeers converts given []peer.Peer into a set of []*Message_Peer, 74 // which can be written to a message and sent out. the key thing this function 75 // does (in addition to PeersToPBPeers) is set the ConnectionType with 76 // information from the given inet.Network. 77 func PeerInfosToPBPeers(n inet.Network, peers []peer.PeerInfo) []*Message_Peer { 78 pbps := RawPeerInfosToPBPeers(peers) 79 for i, pbp := range pbps { 80 c := ConnectionType(n.Connectedness(peers[i].ID)) 81 pbp.Connection = &c 82 } 83 return pbps 84 } 85 86 func PeerRoutingInfosToPBPeers(peers []PeerRoutingInfo) []*Message_Peer { 87 pbpeers := make([]*Message_Peer, len(peers)) 88 for i, p := range peers { 89 pbpeers[i] = peerRoutingInfoToPBPeer(p) 90 } 91 return pbpeers 92 } 93 94 // PBPeersToPeerInfos converts given []*Message_Peer into []peer.PeerInfo 95 // Invalid addresses will be silently omitted. 96 func PBPeersToPeerInfos(pbps []*Message_Peer) []peer.PeerInfo { 97 peers := make([]peer.PeerInfo, 0, len(pbps)) 98 for _, pbp := range pbps { 99 peers = append(peers, PBPeerToPeerInfo(pbp)) 100 } 101 return peers 102 } 103 104 // Addresses returns a multiaddr associated with the Message_Peer entry 105 func (m *Message_Peer) Addresses() []ma.Multiaddr { 106 if m == nil { 107 return nil 108 } 109 110 var err error 111 maddrs := make([]ma.Multiaddr, len(m.Addrs)) 112 for i, addr := range m.Addrs { 113 maddrs[i], err = ma.NewMultiaddrBytes(addr) 114 if err != nil { 115 log.Debugf("error decoding Multiaddr for peer: %s", m.GetId()) 116 continue 117 } 118 } 119 return maddrs 120 } 121 122 // GetClusterLevel gets and adjusts the cluster level on the message. 123 // a +/- 1 adjustment is needed to distinguish a valid first level (1) and 124 // default "no value" protobuf behavior (0) 125 func (m *Message) GetClusterLevel() int { 126 level := m.GetClusterLevelRaw() - 1 127 if level < 0 { 128 return 0 129 } 130 return int(level) 131 } 132 133 // SetClusterLevel adjusts and sets the cluster level on the message. 134 // a +/- 1 adjustment is needed to distinguish a valid first level (1) and 135 // default "no value" protobuf behavior (0) 136 func (m *Message) SetClusterLevel(level int) { 137 lvl := int32(level) 138 m.ClusterLevelRaw = &lvl 139 } 140 141 // Loggable turns a Message into machine-readable log output 142 func (m *Message) Loggable() map[string]interface{} { 143 return map[string]interface{}{ 144 "message": map[string]string{ 145 "type": m.Type.String(), 146 "key": key.Key(m.GetKey()).Pretty(), 147 }, 148 } 149 } 150 151 // ConnectionType returns a Message_ConnectionType associated with the 152 // inet.Connectedness. 153 func ConnectionType(c inet.Connectedness) Message_ConnectionType { 154 switch c { 155 default: 156 return Message_NOT_CONNECTED 157 case inet.NotConnected: 158 return Message_NOT_CONNECTED 159 case inet.Connected: 160 return Message_CONNECTED 161 case inet.CanConnect: 162 return Message_CAN_CONNECT 163 case inet.CannotConnect: 164 return Message_CANNOT_CONNECT 165 } 166 } 167 168 // Connectedness returns an inet.Connectedness associated with the 169 // Message_ConnectionType. 170 func Connectedness(c Message_ConnectionType) inet.Connectedness { 171 switch c { 172 default: 173 return inet.NotConnected 174 case Message_NOT_CONNECTED: 175 return inet.NotConnected 176 case Message_CONNECTED: 177 return inet.Connected 178 case Message_CAN_CONNECT: 179 return inet.CanConnect 180 case Message_CANNOT_CONNECT: 181 return inet.CannotConnect 182 } 183 }