github.com/uber/kraken@v0.1.4/core/peer_id.go (about)

     1  // Copyright (c) 2016-2019 Uber Technologies, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  package core
    15  
    16  import (
    17  	"bytes"
    18  	"crypto/sha1"
    19  	"encoding/hex"
    20  	"errors"
    21  	"fmt"
    22  	"io"
    23  	"math/rand"
    24  )
    25  
    26  // PeerIDFactory defines the method used to generate a peer id.
    27  type PeerIDFactory string
    28  
    29  // RandomPeerIDFactory creates random peer ids.
    30  const RandomPeerIDFactory PeerIDFactory = "random"
    31  
    32  // AddrHashPeerIDFactory creates peers ids based on a full "ip:port" address.
    33  const AddrHashPeerIDFactory PeerIDFactory = "addr_hash"
    34  
    35  // GeneratePeerID creates a new peer id per the factory policy.
    36  func (f PeerIDFactory) GeneratePeerID(ip string, port int) (PeerID, error) {
    37  	switch f {
    38  	case RandomPeerIDFactory:
    39  		return RandomPeerID()
    40  	case AddrHashPeerIDFactory:
    41  		return HashedPeerID(fmt.Sprintf("%s:%d", ip, port))
    42  	default:
    43  		err := fmt.Errorf("invalid peer id factory: %q", string(f))
    44  		return PeerID{}, err
    45  	}
    46  }
    47  
    48  // ErrInvalidPeerIDLength returns when a string peer id does not decode into 20 bytes.
    49  var ErrInvalidPeerIDLength = errors.New("peer id has invalid length")
    50  
    51  // PeerID represents a fixed size peer id.
    52  type PeerID [20]byte
    53  
    54  // NewPeerID parses a PeerID from the given string. Must be in hexadecimal notation,
    55  // encoding exactly 20 bytes.
    56  func NewPeerID(s string) (PeerID, error) {
    57  	b, err := hex.DecodeString(s)
    58  	if err != nil {
    59  		return PeerID{}, err
    60  	}
    61  	if len(b) != 20 {
    62  		return PeerID{}, ErrInvalidPeerIDLength
    63  	}
    64  	var p PeerID
    65  	copy(p[:], b)
    66  	return p, nil
    67  }
    68  
    69  // String encodes the PeerID in hexadecimal notation.
    70  func (p PeerID) String() string {
    71  	return hex.EncodeToString(p[:])
    72  }
    73  
    74  // LessThan returns whether p is less than o.
    75  func (p PeerID) LessThan(o PeerID) bool {
    76  	return bytes.Compare(p[:], o[:]) == -1
    77  }
    78  
    79  // RandomPeerID returns a randomly generated PeerID.
    80  func RandomPeerID() (PeerID, error) {
    81  	var p PeerID
    82  	_, err := rand.Read(p[:])
    83  	return p, err
    84  }
    85  
    86  // HashedPeerID returns a PeerID derived from the hash of s.
    87  func HashedPeerID(s string) (PeerID, error) {
    88  	var p PeerID
    89  	if s == "" {
    90  		return p, errors.New("cannot generate peer id from empty string")
    91  	}
    92  	h := sha1.New()
    93  	io.WriteString(h, s)
    94  	copy(p[:], h.Sum(nil))
    95  	return p, nil
    96  }