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]) }