/
utils.go
123 lines (103 loc) · 1.97 KB
/
utils.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
118
119
120
121
122
123
package kademlia
import (
"crypto/sha1"
"errors"
"math/big"
"net/rpc"
"time"
)
const (
M = 16
K = 10
Alpha = 3
UpdateInterval = 25 * time.Millisecond
RemoteTryTime = 3
RemoteTryInterval = 25 * time.Millisecond
RePublishInterval = 100 * time.Millisecond
)
//can not declared as const
var Mod = big.NewInt(0).Exp(big.NewInt(2), big.NewInt(M), nil)
//A IP address store as a pair due to the hash value is frequently called
type AddrType struct {
Ip string
Id big.Int
}
type StrPair struct {
First string
Second string
}
type BoolStrPair struct {
First bool
Second string
}
//Arg and Ret Type
type FindNodeArg struct {
TarID big.Int
Sender AddrType
}
type FindValueArg struct {
Key string
Hash big.Int
Sender AddrType
}
type StoreArg struct {
Key string
Value string
Sender AddrType
}
type FindValueRet struct {
First ClosestList
Second string
}
//a SHA-1 hash, hash % mod, mod = 2^M
func Hash(str string) big.Int{
hasher := sha1.New()
hasher.Write([]byte(str))
var ret big.Int
ret.SetBytes(hasher.Sum(nil))
ret.Mod(&ret, Mod)
return ret
}
//dis(a, b) = a xor b
func dis(obj1 *big.Int, obj2 *big.Int) big.Int {
var ret big.Int
ret.Xor(obj1, obj2)
return ret
}
//common prefix length between two ID
func cpl(obj1 *big.Int, obj2 *big.Int) int {
xorDis := dis(obj1, obj2)
return xorDis.BitLen() - 1
}
//RPC Service: Diag, Ping
func Diag(addr string) (*rpc.Client, error) {
var ret *rpc.Client
var err error
if addr == "" {
return nil, errors.New("ERROR: empty IP addr")
}
for i := 0; i < RemoteTryTime; i++ {
ret, err = rpc.Dial("tcp", addr)
if err == nil {
return ret, err
}
time.Sleep(RemoteTryInterval)
}
return nil, err
}
func Ping(addr string) error {
var ret *rpc.Client
var err error
if addr == "" {
return errors.New("ERROR: empty IP addr")
}
for i := 0; i < RemoteTryTime; i++ {
ret, err = rpc.Dial("tcp", addr)
if err == nil {
ret.Close()
return err
}
time.Sleep(RemoteTryInterval)
}
return err
}