aboutsummaryrefslogtreecommitdiff
path: root/models/infohash.go
diff options
context:
space:
mode:
authorFelix Hanley <felix@userspace.com.au>2018-02-26 11:27:15 +0000
committerFelix Hanley <felix@userspace.com.au>2018-02-26 11:27:15 +0000
commit19f63bb03bf2a83515fd47e6cf10a4db18a923d7 (patch)
tree2f5b66f49904ed1a5e17bcf566587abb7f894dd3 /models/infohash.go
parent6e449039520843c8df5203d6a16a0c6fadfe312b (diff)
downloaddhtsearch-19f63bb03bf2a83515fd47e6cf10a4db18a923d7.tar.gz
dhtsearch-19f63bb03bf2a83515fd47e6cf10a4db18a923d7.tar.bz2
Moved shared structs to package
Diffstat (limited to 'models/infohash.go')
-rw-r--r--models/infohash.go91
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))
+}