diff options
| author | Felix Hanley <felix@userspace.com.au> | 2018-02-26 11:27:15 +0000 |
|---|---|---|
| committer | Felix Hanley <felix@userspace.com.au> | 2018-02-26 11:27:15 +0000 |
| commit | 19f63bb03bf2a83515fd47e6cf10a4db18a923d7 (patch) | |
| tree | 2f5b66f49904ed1a5e17bcf566587abb7f894dd3 /models/infohash.go | |
| parent | 6e449039520843c8df5203d6a16a0c6fadfe312b (diff) | |
| download | dhtsearch-19f63bb03bf2a83515fd47e6cf10a4db18a923d7.tar.gz dhtsearch-19f63bb03bf2a83515fd47e6cf10a4db18a923d7.tar.bz2 | |
Moved shared structs to package
Diffstat (limited to 'models/infohash.go')
| -rw-r--r-- | models/infohash.go | 91 |
1 files changed, 91 insertions, 0 deletions
diff --git a/models/infohash.go b/models/infohash.go new file mode 100644 index 0000000..e8db422 --- /dev/null +++ b/models/infohash.go @@ -0,0 +1,91 @@ +package models + +import ( + "crypto/sha1" + "encoding/hex" + "fmt" + "io" + "math/rand" + "time" +) + +const InfohashLength = 20 + +// Infohash is a 160 bit (20 byte) value +type Infohash []byte + +// InfohashFromString converts a 40 digit hexadecimal string to an Infohash +func InfohashFromString(s string) (*Infohash, error) { + switch len(s) { + case 20: + // Binary string + ih := Infohash([]byte(s)) + return &ih, nil + case 40: + // Hex string + b, err := hex.DecodeString(s) + if err != nil { + return nil, err + } + ih := Infohash(b) + return &ih, nil + default: + return nil, fmt.Errorf("invalid length %d", len(s)) + } +} + +func (ih Infohash) String() string { + return hex.EncodeToString(ih) +} +func (ih Infohash) Valid() bool { + // TODO + return len(ih) == 20 +} + +func (ih Infohash) Equal(other Infohash) bool { + if len(ih) != len(other) { + return false + } + for i := 0; i < len(ih); i++ { + if ih[i] != other[i] { + return false + } + } + return true +} + +// Distance determines the distance to another infohash as an integer +func (ih Infohash) Distance(other Infohash) int { + i := 0 + for ; i < 20; i++ { + if ih[i] != other[i] { + break + } + } + + if i == 20 { + return 160 + } + + xor := ih[i] ^ other[i] + + j := 0 + for (xor & 0x80) == 0 { + xor <<= 1 + j++ + } + return 8*i + j +} + +func GenerateNeighbour(first, second Infohash) Infohash { + s := append(second[:10], first[10:]...) + return Infohash(s) +} + +func GenInfohash() (ih Infohash) { + random := rand.New(rand.NewSource(time.Now().UnixNano())) + hash := sha1.New() + io.WriteString(hash, time.Now().String()) + io.WriteString(hash, string(random.Int())) + return Infohash(hash.Sum(nil)) +} |
