-
Notifications
You must be signed in to change notification settings - Fork 0
/
routingtable.go
117 lines (105 loc) · 2.32 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package kademlia
import (
"container/list"
"sort"
)
const BucketSize = 20
type routingTable struct {
ownId *KadID
table [KadIdLen]list.List
}
func newRoutingTable(ownId *KadID) *routingTable {
return &routingTable{ownId: ownId}
}
func (rt *routingTable) add(node *Node) bool {
index := rt.index(&node.Id)
if &node.Id != rt.ownId && rt.find(&node.Id) == nil && rt.table[index].Len() <= BucketSize {
rt.table[index].PushBack(node)
return true
}
return false
}
func (rt *routingTable) del(kid *KadID) {
index := rt.index(kid)
for e := rt.table[index].Front(); e != nil; e = e.Next() {
if e.Value.(*Node).Id == *kid {
rt.table[index].Remove(e)
return
}
}
}
func (rt *routingTable) find(kid *KadID) *Node {
index := rt.index(kid)
for e := rt.table[index].Front(); e != nil; e = e.Next() {
if e.Value.(*Node).Id == *kid {
return e.Value.(*Node)
}
}
return nil
}
func (rt *routingTable) closer(kid *KadID) []*Node {
list2slice := func(li list.List) []*Node {
nodes := make([]*Node, 0)
for e := li.Front(); e != nil; e = e.Next() {
nodes = append(nodes, e.Value.(*Node))
}
return nodes
}
closestIndex := rt.index(kid)
nodes := list2slice(rt.table[closestIndex])
for i := 1; i < KadIdLen; i++ {
upper := closestIndex + i
lower := closestIndex - i
tmp := make([]*Node, 0)
if upper < KadIdLen {
tmp = append(tmp, list2slice(rt.table[upper])...)
}
if lower >= 0 {
tmp = append(tmp, list2slice(rt.table[lower])...)
}
sort.Slice(tmp, func(i, j int) bool {
iXor := xor(&tmp[i].Id, kid)
jXor := xor(&tmp[j].Id, kid)
for ii := 0; ii < KadIdLenByte; ii++ {
if iXor[ii] == jXor[ii] {
continue
}
return iXor[ii] < jXor[ii]
}
return true
})
nodes = append(nodes, tmp...)
if len(nodes) >= BucketSize {
return nodes[:BucketSize]
}
}
return nodes
}
func (rt *routingTable) index(kid *KadID) int {
distance := rt.xor(kid)
firstBitIndex := 0
for _, v := range distance {
if v == 0 {
firstBitIndex += 8
continue
}
for i := 0; i < 8; i++ {
if v & (0x80 >> uint(i)) != 0 {
break
}
firstBitIndex++
}
break
}
return firstBitIndex
}
func (rt *routingTable) xor(kid *KadID) *KadID {
return xor(rt.ownId, kid)
}
func xor(kid1 *KadID, kid2 *KadID) *KadID {
xor := &KadID{}
for i := range kid1 {
xor[i] = kid1[i] ^ kid2[i]
}
return xor
}