github.com/keltia/go-ipfs@v0.3.8-0.20150909044612-210793031c63/p2p/peer/peer.go (about) 1 // package peer implements an object used to represent peers in the ipfs network. 2 package peer 3 4 import ( 5 "encoding/hex" 6 "encoding/json" 7 "fmt" 8 "strings" 9 10 b58 "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-base58" 11 ma "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multiaddr" 12 mh "github.com/ipfs/go-ipfs/Godeps/_workspace/src/github.com/jbenet/go-multihash" 13 14 ic "github.com/ipfs/go-ipfs/p2p/crypto" 15 u "github.com/ipfs/go-ipfs/util" 16 ) 17 18 var log = u.Logger("peer") 19 20 // ID represents the identity of a peer. 21 type ID string 22 23 // Pretty returns a b58-encoded string of the ID 24 func (id ID) Pretty() string { 25 return IDB58Encode(id) 26 } 27 28 func (id ID) Loggable() map[string]interface{} { 29 return map[string]interface{}{ 30 "peerID": id.Pretty(), 31 } 32 } 33 34 // String prints out the peer. 35 // 36 // TODO(brian): ensure correctness at ID generation and 37 // enforce this by only exposing functions that generate 38 // IDs safely. Then any peer.ID type found in the 39 // codebase is known to be correct. 40 func (id ID) String() string { 41 pid := id.Pretty() 42 43 //All sha256 nodes start with Qm 44 //We can skip the Qm to make the peer.ID more useful 45 if strings.HasPrefix(pid, "Qm") { 46 pid = pid[2:] 47 } 48 49 maxRunes := 6 50 if len(pid) < maxRunes { 51 maxRunes = len(pid) 52 } 53 return fmt.Sprintf("<peer.ID %s>", pid[:maxRunes]) 54 } 55 56 // MatchesPrivateKey tests whether this ID was derived from sk 57 func (id ID) MatchesPrivateKey(sk ic.PrivKey) bool { 58 return id.MatchesPublicKey(sk.GetPublic()) 59 } 60 61 // MatchesPublicKey tests whether this ID was derived from pk 62 func (id ID) MatchesPublicKey(pk ic.PubKey) bool { 63 oid, err := IDFromPublicKey(pk) 64 if err != nil { 65 return false 66 } 67 return oid == id 68 } 69 70 // IDFromString cast a string to ID type, and validate 71 // the id to make sure it is a multihash. 72 func IDFromString(s string) (ID, error) { 73 if _, err := mh.Cast([]byte(s)); err != nil { 74 return ID(""), err 75 } 76 return ID(s), nil 77 } 78 79 // IDFromBytes cast a string to ID type, and validate 80 // the id to make sure it is a multihash. 81 func IDFromBytes(b []byte) (ID, error) { 82 if _, err := mh.Cast(b); err != nil { 83 return ID(""), err 84 } 85 return ID(b), nil 86 } 87 88 // IDB58Decode returns a b58-decoded Peer 89 func IDB58Decode(s string) (ID, error) { 90 m, err := mh.FromB58String(s) 91 if err != nil { 92 return "", err 93 } 94 return ID(m), err 95 } 96 97 // IDB58Encode returns b58-encoded string 98 func IDB58Encode(id ID) string { 99 return b58.Encode([]byte(id)) 100 } 101 102 // IDHexDecode returns a b58-decoded Peer 103 func IDHexDecode(s string) (ID, error) { 104 m, err := mh.FromHexString(s) 105 if err != nil { 106 return "", err 107 } 108 return ID(m), err 109 } 110 111 // IDHexEncode returns b58-encoded string 112 func IDHexEncode(id ID) string { 113 return hex.EncodeToString([]byte(id)) 114 } 115 116 // IDFromPublicKey returns the Peer ID corresponding to pk 117 func IDFromPublicKey(pk ic.PubKey) (ID, error) { 118 b, err := pk.Bytes() 119 if err != nil { 120 return "", err 121 } 122 hash := u.Hash(b) 123 return ID(hash), nil 124 } 125 126 // IDFromPrivateKey returns the Peer ID corresponding to sk 127 func IDFromPrivateKey(sk ic.PrivKey) (ID, error) { 128 return IDFromPublicKey(sk.GetPublic()) 129 } 130 131 // Map maps a Peer ID to a struct. 132 type Set map[ID]struct{} 133 134 // PeerInfo is a small struct used to pass around a peer with 135 // a set of addresses (and later, keys?). This is not meant to be 136 // a complete view of the system, but rather to model updates to 137 // the peerstore. It is used by things like the routing system. 138 type PeerInfo struct { 139 ID ID 140 Addrs []ma.Multiaddr 141 } 142 143 func (pi *PeerInfo) MarshalJSON() ([]byte, error) { 144 out := make(map[string]interface{}) 145 out["ID"] = IDB58Encode(pi.ID) 146 var addrs []string 147 for _, a := range pi.Addrs { 148 addrs = append(addrs, a.String()) 149 } 150 out["Addrs"] = addrs 151 return json.Marshal(out) 152 } 153 154 func (pi *PeerInfo) UnmarshalJSON(b []byte) error { 155 var data map[string]interface{} 156 err := json.Unmarshal(b, &data) 157 if err != nil { 158 return err 159 } 160 pid, err := IDB58Decode(data["ID"].(string)) 161 if err != nil { 162 return err 163 } 164 pi.ID = pid 165 addrs, ok := data["Addrs"].([]interface{}) 166 if ok { 167 for _, a := range addrs { 168 pi.Addrs = append(pi.Addrs, ma.StringCast(a.(string))) 169 } 170 } 171 return nil 172 } 173 174 // IDSlice for sorting peers 175 type IDSlice []ID 176 177 func (es IDSlice) Len() int { return len(es) } 178 func (es IDSlice) Swap(i, j int) { es[i], es[j] = es[j], es[i] } 179 func (es IDSlice) Less(i, j int) bool { return string(es[i]) < string(es[j]) }