-
Notifications
You must be signed in to change notification settings - Fork 1
/
routingtable.go
executable file
·78 lines (65 loc) · 2.1 KB
/
routingtable.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
package d7024e
// "fmt"
// RoutingTable definition
// keeps a refrence contact of me and an array of buckets
type RoutingTable struct {
me Contact
buckets [IDLength * 8]*bucket
}
// NewRoutingTable returns a new instance of a RoutingTable
func NewRoutingTable(me Contact) *RoutingTable {
routingTable := &RoutingTable{}
for i := 0; i < IDLength*8; i++ {
routingTable.buckets[i] = newBucket()
}
routingTable.me = me
return routingTable
}
// AddContact add a new contact to the correct Bucket
func (routingTable *RoutingTable) AddContact(contact Contact) {
if contact.ID.Equals(routingTable.me.ID) {
return
}
bucketIndex := routingTable.getBucketIndex(contact.ID)
bucket := routingTable.buckets[bucketIndex]
bucket.AddContact(contact)
}
func (routingTable *RoutingTable) AddContacts(contacts []Contact) {
for _, contact := range contacts {
routingTable.AddContact(contact)
}
}
// FindClosestContacts finds the count closest Contacts to the target in the RoutingTable
func (routingTable *RoutingTable) FindClosestContacts(target *KademliaID, count int) []Contact {
var candidates ContactCandidates
bucketIndex := routingTable.getBucketIndex(target)
bucket := routingTable.buckets[bucketIndex]
candidates.Append(bucket.GetContactAndCalcDistance(target))
for i := 1; (bucketIndex-i >= 0 || bucketIndex+i < IDLength*8) && candidates.Len() < count; i++ {
if bucketIndex-i >= 0 {
bucket = routingTable.buckets[bucketIndex-i]
candidates.Append(bucket.GetContactAndCalcDistance(target))
}
if bucketIndex+i < IDLength*8 {
bucket = routingTable.buckets[bucketIndex+i]
candidates.Append(bucket.GetContactAndCalcDistance(target))
}
}
candidates.Sort()
if count > candidates.Len() {
count = candidates.Len()
}
return candidates.GetContacts(count)
}
// getBucketIndex get the correct Bucket index for the KademliaID
func (routingTable *RoutingTable) getBucketIndex(id *KademliaID) int {
distance := id.CalcDistance(routingTable.me.ID)
for i := 0; i < IDLength; i++ {
for j := 0; j < 8; j++ {
if (distance[i]>>uint8(7-j))&0x1 != 0 {
return i*8 + j
}
}
}
return IDLength*8 - 1
}