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 }