62 lines
1.3 KiB
Go
62 lines
1.3 KiB
Go
package chord
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"errors"
|
|
"net/netip"
|
|
)
|
|
|
|
type ID [20]byte
|
|
|
|
func addrID(addr netip.AddrPort) ID {
|
|
if !addr.IsValid() {
|
|
return ID{}
|
|
}
|
|
b := make([]byte, 0, len("[ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff%enp5s0]:65535"))
|
|
b = addr.AppendTo(b)
|
|
return keyID(b)
|
|
}
|
|
|
|
func keyID[T string | []byte](key T) ID {
|
|
s := sha1.Sum([]byte(key))
|
|
return s
|
|
}
|
|
|
|
// contains reports whether a clockwise traversal through the hash space
|
|
// starting immediately after left reaches x no later than it reaches right.
|
|
func contains(left, right, x ID) bool {
|
|
lr := bytes.Compare(left[:], right[:])
|
|
lx := bytes.Compare(left[:], x[:])
|
|
xr := bytes.Compare(x[:], right[:])
|
|
switch {
|
|
case lr < 0:
|
|
// left is less than right, so the interval does not cross the origin.
|
|
// | L-----R |
|
|
return (lx < 0) == (xr <= 0)
|
|
case lr > 0:
|
|
// The interval crosses the origin.
|
|
// |-----R L-----|
|
|
return (lx < 0) != (xr <= 0)
|
|
default:
|
|
// The interval is the entire hash space.
|
|
return true
|
|
}
|
|
}
|
|
|
|
func (id ID) String() string {
|
|
b := make([]byte, 0, len(ID{})*2)
|
|
b = hex.AppendEncode(b, id[:])
|
|
return string(b)
|
|
}
|
|
|
|
func ParseID(s string) (ID, error) {
|
|
if len(s) != len(ID{})*2 {
|
|
return ID{}, errors.New("invalid ID")
|
|
}
|
|
var id ID
|
|
_, err := hex.AppendDecode(id[:], []byte(s))
|
|
return id, err
|
|
}
|