routing: use extracted dht and routing code
License: MIT Signed-off-by: Jeromy <why@ipfs.io>
Jeromy committed
Sep 13, 2016 at 15:17 UTC
2e6e0f18e3d7345536e46a48e318f9faee732ec6
56 files changed
+74
-5756
core/commands/dht.go
+2
-2
@@ -11,9 +11,9 @@ import (
11
dag "github.com/ipfs/go-ipfs/merkledag"
12
notif "github.com/ipfs/go-ipfs/notifications"
13
path "github.com/ipfs/go-ipfs/path"
14
- routing "github.com/ipfs/go-ipfs/routing"
15
- ipdht "github.com/ipfs/go-ipfs/routing/dht"
14
+ ipdht "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht"
15
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
16
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
17
18
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
19
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
core/commands/id.go
+1
-1
@@ -12,7 +12,7 @@ import (
12
13
cmds "github.com/ipfs/go-ipfs/commands"
14
core "github.com/ipfs/go-ipfs/core"
15
- kb "github.com/ipfs/go-ipfs/routing/kbucket"
15
+ kb "gx/ipfs/QmTZsN8hysGnbakvK6mS8rwDQ9uwokxmWFBv94pig6zGd1/go-libp2p-kbucket"
16
17
identify "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/protocol/identify"
18
ic "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
core/core.go
+2
-2
@@ -37,10 +37,10 @@ import (
37
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
38
cid "gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
39
40
- routing "github.com/ipfs/go-ipfs/routing"
41
- dht "github.com/ipfs/go-ipfs/routing/dht"
40
nilrouting "github.com/ipfs/go-ipfs/routing/none"
41
offroute "github.com/ipfs/go-ipfs/routing/offline"
42
+ dht "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht"
43
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
44
45
bstore "github.com/ipfs/go-ipfs/blocks/blockstore"
46
bserv "github.com/ipfs/go-ipfs/blockservice"
core/corehttp/gateway_handler.go
+5
-5
@@ -10,18 +10,18 @@ import (
10
"strings"
11
"time"
12
13
- humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
14
- "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
15
- cid "gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
16
-
13
core "github.com/ipfs/go-ipfs/core"
14
"github.com/ipfs/go-ipfs/importer"
15
chunk "github.com/ipfs/go-ipfs/importer/chunk"
16
dag "github.com/ipfs/go-ipfs/merkledag"
17
dagutils "github.com/ipfs/go-ipfs/merkledag/utils"
18
path "github.com/ipfs/go-ipfs/path"
23
- "github.com/ipfs/go-ipfs/routing"
19
uio "github.com/ipfs/go-ipfs/unixfs/io"
20
+
21
+ humanize "gx/ipfs/QmPSBJL4momYnE7DcUyk2DVhD6rH488ZmHBGLbxNdhU44K/go-humanize"
22
+ "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
23
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
24
+ cid "gx/ipfs/QmfSc2xehWmWLnwwYR91Y8QF4xdASypTFVknutoKQS3GHp/go-cid"
25
)
26
27
const (
core/corerouting/core.go
+1
-1
@@ -5,12 +5,12 @@ import (
5
6
core "github.com/ipfs/go-ipfs/core"
7
repo "github.com/ipfs/go-ipfs/repo"
8
- routing "github.com/ipfs/go-ipfs/routing"
8
supernode "github.com/ipfs/go-ipfs/routing/supernode"
9
gcproxy "github.com/ipfs/go-ipfs/routing/supernode/proxy"
10
"gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/host"
11
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
12
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
13
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
14
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
15
)
16
diagnostics/vis.go
+1
-1
@@ -5,7 +5,7 @@ import (
5
"fmt"
6
"io"
7
8
- rtable "github.com/ipfs/go-ipfs/routing/kbucket"
8
+ rtable "gx/ipfs/QmTZsN8hysGnbakvK6mS8rwDQ9uwokxmWFBv94pig6zGd1/go-libp2p-kbucket"
9
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
10
)
11
exchange/bitswap/network/ipfs_impl.go
+1
-1
@@ -4,8 +4,8 @@ import (
4
"io"
5
6
bsmsg "github.com/ipfs/go-ipfs/exchange/bitswap/message"
7
- routing "github.com/ipfs/go-ipfs/routing"
7
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
8
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
9
10
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
11
host "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/host"
exchange/bitswap/testnet/virtual.go
+1
-1
@@ -5,13 +5,13 @@ import (
5
6
bsmsg "github.com/ipfs/go-ipfs/exchange/bitswap/message"
7
bsnet "github.com/ipfs/go-ipfs/exchange/bitswap/network"
8
- routing "github.com/ipfs/go-ipfs/routing"
8
mockrouting "github.com/ipfs/go-ipfs/routing/mock"
9
delay "github.com/ipfs/go-ipfs/thirdparty/delay"
10
testutil "github.com/ipfs/go-ipfs/thirdparty/testutil"
11
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
12
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
13
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
14
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
15
)
16
17
func VirtualNetwork(rs mockrouting.Server, d delay.D) Network {
exchange/reprovide/reprovide.go
+1
-1
@@ -5,10 +5,10 @@ import (
5
"time"
6
7
blocks "github.com/ipfs/go-ipfs/blocks/blockstore"
8
- routing "github.com/ipfs/go-ipfs/routing"
8
backoff "gx/ipfs/QmPJUtEJsm5YLUWhF6imvyCH8KZXRJa9Wup7FDMwTy5Ufz/backoff"
9
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
10
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
11
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
12
)
13
14
var log = logging.Logger("reprovider")
namesys/namesys.go
+1
-1
@@ -5,10 +5,10 @@ import (
5
"time"
6
7
path "github.com/ipfs/go-ipfs/path"
8
- routing "github.com/ipfs/go-ipfs/routing"
8
ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
9
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
10
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
11
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
12
)
13
14
// mpns (a multi-protocol NameSystem) implements generic IPFS naming.
namesys/publisher.go
+7
-7
@@ -6,22 +6,22 @@ import (
6
"fmt"
7
"time"
8
9
- proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
10
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
11
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
12
-
9
dag "github.com/ipfs/go-ipfs/merkledag"
10
pb "github.com/ipfs/go-ipfs/namesys/pb"
11
path "github.com/ipfs/go-ipfs/path"
12
pin "github.com/ipfs/go-ipfs/pin"
17
- routing "github.com/ipfs/go-ipfs/routing"
18
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
19
- record "github.com/ipfs/go-ipfs/routing/record"
13
ft "github.com/ipfs/go-ipfs/unixfs"
14
+
15
ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
16
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
17
+ proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
18
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
19
+ context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
20
+ ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
21
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
22
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
23
+ record "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record"
24
+ dhtpb "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record/pb"
25
)
26
27
// ErrExpiredRecord should be returned when an ipns record is
namesys/republisher/repub.go
+4
-4
@@ -8,9 +8,6 @@ import (
8
namesys "github.com/ipfs/go-ipfs/namesys"
9
pb "github.com/ipfs/go-ipfs/namesys/pb"
10
path "github.com/ipfs/go-ipfs/path"
11
- "github.com/ipfs/go-ipfs/routing"
12
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
13
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
11
12
goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
13
gpctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context"
@@ -19,7 +16,10 @@ import (
16
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
17
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
18
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
19
+ key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
20
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
21
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
22
+ recpb "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record/pb"
23
)
24
25
var errNoEntry = errors.New("no previous entry")
@@ -115,7 +115,7 @@ func (rp *Republisher) getLastVal(k key.Key) (path.Path, uint64, error) {
115
}
116
117
val := ival.([]byte)
118
- dhtrec := new(dhtpb.Record)
118
+ dhtrec := new(recpb.Record)
119
err = proto.Unmarshal(val, dhtrec)
120
if err != nil {
121
return "", 0, err
namesys/routing.go
+1
-1
@@ -12,8 +12,8 @@ import (
12
13
pb "github.com/ipfs/go-ipfs/namesys/pb"
14
path "github.com/ipfs/go-ipfs/path"
15
- routing "github.com/ipfs/go-ipfs/routing"
15
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
16
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
17
18
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
19
ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
package.json
+5
@@ -251,6 +251,11 @@
251
"hash": "QmRg1gKTHzc3CZXSKzem8aR4E3TubFhbgXwfVuWnSK5CC5",
252
"name": "go-metrics-interface",
253
"version": "0.1.2"
254
+ },
255
+ {
256
+ "hash": "QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB",
257
+ "name": "go-libp2p-kad-dht",
258
+ "version": "1.1.0"
259
}
260
],
261
"gxVersion": "0.4.0",
routing/dht/dht.go
deleted
-342
@@ -1,342 +0,0 @@
1
-// Package dht implements a distributed hash table that satisfies the ipfs routing
2
-// interface. This DHT is modeled after kademlia with Coral and S/Kademlia modifications.
3
-package dht
4
-
5
-import (
6
- "bytes"
7
- "errors"
8
- "fmt"
9
- "sync"
10
- "time"
11
-
12
- routing "github.com/ipfs/go-ipfs/routing"
13
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
14
- providers "github.com/ipfs/go-ipfs/routing/dht/providers"
15
- kb "github.com/ipfs/go-ipfs/routing/kbucket"
16
- record "github.com/ipfs/go-ipfs/routing/record"
17
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
18
-
19
- goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
20
- goprocessctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context"
21
- logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
22
- host "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/host"
23
- protocol "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/protocol"
24
- ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
25
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
26
- proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
27
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
28
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
29
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
30
-)
31
-
32
-var log = logging.Logger("dht")
33
-
34
-var ProtocolDHT protocol.ID = "/ipfs/kad/1.0.0"
35
-var ProtocolDHTOld protocol.ID = "/ipfs/dht"
36
-
37
-// NumBootstrapQueries defines the number of random dht queries to do to
38
-// collect members of the routing table.
39
-const NumBootstrapQueries = 5
40
-
41
-// TODO. SEE https://github.com/jbenet/node-ipfs/blob/master/submodules/ipfs-dht/index.js
42
-
43
-// IpfsDHT is an implementation of Kademlia with Coral and S/Kademlia modifications.
44
-// It is used to implement the base IpfsRouting module.
45
-type IpfsDHT struct {
46
- host host.Host // the network services we need
47
- self peer.ID // Local peer (yourself)
48
- peerstore pstore.Peerstore // Peer Registry
49
-
50
- datastore ds.Datastore // Local data
51
-
52
- routingTable *kb.RoutingTable // Array of routing tables for differently distanced nodes
53
- providers *providers.ProviderManager
54
-
55
- birth time.Time // When this peer started up
56
- diaglock sync.Mutex // lock to make diagnostics work better
57
-
58
- Validator record.Validator // record validator funcs
59
- Selector record.Selector // record selection funcs
60
-
61
- ctx context.Context
62
- proc goprocess.Process
63
-
64
- strmap map[peer.ID]*messageSender
65
- smlk sync.Mutex
66
-}
67
-
68
-// NewDHT creates a new DHT object with the given peer as the 'local' host
69
-func NewDHT(ctx context.Context, h host.Host, dstore ds.Batching) *IpfsDHT {
70
- dht := new(IpfsDHT)
71
- dht.datastore = dstore
72
- dht.self = h.ID()
73
- dht.peerstore = h.Peerstore()
74
- dht.host = h
75
-
76
- // register for network notifs.
77
- dht.host.Network().Notify((*netNotifiee)(dht))
78
-
79
- dht.proc = goprocess.WithTeardown(func() error {
80
- // remove ourselves from network notifs.
81
- dht.host.Network().StopNotify((*netNotifiee)(dht))
82
- return nil
83
- })
84
-
85
- dht.strmap = make(map[peer.ID]*messageSender)
86
- dht.ctx = ctx
87
-
88
- h.SetStreamHandler(ProtocolDHT, dht.handleNewStream)
89
- h.SetStreamHandler(ProtocolDHTOld, dht.handleNewStream)
90
- dht.providers = providers.NewProviderManager(dht.ctx, dht.self, dstore)
91
- dht.proc.AddChild(dht.providers.Process())
92
- goprocessctx.CloseAfterContext(dht.proc, ctx)
93
-
94
- dht.routingTable = kb.NewRoutingTable(20, kb.ConvertPeerID(dht.self), time.Minute, dht.peerstore)
95
- dht.birth = time.Now()
96
-
97
- dht.Validator = make(record.Validator)
98
- dht.Validator["pk"] = record.PublicKeyValidator
99
-
100
- dht.Selector = make(record.Selector)
101
- dht.Selector["pk"] = record.PublicKeySelector
102
-
103
- return dht
104
-}
105
-
106
-// putValueToPeer stores the given key/value pair at the peer 'p'
107
-func (dht *IpfsDHT) putValueToPeer(ctx context.Context, p peer.ID,
108
- key key.Key, rec *pb.Record) error {
109
-
110
- pmes := pb.NewMessage(pb.Message_PUT_VALUE, string(key), 0)
111
- pmes.Record = rec
112
- rpmes, err := dht.sendRequest(ctx, p, pmes)
113
- switch err {
114
- case ErrReadTimeout:
115
- log.Warningf("read timeout: %s %s", p.Pretty(), key)
116
- fallthrough
117
- default:
118
- return err
119
- case nil:
120
- break
121
- }
122
-
123
- if err != nil {
124
- return err
125
- }
126
-
127
- if !bytes.Equal(rpmes.GetRecord().Value, pmes.GetRecord().Value) {
128
- return errors.New("value not put correctly")
129
- }
130
- return nil
131
-}
132
-
133
-var errInvalidRecord = errors.New("received invalid record")
134
-
135
-// getValueOrPeers queries a particular peer p for the value for
136
-// key. It returns either the value or a list of closer peers.
137
-// NOTE: It will update the dht's peerstore with any new addresses
138
-// it finds for the given peer.
139
-func (dht *IpfsDHT) getValueOrPeers(ctx context.Context, p peer.ID,
140
- key key.Key) (*pb.Record, []pstore.PeerInfo, error) {
141
-
142
- pmes, err := dht.getValueSingle(ctx, p, key)
143
- if err != nil {
144
- return nil, nil, err
145
- }
146
-
147
- // Perhaps we were given closer peers
148
- peers := pb.PBPeersToPeerInfos(pmes.GetCloserPeers())
149
-
150
- if record := pmes.GetRecord(); record != nil {
151
- // Success! We were given the value
152
- log.Debug("getValueOrPeers: got value")
153
-
154
- // make sure record is valid.
155
- err = dht.verifyRecordOnline(ctx, record)
156
- if err != nil {
157
- log.Info("Received invalid record! (discarded)")
158
- // return a sentinal to signify an invalid record was received
159
- err = errInvalidRecord
160
- record = new(pb.Record)
161
- }
162
- return record, peers, err
163
- }
164
-
165
- if len(peers) > 0 {
166
- log.Debug("getValueOrPeers: peers")
167
- return nil, peers, nil
168
- }
169
-
170
- log.Warning("getValueOrPeers: routing.ErrNotFound")
171
- return nil, nil, routing.ErrNotFound
172
-}
173
-
174
-// getValueSingle simply performs the get value RPC with the given parameters
175
-func (dht *IpfsDHT) getValueSingle(ctx context.Context, p peer.ID,
176
- key key.Key) (*pb.Message, error) {
177
- defer log.EventBegin(ctx, "getValueSingle", p, &key).Done()
178
-
179
- pmes := pb.NewMessage(pb.Message_GET_VALUE, string(key), 0)
180
- resp, err := dht.sendRequest(ctx, p, pmes)
181
- switch err {
182
- case nil:
183
- return resp, nil
184
- case ErrReadTimeout:
185
- log.Warningf("read timeout: %s %s", p.Pretty(), key)
186
- fallthrough
187
- default:
188
- return nil, err
189
- }
190
-}
191
-
192
-// getLocal attempts to retrieve the value from the datastore
193
-func (dht *IpfsDHT) getLocal(key key.Key) (*pb.Record, error) {
194
-
195
- log.Debug("getLocal %s", key)
196
- v, err := dht.datastore.Get(key.DsKey())
197
- if err != nil {
198
- return nil, err
199
- }
200
- log.Debug("found in db")
201
-
202
- byt, ok := v.([]byte)
203
- if !ok {
204
- return nil, errors.New("value stored in datastore not []byte")
205
- }
206
- rec := new(pb.Record)
207
- err = proto.Unmarshal(byt, rec)
208
- if err != nil {
209
- return nil, err
210
- }
211
-
212
- err = dht.verifyRecordLocally(rec)
213
- if err != nil {
214
- log.Debugf("local record verify failed: %s (discarded)", err)
215
- return nil, err
216
- }
217
-
218
- return rec, nil
219
-}
220
-
221
-// getOwnPrivateKey attempts to load the local peers private
222
-// key from the peerstore.
223
-func (dht *IpfsDHT) getOwnPrivateKey() (ci.PrivKey, error) {
224
- sk := dht.peerstore.PrivKey(dht.self)
225
- if sk == nil {
226
- log.Warningf("%s dht cannot get own private key!", dht.self)
227
- return nil, fmt.Errorf("cannot get private key to sign record!")
228
- }
229
- return sk, nil
230
-}
231
-
232
-// putLocal stores the key value pair in the datastore
233
-func (dht *IpfsDHT) putLocal(key key.Key, rec *pb.Record) error {
234
- data, err := proto.Marshal(rec)
235
- if err != nil {
236
- return err
237
- }
238
-
239
- return dht.datastore.Put(key.DsKey(), data)
240
-}
241
-
242
-// Update signals the routingTable to Update its last-seen status
243
-// on the given peer.
244
-func (dht *IpfsDHT) Update(ctx context.Context, p peer.ID) {
245
- log.Event(ctx, "updatePeer", p)
246
- dht.routingTable.Update(p)
247
-}
248
-
249
-// FindLocal looks for a peer with a given ID connected to this dht and returns the peer and the table it was found in.
250
-func (dht *IpfsDHT) FindLocal(id peer.ID) pstore.PeerInfo {
251
- p := dht.routingTable.Find(id)
252
- if p != "" {
253
- return dht.peerstore.PeerInfo(p)
254
- }
255
- return pstore.PeerInfo{}
256
-}
257
-
258
-// findPeerSingle asks peer 'p' if they know where the peer with id 'id' is
259
-func (dht *IpfsDHT) findPeerSingle(ctx context.Context, p peer.ID, id peer.ID) (*pb.Message, error) {
260
- defer log.EventBegin(ctx, "findPeerSingle", p, id).Done()
261
-
262
- pmes := pb.NewMessage(pb.Message_FIND_NODE, string(id), 0)
263
- resp, err := dht.sendRequest(ctx, p, pmes)
264
- switch err {
265
- case nil:
266
- return resp, nil
267
- case ErrReadTimeout:
268
- log.Warningf("read timeout: %s %s", p.Pretty(), id)
269
- fallthrough
270
- default:
271
- return nil, err
272
- }
273
-}
274
-
275
-func (dht *IpfsDHT) findProvidersSingle(ctx context.Context, p peer.ID, key key.Key) (*pb.Message, error) {
276
- defer log.EventBegin(ctx, "findProvidersSingle", p, &key).Done()
277
-
278
- pmes := pb.NewMessage(pb.Message_GET_PROVIDERS, string(key), 0)
279
- resp, err := dht.sendRequest(ctx, p, pmes)
280
- switch err {
281
- case nil:
282
- return resp, nil
283
- case ErrReadTimeout:
284
- log.Warningf("read timeout: %s %s", p.Pretty(), key)
285
- fallthrough
286
- default:
287
- return nil, err
288
- }
289
-}
290
-
291
-// nearestPeersToQuery returns the routing tables closest peers.
292
-func (dht *IpfsDHT) nearestPeersToQuery(pmes *pb.Message, count int) []peer.ID {
293
- key := key.Key(pmes.GetKey())
294
- closer := dht.routingTable.NearestPeers(kb.ConvertKey(key), count)
295
- return closer
296
-}
297
-
298
-// betterPeerToQuery returns nearestPeersToQuery, but iff closer than self.
299
-func (dht *IpfsDHT) betterPeersToQuery(pmes *pb.Message, p peer.ID, count int) []peer.ID {
300
- closer := dht.nearestPeersToQuery(pmes, count)
301
-
302
- // no node? nil
303
- if closer == nil {
304
- return nil
305
- }
306
-
307
- // == to self? thats bad
308
- for _, p := range closer {
309
- if p == dht.self {
310
- log.Debug("attempted to return self! this shouldn't happen...")
311
- return nil
312
- }
313
- }
314
-
315
- var filtered []peer.ID
316
- for _, clp := range closer {
317
- // Dont send a peer back themselves
318
- if p == clp {
319
- continue
320
- }
321
-
322
- filtered = append(filtered, clp)
323
- }
324
-
325
- // ok seems like closer nodes
326
- return filtered
327
-}
328
-
329
-// Context return dht's context
330
-func (dht *IpfsDHT) Context() context.Context {
331
- return dht.ctx
332
-}
333
-
334
-// Process return dht's process
335
-func (dht *IpfsDHT) Process() goprocess.Process {
336
- return dht.proc
337
-}
338
-
339
-// Close calls Process Close
340
-func (dht *IpfsDHT) Close() error {
341
- return dht.proc.Close()
342
-}
routing/dht/dht_bootstrap.go
deleted
-182
@@ -1,182 +0,0 @@
1
-// Package dht implements a distributed hash table that satisfies the ipfs routing
2
-// interface. This DHT is modeled after kademlia with Coral and S/Kademlia modifications.
3
-package dht
4
-
5
-import (
6
- "crypto/rand"
7
- "fmt"
8
- "sync"
9
- "time"
10
-
11
- routing "github.com/ipfs/go-ipfs/routing"
12
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
13
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
14
-
15
- goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
16
- periodicproc "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/periodic"
17
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
18
-)
19
-
20
-// BootstrapConfig specifies parameters used bootstrapping the DHT.
21
-//
22
-// Note there is a tradeoff between the bootstrap period and the
23
-// number of queries. We could support a higher period with less
24
-// queries.
25
-type BootstrapConfig struct {
26
- Queries int // how many queries to run per period
27
- Period time.Duration // how often to run periodi cbootstrap.
28
- Timeout time.Duration // how long to wait for a bootstrao query to run
29
-}
30
-
31
-var DefaultBootstrapConfig = BootstrapConfig{
32
- // For now, this is set to 1 query.
33
- // We are currently more interested in ensuring we have a properly formed
34
- // DHT than making sure our dht minimizes traffic. Once we are more certain
35
- // of our implementation's robustness, we should lower this down to 8 or 4.
36
- Queries: 1,
37
-
38
- // For now, this is set to 1 minute, which is a medium period. We are
39
- // We are currently more interested in ensuring we have a properly formed
40
- // DHT than making sure our dht minimizes traffic.
41
- Period: time.Duration(5 * time.Minute),
42
-
43
- Timeout: time.Duration(10 * time.Second),
44
-}
45
-
46
-// Bootstrap ensures the dht routing table remains healthy as peers come and go.
47
-// it builds up a list of peers by requesting random peer IDs. The Bootstrap
48
-// process will run a number of queries each time, and run every time signal fires.
49
-// These parameters are configurable.
50
-//
51
-// As opposed to BootstrapWithConfig, Bootstrap satisfies the routing interface
52
-func (dht *IpfsDHT) Bootstrap(ctx context.Context) error {
53
- proc, err := dht.BootstrapWithConfig(DefaultBootstrapConfig)
54
- if err != nil {
55
- return err
56
- }
57
-
58
- // wait till ctx or dht.Context exits.
59
- // we have to do it this way to satisfy the Routing interface (contexts)
60
- go func() {
61
- defer proc.Close()
62
- select {
63
- case <-ctx.Done():
64
- case <-dht.Context().Done():
65
- }
66
- }()
67
-
68
- return nil
69
-}
70
-
71
-// BootstrapWithConfig ensures the dht routing table remains healthy as peers come and go.
72
-// it builds up a list of peers by requesting random peer IDs. The Bootstrap
73
-// process will run a number of queries each time, and run every time signal fires.
74
-// These parameters are configurable.
75
-//
76
-// BootstrapWithConfig returns a process, so the user can stop it.
77
-func (dht *IpfsDHT) BootstrapWithConfig(config BootstrapConfig) (goprocess.Process, error) {
78
- sig := time.Tick(config.Period)
79
- return dht.BootstrapOnSignal(config, sig)
80
-}
81
-
82
-// SignalBootstrap ensures the dht routing table remains healthy as peers come and go.
83
-// it builds up a list of peers by requesting random peer IDs. The Bootstrap
84
-// process will run a number of queries each time, and run every time signal fires.
85
-// These parameters are configurable.
86
-//
87
-// SignalBootstrap returns a process, so the user can stop it.
88
-func (dht *IpfsDHT) BootstrapOnSignal(cfg BootstrapConfig, signal <-chan time.Time) (goprocess.Process, error) {
89
- if cfg.Queries <= 0 {
90
- return nil, fmt.Errorf("invalid number of queries: %d", cfg.Queries)
91
- }
92
-
93
- if signal == nil {
94
- return nil, fmt.Errorf("invalid signal: %v", signal)
95
- }
96
-
97
- proc := periodicproc.Ticker(signal, func(worker goprocess.Process) {
98
- // it would be useful to be able to send out signals of when we bootstrap, too...
99
- // maybe this is a good case for whole module event pub/sub?
100
-
101
- ctx := dht.Context()
102
- if err := dht.runBootstrap(ctx, cfg); err != nil {
103
- log.Warning(err)
104
- // A bootstrapping error is important to notice but not fatal.
105
- }
106
- })
107
-
108
- return proc, nil
109
-}
110
-
111
-// runBootstrap builds up list of peers by requesting random peer IDs
112
-func (dht *IpfsDHT) runBootstrap(ctx context.Context, cfg BootstrapConfig) error {
113
- bslog := func(msg string) {
114
- log.Debugf("DHT %s dhtRunBootstrap %s -- routing table size: %d", dht.self, msg, dht.routingTable.Size())
115
- }
116
- bslog("start")
117
- defer bslog("end")
118
- defer log.EventBegin(ctx, "dhtRunBootstrap").Done()
119
-
120
- var merr u.MultiErr
121
-
122
- randomID := func() peer.ID {
123
- // 16 random bytes is not a valid peer id. it may be fine becuase
124
- // the dht will rehash to its own keyspace anyway.
125
- id := make([]byte, 16)
126
- rand.Read(id)
127
- id = u.Hash(id)
128
- return peer.ID(id)
129
- }
130
-
131
- // bootstrap sequentially, as results will compound
132
- ctx, cancel := context.WithTimeout(ctx, cfg.Timeout)
133
- defer cancel()
134
- runQuery := func(ctx context.Context, id peer.ID) {
135
- p, err := dht.FindPeer(ctx, id)
136
- if err == routing.ErrNotFound {
137
- // this isn't an error. this is precisely what we expect.
138
- } else if err != nil {
139
- merr = append(merr, err)
140
- } else {
141
- // woah, actually found a peer with that ID? this shouldn't happen normally
142
- // (as the ID we use is not a real ID). this is an odd error worth logging.
143
- err := fmt.Errorf("Bootstrap peer error: Actually FOUND peer. (%s, %s)", id, p)
144
- log.Warningf("%s", err)
145
- merr = append(merr, err)
146
- }
147
- }
148
-
149
- sequential := true
150
- if sequential {
151
- // these should be parallel normally. but can make them sequential for debugging.
152
- // note that the core/bootstrap context deadline should be extended too for that.
153
- for i := 0; i < cfg.Queries; i++ {
154
- id := randomID()
155
- log.Debugf("Bootstrapping query (%d/%d) to random ID: %s", i+1, cfg.Queries, id)
156
- runQuery(ctx, id)
157
- }
158
-
159
- } else {
160
- // note on parallelism here: the context is passed in to the queries, so they
161
- // **should** exit when it exceeds, making this function exit on ctx cancel.
162
- // normally, we should be selecting on ctx.Done() here too, but this gets
163
- // complicated to do with WaitGroup, and doesnt wait for the children to exit.
164
- var wg sync.WaitGroup
165
- for i := 0; i < cfg.Queries; i++ {
166
- wg.Add(1)
167
- go func() {
168
- defer wg.Done()
169
-
170
- id := randomID()
171
- log.Debugf("Bootstrapping query (%d/%d) to random ID: %s", i+1, cfg.Queries, id)
172
- runQuery(ctx, id)
173
- }()
174
- }
175
- wg.Wait()
176
- }
177
-
178
- if len(merr) > 0 {
179
- return merr
180
- }
181
- return nil
182
-}
routing/dht/dht_net.go
deleted
-250
@@ -1,250 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "fmt"
5
- "sync"
6
- "time"
7
-
8
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
9
- inet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net"
10
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
11
- ctxio "gx/ipfs/QmX6DhWrpBB5NtadXmPSXYNdVvuLfJXoFNMvUMoVvP5UJa/go-context/io"
12
- ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io"
13
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
14
-)
15
-
16
-var dhtReadMessageTimeout = time.Minute
17
-var ErrReadTimeout = fmt.Errorf("timed out reading response")
18
-
19
-// handleNewStream implements the inet.StreamHandler
20
-func (dht *IpfsDHT) handleNewStream(s inet.Stream) {
21
- go dht.handleNewMessage(s)
22
-}
23
-
24
-func (dht *IpfsDHT) handleNewMessage(s inet.Stream) {
25
- defer s.Close()
26
-
27
- ctx := dht.Context()
28
- cr := ctxio.NewReader(ctx, s) // ok to use. we defer close stream in this func
29
- cw := ctxio.NewWriter(ctx, s) // ok to use. we defer close stream in this func
30
- r := ggio.NewDelimitedReader(cr, inet.MessageSizeMax)
31
- w := ggio.NewDelimitedWriter(cw)
32
- mPeer := s.Conn().RemotePeer()
33
-
34
- for {
35
- // receive msg
36
- pmes := new(pb.Message)
37
- if err := r.ReadMsg(pmes); err != nil {
38
- log.Debugf("Error unmarshaling data: %s", err)
39
- return
40
- }
41
-
42
- // update the peer (on valid msgs only)
43
- dht.updateFromMessage(ctx, mPeer, pmes)
44
-
45
- // get handler for this msg type.
46
- handler := dht.handlerForMsgType(pmes.GetType())
47
- if handler == nil {
48
- log.Debug("got back nil handler from handlerForMsgType")
49
- return
50
- }
51
-
52
- // dispatch handler.
53
- rpmes, err := handler(ctx, mPeer, pmes)
54
- if err != nil {
55
- log.Debugf("handle message error: %s", err)
56
- return
57
- }
58
-
59
- // if nil response, return it before serializing
60
- if rpmes == nil {
61
- log.Debug("got back nil response from request")
62
- continue
63
- }
64
-
65
- // send out response msg
66
- if err := w.WriteMsg(rpmes); err != nil {
67
- log.Debugf("send response error: %s", err)
68
- return
69
- }
70
- }
71
-}
72
-
73
-// sendRequest sends out a request, but also makes sure to
74
-// measure the RTT for latency measurements.
75
-func (dht *IpfsDHT) sendRequest(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
76
-
77
- ms := dht.messageSenderForPeer(p)
78
-
79
- start := time.Now()
80
-
81
- rpmes, err := ms.SendRequest(ctx, pmes)
82
- if err != nil {
83
- return nil, err
84
- }
85
-
86
- // update the peer (on valid msgs only)
87
- dht.updateFromMessage(ctx, p, rpmes)
88
-
89
- dht.peerstore.RecordLatency(p, time.Since(start))
90
- log.Event(ctx, "dhtReceivedMessage", dht.self, p, rpmes)
91
- return rpmes, nil
92
-}
93
-
94
-// sendMessage sends out a message
95
-func (dht *IpfsDHT) sendMessage(ctx context.Context, p peer.ID, pmes *pb.Message) error {
96
-
97
- ms := dht.messageSenderForPeer(p)
98
-
99
- if err := ms.SendMessage(ctx, pmes); err != nil {
100
- return err
101
- }
102
- log.Event(ctx, "dhtSentMessage", dht.self, p, pmes)
103
- return nil
104
-}
105
-
106
-func (dht *IpfsDHT) updateFromMessage(ctx context.Context, p peer.ID, mes *pb.Message) error {
107
- dht.Update(ctx, p)
108
- return nil
109
-}
110
-
111
-func (dht *IpfsDHT) messageSenderForPeer(p peer.ID) *messageSender {
112
- dht.smlk.Lock()
113
- defer dht.smlk.Unlock()
114
-
115
- ms, ok := dht.strmap[p]
116
- if !ok {
117
- ms = dht.newMessageSender(p)
118
- dht.strmap[p] = ms
119
- }
120
-
121
- return ms
122
-}
123
-
124
-type messageSender struct {
125
- s inet.Stream
126
- r ggio.ReadCloser
127
- w ggio.WriteCloser
128
- lk sync.Mutex
129
- p peer.ID
130
- dht *IpfsDHT
131
-
132
- singleMes int
133
-}
134
-
135
-func (dht *IpfsDHT) newMessageSender(p peer.ID) *messageSender {
136
- return &messageSender{p: p, dht: dht}
137
-}
138
-
139
-func (ms *messageSender) prep() error {
140
- if ms.s != nil {
141
- return nil
142
- }
143
-
144
- nstr, err := ms.dht.host.NewStream(ms.dht.ctx, ms.p, ProtocolDHT, ProtocolDHTOld)
145
- if err != nil {
146
- return err
147
- }
148
-
149
- ms.r = ggio.NewDelimitedReader(nstr, inet.MessageSizeMax)
150
- ms.w = ggio.NewDelimitedWriter(nstr)
151
- ms.s = nstr
152
-
153
- return nil
154
-}
155
-
156
-// streamReuseTries is the number of times we will try to reuse a stream to a
157
-// given peer before giving up and reverting to the old one-message-per-stream
158
-// behaviour.
159
-const streamReuseTries = 3
160
-
161
-func (ms *messageSender) SendMessage(ctx context.Context, pmes *pb.Message) error {
162
- ms.lk.Lock()
163
- defer ms.lk.Unlock()
164
- if err := ms.prep(); err != nil {
165
- return err
166
- }
167
-
168
- if err := ms.writeMessage(pmes); err != nil {
169
- return err
170
- }
171
-
172
- if ms.singleMes > streamReuseTries {
173
- ms.s.Close()
174
- ms.s = nil
175
- }
176
-
177
- return nil
178
-}
179
-
180
-func (ms *messageSender) writeMessage(pmes *pb.Message) error {
181
- err := ms.w.WriteMsg(pmes)
182
- if err != nil {
183
- // If the other side isnt expecting us to be reusing streams, we're gonna
184
- // end up erroring here. To make sure things work seamlessly, lets retry once
185
- // before continuing
186
-
187
- log.Infof("error writing message: ", err)
188
- ms.s.Close()
189
- ms.s = nil
190
- if err := ms.prep(); err != nil {
191
- return err
192
- }
193
-
194
- if err := ms.w.WriteMsg(pmes); err != nil {
195
- return err
196
- }
197
-
198
- // keep track of this happening. If it happens a few times, its
199
- // likely we can assume the otherside will never support stream reuse
200
- ms.singleMes++
201
- }
202
- return nil
203
-}
204
-
205
-func (ms *messageSender) SendRequest(ctx context.Context, pmes *pb.Message) (*pb.Message, error) {
206
- ms.lk.Lock()
207
- defer ms.lk.Unlock()
208
- if err := ms.prep(); err != nil {
209
- return nil, err
210
- }
211
-
212
- if err := ms.writeMessage(pmes); err != nil {
213
- return nil, err
214
- }
215
-
216
- log.Event(ctx, "dhtSentMessage", ms.dht.self, ms.p, pmes)
217
-
218
- mes := new(pb.Message)
219
- if err := ms.ctxReadMsg(ctx, mes); err != nil {
220
- ms.s.Close()
221
- ms.s = nil
222
- return nil, err
223
- }
224
-
225
- if ms.singleMes > streamReuseTries {
226
- ms.s.Close()
227
- ms.s = nil
228
- }
229
-
230
- return mes, nil
231
-}
232
-
233
-func (ms *messageSender) ctxReadMsg(ctx context.Context, mes *pb.Message) error {
234
- errc := make(chan error, 1)
235
- go func(r ggio.ReadCloser) {
236
- errc <- r.ReadMsg(mes)
237
- }(ms.r)
238
-
239
- t := time.NewTimer(dhtReadMessageTimeout)
240
- defer t.Stop()
241
-
242
- select {
243
- case err := <-errc:
244
- return err
245
- case <-ctx.Done():
246
- return ctx.Err()
247
- case <-t.C:
248
- return ErrReadTimeout
249
- }
250
-}
routing/dht/dht_test.go
deleted
-828
@@ -1,828 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "bytes"
5
- "fmt"
6
- "math/rand"
7
- "sort"
8
- "sync"
9
- "testing"
10
- "time"
11
-
12
- routing "github.com/ipfs/go-ipfs/routing"
13
- record "github.com/ipfs/go-ipfs/routing/record"
14
- ci "github.com/ipfs/go-ipfs/thirdparty/testutil/ci"
15
- travisci "github.com/ipfs/go-ipfs/thirdparty/testutil/ci/travis"
16
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
17
- dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
18
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
19
-
20
- netutil "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/test/util"
21
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
22
- ma "gx/ipfs/QmYzDkkgAEmrcNzFCiYo6L1dTX4EAG1gZkbtdbd9trL4vd/go-multiaddr"
23
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
24
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
25
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
26
-)
27
-
28
-var testCaseValues = map[key.Key][]byte{}
29
-
30
-func init() {
31
- testCaseValues["hello"] = []byte("world")
32
- for i := 0; i < 100; i++ {
33
- k := fmt.Sprintf("%d -- key", i)
34
- v := fmt.Sprintf("%d -- value", i)
35
- testCaseValues[key.Key(k)] = []byte(v)
36
- }
37
-}
38
-
39
-func setupDHT(ctx context.Context, t *testing.T) *IpfsDHT {
40
- h := netutil.GenHostSwarm(t, ctx)
41
-
42
- dss := dssync.MutexWrap(ds.NewMapDatastore())
43
- d := NewDHT(ctx, h, dss)
44
-
45
- d.Validator["v"] = &record.ValidChecker{
46
- Func: func(key.Key, []byte) error {
47
- return nil
48
- },
49
- Sign: false,
50
- }
51
- return d
52
-}
53
-
54
-func setupDHTS(ctx context.Context, n int, t *testing.T) ([]ma.Multiaddr, []peer.ID, []*IpfsDHT) {
55
- addrs := make([]ma.Multiaddr, n)
56
- dhts := make([]*IpfsDHT, n)
57
- peers := make([]peer.ID, n)
58
-
59
- sanityAddrsMap := make(map[string]struct{})
60
- sanityPeersMap := make(map[string]struct{})
61
-
62
- for i := 0; i < n; i++ {
63
- dhts[i] = setupDHT(ctx, t)
64
- peers[i] = dhts[i].self
65
- addrs[i] = dhts[i].peerstore.Addrs(dhts[i].self)[0]
66
-
67
- if _, lol := sanityAddrsMap[addrs[i].String()]; lol {
68
- t.Fatal("While setting up DHTs address got duplicated.")
69
- } else {
70
- sanityAddrsMap[addrs[i].String()] = struct{}{}
71
- }
72
- if _, lol := sanityPeersMap[peers[i].String()]; lol {
73
- t.Fatal("While setting up DHTs peerid got duplicated.")
74
- } else {
75
- sanityPeersMap[peers[i].String()] = struct{}{}
76
- }
77
- }
78
-
79
- return addrs, peers, dhts
80
-}
81
-
82
-func connect(t *testing.T, ctx context.Context, a, b *IpfsDHT) {
83
-
84
- idB := b.self
85
- addrB := b.peerstore.Addrs(idB)
86
- if len(addrB) == 0 {
87
- t.Fatal("peers setup incorrectly: no local address")
88
- }
89
-
90
- a.peerstore.AddAddrs(idB, addrB, pstore.TempAddrTTL)
91
- pi := pstore.PeerInfo{ID: idB}
92
- if err := a.host.Connect(ctx, pi); err != nil {
93
- t.Fatal(err)
94
- }
95
-
96
- // loop until connection notification has been received.
97
- // under high load, this may not happen as immediately as we would like.
98
- for a.routingTable.Find(b.self) == "" {
99
- time.Sleep(time.Millisecond * 5)
100
- }
101
-
102
- for b.routingTable.Find(a.self) == "" {
103
- time.Sleep(time.Millisecond * 5)
104
- }
105
-}
106
-
107
-func bootstrap(t *testing.T, ctx context.Context, dhts []*IpfsDHT) {
108
-
109
- ctx, cancel := context.WithCancel(ctx)
110
- log.Debugf("Bootstrapping DHTs...")
111
-
112
- // tried async. sequential fares much better. compare:
113
- // 100 async https://gist.github.com/jbenet/56d12f0578d5f34810b2
114
- // 100 sync https://gist.github.com/jbenet/6c59e7c15426e48aaedd
115
- // probably because results compound
116
-
117
- var cfg BootstrapConfig
118
- cfg = DefaultBootstrapConfig
119
- cfg.Queries = 3
120
-
121
- start := rand.Intn(len(dhts)) // randomize to decrease bias.
122
- for i := range dhts {
123
- dht := dhts[(start+i)%len(dhts)]
124
- dht.runBootstrap(ctx, cfg)
125
- }
126
- cancel()
127
-}
128
-
129
-func TestValueGetSet(t *testing.T) {
130
- // t.Skip("skipping test to debug another")
131
-
132
- ctx := context.Background()
133
-
134
- dhtA := setupDHT(ctx, t)
135
- dhtB := setupDHT(ctx, t)
136
-
137
- defer dhtA.Close()
138
- defer dhtB.Close()
139
- defer dhtA.host.Close()
140
- defer dhtB.host.Close()
141
-
142
- vf := &record.ValidChecker{
143
- Func: func(key.Key, []byte) error {
144
- return nil
145
- },
146
- Sign: false,
147
- }
148
- nulsel := func(_ key.Key, bs [][]byte) (int, error) {
149
- return 0, nil
150
- }
151
-
152
- dhtA.Validator["v"] = vf
153
- dhtB.Validator["v"] = vf
154
- dhtA.Selector["v"] = nulsel
155
- dhtB.Selector["v"] = nulsel
156
-
157
- connect(t, ctx, dhtA, dhtB)
158
-
159
- ctxT, _ := context.WithTimeout(ctx, time.Second)
160
- dhtA.PutValue(ctxT, "/v/hello", []byte("world"))
161
-
162
- ctxT, _ = context.WithTimeout(ctx, time.Second*2)
163
- val, err := dhtA.GetValue(ctxT, "/v/hello")
164
- if err != nil {
165
- t.Fatal(err)
166
- }
167
-
168
- if string(val) != "world" {
169
- t.Fatalf("Expected 'world' got '%s'", string(val))
170
- }
171
-
172
- ctxT, _ = context.WithTimeout(ctx, time.Second*2)
173
- val, err = dhtB.GetValue(ctxT, "/v/hello")
174
- if err != nil {
175
- t.Fatal(err)
176
- }
177
-
178
- if string(val) != "world" {
179
- t.Fatalf("Expected 'world' got '%s'", string(val))
180
- }
181
-}
182
-
183
-func TestProvides(t *testing.T) {
184
- // t.Skip("skipping test to debug another")
185
- ctx := context.Background()
186
-
187
- _, _, dhts := setupDHTS(ctx, 4, t)
188
- defer func() {
189
- for i := 0; i < 4; i++ {
190
- dhts[i].Close()
191
- defer dhts[i].host.Close()
192
- }
193
- }()
194
-
195
- connect(t, ctx, dhts[0], dhts[1])
196
- connect(t, ctx, dhts[1], dhts[2])
197
- connect(t, ctx, dhts[1], dhts[3])
198
-
199
- for k, v := range testCaseValues {
200
- log.Debugf("adding local values for %s = %s", k, v)
201
- sk := dhts[3].peerstore.PrivKey(dhts[3].self)
202
- rec, err := record.MakePutRecord(sk, k, v, false)
203
- if err != nil {
204
- t.Fatal(err)
205
- }
206
-
207
- err = dhts[3].putLocal(k, rec)
208
- if err != nil {
209
- t.Fatal(err)
210
- }
211
-
212
- bits, err := dhts[3].getLocal(k)
213
- if err != nil {
214
- t.Fatal(err)
215
- }
216
- if !bytes.Equal(bits.GetValue(), v) {
217
- t.Fatalf("didn't store the right bits (%s, %s)", k, v)
218
- }
219
- }
220
-
221
- for k := range testCaseValues {
222
- log.Debugf("announcing provider for %s", k)
223
- if err := dhts[3].Provide(ctx, k); err != nil {
224
- t.Fatal(err)
225
- }
226
- }
227
-
228
- // what is this timeout for? was 60ms before.
229
- time.Sleep(time.Millisecond * 6)
230
-
231
- n := 0
232
- for k := range testCaseValues {
233
- n = (n + 1) % 3
234
-
235
- log.Debugf("getting providers for %s from %d", k, n)
236
- ctxT, _ := context.WithTimeout(ctx, time.Second)
237
- provchan := dhts[n].FindProvidersAsync(ctxT, k, 1)
238
-
239
- select {
240
- case prov := <-provchan:
241
- if prov.ID == "" {
242
- t.Fatal("Got back nil provider")
243
- }
244
- if prov.ID != dhts[3].self {
245
- t.Fatal("Got back wrong provider")
246
- }
247
- case <-ctxT.Done():
248
- t.Fatal("Did not get a provider back.")
249
- }
250
- }
251
-}
252
-
253
-// if minPeers or avgPeers is 0, dont test for it.
254
-func waitForWellFormedTables(t *testing.T, dhts []*IpfsDHT, minPeers, avgPeers int, timeout time.Duration) bool {
255
- // test "well-formed-ness" (>= minPeers peers in every routing table)
256
-
257
- checkTables := func() bool {
258
- totalPeers := 0
259
- for _, dht := range dhts {
260
- rtlen := dht.routingTable.Size()
261
- totalPeers += rtlen
262
- if minPeers > 0 && rtlen < minPeers {
263
- t.Logf("routing table for %s only has %d peers (should have >%d)", dht.self, rtlen, minPeers)
264
- return false
265
- }
266
- }
267
- actualAvgPeers := totalPeers / len(dhts)
268
- t.Logf("avg rt size: %d", actualAvgPeers)
269
- if avgPeers > 0 && actualAvgPeers < avgPeers {
270
- t.Logf("avg rt size: %d < %d", actualAvgPeers, avgPeers)
271
- return false
272
- }
273
- return true
274
- }
275
-
276
- timeoutA := time.After(timeout)
277
- for {
278
- select {
279
- case <-timeoutA:
280
- log.Debugf("did not reach well-formed routing tables by %s", timeout)
281
- return false // failed
282
- case <-time.After(5 * time.Millisecond):
283
- if checkTables() {
284
- return true // succeeded
285
- }
286
- }
287
- }
288
-}
289
-
290
-func printRoutingTables(dhts []*IpfsDHT) {
291
- // the routing tables should be full now. let's inspect them.
292
- fmt.Printf("checking routing table of %d\n", len(dhts))
293
- for _, dht := range dhts {
294
- fmt.Printf("checking routing table of %s\n", dht.self)
295
- dht.routingTable.Print()
296
- fmt.Println("")
297
- }
298
-}
299
-
300
-func TestBootstrap(t *testing.T) {
301
- // t.Skip("skipping test to debug another")
302
- if testing.Short() {
303
- t.SkipNow()
304
- }
305
-
306
- ctx := context.Background()
307
-
308
- nDHTs := 30
309
- _, _, dhts := setupDHTS(ctx, nDHTs, t)
310
- defer func() {
311
- for i := 0; i < nDHTs; i++ {
312
- dhts[i].Close()
313
- defer dhts[i].host.Close()
314
- }
315
- }()
316
-
317
- t.Logf("connecting %d dhts in a ring", nDHTs)
318
- for i := 0; i < nDHTs; i++ {
319
- connect(t, ctx, dhts[i], dhts[(i+1)%len(dhts)])
320
- }
321
-
322
- <-time.After(100 * time.Millisecond)
323
- // bootstrap a few times until we get good tables.
324
- stop := make(chan struct{})
325
- go func() {
326
- for {
327
- t.Logf("bootstrapping them so they find each other", nDHTs)
328
- ctxT, _ := context.WithTimeout(ctx, 5*time.Second)
329
- bootstrap(t, ctxT, dhts)
330
-
331
- select {
332
- case <-time.After(50 * time.Millisecond):
333
- continue // being explicit
334
- case <-stop:
335
- return
336
- }
337
- }
338
- }()
339
-
340
- waitForWellFormedTables(t, dhts, 7, 10, 20*time.Second)
341
- close(stop)
342
-
343
- if u.Debug {
344
- // the routing tables should be full now. let's inspect them.
345
- printRoutingTables(dhts)
346
- }
347
-}
348
-
349
-func TestPeriodicBootstrap(t *testing.T) {
350
- // t.Skip("skipping test to debug another")
351
- if ci.IsRunning() {
352
- t.Skip("skipping on CI. highly timing dependent")
353
- }
354
- if testing.Short() {
355
- t.SkipNow()
356
- }
357
-
358
- ctx := context.Background()
359
-
360
- nDHTs := 30
361
- _, _, dhts := setupDHTS(ctx, nDHTs, t)
362
- defer func() {
363
- for i := 0; i < nDHTs; i++ {
364
- dhts[i].Close()
365
- defer dhts[i].host.Close()
366
- }
367
- }()
368
-
369
- // signal amplifier
370
- amplify := func(signal chan time.Time, other []chan time.Time) {
371
- for t := range signal {
372
- for _, s := range other {
373
- s <- t
374
- }
375
- }
376
- for _, s := range other {
377
- close(s)
378
- }
379
- }
380
-
381
- signal := make(chan time.Time)
382
- allSignals := []chan time.Time{}
383
-
384
- var cfg BootstrapConfig
385
- cfg = DefaultBootstrapConfig
386
- cfg.Queries = 5
387
-
388
- // kick off periodic bootstrappers with instrumented signals.
389
- for _, dht := range dhts {
390
- s := make(chan time.Time)
391
- allSignals = append(allSignals, s)
392
- dht.BootstrapOnSignal(cfg, s)
393
- }
394
- go amplify(signal, allSignals)
395
-
396
- t.Logf("dhts are not connected.", nDHTs)
397
- for _, dht := range dhts {
398
- rtlen := dht.routingTable.Size()
399
- if rtlen > 0 {
400
- t.Errorf("routing table for %s should have 0 peers. has %d", dht.self, rtlen)
401
- }
402
- }
403
-
404
- for i := 0; i < nDHTs; i++ {
405
- connect(t, ctx, dhts[i], dhts[(i+1)%len(dhts)])
406
- }
407
-
408
- t.Logf("DHTs are now connected to 1-2 others.", nDHTs)
409
- for _, dht := range dhts {
410
- rtlen := dht.routingTable.Size()
411
- if rtlen > 2 {
412
- t.Errorf("routing table for %s should have at most 2 peers. has %d", dht.self, rtlen)
413
- }
414
- }
415
-
416
- if u.Debug {
417
- printRoutingTables(dhts)
418
- }
419
-
420
- t.Logf("bootstrapping them so they find each other", nDHTs)
421
- signal <- time.Now()
422
-
423
- // this is async, and we dont know when it's finished with one cycle, so keep checking
424
- // until the routing tables look better, or some long timeout for the failure case.
425
- waitForWellFormedTables(t, dhts, 7, 10, 20*time.Second)
426
-
427
- if u.Debug {
428
- printRoutingTables(dhts)
429
- }
430
-}
431
-
432
-func TestProvidesMany(t *testing.T) {
433
- t.Skip("this test doesn't work")
434
- // t.Skip("skipping test to debug another")
435
- ctx := context.Background()
436
-
437
- nDHTs := 40
438
- _, _, dhts := setupDHTS(ctx, nDHTs, t)
439
- defer func() {
440
- for i := 0; i < nDHTs; i++ {
441
- dhts[i].Close()
442
- defer dhts[i].host.Close()
443
- }
444
- }()
445
-
446
- t.Logf("connecting %d dhts in a ring", nDHTs)
447
- for i := 0; i < nDHTs; i++ {
448
- connect(t, ctx, dhts[i], dhts[(i+1)%len(dhts)])
449
- }
450
-
451
- <-time.After(100 * time.Millisecond)
452
- t.Logf("bootstrapping them so they find each other", nDHTs)
453
- ctxT, _ := context.WithTimeout(ctx, 20*time.Second)
454
- bootstrap(t, ctxT, dhts)
455
-
456
- if u.Debug {
457
- // the routing tables should be full now. let's inspect them.
458
- t.Logf("checking routing table of %d", nDHTs)
459
- for _, dht := range dhts {
460
- fmt.Printf("checking routing table of %s\n", dht.self)
461
- dht.routingTable.Print()
462
- fmt.Println("")
463
- }
464
- }
465
-
466
- var providers = map[key.Key]peer.ID{}
467
-
468
- d := 0
469
- for k, v := range testCaseValues {
470
- d = (d + 1) % len(dhts)
471
- dht := dhts[d]
472
- providers[k] = dht.self
473
-
474
- t.Logf("adding local values for %s = %s (on %s)", k, v, dht.self)
475
- rec, err := record.MakePutRecord(nil, k, v, false)
476
- if err != nil {
477
- t.Fatal(err)
478
- }
479
-
480
- err = dht.putLocal(k, rec)
481
- if err != nil {
482
- t.Fatal(err)
483
- }
484
-
485
- bits, err := dht.getLocal(k)
486
- if err != nil {
487
- t.Fatal(err)
488
- }
489
- if !bytes.Equal(bits.GetValue(), v) {
490
- t.Fatalf("didn't store the right bits (%s, %s)", k, v)
491
- }
492
-
493
- t.Logf("announcing provider for %s", k)
494
- if err := dht.Provide(ctx, k); err != nil {
495
- t.Fatal(err)
496
- }
497
- }
498
-
499
- // what is this timeout for? was 60ms before.
500
- time.Sleep(time.Millisecond * 6)
501
-
502
- errchan := make(chan error)
503
-
504
- ctxT, _ = context.WithTimeout(ctx, 5*time.Second)
505
-
506
- var wg sync.WaitGroup
507
- getProvider := func(dht *IpfsDHT, k key.Key) {
508
- defer wg.Done()
509
-
510
- expected := providers[k]
511
-
512
- provchan := dht.FindProvidersAsync(ctxT, k, 1)
513
- select {
514
- case prov := <-provchan:
515
- actual := prov.ID
516
- if actual == "" {
517
- errchan <- fmt.Errorf("Got back nil provider (%s at %s)", k, dht.self)
518
- } else if actual != expected {
519
- errchan <- fmt.Errorf("Got back wrong provider (%s != %s) (%s at %s)",
520
- expected, actual, k, dht.self)
521
- }
522
- case <-ctxT.Done():
523
- errchan <- fmt.Errorf("Did not get a provider back (%s at %s)", k, dht.self)
524
- }
525
- }
526
-
527
- for k := range testCaseValues {
528
- // everyone should be able to find it...
529
- for _, dht := range dhts {
530
- log.Debugf("getting providers for %s at %s", k, dht.self)
531
- wg.Add(1)
532
- go getProvider(dht, k)
533
- }
534
- }
535
-
536
- // we need this because of printing errors
537
- go func() {
538
- wg.Wait()
539
- close(errchan)
540
- }()
541
-
542
- for err := range errchan {
543
- t.Error(err)
544
- }
545
-}
546
-
547
-func TestProvidesAsync(t *testing.T) {
548
- // t.Skip("skipping test to debug another")
549
- if testing.Short() {
550
- t.SkipNow()
551
- }
552
-
553
- ctx := context.Background()
554
-
555
- _, _, dhts := setupDHTS(ctx, 4, t)
556
- defer func() {
557
- for i := 0; i < 4; i++ {
558
- dhts[i].Close()
559
- defer dhts[i].host.Close()
560
- }
561
- }()
562
-
563
- connect(t, ctx, dhts[0], dhts[1])
564
- connect(t, ctx, dhts[1], dhts[2])
565
- connect(t, ctx, dhts[1], dhts[3])
566
-
567
- k := key.Key("hello")
568
- val := []byte("world")
569
- sk := dhts[3].peerstore.PrivKey(dhts[3].self)
570
- rec, err := record.MakePutRecord(sk, k, val, false)
571
- if err != nil {
572
- t.Fatal(err)
573
- }
574
-
575
- err = dhts[3].putLocal(k, rec)
576
- if err != nil {
577
- t.Fatal(err)
578
- }
579
-
580
- bits, err := dhts[3].getLocal(k)
581
- if err != nil && bytes.Equal(bits.GetValue(), val) {
582
- t.Fatal(err)
583
- }
584
-
585
- err = dhts[3].Provide(ctx, key.Key("hello"))
586
- if err != nil {
587
- t.Fatal(err)
588
- }
589
-
590
- time.Sleep(time.Millisecond * 60)
591
-
592
- ctxT, _ := context.WithTimeout(ctx, time.Millisecond*300)
593
- provs := dhts[0].FindProvidersAsync(ctxT, key.Key("hello"), 5)
594
- select {
595
- case p, ok := <-provs:
596
- if !ok {
597
- t.Fatal("Provider channel was closed...")
598
- }
599
- if p.ID == "" {
600
- t.Fatal("Got back nil provider!")
601
- }
602
- if p.ID != dhts[3].self {
603
- t.Fatalf("got a provider, but not the right one. %s", p)
604
- }
605
- case <-ctxT.Done():
606
- t.Fatal("Didnt get back providers")
607
- }
608
-}
609
-
610
-func TestLayeredGet(t *testing.T) {
611
- // t.Skip("skipping test to debug another")
612
- if testing.Short() {
613
- t.SkipNow()
614
- }
615
-
616
- ctx := context.Background()
617
-
618
- _, _, dhts := setupDHTS(ctx, 4, t)
619
- defer func() {
620
- for i := 0; i < 4; i++ {
621
- dhts[i].Close()
622
- defer dhts[i].host.Close()
623
- }
624
- }()
625
-
626
- connect(t, ctx, dhts[0], dhts[1])
627
- connect(t, ctx, dhts[1], dhts[2])
628
- connect(t, ctx, dhts[1], dhts[3])
629
-
630
- err := dhts[3].Provide(ctx, key.Key("/v/hello"))
631
- if err != nil {
632
- t.Fatal(err)
633
- }
634
-
635
- time.Sleep(time.Millisecond * 6)
636
-
637
- t.Log("interface was changed. GetValue should not use providers.")
638
- ctxT, _ := context.WithTimeout(ctx, time.Second)
639
- val, err := dhts[0].GetValue(ctxT, key.Key("/v/hello"))
640
- if err != routing.ErrNotFound {
641
- t.Error(err)
642
- }
643
- if string(val) == "world" {
644
- t.Error("should not get value.")
645
- }
646
- if len(val) > 0 && string(val) != "world" {
647
- t.Error("worse, there's a value and its not even the right one.")
648
- }
649
-}
650
-
651
-func TestFindPeer(t *testing.T) {
652
- // t.Skip("skipping test to debug another")
653
- if testing.Short() {
654
- t.SkipNow()
655
- }
656
-
657
- ctx := context.Background()
658
-
659
- _, peers, dhts := setupDHTS(ctx, 4, t)
660
- defer func() {
661
- for i := 0; i < 4; i++ {
662
- dhts[i].Close()
663
- dhts[i].host.Close()
664
- }
665
- }()
666
-
667
- connect(t, ctx, dhts[0], dhts[1])
668
- connect(t, ctx, dhts[1], dhts[2])
669
- connect(t, ctx, dhts[1], dhts[3])
670
-
671
- ctxT, _ := context.WithTimeout(ctx, time.Second)
672
- p, err := dhts[0].FindPeer(ctxT, peers[2])
673
- if err != nil {
674
- t.Fatal(err)
675
- }
676
-
677
- if p.ID == "" {
678
- t.Fatal("Failed to find peer.")
679
- }
680
-
681
- if p.ID != peers[2] {
682
- t.Fatal("Didnt find expected peer.")
683
- }
684
-}
685
-
686
-func TestFindPeersConnectedToPeer(t *testing.T) {
687
- t.Skip("not quite correct (see note)")
688
-
689
- if testing.Short() {
690
- t.SkipNow()
691
- }
692
-
693
- ctx := context.Background()
694
-
695
- _, peers, dhts := setupDHTS(ctx, 4, t)
696
- defer func() {
697
- for i := 0; i < 4; i++ {
698
- dhts[i].Close()
699
- dhts[i].host.Close()
700
- }
701
- }()
702
-
703
- // topology:
704
- // 0-1, 1-2, 1-3, 2-3
705
- connect(t, ctx, dhts[0], dhts[1])
706
- connect(t, ctx, dhts[1], dhts[2])
707
- connect(t, ctx, dhts[1], dhts[3])
708
- connect(t, ctx, dhts[2], dhts[3])
709
-
710
- // fmt.Println("0 is", peers[0])
711
- // fmt.Println("1 is", peers[1])
712
- // fmt.Println("2 is", peers[2])
713
- // fmt.Println("3 is", peers[3])
714
-
715
- ctxT, _ := context.WithTimeout(ctx, time.Second)
716
- pchan, err := dhts[0].FindPeersConnectedToPeer(ctxT, peers[2])
717
- if err != nil {
718
- t.Fatal(err)
719
- }
720
-
721
- // shouldFind := []peer.ID{peers[1], peers[3]}
722
- var found []pstore.PeerInfo
723
- for nextp := range pchan {
724
- found = append(found, nextp)
725
- }
726
-
727
- // fmt.Printf("querying 0 (%s) FindPeersConnectedToPeer 2 (%s)\n", peers[0], peers[2])
728
- // fmt.Println("should find 1, 3", shouldFind)
729
- // fmt.Println("found", found)
730
-
731
- // testPeerListsMatch(t, shouldFind, found)
732
-
733
- log.Warning("TestFindPeersConnectedToPeer is not quite correct")
734
- if len(found) == 0 {
735
- t.Fatal("didn't find any peers.")
736
- }
737
-}
738
-
739
-func testPeerListsMatch(t *testing.T, p1, p2 []peer.ID) {
740
-
741
- if len(p1) != len(p2) {
742
- t.Fatal("did not find as many peers as should have", p1, p2)
743
- }
744
-
745
- ids1 := make([]string, len(p1))
746
- ids2 := make([]string, len(p2))
747
-
748
- for i, p := range p1 {
749
- ids1[i] = string(p)
750
- }
751
-
752
- for i, p := range p2 {
753
- ids2[i] = string(p)
754
- }
755
-
756
- sort.Sort(sort.StringSlice(ids1))
757
- sort.Sort(sort.StringSlice(ids2))
758
-
759
- for i := range ids1 {
760
- if ids1[i] != ids2[i] {
761
- t.Fatal("Didnt find expected peer", ids1[i], ids2)
762
- }
763
- }
764
-}
765
-
766
-func TestConnectCollision(t *testing.T) {
767
- // t.Skip("skipping test to debug another")
768
- if testing.Short() {
769
- t.SkipNow()
770
- }
771
- if travisci.IsRunning() {
772
- t.Skip("Skipping on Travis-CI.")
773
- }
774
-
775
- runTimes := 10
776
-
777
- for rtime := 0; rtime < runTimes; rtime++ {
778
- log.Info("Running Time: ", rtime)
779
-
780
- ctx := context.Background()
781
-
782
- dhtA := setupDHT(ctx, t)
783
- dhtB := setupDHT(ctx, t)
784
-
785
- addrA := dhtA.peerstore.Addrs(dhtA.self)[0]
786
- addrB := dhtB.peerstore.Addrs(dhtB.self)[0]
787
-
788
- peerA := dhtA.self
789
- peerB := dhtB.self
790
-
791
- errs := make(chan error)
792
- go func() {
793
- dhtA.peerstore.AddAddr(peerB, addrB, pstore.TempAddrTTL)
794
- pi := pstore.PeerInfo{ID: peerB}
795
- err := dhtA.host.Connect(ctx, pi)
796
- errs <- err
797
- }()
798
- go func() {
799
- dhtB.peerstore.AddAddr(peerA, addrA, pstore.TempAddrTTL)
800
- pi := pstore.PeerInfo{ID: peerA}
801
- err := dhtB.host.Connect(ctx, pi)
802
- errs <- err
803
- }()
804
-
805
- timeout := time.After(5 * time.Second)
806
- select {
807
- case e := <-errs:
808
- if e != nil {
809
- t.Fatal(e)
810
- }
811
- case <-timeout:
812
- t.Fatal("Timeout received!")
813
- }
814
- select {
815
- case e := <-errs:
816
- if e != nil {
817
- t.Fatal(e)
818
- }
819
- case <-timeout:
820
- t.Fatal("Timeout received!")
821
- }
822
-
823
- dhtA.Close()
824
- dhtB.Close()
825
- dhtA.host.Close()
826
- dhtB.host.Close()
827
- }
828
-}
routing/dht/ext_test.go
deleted
-290
@@ -1,290 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "io"
5
- "math/rand"
6
- "testing"
7
- "time"
8
-
9
- routing "github.com/ipfs/go-ipfs/routing"
10
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
11
- record "github.com/ipfs/go-ipfs/routing/record"
12
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
13
- dssync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
14
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
15
-
16
- inet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net"
17
- mocknet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net/mock"
18
- ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io"
19
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
20
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
21
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
22
-)
23
-
24
-func TestGetFailures(t *testing.T) {
25
- if testing.Short() {
26
- t.SkipNow()
27
- }
28
-
29
- ctx := context.Background()
30
- mn, err := mocknet.FullMeshConnected(ctx, 2)
31
- if err != nil {
32
- t.Fatal(err)
33
- }
34
- hosts := mn.Hosts()
35
-
36
- tsds := dssync.MutexWrap(ds.NewMapDatastore())
37
- d := NewDHT(ctx, hosts[0], tsds)
38
- d.Update(ctx, hosts[1].ID())
39
-
40
- // Reply with failures to every message
41
- hosts[1].SetStreamHandler(ProtocolDHT, func(s inet.Stream) {
42
- s.Close()
43
- })
44
-
45
- // This one should time out
46
- ctx1, _ := context.WithTimeout(context.Background(), 200*time.Millisecond)
47
- if _, err := d.GetValue(ctx1, key.Key("test")); err != nil {
48
- if merr, ok := err.(u.MultiErr); ok && len(merr) > 0 {
49
- err = merr[0]
50
- }
51
-
52
- if err != io.EOF {
53
- t.Fatal("Got different error than we expected", err)
54
- }
55
- } else {
56
- t.Fatal("Did not get expected error!")
57
- }
58
-
59
- t.Log("Timeout test passed.")
60
-
61
- // Reply with failures to every message
62
- hosts[1].SetStreamHandler(ProtocolDHT, func(s inet.Stream) {
63
- defer s.Close()
64
-
65
- pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
66
- pbw := ggio.NewDelimitedWriter(s)
67
-
68
- pmes := new(pb.Message)
69
- if err := pbr.ReadMsg(pmes); err != nil {
70
- panic(err)
71
- }
72
-
73
- resp := &pb.Message{
74
- Type: pmes.Type,
75
- }
76
- if err := pbw.WriteMsg(resp); err != nil {
77
- panic(err)
78
- }
79
- })
80
-
81
- // This one should fail with NotFound.
82
- // long context timeout to ensure we dont end too early.
83
- // the dht should be exhausting its query and returning not found.
84
- // (was 3 seconds before which should be _plenty_ of time, but maybe
85
- // travis machines really have a hard time...)
86
- ctx2, _ := context.WithTimeout(context.Background(), 20*time.Second)
87
- _, err = d.GetValue(ctx2, key.Key("test"))
88
- if err != nil {
89
- if merr, ok := err.(u.MultiErr); ok && len(merr) > 0 {
90
- err = merr[0]
91
- }
92
- if err != routing.ErrNotFound {
93
- t.Fatalf("Expected ErrNotFound, got: %s", err)
94
- }
95
- } else {
96
- t.Fatal("expected error, got none.")
97
- }
98
-
99
- t.Log("ErrNotFound check passed!")
100
-
101
- // Now we test this DHT's handleGetValue failure
102
- {
103
- typ := pb.Message_GET_VALUE
104
- str := "hello"
105
-
106
- sk, err := d.getOwnPrivateKey()
107
- if err != nil {
108
- t.Fatal(err)
109
- }
110
-
111
- rec, err := record.MakePutRecord(sk, key.Key(str), []byte("blah"), true)
112
- if err != nil {
113
- t.Fatal(err)
114
- }
115
- req := pb.Message{
116
- Type: &typ,
117
- Key: &str,
118
- Record: rec,
119
- }
120
-
121
- s, err := hosts[1].NewStream(context.Background(), hosts[0].ID(), ProtocolDHT)
122
- if err != nil {
123
- t.Fatal(err)
124
- }
125
- defer s.Close()
126
-
127
- pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
128
- pbw := ggio.NewDelimitedWriter(s)
129
-
130
- if err := pbw.WriteMsg(&req); err != nil {
131
- t.Fatal(err)
132
- }
133
-
134
- pmes := new(pb.Message)
135
- if err := pbr.ReadMsg(pmes); err != nil {
136
- t.Fatal(err)
137
- }
138
- if pmes.GetRecord() != nil {
139
- t.Fatal("shouldnt have value")
140
- }
141
- if pmes.GetProviderPeers() != nil {
142
- t.Fatal("shouldnt have provider peers")
143
- }
144
- }
145
-}
146
-
147
-func TestNotFound(t *testing.T) {
148
- // t.Skip("skipping test to debug another")
149
- if testing.Short() {
150
- t.SkipNow()
151
- }
152
-
153
- ctx := context.Background()
154
- mn, err := mocknet.FullMeshConnected(ctx, 16)
155
- if err != nil {
156
- t.Fatal(err)
157
- }
158
- hosts := mn.Hosts()
159
- tsds := dssync.MutexWrap(ds.NewMapDatastore())
160
- d := NewDHT(ctx, hosts[0], tsds)
161
-
162
- for _, p := range hosts {
163
- d.Update(ctx, p.ID())
164
- }
165
-
166
- // Reply with random peers to every message
167
- for _, host := range hosts {
168
- host := host // shadow loop var
169
- host.SetStreamHandler(ProtocolDHT, func(s inet.Stream) {
170
- defer s.Close()
171
-
172
- pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
173
- pbw := ggio.NewDelimitedWriter(s)
174
-
175
- pmes := new(pb.Message)
176
- if err := pbr.ReadMsg(pmes); err != nil {
177
- panic(err)
178
- }
179
-
180
- switch pmes.GetType() {
181
- case pb.Message_GET_VALUE:
182
- resp := &pb.Message{Type: pmes.Type}
183
-
184
- ps := []pstore.PeerInfo{}
185
- for i := 0; i < 7; i++ {
186
- p := hosts[rand.Intn(len(hosts))].ID()
187
- pi := host.Peerstore().PeerInfo(p)
188
- ps = append(ps, pi)
189
- }
190
-
191
- resp.CloserPeers = pb.PeerInfosToPBPeers(d.host.Network(), ps)
192
- if err := pbw.WriteMsg(resp); err != nil {
193
- panic(err)
194
- }
195
-
196
- default:
197
- panic("Shouldnt recieve this.")
198
- }
199
- })
200
- }
201
-
202
- // long timeout to ensure timing is not at play.
203
- ctx, cancel := context.WithTimeout(ctx, time.Second*20)
204
- defer cancel()
205
- v, err := d.GetValue(ctx, key.Key("hello"))
206
- log.Debugf("get value got %v", v)
207
- if err != nil {
208
- if merr, ok := err.(u.MultiErr); ok && len(merr) > 0 {
209
- err = merr[0]
210
- }
211
- switch err {
212
- case routing.ErrNotFound:
213
- //Success!
214
- return
215
- case u.ErrTimeout:
216
- t.Fatal("Should not have gotten timeout!")
217
- default:
218
- t.Fatalf("Got unexpected error: %s", err)
219
- }
220
- }
221
- t.Fatal("Expected to recieve an error.")
222
-}
223
-
224
-// If less than K nodes are in the entire network, it should fail when we make
225
-// a GET rpc and nobody has the value
226
-func TestLessThanKResponses(t *testing.T) {
227
- // t.Skip("skipping test to debug another")
228
- // t.Skip("skipping test because it makes a lot of output")
229
-
230
- ctx := context.Background()
231
- mn, err := mocknet.FullMeshConnected(ctx, 6)
232
- if err != nil {
233
- t.Fatal(err)
234
- }
235
- hosts := mn.Hosts()
236
-
237
- tsds := dssync.MutexWrap(ds.NewMapDatastore())
238
- d := NewDHT(ctx, hosts[0], tsds)
239
-
240
- for i := 1; i < 5; i++ {
241
- d.Update(ctx, hosts[i].ID())
242
- }
243
-
244
- // Reply with random peers to every message
245
- for _, host := range hosts {
246
- host := host // shadow loop var
247
- host.SetStreamHandler(ProtocolDHT, func(s inet.Stream) {
248
- defer s.Close()
249
-
250
- pbr := ggio.NewDelimitedReader(s, inet.MessageSizeMax)
251
- pbw := ggio.NewDelimitedWriter(s)
252
-
253
- pmes := new(pb.Message)
254
- if err := pbr.ReadMsg(pmes); err != nil {
255
- panic(err)
256
- }
257
-
258
- switch pmes.GetType() {
259
- case pb.Message_GET_VALUE:
260
- pi := host.Peerstore().PeerInfo(hosts[1].ID())
261
- resp := &pb.Message{
262
- Type: pmes.Type,
263
- CloserPeers: pb.PeerInfosToPBPeers(d.host.Network(), []pstore.PeerInfo{pi}),
264
- }
265
-
266
- if err := pbw.WriteMsg(resp); err != nil {
267
- panic(err)
268
- }
269
- default:
270
- panic("Shouldnt recieve this.")
271
- }
272
-
273
- })
274
- }
275
-
276
- ctx, cancel := context.WithTimeout(ctx, time.Second*30)
277
- defer cancel()
278
- if _, err := d.GetValue(ctx, key.Key("hello")); err != nil {
279
- switch err {
280
- case routing.ErrNotFound:
281
- //Success!
282
- return
283
- case u.ErrTimeout:
284
- t.Fatal("Should not have gotten timeout!")
285
- default:
286
- t.Fatalf("Got unexpected error: %s", err)
287
- }
288
- }
289
- t.Fatal("Expected to recieve an error.")
290
-}
routing/dht/handlers.go
deleted
-288
@@ -1,288 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "errors"
5
- "fmt"
6
- "time"
7
-
8
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
9
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
10
-
11
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
12
- lgbl "gx/ipfs/QmYrv4LgCC8FhG2Ab4bwuq5DqBdwMtx3hMb3KKJDZcr2d7/go-libp2p-loggables"
13
-
14
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
15
- proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
16
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
17
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
18
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
19
-)
20
-
21
-// The number of closer peers to send on requests.
22
-var CloserPeerCount = KValue
23
-
24
-// dhthandler specifies the signature of functions that handle DHT messages.
25
-type dhtHandler func(context.Context, peer.ID, *pb.Message) (*pb.Message, error)
26
-
27
-func (dht *IpfsDHT) handlerForMsgType(t pb.Message_MessageType) dhtHandler {
28
- switch t {
29
- case pb.Message_GET_VALUE:
30
- return dht.handleGetValue
31
- case pb.Message_PUT_VALUE:
32
- return dht.handlePutValue
33
- case pb.Message_FIND_NODE:
34
- return dht.handleFindPeer
35
- case pb.Message_ADD_PROVIDER:
36
- return dht.handleAddProvider
37
- case pb.Message_GET_PROVIDERS:
38
- return dht.handleGetProviders
39
- case pb.Message_PING:
40
- return dht.handlePing
41
- default:
42
- return nil
43
- }
44
-}
45
-
46
-func (dht *IpfsDHT) handleGetValue(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
47
- defer log.EventBegin(ctx, "handleGetValue", p).Done()
48
- log.Debugf("%s handleGetValue for key: %s", dht.self, pmes.GetKey())
49
-
50
- // setup response
51
- resp := pb.NewMessage(pmes.GetType(), pmes.GetKey(), pmes.GetClusterLevel())
52
-
53
- // first, is there even a key?
54
- k := key.Key(pmes.GetKey())
55
- if k == "" {
56
- return nil, errors.New("handleGetValue but no key was provided")
57
- // TODO: send back an error response? could be bad, but the other node's hanging.
58
- }
59
-
60
- rec, err := dht.checkLocalDatastore(k)
61
- if err != nil {
62
- return nil, err
63
- }
64
- resp.Record = rec
65
-
66
- // Find closest peer on given cluster to desired key and reply with that info
67
- closer := dht.betterPeersToQuery(pmes, p, CloserPeerCount)
68
- if len(closer) > 0 {
69
- closerinfos := pstore.PeerInfos(dht.peerstore, closer)
70
- for _, pi := range closerinfos {
71
- log.Debugf("handleGetValue returning closer peer: '%s'", pi.ID)
72
- if len(pi.Addrs) < 1 {
73
- log.Errorf(`no addresses on peer being sent!
74
- [local:%s]
75
- [sending:%s]
76
- [remote:%s]`, dht.self, pi.ID, p)
77
- }
78
- }
79
-
80
- resp.CloserPeers = pb.PeerInfosToPBPeers(dht.host.Network(), closerinfos)
81
- }
82
-
83
- return resp, nil
84
-}
85
-
86
-func (dht *IpfsDHT) checkLocalDatastore(k key.Key) (*pb.Record, error) {
87
- log.Debugf("%s handleGetValue looking into ds", dht.self)
88
- dskey := k.DsKey()
89
- iVal, err := dht.datastore.Get(dskey)
90
- log.Debugf("%s handleGetValue looking into ds GOT %v", dht.self, iVal)
91
-
92
- if err == ds.ErrNotFound {
93
- return nil, nil
94
- }
95
-
96
- // if we got an unexpected error, bail.
97
- if err != nil {
98
- return nil, err
99
- }
100
-
101
- // if we have the value, send it back
102
- log.Debugf("%s handleGetValue success!", dht.self)
103
-
104
- byts, ok := iVal.([]byte)
105
- if !ok {
106
- return nil, fmt.Errorf("datastore had non byte-slice value for %v", dskey)
107
- }
108
-
109
- rec := new(pb.Record)
110
- err = proto.Unmarshal(byts, rec)
111
- if err != nil {
112
- log.Debug("failed to unmarshal DHT record from datastore")
113
- return nil, err
114
- }
115
-
116
- // if its our record, dont bother checking the times on it
117
- if peer.ID(rec.GetAuthor()) == dht.self {
118
- return rec, nil
119
- }
120
-
121
- var recordIsBad bool
122
- recvtime, err := u.ParseRFC3339(rec.GetTimeReceived())
123
- if err != nil {
124
- log.Info("either no receive time set on record, or it was invalid: ", err)
125
- recordIsBad = true
126
- }
127
-
128
- if time.Now().Sub(recvtime) > MaxRecordAge {
129
- log.Debug("old record found, tossing.")
130
- recordIsBad = true
131
- }
132
-
133
- // NOTE: We do not verify the record here beyond checking these timestamps.
134
- // we put the burden of checking the records on the requester as checking a record
135
- // may be computationally expensive
136
-
137
- if recordIsBad {
138
- err := dht.datastore.Delete(dskey)
139
- if err != nil {
140
- log.Error("Failed to delete bad record from datastore: ", err)
141
- }
142
-
143
- return nil, nil // can treat this as not having the record at all
144
- }
145
-
146
- return rec, nil
147
-}
148
-
149
-// Store a value in this peer local storage
150
-func (dht *IpfsDHT) handlePutValue(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
151
- defer log.EventBegin(ctx, "handlePutValue", p).Done()
152
- dskey := key.Key(pmes.GetKey()).DsKey()
153
-
154
- if err := dht.verifyRecordLocally(pmes.GetRecord()); err != nil {
155
- log.Warningf("Bad dht record in PUT from: %s. %s", key.Key(pmes.GetRecord().GetAuthor()), err)
156
- return nil, err
157
- }
158
-
159
- rec := pmes.GetRecord()
160
-
161
- // record the time we receive every record
162
- rec.TimeReceived = proto.String(u.FormatRFC3339(time.Now()))
163
-
164
- data, err := proto.Marshal(rec)
165
- if err != nil {
166
- return nil, err
167
- }
168
-
169
- err = dht.datastore.Put(dskey, data)
170
- log.Debugf("%s handlePutValue %v", dht.self, dskey)
171
- return pmes, err
172
-}
173
-
174
-func (dht *IpfsDHT) handlePing(_ context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
175
- log.Debugf("%s Responding to ping from %s!\n", dht.self, p)
176
- return pmes, nil
177
-}
178
-
179
-func (dht *IpfsDHT) handleFindPeer(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
180
- defer log.EventBegin(ctx, "handleFindPeer", p).Done()
181
- resp := pb.NewMessage(pmes.GetType(), "", pmes.GetClusterLevel())
182
- var closest []peer.ID
183
-
184
- // if looking for self... special case where we send it on CloserPeers.
185
- if peer.ID(pmes.GetKey()) == dht.self {
186
- closest = []peer.ID{dht.self}
187
- } else {
188
- closest = dht.betterPeersToQuery(pmes, p, CloserPeerCount)
189
- }
190
-
191
- if closest == nil {
192
- log.Infof("%s handleFindPeer %s: could not find anything.", dht.self, p)
193
- return resp, nil
194
- }
195
-
196
- var withAddresses []pstore.PeerInfo
197
- closestinfos := pstore.PeerInfos(dht.peerstore, closest)
198
- for _, pi := range closestinfos {
199
- if len(pi.Addrs) > 0 {
200
- withAddresses = append(withAddresses, pi)
201
- log.Debugf("handleFindPeer: sending back '%s'", pi.ID)
202
- }
203
- }
204
-
205
- resp.CloserPeers = pb.PeerInfosToPBPeers(dht.host.Network(), withAddresses)
206
- return resp, nil
207
-}
208
-
209
-func (dht *IpfsDHT) handleGetProviders(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
210
- lm := make(lgbl.DeferredMap)
211
- lm["peer"] = func() interface{} { return p.Pretty() }
212
- defer log.EventBegin(ctx, "handleGetProviders", lm).Done()
213
-
214
- resp := pb.NewMessage(pmes.GetType(), pmes.GetKey(), pmes.GetClusterLevel())
215
- key := key.Key(pmes.GetKey())
216
- lm["key"] = func() interface{} { return key.B58String() }
217
-
218
- // debug logging niceness.
219
- reqDesc := fmt.Sprintf("%s handleGetProviders(%s, %s): ", dht.self, p, key)
220
- log.Debugf("%s begin", reqDesc)
221
- defer log.Debugf("%s end", reqDesc)
222
-
223
- // check if we have this value, to add ourselves as provider.
224
- has, err := dht.datastore.Has(key.DsKey())
225
- if err != nil && err != ds.ErrNotFound {
226
- log.Debugf("unexpected datastore error: %v\n", err)
227
- has = false
228
- }
229
-
230
- // setup providers
231
- providers := dht.providers.GetProviders(ctx, key)
232
- if has {
233
- providers = append(providers, dht.self)
234
- log.Debugf("%s have the value. added self as provider", reqDesc)
235
- }
236
-
237
- if providers != nil && len(providers) > 0 {
238
- infos := pstore.PeerInfos(dht.peerstore, providers)
239
- resp.ProviderPeers = pb.PeerInfosToPBPeers(dht.host.Network(), infos)
240
- log.Debugf("%s have %d providers: %s", reqDesc, len(providers), infos)
241
- }
242
-
243
- // Also send closer peers.
244
- closer := dht.betterPeersToQuery(pmes, p, CloserPeerCount)
245
- if closer != nil {
246
- infos := pstore.PeerInfos(dht.peerstore, closer)
247
- resp.CloserPeers = pb.PeerInfosToPBPeers(dht.host.Network(), infos)
248
- log.Debugf("%s have %d closer peers: %s", reqDesc, len(closer), infos)
249
- }
250
-
251
- return resp, nil
252
-}
253
-
254
-func (dht *IpfsDHT) handleAddProvider(ctx context.Context, p peer.ID, pmes *pb.Message) (*pb.Message, error) {
255
- lm := make(lgbl.DeferredMap)
256
- lm["peer"] = func() interface{} { return p.Pretty() }
257
-
258
- defer log.EventBegin(ctx, "handleAddProvider", lm).Done()
259
- key := key.Key(pmes.GetKey())
260
- lm["key"] = func() interface{} { return key.B58String() }
261
-
262
- log.Debugf("%s adding %s as a provider for '%s'\n", dht.self, p, key)
263
-
264
- // add provider should use the address given in the message
265
- pinfos := pb.PBPeersToPeerInfos(pmes.GetProviderPeers())
266
- for _, pi := range pinfos {
267
- if pi.ID != p {
268
- // we should ignore this provider reccord! not from originator.
269
- // (we chould sign them and check signature later...)
270
- log.Debugf("handleAddProvider received provider %s from %s. Ignore.", pi.ID, p)
271
- continue
272
- }
273
-
274
- if len(pi.Addrs) < 1 {
275
- log.Debugf("%s got no valid addresses for provider %s. Ignore.", dht.self, p)
276
- continue
277
- }
278
-
279
- log.Infof("received provider %s for %s (addrs: %s)", p, key, pi.Addrs)
280
- if pi.ID != dht.self { // dont add own addrs.
281
- // add the received addresses to our peerstore.
282
- dht.peerstore.AddAddrs(pi.ID, pi.Addrs, pstore.ProviderAddrTTL)
283
- }
284
- dht.providers.AddProvider(ctx, key, p)
285
- }
286
-
287
- return nil, nil
288
-}
routing/dht/lookup.go
deleted
-112
@@ -1,112 +0,0 @@
1
-package dht
2
-
3
-import (
4
- pset "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer/peerset"
5
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
6
-
7
- notif "github.com/ipfs/go-ipfs/notifications"
8
- kb "github.com/ipfs/go-ipfs/routing/kbucket"
9
-
10
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
11
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
12
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
13
-)
14
-
15
-// Required in order for proper JSON marshaling
16
-func pointerizePeerInfos(pis []pstore.PeerInfo) []*pstore.PeerInfo {
17
- out := make([]*pstore.PeerInfo, len(pis))
18
- for i, p := range pis {
19
- np := p
20
- out[i] = &np
21
- }
22
- return out
23
-}
24
-
25
-// Kademlia 'node lookup' operation. Returns a channel of the K closest peers
26
-// to the given key
27
-func (dht *IpfsDHT) GetClosestPeers(ctx context.Context, key key.Key) (<-chan peer.ID, error) {
28
- e := log.EventBegin(ctx, "getClosestPeers", &key)
29
- tablepeers := dht.routingTable.NearestPeers(kb.ConvertKey(key), KValue)
30
- if len(tablepeers) == 0 {
31
- return nil, kb.ErrLookupFailure
32
- }
33
-
34
- out := make(chan peer.ID, KValue)
35
- peerset := pset.NewLimited(KValue)
36
-
37
- for _, p := range tablepeers {
38
- select {
39
- case out <- p:
40
- case <-ctx.Done():
41
- return nil, ctx.Err()
42
- }
43
- peerset.Add(p)
44
- }
45
-
46
- // since the query doesnt actually pass our context down
47
- // we have to hack this here. whyrusleeping isnt a huge fan of goprocess
48
- parent := ctx
49
- query := dht.newQuery(key, func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
50
- // For DHT query command
51
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
52
- Type: notif.SendingQuery,
53
- ID: p,
54
- })
55
-
56
- closer, err := dht.closerPeersSingle(ctx, key, p)
57
- if err != nil {
58
- log.Debugf("error getting closer peers: %s", err)
59
- return nil, err
60
- }
61
-
62
- var filtered []pstore.PeerInfo
63
- for _, clp := range closer {
64
- if kb.Closer(clp, dht.self, key) && peerset.TryAdd(clp) {
65
- select {
66
- case out <- clp:
67
- case <-ctx.Done():
68
- return nil, ctx.Err()
69
- }
70
- filtered = append(filtered, dht.peerstore.PeerInfo(clp))
71
- }
72
- }
73
-
74
- // For DHT query command
75
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
76
- Type: notif.PeerResponse,
77
- ID: p,
78
- Responses: pointerizePeerInfos(filtered),
79
- })
80
-
81
- return &dhtQueryResult{closerPeers: filtered}, nil
82
- })
83
-
84
- go func() {
85
- defer close(out)
86
- defer e.Done()
87
- // run it!
88
- _, err := query.Run(ctx, tablepeers)
89
- if err != nil {
90
- log.Debugf("closestPeers query run error: %s", err)
91
- }
92
- }()
93
-
94
- return out, nil
95
-}
96
-
97
-func (dht *IpfsDHT) closerPeersSingle(ctx context.Context, key key.Key, p peer.ID) ([]peer.ID, error) {
98
- pmes, err := dht.findPeerSingle(ctx, p, peer.ID(key))
99
- if err != nil {
100
- return nil, err
101
- }
102
-
103
- var out []peer.ID
104
- for _, pbp := range pmes.GetCloserPeers() {
105
- pid := peer.ID(pbp.GetId())
106
- if pid != dht.self { // dont add self
107
- dht.peerstore.AddAddrs(pid, pbp.Addresses(), pstore.TempAddrTTL)
108
- out = append(out, pid)
109
- }
110
- }
111
- return out, nil
112
-}
routing/dht/notif.go
deleted
-39
@@ -1,39 +0,0 @@
1
-package dht
2
-
3
-import (
4
- ma "gx/ipfs/QmYzDkkgAEmrcNzFCiYo6L1dTX4EAG1gZkbtdbd9trL4vd/go-multiaddr"
5
-
6
- inet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net"
7
-)
8
-
9
-// netNotifiee defines methods to be used with the IpfsDHT
10
-type netNotifiee IpfsDHT
11
-
12
-func (nn *netNotifiee) DHT() *IpfsDHT {
13
- return (*IpfsDHT)(nn)
14
-}
15
-
16
-func (nn *netNotifiee) Connected(n inet.Network, v inet.Conn) {
17
- dht := nn.DHT()
18
- select {
19
- case <-dht.Process().Closing():
20
- return
21
- default:
22
- }
23
- dht.Update(dht.Context(), v.RemotePeer())
24
-}
25
-
26
-func (nn *netNotifiee) Disconnected(n inet.Network, v inet.Conn) {
27
- dht := nn.DHT()
28
- select {
29
- case <-dht.Process().Closing():
30
- return
31
- default:
32
- }
33
- dht.routingTable.Remove(v.RemotePeer())
34
-}
35
-
36
-func (nn *netNotifiee) OpenedStream(n inet.Network, v inet.Stream) {}
37
-func (nn *netNotifiee) ClosedStream(n inet.Network, v inet.Stream) {}
38
-func (nn *netNotifiee) Listen(n inet.Network, a ma.Multiaddr) {}
39
-func (nn *netNotifiee) ListenClose(n inet.Network, a ma.Multiaddr) {}
routing/dht/pb/Makefile
deleted
-11
@@ -1,11 +0,0 @@
1
-PB = $(wildcard *.proto)
2
-GO = $(PB:.proto=.pb.go)
3
-
4
-all: $(GO)
5
-
6
-%.pb.go: %.proto
7
- protoc --gogo_out=. --proto_path=../../../../../../:/usr/local/opt/protobuf/include:. $<
8
-
9
-clean:
10
- rm -f *.pb.go
11
- rm -f *.go
routing/dht/pb/dht.pb.go
deleted
-272
@@ -1,272 +0,0 @@
1
-// Code generated by protoc-gen-gogo.
2
-// source: dht.proto
3
-// DO NOT EDIT!
4
-
5
-/*
6
-Package dht_pb is a generated protocol buffer package.
7
-
8
-It is generated from these files:
9
- dht.proto
10
-
11
-It has these top-level messages:
12
- Message
13
- Record
14
-*/
15
-package dht_pb
16
-
17
-import proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
18
-import math "math"
19
-
20
-// Reference imports to suppress errors if they are not otherwise used.
21
-var _ = proto.Marshal
22
-var _ = math.Inf
23
-
24
-type Message_MessageType int32
25
-
26
-const (
27
- Message_PUT_VALUE Message_MessageType = 0
28
- Message_GET_VALUE Message_MessageType = 1
29
- Message_ADD_PROVIDER Message_MessageType = 2
30
- Message_GET_PROVIDERS Message_MessageType = 3
31
- Message_FIND_NODE Message_MessageType = 4
32
- Message_PING Message_MessageType = 5
33
-)
34
-
35
-var Message_MessageType_name = map[int32]string{
36
- 0: "PUT_VALUE",
37
- 1: "GET_VALUE",
38
- 2: "ADD_PROVIDER",
39
- 3: "GET_PROVIDERS",
40
- 4: "FIND_NODE",
41
- 5: "PING",
42
-}
43
-var Message_MessageType_value = map[string]int32{
44
- "PUT_VALUE": 0,
45
- "GET_VALUE": 1,
46
- "ADD_PROVIDER": 2,
47
- "GET_PROVIDERS": 3,
48
- "FIND_NODE": 4,
49
- "PING": 5,
50
-}
51
-
52
-func (x Message_MessageType) Enum() *Message_MessageType {
53
- p := new(Message_MessageType)
54
- *p = x
55
- return p
56
-}
57
-func (x Message_MessageType) String() string {
58
- return proto.EnumName(Message_MessageType_name, int32(x))
59
-}
60
-func (x *Message_MessageType) UnmarshalJSON(data []byte) error {
61
- value, err := proto.UnmarshalJSONEnum(Message_MessageType_value, data, "Message_MessageType")
62
- if err != nil {
63
- return err
64
- }
65
- *x = Message_MessageType(value)
66
- return nil
67
-}
68
-
69
-type Message_ConnectionType int32
70
-
71
-const (
72
- // sender does not have a connection to peer, and no extra information (default)
73
- Message_NOT_CONNECTED Message_ConnectionType = 0
74
- // sender has a live connection to peer
75
- Message_CONNECTED Message_ConnectionType = 1
76
- // sender recently connected to peer
77
- Message_CAN_CONNECT Message_ConnectionType = 2
78
- // sender recently tried to connect to peer repeatedly but failed to connect
79
- // ("try" here is loose, but this should signal "made strong effort, failed")
80
- Message_CANNOT_CONNECT Message_ConnectionType = 3
81
-)
82
-
83
-var Message_ConnectionType_name = map[int32]string{
84
- 0: "NOT_CONNECTED",
85
- 1: "CONNECTED",
86
- 2: "CAN_CONNECT",
87
- 3: "CANNOT_CONNECT",
88
-}
89
-var Message_ConnectionType_value = map[string]int32{
90
- "NOT_CONNECTED": 0,
91
- "CONNECTED": 1,
92
- "CAN_CONNECT": 2,
93
- "CANNOT_CONNECT": 3,
94
-}
95
-
96
-func (x Message_ConnectionType) Enum() *Message_ConnectionType {
97
- p := new(Message_ConnectionType)
98
- *p = x
99
- return p
100
-}
101
-func (x Message_ConnectionType) String() string {
102
- return proto.EnumName(Message_ConnectionType_name, int32(x))
103
-}
104
-func (x *Message_ConnectionType) UnmarshalJSON(data []byte) error {
105
- value, err := proto.UnmarshalJSONEnum(Message_ConnectionType_value, data, "Message_ConnectionType")
106
- if err != nil {
107
- return err
108
- }
109
- *x = Message_ConnectionType(value)
110
- return nil
111
-}
112
-
113
-type Message struct {
114
- // defines what type of message it is.
115
- Type *Message_MessageType `protobuf:"varint,1,opt,name=type,enum=dht.pb.Message_MessageType" json:"type,omitempty"`
116
- // defines what coral cluster level this query/response belongs to.
117
- ClusterLevelRaw *int32 `protobuf:"varint,10,opt,name=clusterLevelRaw" json:"clusterLevelRaw,omitempty"`
118
- // Used to specify the key associated with this message.
119
- // PUT_VALUE, GET_VALUE, ADD_PROVIDER, GET_PROVIDERS
120
- Key *string `protobuf:"bytes,2,opt,name=key" json:"key,omitempty"`
121
- // Used to return a value
122
- // PUT_VALUE, GET_VALUE
123
- Record *Record `protobuf:"bytes,3,opt,name=record" json:"record,omitempty"`
124
- // Used to return peers closer to a key in a query
125
- // GET_VALUE, GET_PROVIDERS, FIND_NODE
126
- CloserPeers []*Message_Peer `protobuf:"bytes,8,rep,name=closerPeers" json:"closerPeers,omitempty"`
127
- // Used to return Providers
128
- // GET_VALUE, ADD_PROVIDER, GET_PROVIDERS
129
- ProviderPeers []*Message_Peer `protobuf:"bytes,9,rep,name=providerPeers" json:"providerPeers,omitempty"`
130
- XXX_unrecognized []byte `json:"-"`
131
-}
132
-
133
-func (m *Message) Reset() { *m = Message{} }
134
-func (m *Message) String() string { return proto.CompactTextString(m) }
135
-func (*Message) ProtoMessage() {}
136
-
137
-func (m *Message) GetType() Message_MessageType {
138
- if m != nil && m.Type != nil {
139
- return *m.Type
140
- }
141
- return Message_PUT_VALUE
142
-}
143
-
144
-func (m *Message) GetClusterLevelRaw() int32 {
145
- if m != nil && m.ClusterLevelRaw != nil {
146
- return *m.ClusterLevelRaw
147
- }
148
- return 0
149
-}
150
-
151
-func (m *Message) GetKey() string {
152
- if m != nil && m.Key != nil {
153
- return *m.Key
154
- }
155
- return ""
156
-}
157
-
158
-func (m *Message) GetRecord() *Record {
159
- if m != nil {
160
- return m.Record
161
- }
162
- return nil
163
-}
164
-
165
-func (m *Message) GetCloserPeers() []*Message_Peer {
166
- if m != nil {
167
- return m.CloserPeers
168
- }
169
- return nil
170
-}
171
-
172
-func (m *Message) GetProviderPeers() []*Message_Peer {
173
- if m != nil {
174
- return m.ProviderPeers
175
- }
176
- return nil
177
-}
178
-
179
-type Message_Peer struct {
180
- // ID of a given peer.
181
- Id *string `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
182
- // multiaddrs for a given peer
183
- Addrs [][]byte `protobuf:"bytes,2,rep,name=addrs" json:"addrs,omitempty"`
184
- // used to signal the sender's connection capabilities to the peer
185
- Connection *Message_ConnectionType `protobuf:"varint,3,opt,name=connection,enum=dht.pb.Message_ConnectionType" json:"connection,omitempty"`
186
- XXX_unrecognized []byte `json:"-"`
187
-}
188
-
189
-func (m *Message_Peer) Reset() { *m = Message_Peer{} }
190
-func (m *Message_Peer) String() string { return proto.CompactTextString(m) }
191
-func (*Message_Peer) ProtoMessage() {}
192
-
193
-func (m *Message_Peer) GetId() string {
194
- if m != nil && m.Id != nil {
195
- return *m.Id
196
- }
197
- return ""
198
-}
199
-
200
-func (m *Message_Peer) GetAddrs() [][]byte {
201
- if m != nil {
202
- return m.Addrs
203
- }
204
- return nil
205
-}
206
-
207
-func (m *Message_Peer) GetConnection() Message_ConnectionType {
208
- if m != nil && m.Connection != nil {
209
- return *m.Connection
210
- }
211
- return Message_NOT_CONNECTED
212
-}
213
-
214
-// Record represents a dht record that contains a value
215
-// for a key value pair
216
-type Record struct {
217
- // The key that references this record
218
- Key *string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"`
219
- // The actual value this record is storing
220
- Value []byte `protobuf:"bytes,2,opt,name=value" json:"value,omitempty"`
221
- // hash of the authors public key
222
- Author *string `protobuf:"bytes,3,opt,name=author" json:"author,omitempty"`
223
- // A PKI signature for the key+value+author
224
- Signature []byte `protobuf:"bytes,4,opt,name=signature" json:"signature,omitempty"`
225
- // Time the record was received, set by receiver
226
- TimeReceived *string `protobuf:"bytes,5,opt,name=timeReceived" json:"timeReceived,omitempty"`
227
- XXX_unrecognized []byte `json:"-"`
228
-}
229
-
230
-func (m *Record) Reset() { *m = Record{} }
231
-func (m *Record) String() string { return proto.CompactTextString(m) }
232
-func (*Record) ProtoMessage() {}
233
-
234
-func (m *Record) GetKey() string {
235
- if m != nil && m.Key != nil {
236
- return *m.Key
237
- }
238
- return ""
239
-}
240
-
241
-func (m *Record) GetValue() []byte {
242
- if m != nil {
243
- return m.Value
244
- }
245
- return nil
246
-}
247
-
248
-func (m *Record) GetAuthor() string {
249
- if m != nil && m.Author != nil {
250
- return *m.Author
251
- }
252
- return ""
253
-}
254
-
255
-func (m *Record) GetSignature() []byte {
256
- if m != nil {
257
- return m.Signature
258
- }
259
- return nil
260
-}
261
-
262
-func (m *Record) GetTimeReceived() string {
263
- if m != nil && m.TimeReceived != nil {
264
- return *m.TimeReceived
265
- }
266
- return ""
267
-}
268
-
269
-func init() {
270
- proto.RegisterEnum("dht.pb.Message_MessageType", Message_MessageType_name, Message_MessageType_value)
271
- proto.RegisterEnum("dht.pb.Message_ConnectionType", Message_ConnectionType_name, Message_ConnectionType_value)
272
-}
routing/dht/pb/dht.proto
deleted
-81
@@ -1,81 +0,0 @@
1
-package dht.pb;
2
-
3
-//run `protoc --go_out=. *.proto` to generate
4
-
5
-message Message {
6
- enum MessageType {
7
- PUT_VALUE = 0;
8
- GET_VALUE = 1;
9
- ADD_PROVIDER = 2;
10
- GET_PROVIDERS = 3;
11
- FIND_NODE = 4;
12
- PING = 5;
13
- }
14
-
15
- enum ConnectionType {
16
- // sender does not have a connection to peer, and no extra information (default)
17
- NOT_CONNECTED = 0;
18
-
19
- // sender has a live connection to peer
20
- CONNECTED = 1;
21
-
22
- // sender recently connected to peer
23
- CAN_CONNECT = 2;
24
-
25
- // sender recently tried to connect to peer repeatedly but failed to connect
26
- // ("try" here is loose, but this should signal "made strong effort, failed")
27
- CANNOT_CONNECT = 3;
28
- }
29
-
30
- message Peer {
31
- // ID of a given peer.
32
- optional string id = 1;
33
-
34
- // multiaddrs for a given peer
35
- repeated bytes addrs = 2;
36
-
37
- // used to signal the sender's connection capabilities to the peer
38
- optional ConnectionType connection = 3;
39
- }
40
-
41
- // defines what type of message it is.
42
- optional MessageType type = 1;
43
-
44
- // defines what coral cluster level this query/response belongs to.
45
- optional int32 clusterLevelRaw = 10;
46
-
47
- // Used to specify the key associated with this message.
48
- // PUT_VALUE, GET_VALUE, ADD_PROVIDER, GET_PROVIDERS
49
- optional string key = 2;
50
-
51
- // Used to return a value
52
- // PUT_VALUE, GET_VALUE
53
- optional Record record = 3;
54
-
55
- // Used to return peers closer to a key in a query
56
- // GET_VALUE, GET_PROVIDERS, FIND_NODE
57
- repeated Peer closerPeers = 8;
58
-
59
- // Used to return Providers
60
- // GET_VALUE, ADD_PROVIDER, GET_PROVIDERS
61
- repeated Peer providerPeers = 9;
62
-}
63
-
64
-// Record represents a dht record that contains a value
65
-// for a key value pair
66
-message Record {
67
- // The key that references this record
68
- optional string key = 1;
69
-
70
- // The actual value this record is storing
71
- optional bytes value = 2;
72
-
73
- // hash of the authors public key
74
- optional string author = 3;
75
-
76
- // A PKI signature for the key+value+author
77
- optional bytes signature = 4;
78
-
79
- // Time the record was received, set by receiver
80
- optional string timeReceived = 5;
81
-}
routing/dht/pb/message.go
deleted
-185
@@ -1,185 +0,0 @@
1
-package dht_pb
2
-
3
-import (
4
- ma "gx/ipfs/QmYzDkkgAEmrcNzFCiYo6L1dTX4EAG1gZkbtdbd9trL4vd/go-multiaddr"
5
-
6
- logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
7
- inet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net"
8
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
9
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
10
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
11
-)
12
-
13
-var log = logging.Logger("dht.pb")
14
-
15
-type PeerRoutingInfo struct {
16
- pstore.PeerInfo
17
- inet.Connectedness
18
-}
19
-
20
-// NewMessage constructs a new dht message with given type, key, and level
21
-func NewMessage(typ Message_MessageType, key string, level int) *Message {
22
- m := &Message{
23
- Type: &typ,
24
- Key: &key,
25
- }
26
- m.SetClusterLevel(level)
27
- return m
28
-}
29
-
30
-func peerRoutingInfoToPBPeer(p PeerRoutingInfo) *Message_Peer {
31
- pbp := new(Message_Peer)
32
-
33
- pbp.Addrs = make([][]byte, len(p.Addrs))
34
- for i, maddr := range p.Addrs {
35
- pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed.
36
- }
37
- s := string(p.ID)
38
- pbp.Id = &s
39
- c := ConnectionType(p.Connectedness)
40
- pbp.Connection = &c
41
- return pbp
42
-}
43
-
44
-func peerInfoToPBPeer(p pstore.PeerInfo) *Message_Peer {
45
- pbp := new(Message_Peer)
46
-
47
- pbp.Addrs = make([][]byte, len(p.Addrs))
48
- for i, maddr := range p.Addrs {
49
- pbp.Addrs[i] = maddr.Bytes() // Bytes, not String. Compressed.
50
- }
51
- s := string(p.ID)
52
- pbp.Id = &s
53
- return pbp
54
-}
55
-
56
-// PBPeerToPeer turns a *Message_Peer into its pstore.PeerInfo counterpart
57
-func PBPeerToPeerInfo(pbp *Message_Peer) pstore.PeerInfo {
58
- return pstore.PeerInfo{
59
- ID: peer.ID(pbp.GetId()),
60
- Addrs: pbp.Addresses(),
61
- }
62
-}
63
-
64
-// RawPeerInfosToPBPeers converts a slice of Peers into a slice of *Message_Peers,
65
-// ready to go out on the wire.
66
-func RawPeerInfosToPBPeers(peers []pstore.PeerInfo) []*Message_Peer {
67
- pbpeers := make([]*Message_Peer, len(peers))
68
- for i, p := range peers {
69
- pbpeers[i] = peerInfoToPBPeer(p)
70
- }
71
- return pbpeers
72
-}
73
-
74
-// PeersToPBPeers converts given []peer.Peer into a set of []*Message_Peer,
75
-// which can be written to a message and sent out. the key thing this function
76
-// does (in addition to PeersToPBPeers) is set the ConnectionType with
77
-// information from the given inet.Network.
78
-func PeerInfosToPBPeers(n inet.Network, peers []pstore.PeerInfo) []*Message_Peer {
79
- pbps := RawPeerInfosToPBPeers(peers)
80
- for i, pbp := range pbps {
81
- c := ConnectionType(n.Connectedness(peers[i].ID))
82
- pbp.Connection = &c
83
- }
84
- return pbps
85
-}
86
-
87
-func PeerRoutingInfosToPBPeers(peers []PeerRoutingInfo) []*Message_Peer {
88
- pbpeers := make([]*Message_Peer, len(peers))
89
- for i, p := range peers {
90
- pbpeers[i] = peerRoutingInfoToPBPeer(p)
91
- }
92
- return pbpeers
93
-}
94
-
95
-// PBPeersToPeerInfos converts given []*Message_Peer into []pstore.PeerInfo
96
-// Invalid addresses will be silently omitted.
97
-func PBPeersToPeerInfos(pbps []*Message_Peer) []pstore.PeerInfo {
98
- peers := make([]pstore.PeerInfo, 0, len(pbps))
99
- for _, pbp := range pbps {
100
- peers = append(peers, PBPeerToPeerInfo(pbp))
101
- }
102
- return peers
103
-}
104
-
105
-// Addresses returns a multiaddr associated with the Message_Peer entry
106
-func (m *Message_Peer) Addresses() []ma.Multiaddr {
107
- if m == nil {
108
- return nil
109
- }
110
-
111
- maddrs := make([]ma.Multiaddr, 0, len(m.Addrs))
112
- for _, addr := range m.Addrs {
113
- maddr, err := ma.NewMultiaddrBytes(addr)
114
- if err != nil {
115
- log.Warningf("error decoding Multiaddr for peer: %s", m.GetId())
116
- continue
117
- }
118
-
119
- maddrs = append(maddrs, maddr)
120
- }
121
- return maddrs
122
-}
123
-
124
-// GetClusterLevel gets and adjusts the cluster level on the message.
125
-// a +/- 1 adjustment is needed to distinguish a valid first level (1) and
126
-// default "no value" protobuf behavior (0)
127
-func (m *Message) GetClusterLevel() int {
128
- level := m.GetClusterLevelRaw() - 1
129
- if level < 0 {
130
- return 0
131
- }
132
- return int(level)
133
-}
134
-
135
-// SetClusterLevel adjusts and sets the cluster level on the message.
136
-// a +/- 1 adjustment is needed to distinguish a valid first level (1) and
137
-// default "no value" protobuf behavior (0)
138
-func (m *Message) SetClusterLevel(level int) {
139
- lvl := int32(level)
140
- m.ClusterLevelRaw = &lvl
141
-}
142
-
143
-// Loggable turns a Message into machine-readable log output
144
-func (m *Message) Loggable() map[string]interface{} {
145
- return map[string]interface{}{
146
- "message": map[string]string{
147
- "type": m.Type.String(),
148
- "key": key.Key(m.GetKey()).B58String(),
149
- },
150
- }
151
-}
152
-
153
-// ConnectionType returns a Message_ConnectionType associated with the
154
-// inet.Connectedness.
155
-func ConnectionType(c inet.Connectedness) Message_ConnectionType {
156
- switch c {
157
- default:
158
- return Message_NOT_CONNECTED
159
- case inet.NotConnected:
160
- return Message_NOT_CONNECTED
161
- case inet.Connected:
162
- return Message_CONNECTED
163
- case inet.CanConnect:
164
- return Message_CAN_CONNECT
165
- case inet.CannotConnect:
166
- return Message_CANNOT_CONNECT
167
- }
168
-}
169
-
170
-// Connectedness returns an inet.Connectedness associated with the
171
-// Message_ConnectionType.
172
-func Connectedness(c Message_ConnectionType) inet.Connectedness {
173
- switch c {
174
- default:
175
- return inet.NotConnected
176
- case Message_NOT_CONNECTED:
177
- return inet.NotConnected
178
- case Message_CONNECTED:
179
- return inet.Connected
180
- case Message_CAN_CONNECT:
181
- return inet.CanConnect
182
- case Message_CANNOT_CONNECT:
183
- return inet.CannotConnect
184
- }
185
-}
routing/dht/pb/message_test.go
deleted
-15
@@ -1,15 +0,0 @@
1
-package dht_pb
2
-
3
-import (
4
- "testing"
5
-)
6
-
7
-func TestBadAddrsDontReturnNil(t *testing.T) {
8
- mp := new(Message_Peer)
9
- mp.Addrs = [][]byte{[]byte("NOT A VALID MULTIADDR")}
10
-
11
- addrs := mp.Addresses()
12
- if len(addrs) > 0 {
13
- t.Fatal("shouldnt have any multiaddrs")
14
- }
15
-}
routing/dht/providers/providers.go
deleted
-353
@@ -1,353 +0,0 @@
1
-package providers
2
-
3
-import (
4
- "encoding/binary"
5
- "fmt"
6
- "strings"
7
- "time"
8
-
9
- goprocess "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
10
- goprocessctx "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context"
11
- autobatch "gx/ipfs/QmSp3diFRRv4zR25nHU4MWNCdhT4R6cxrTPLx12MCi1TZb/autobatch"
12
- logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
13
- lru "gx/ipfs/QmVYxfoJQiZijTgPNHCHgHELvQpbsJNTg6Crmc3dQkj3yy/golang-lru"
14
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
15
- base32 "gx/ipfs/Qmb1DA2A9LS2wR4FFweB4uEDomFsdmnw1VLawLE1yQzudj/base32"
16
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
17
- dsq "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/query"
18
-
19
- flags "github.com/ipfs/go-ipfs/flags"
20
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
21
-
22
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
23
-)
24
-
25
-var batchBufferSize = 256
26
-
27
-func init() {
28
- if flags.LowMemMode {
29
- batchBufferSize = 8
30
- }
31
-}
32
-
33
-var log = logging.Logger("providers")
34
-
35
-var lruCacheSize = 256
36
-var ProvideValidity = time.Hour * 24
37
-var defaultCleanupInterval = time.Hour
38
-
39
-type ProviderManager struct {
40
- // all non channel fields are meant to be accessed only within
41
- // the run method
42
- providers *lru.Cache
43
- lpeer peer.ID
44
- dstore ds.Datastore
45
-
46
- newprovs chan *addProv
47
- getprovs chan *getProv
48
- period time.Duration
49
- proc goprocess.Process
50
-
51
- cleanupInterval time.Duration
52
-}
53
-
54
-type providerSet struct {
55
- providers []peer.ID
56
- set map[peer.ID]time.Time
57
-}
58
-
59
-type addProv struct {
60
- k key.Key
61
- val peer.ID
62
-}
63
-
64
-type getProv struct {
65
- k key.Key
66
- resp chan []peer.ID
67
-}
68
-
69
-func NewProviderManager(ctx context.Context, local peer.ID, dstore ds.Batching) *ProviderManager {
70
- pm := new(ProviderManager)
71
- pm.getprovs = make(chan *getProv)
72
- pm.newprovs = make(chan *addProv)
73
- pm.dstore = autobatch.NewAutoBatching(dstore, batchBufferSize)
74
- cache, err := lru.New(lruCacheSize)
75
- if err != nil {
76
- panic(err) //only happens if negative value is passed to lru constructor
77
- }
78
- pm.providers = cache
79
-
80
- pm.proc = goprocessctx.WithContext(ctx)
81
- pm.cleanupInterval = defaultCleanupInterval
82
- pm.proc.Go(func(p goprocess.Process) { pm.run() })
83
-
84
- return pm
85
-}
86
-
87
-const providersKeyPrefix = "/providers/"
88
-
89
-func mkProvKey(k key.Key) ds.Key {
90
- return ds.NewKey(providersKeyPrefix + base32.RawStdEncoding.EncodeToString([]byte(k)))
91
-}
92
-
93
-func (pm *ProviderManager) Process() goprocess.Process {
94
- return pm.proc
95
-}
96
-
97
-func (pm *ProviderManager) providersForKey(k key.Key) ([]peer.ID, error) {
98
- pset, err := pm.getProvSet(k)
99
- if err != nil {
100
- return nil, err
101
- }
102
- return pset.providers, nil
103
-}
104
-
105
-func (pm *ProviderManager) getProvSet(k key.Key) (*providerSet, error) {
106
- cached, ok := pm.providers.Get(k)
107
- if ok {
108
- return cached.(*providerSet), nil
109
- }
110
-
111
- pset, err := loadProvSet(pm.dstore, k)
112
- if err != nil {
113
- return nil, err
114
- }
115
-
116
- if len(pset.providers) > 0 {
117
- pm.providers.Add(k, pset)
118
- }
119
-
120
- return pset, nil
121
-}
122
-
123
-func loadProvSet(dstore ds.Datastore, k key.Key) (*providerSet, error) {
124
- res, err := dstore.Query(dsq.Query{Prefix: mkProvKey(k).String()})
125
- if err != nil {
126
- return nil, err
127
- }
128
-
129
- out := newProviderSet()
130
- for e := range res.Next() {
131
- if e.Error != nil {
132
- log.Error("got an error: ", e.Error)
133
- continue
134
- }
135
- parts := strings.Split(e.Key, "/")
136
- if len(parts) != 4 {
137
- log.Warning("incorrectly formatted key: ", e.Key)
138
- continue
139
- }
140
-
141
- decstr, err := base32.RawStdEncoding.DecodeString(parts[len(parts)-1])
142
- if err != nil {
143
- log.Error("base32 decoding error: ", err)
144
- continue
145
- }
146
-
147
- pid := peer.ID(decstr)
148
-
149
- t, err := readTimeValue(e.Value)
150
- if err != nil {
151
- log.Warning("parsing providers record from disk: ", err)
152
- continue
153
- }
154
-
155
- out.setVal(pid, t)
156
- }
157
-
158
- return out, nil
159
-}
160
-
161
-func readTimeValue(i interface{}) (time.Time, error) {
162
- data, ok := i.([]byte)
163
- if !ok {
164
- return time.Time{}, fmt.Errorf("data was not a []byte")
165
- }
166
-
167
- nsec, _ := binary.Varint(data)
168
-
169
- return time.Unix(0, nsec), nil
170
-}
171
-
172
-func (pm *ProviderManager) addProv(k key.Key, p peer.ID) error {
173
- iprovs, ok := pm.providers.Get(k)
174
- if !ok {
175
- iprovs = newProviderSet()
176
- pm.providers.Add(k, iprovs)
177
- }
178
- provs := iprovs.(*providerSet)
179
- now := time.Now()
180
- provs.setVal(p, now)
181
-
182
- return writeProviderEntry(pm.dstore, k, p, now)
183
-}
184
-
185
-func writeProviderEntry(dstore ds.Datastore, k key.Key, p peer.ID, t time.Time) error {
186
- dsk := mkProvKey(k).ChildString(base32.RawStdEncoding.EncodeToString([]byte(p)))
187
-
188
- buf := make([]byte, 16)
189
- n := binary.PutVarint(buf, t.UnixNano())
190
-
191
- return dstore.Put(dsk, buf[:n])
192
-}
193
-
194
-func (pm *ProviderManager) deleteProvSet(k key.Key) error {
195
- pm.providers.Remove(k)
196
-
197
- res, err := pm.dstore.Query(dsq.Query{
198
- KeysOnly: true,
199
- Prefix: mkProvKey(k).String(),
200
- })
201
-
202
- entries, err := res.Rest()
203
- if err != nil {
204
- return err
205
- }
206
-
207
- for _, e := range entries {
208
- err := pm.dstore.Delete(ds.NewKey(e.Key))
209
- if err != nil {
210
- log.Error("deleting provider set: ", err)
211
- }
212
- }
213
- return nil
214
-}
215
-
216
-func (pm *ProviderManager) getAllProvKeys() ([]key.Key, error) {
217
- res, err := pm.dstore.Query(dsq.Query{
218
- KeysOnly: true,
219
- Prefix: providersKeyPrefix,
220
- })
221
-
222
- if err != nil {
223
- return nil, err
224
- }
225
-
226
- entries, err := res.Rest()
227
- if err != nil {
228
- return nil, err
229
- }
230
-
231
- out := make([]key.Key, 0, len(entries))
232
- seen := make(map[key.Key]struct{})
233
- for _, e := range entries {
234
- parts := strings.Split(e.Key, "/")
235
- if len(parts) != 4 {
236
- log.Warning("incorrectly formatted provider entry in datastore")
237
- continue
238
- }
239
- decoded, err := base32.RawStdEncoding.DecodeString(parts[2])
240
- if err != nil {
241
- log.Warning("error decoding base32 provider key")
242
- continue
243
- }
244
-
245
- k := key.Key(decoded)
246
- if _, ok := seen[k]; !ok {
247
- out = append(out, key.Key(decoded))
248
- seen[k] = struct{}{}
249
- }
250
- }
251
-
252
- return out, nil
253
-}
254
-
255
-func (pm *ProviderManager) run() {
256
- tick := time.NewTicker(pm.cleanupInterval)
257
- for {
258
- select {
259
- case np := <-pm.newprovs:
260
- err := pm.addProv(np.k, np.val)
261
- if err != nil {
262
- log.Error("error adding new providers: ", err)
263
- }
264
- case gp := <-pm.getprovs:
265
- provs, err := pm.providersForKey(gp.k)
266
- if err != nil && err != ds.ErrNotFound {
267
- log.Error("error reading providers: ", err)
268
- }
269
-
270
- gp.resp <- provs
271
- case <-tick.C:
272
- keys, err := pm.getAllProvKeys()
273
- if err != nil {
274
- log.Error("Error loading provider keys: ", err)
275
- continue
276
- }
277
- for _, k := range keys {
278
- provs, err := pm.getProvSet(k)
279
- if err != nil {
280
- log.Error("error loading known provset: ", err)
281
- continue
282
- }
283
- var filtered []peer.ID
284
- for p, t := range provs.set {
285
- if time.Now().Sub(t) > ProvideValidity {
286
- delete(provs.set, p)
287
- } else {
288
- filtered = append(filtered, p)
289
- }
290
- }
291
-
292
- if len(filtered) > 0 {
293
- provs.providers = filtered
294
- } else {
295
- err := pm.deleteProvSet(k)
296
- if err != nil {
297
- log.Error("error deleting provider set: ", err)
298
- }
299
- }
300
- }
301
- case <-pm.proc.Closing():
302
- return
303
- }
304
- }
305
-}
306
-
307
-func (pm *ProviderManager) AddProvider(ctx context.Context, k key.Key, val peer.ID) {
308
- prov := &addProv{
309
- k: k,
310
- val: val,
311
- }
312
- select {
313
- case pm.newprovs <- prov:
314
- case <-ctx.Done():
315
- }
316
-}
317
-
318
-func (pm *ProviderManager) GetProviders(ctx context.Context, k key.Key) []peer.ID {
319
- gp := &getProv{
320
- k: k,
321
- resp: make(chan []peer.ID, 1), // buffered to prevent sender from blocking
322
- }
323
- select {
324
- case <-ctx.Done():
325
- return nil
326
- case pm.getprovs <- gp:
327
- }
328
- select {
329
- case <-ctx.Done():
330
- return nil
331
- case peers := <-gp.resp:
332
- return peers
333
- }
334
-}
335
-
336
-func newProviderSet() *providerSet {
337
- return &providerSet{
338
- set: make(map[peer.ID]time.Time),
339
- }
340
-}
341
-
342
-func (ps *providerSet) Add(p peer.ID) {
343
- ps.setVal(p, time.Now())
344
-}
345
-
346
-func (ps *providerSet) setVal(p peer.ID, t time.Time) {
347
- _, found := ps.set[p]
348
- if !found {
349
- ps.providers = append(ps.providers, p)
350
- }
351
-
352
- ps.set[p] = t
353
-}
routing/dht/providers/providers_test.go
deleted
-150
@@ -1,150 +0,0 @@
1
-package providers
2
-
3
-import (
4
- "fmt"
5
- "testing"
6
- "time"
7
-
8
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
9
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
10
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
11
-
12
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
13
-)
14
-
15
-func TestProviderManager(t *testing.T) {
16
- ctx := context.Background()
17
- mid := peer.ID("testing")
18
- p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
19
- a := key.Key("test")
20
- p.AddProvider(ctx, a, peer.ID("testingprovider"))
21
- resp := p.GetProviders(ctx, a)
22
- if len(resp) != 1 {
23
- t.Fatal("Could not retrieve provider.")
24
- }
25
- p.proc.Close()
26
-}
27
-
28
-func TestProvidersDatastore(t *testing.T) {
29
- old := lruCacheSize
30
- lruCacheSize = 10
31
- defer func() { lruCacheSize = old }()
32
-
33
- ctx := context.Background()
34
- mid := peer.ID("testing")
35
- p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
36
- defer p.proc.Close()
37
-
38
- friend := peer.ID("friend")
39
- var keys []key.Key
40
- for i := 0; i < 100; i++ {
41
- k := key.Key(fmt.Sprint(i))
42
- keys = append(keys, k)
43
- p.AddProvider(ctx, k, friend)
44
- }
45
-
46
- for _, k := range keys {
47
- resp := p.GetProviders(ctx, k)
48
- if len(resp) != 1 {
49
- t.Fatal("Could not retrieve provider.")
50
- }
51
- if resp[0] != friend {
52
- t.Fatal("expected provider to be 'friend'")
53
- }
54
- }
55
-}
56
-
57
-func TestProvidersSerialization(t *testing.T) {
58
- dstore := ds.NewMapDatastore()
59
-
60
- k := key.Key("my key!")
61
- p1 := peer.ID("peer one")
62
- p2 := peer.ID("peer two")
63
- pt1 := time.Now()
64
- pt2 := pt1.Add(time.Hour)
65
-
66
- err := writeProviderEntry(dstore, k, p1, pt1)
67
- if err != nil {
68
- t.Fatal(err)
69
- }
70
-
71
- err = writeProviderEntry(dstore, k, p2, pt2)
72
- if err != nil {
73
- t.Fatal(err)
74
- }
75
-
76
- pset, err := loadProvSet(dstore, k)
77
- if err != nil {
78
- t.Fatal(err)
79
- }
80
-
81
- lt1, ok := pset.set[p1]
82
- if !ok {
83
- t.Fatal("failed to load set correctly")
84
- }
85
-
86
- if pt1 != lt1 {
87
- t.Fatal("time wasnt serialized correctly")
88
- }
89
-
90
- lt2, ok := pset.set[p2]
91
- if !ok {
92
- t.Fatal("failed to load set correctly")
93
- }
94
-
95
- if pt2 != lt2 {
96
- t.Fatal("time wasnt serialized correctly")
97
- }
98
-}
99
-
100
-func TestProvidesExpire(t *testing.T) {
101
- pval := ProvideValidity
102
- cleanup := defaultCleanupInterval
103
- ProvideValidity = time.Second / 2
104
- defaultCleanupInterval = time.Second / 2
105
- defer func() {
106
- ProvideValidity = pval
107
- defaultCleanupInterval = cleanup
108
- }()
109
-
110
- ctx := context.Background()
111
- mid := peer.ID("testing")
112
- p := NewProviderManager(ctx, mid, ds.NewMapDatastore())
113
-
114
- peers := []peer.ID{"a", "b"}
115
- var keys []key.Key
116
- for i := 0; i < 10; i++ {
117
- k := key.Key(i)
118
- keys = append(keys, k)
119
- p.AddProvider(ctx, k, peers[0])
120
- p.AddProvider(ctx, k, peers[1])
121
- }
122
-
123
- for i := 0; i < 10; i++ {
124
- out := p.GetProviders(ctx, keys[i])
125
- if len(out) != 2 {
126
- t.Fatal("expected providers to still be there")
127
- }
128
- }
129
-
130
- time.Sleep(time.Second)
131
- for i := 0; i < 10; i++ {
132
- out := p.GetProviders(ctx, keys[i])
133
- if len(out) > 2 {
134
- t.Fatal("expected providers to be cleaned up")
135
- }
136
- }
137
-
138
- if p.providers.Len() != 0 {
139
- t.Fatal("providers map not cleaned up")
140
- }
141
-
142
- allprovs, err := p.getAllProvKeys()
143
- if err != nil {
144
- t.Fatal(err)
145
- }
146
-
147
- if len(allprovs) != 0 {
148
- t.Fatal("expected everything to be cleaned out of the datastore")
149
- }
150
-}
routing/dht/query.go
deleted
-298
@@ -1,298 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "sync"
5
-
6
- pset "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer/peerset"
7
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
8
-
9
- notif "github.com/ipfs/go-ipfs/notifications"
10
- "github.com/ipfs/go-ipfs/routing"
11
- todoctr "github.com/ipfs/go-ipfs/thirdparty/todocounter"
12
-
13
- process "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess"
14
- ctxproc "gx/ipfs/QmSF8fPo3jgVBAy8fpdjjYqgG87dkJgUprRBHRd2tmfgpP/goprocess/context"
15
- logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
16
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
17
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
18
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
19
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
20
- queue "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore/queue"
21
-)
22
-
23
-var maxQueryConcurrency = AlphaValue
24
-
25
-type dhtQuery struct {
26
- dht *IpfsDHT
27
- key key.Key // the key we're querying for
28
- qfunc queryFunc // the function to execute per peer
29
- concurrency int // the concurrency parameter
30
-}
31
-
32
-type dhtQueryResult struct {
33
- value []byte // GetValue
34
- peer pstore.PeerInfo // FindPeer
35
- providerPeers []pstore.PeerInfo // GetProviders
36
- closerPeers []pstore.PeerInfo // *
37
- success bool
38
-}
39
-
40
-// constructs query
41
-func (dht *IpfsDHT) newQuery(k key.Key, f queryFunc) *dhtQuery {
42
- return &dhtQuery{
43
- key: k,
44
- dht: dht,
45
- qfunc: f,
46
- concurrency: maxQueryConcurrency,
47
- }
48
-}
49
-
50
-// QueryFunc is a function that runs a particular query with a given peer.
51
-// It returns either:
52
-// - the value
53
-// - a list of peers potentially better able to serve the query
54
-// - an error
55
-type queryFunc func(context.Context, peer.ID) (*dhtQueryResult, error)
56
-
57
-// Run runs the query at hand. pass in a list of peers to use first.
58
-func (q *dhtQuery) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, error) {
59
- select {
60
- case <-ctx.Done():
61
- return nil, ctx.Err()
62
- default:
63
- }
64
-
65
- ctx, cancel := context.WithCancel(ctx)
66
- defer cancel()
67
-
68
- runner := newQueryRunner(q)
69
- return runner.Run(ctx, peers)
70
-}
71
-
72
-type dhtQueryRunner struct {
73
- query *dhtQuery // query to run
74
- peersSeen *pset.PeerSet // all peers queried. prevent querying same peer 2x
75
- peersToQuery *queue.ChanQueue // peers remaining to be queried
76
- peersRemaining todoctr.Counter // peersToQuery + currently processing
77
-
78
- result *dhtQueryResult // query result
79
- errs u.MultiErr // result errors. maybe should be a map[peer.ID]error
80
-
81
- rateLimit chan struct{} // processing semaphore
82
- log logging.EventLogger
83
-
84
- runCtx context.Context
85
-
86
- proc process.Process
87
- sync.RWMutex
88
-}
89
-
90
-func newQueryRunner(q *dhtQuery) *dhtQueryRunner {
91
- proc := process.WithParent(process.Background())
92
- ctx := ctxproc.OnClosingContext(proc)
93
- return &dhtQueryRunner{
94
- query: q,
95
- peersToQuery: queue.NewChanQueue(ctx, queue.NewXORDistancePQ(string(q.key))),
96
- peersRemaining: todoctr.NewSyncCounter(),
97
- peersSeen: pset.New(),
98
- rateLimit: make(chan struct{}, q.concurrency),
99
- proc: proc,
100
- }
101
-}
102
-
103
-func (r *dhtQueryRunner) Run(ctx context.Context, peers []peer.ID) (*dhtQueryResult, error) {
104
- r.log = log
105
- r.runCtx = ctx
106
-
107
- if len(peers) == 0 {
108
- log.Warning("Running query with no peers!")
109
- return nil, nil
110
- }
111
-
112
- // setup concurrency rate limiting
113
- for i := 0; i < r.query.concurrency; i++ {
114
- r.rateLimit <- struct{}{}
115
- }
116
-
117
- // add all the peers we got first.
118
- for _, p := range peers {
119
- r.addPeerToQuery(p)
120
- }
121
-
122
- // go do this thing.
123
- // do it as a child proc to make sure Run exits
124
- // ONLY AFTER spawn workers has exited.
125
- r.proc.Go(r.spawnWorkers)
126
-
127
- // so workers are working.
128
-
129
- // wait until they're done.
130
- err := routing.ErrNotFound
131
-
132
- // now, if the context finishes, close the proc.
133
- // we have to do it here because the logic before is setup, which
134
- // should run without closing the proc.
135
- ctxproc.CloseAfterContext(r.proc, ctx)
136
-
137
- select {
138
- case <-r.peersRemaining.Done():
139
- r.proc.Close()
140
- r.RLock()
141
- defer r.RUnlock()
142
-
143
- err = routing.ErrNotFound
144
-
145
- // if every query to every peer failed, something must be very wrong.
146
- if len(r.errs) > 0 && len(r.errs) == r.peersSeen.Size() {
147
- log.Debugf("query errs: %s", r.errs)
148
- err = r.errs[0]
149
- }
150
-
151
- case <-r.proc.Closed():
152
- r.RLock()
153
- defer r.RUnlock()
154
- err = context.DeadlineExceeded
155
- }
156
-
157
- if r.result != nil && r.result.success {
158
- return r.result, nil
159
- }
160
-
161
- return nil, err
162
-}
163
-
164
-func (r *dhtQueryRunner) addPeerToQuery(next peer.ID) {
165
- // if new peer is ourselves...
166
- if next == r.query.dht.self {
167
- r.log.Debug("addPeerToQuery skip self")
168
- return
169
- }
170
-
171
- if !r.peersSeen.TryAdd(next) {
172
- return
173
- }
174
-
175
- notif.PublishQueryEvent(r.runCtx, ¬if.QueryEvent{
176
- Type: notif.AddingPeer,
177
- ID: next,
178
- })
179
-
180
- r.peersRemaining.Increment(1)
181
- select {
182
- case r.peersToQuery.EnqChan <- next:
183
- case <-r.proc.Closing():
184
- }
185
-}
186
-
187
-func (r *dhtQueryRunner) spawnWorkers(proc process.Process) {
188
- for {
189
-
190
- select {
191
- case <-r.peersRemaining.Done():
192
- return
193
-
194
- case <-r.proc.Closing():
195
- return
196
-
197
- case <-r.rateLimit:
198
- select {
199
- case p, more := <-r.peersToQuery.DeqChan:
200
- if !more {
201
- return // channel closed.
202
- }
203
-
204
- // do it as a child func to make sure Run exits
205
- // ONLY AFTER spawn workers has exited.
206
- proc.Go(func(proc process.Process) {
207
- r.queryPeer(proc, p)
208
- })
209
- case <-r.proc.Closing():
210
- return
211
- case <-r.peersRemaining.Done():
212
- return
213
- }
214
- }
215
- }
216
-}
217
-
218
-func (r *dhtQueryRunner) queryPeer(proc process.Process, p peer.ID) {
219
- // ok let's do this!
220
-
221
- // create a context from our proc.
222
- ctx := ctxproc.OnClosingContext(proc)
223
-
224
- // make sure we do this when we exit
225
- defer func() {
226
- // signal we're done proccessing peer p
227
- r.peersRemaining.Decrement(1)
228
- r.rateLimit <- struct{}{}
229
- }()
230
-
231
- // make sure we're connected to the peer.
232
- // FIXME abstract away into the network layer
233
- if conns := r.query.dht.host.Network().ConnsToPeer(p); len(conns) == 0 {
234
- log.Debug("not connected. dialing.")
235
-
236
- notif.PublishQueryEvent(r.runCtx, ¬if.QueryEvent{
237
- Type: notif.DialingPeer,
238
- ID: p,
239
- })
240
- // while we dial, we do not take up a rate limit. this is to allow
241
- // forward progress during potentially very high latency dials.
242
- r.rateLimit <- struct{}{}
243
-
244
- pi := pstore.PeerInfo{ID: p}
245
-
246
- if err := r.query.dht.host.Connect(ctx, pi); err != nil {
247
- log.Debugf("Error connecting: %s", err)
248
-
249
- notif.PublishQueryEvent(r.runCtx, ¬if.QueryEvent{
250
- Type: notif.QueryError,
251
- Extra: err.Error(),
252
- ID: p,
253
- })
254
-
255
- r.Lock()
256
- r.errs = append(r.errs, err)
257
- r.Unlock()
258
- <-r.rateLimit // need to grab it again, as we deferred.
259
- return
260
- }
261
- <-r.rateLimit // need to grab it again, as we deferred.
262
- log.Debugf("connected. dial success.")
263
- }
264
-
265
- // finally, run the query against this peer
266
- res, err := r.query.qfunc(ctx, p)
267
-
268
- if err != nil {
269
- log.Debugf("ERROR worker for: %v %v", p, err)
270
- r.Lock()
271
- r.errs = append(r.errs, err)
272
- r.Unlock()
273
-
274
- } else if res.success {
275
- log.Debugf("SUCCESS worker for: %v %s", p, res)
276
- r.Lock()
277
- r.result = res
278
- r.Unlock()
279
- go r.proc.Close() // signal to everyone that we're done.
280
- // must be async, as we're one of the children, and Close blocks.
281
-
282
- } else if len(res.closerPeers) > 0 {
283
- log.Debugf("PEERS CLOSER -- worker for: %v (%d closer peers)", p, len(res.closerPeers))
284
- for _, next := range res.closerPeers {
285
- if next.ID == r.query.dht.self { // dont add self.
286
- log.Debugf("PEERS CLOSER -- worker for: %v found self", p)
287
- continue
288
- }
289
-
290
- // add their addresses to the dialer's peerstore
291
- r.query.dht.peerstore.AddAddrs(next.ID, next.Addrs, pstore.TempAddrTTL)
292
- r.addPeerToQuery(next.ID)
293
- log.Debugf("PEERS CLOSER -- worker for: %v added %v (%v)", p, next.ID, next.Addrs)
294
- }
295
- } else {
296
- log.Debugf("QUERY worker for: %v - not found, and no closer peers.", p)
297
- }
298
-}
routing/dht/records.go
deleted
-149
@@ -1,149 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "fmt"
5
- "time"
6
-
7
- routing "github.com/ipfs/go-ipfs/routing"
8
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
9
- record "github.com/ipfs/go-ipfs/routing/record"
10
- ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
11
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
12
- ctxfrac "gx/ipfs/QmX6DhWrpBB5NtadXmPSXYNdVvuLfJXoFNMvUMoVvP5UJa/go-context/frac"
13
- "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
14
-)
15
-
16
-// MaxRecordAge specifies the maximum time that any node will hold onto a record
17
-// from the time its received. This does not apply to any other forms of validity that
18
-// the record may contain.
19
-// For example, a record may contain an ipns entry with an EOL saying its valid
20
-// until the year 2020 (a great time in the future). For that record to stick around
21
-// it must be rebroadcasted more frequently than once every 'MaxRecordAge'
22
-const MaxRecordAge = time.Hour * 36
23
-
24
-func (dht *IpfsDHT) GetPublicKey(ctx context.Context, p peer.ID) (ci.PubKey, error) {
25
- log.Debugf("getPublicKey for: %s", p)
26
-
27
- // check locally.
28
- pk := dht.peerstore.PubKey(p)
29
- if pk != nil {
30
- return pk, nil
31
- }
32
-
33
- // ok, try the node itself. if they're overwhelmed or slow we can move on.
34
- ctxT, cancelFunc := ctxfrac.WithDeadlineFraction(ctx, 0.3)
35
- defer cancelFunc()
36
- if pk, err := dht.getPublicKeyFromNode(ctx, p); err == nil {
37
- err := dht.peerstore.AddPubKey(p, pk)
38
- if err != nil {
39
- return pk, err
40
- }
41
- return pk, nil
42
- }
43
-
44
- // last ditch effort: let's try the dht.
45
- log.Debugf("pk for %s not in peerstore, and peer failed. Trying DHT.", p)
46
- pkkey := routing.KeyForPublicKey(p)
47
-
48
- val, err := dht.GetValue(ctxT, pkkey)
49
- if err != nil {
50
- log.Warning("Failed to find requested public key.")
51
- return nil, err
52
- }
53
-
54
- pk, err = ci.UnmarshalPublicKey(val)
55
- if err != nil {
56
- log.Debugf("Failed to unmarshal public key: %s", err)
57
- return nil, err
58
- }
59
-
60
- return pk, dht.peerstore.AddPubKey(p, pk)
61
-}
62
-
63
-func (dht *IpfsDHT) getPublicKeyFromNode(ctx context.Context, p peer.ID) (ci.PubKey, error) {
64
-
65
- // check locally, just in case...
66
- pk := dht.peerstore.PubKey(p)
67
- if pk != nil {
68
- return pk, nil
69
- }
70
-
71
- pkkey := routing.KeyForPublicKey(p)
72
- pmes, err := dht.getValueSingle(ctx, p, pkkey)
73
- if err != nil {
74
- return nil, err
75
- }
76
-
77
- // node doesn't have key :(
78
- record := pmes.GetRecord()
79
- if record == nil {
80
- return nil, fmt.Errorf("Node not responding with its public key: %s", p)
81
- }
82
-
83
- // Success! We were given the value. we don't need to check
84
- // validity because a) we can't. b) we know the hash of the
85
- // key we're looking for.
86
- val := record.GetValue()
87
- log.Debug("DHT got a value from other peer")
88
-
89
- pk, err = ci.UnmarshalPublicKey(val)
90
- if err != nil {
91
- return nil, err
92
- }
93
-
94
- id, err := peer.IDFromPublicKey(pk)
95
- if err != nil {
96
- return nil, err
97
- }
98
- if id != p {
99
- return nil, fmt.Errorf("public key does not match id: %s", p)
100
- }
101
-
102
- // ok! it's valid. we got it!
103
- log.Debugf("DHT got public key from node itself.")
104
- return pk, nil
105
-}
106
-
107
-// verifyRecordLocally attempts to verify a record. if we do not have the public
108
-// key, we fail. we do not search the dht.
109
-func (dht *IpfsDHT) verifyRecordLocally(r *pb.Record) error {
110
-
111
- if len(r.Signature) > 0 {
112
- // First, validate the signature
113
- p := peer.ID(r.GetAuthor())
114
- pk := dht.peerstore.PubKey(p)
115
- if pk == nil {
116
- return fmt.Errorf("do not have public key for %s", p)
117
- }
118
-
119
- if err := record.CheckRecordSig(r, pk); err != nil {
120
- return err
121
- }
122
- }
123
-
124
- return dht.Validator.VerifyRecord(r)
125
-}
126
-
127
-// verifyRecordOnline verifies a record, searching the DHT for the public key
128
-// if necessary. The reason there is a distinction in the functions is that
129
-// retrieving arbitrary public keys from the DHT as a result of passively
130
-// receiving records (e.g. through a PUT_VALUE or ADD_PROVIDER) can cause a
131
-// massive amplification attack on the dht. Use with care.
132
-func (dht *IpfsDHT) verifyRecordOnline(ctx context.Context, r *pb.Record) error {
133
-
134
- if len(r.Signature) > 0 {
135
- // get the public key, search for it if necessary.
136
- p := peer.ID(r.GetAuthor())
137
- pk, err := dht.GetPublicKey(ctx, p)
138
- if err != nil {
139
- return err
140
- }
141
-
142
- err = record.CheckRecordSig(r, pk)
143
- if err != nil {
144
- return err
145
- }
146
- }
147
-
148
- return dht.Validator.VerifyRecord(r)
149
-}
routing/dht/routing.go
deleted
-538
@@ -1,538 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "bytes"
5
- "fmt"
6
- "runtime"
7
- "sync"
8
- "time"
9
-
10
- pset "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer/peerset"
11
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
12
-
13
- notif "github.com/ipfs/go-ipfs/notifications"
14
- "github.com/ipfs/go-ipfs/routing"
15
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
16
- kb "github.com/ipfs/go-ipfs/routing/kbucket"
17
- record "github.com/ipfs/go-ipfs/routing/record"
18
-
19
- inet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net"
20
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
21
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
22
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
23
-)
24
-
25
-// asyncQueryBuffer is the size of buffered channels in async queries. This
26
-// buffer allows multiple queries to execute simultaneously, return their
27
-// results and continue querying closer peers. Note that different query
28
-// results will wait for the channel to drain.
29
-var asyncQueryBuffer = 10
30
-
31
-// This file implements the Routing interface for the IpfsDHT struct.
32
-
33
-// Basic Put/Get
34
-
35
-// PutValue adds value corresponding to given Key.
36
-// This is the top level "Store" operation of the DHT
37
-func (dht *IpfsDHT) PutValue(ctx context.Context, key key.Key, value []byte) error {
38
- log.Debugf("PutValue %s", key)
39
- sk, err := dht.getOwnPrivateKey()
40
- if err != nil {
41
- return err
42
- }
43
-
44
- sign, err := dht.Validator.IsSigned(key)
45
- if err != nil {
46
- return err
47
- }
48
-
49
- rec, err := record.MakePutRecord(sk, key, value, sign)
50
- if err != nil {
51
- log.Debug("creation of record failed!")
52
- return err
53
- }
54
-
55
- err = dht.putLocal(key, rec)
56
- if err != nil {
57
- return err
58
- }
59
-
60
- pchan, err := dht.GetClosestPeers(ctx, key)
61
- if err != nil {
62
- return err
63
- }
64
-
65
- wg := sync.WaitGroup{}
66
- for p := range pchan {
67
- wg.Add(1)
68
- go func(p peer.ID) {
69
- ctx, cancel := context.WithCancel(ctx)
70
- defer cancel()
71
- defer wg.Done()
72
- notif.PublishQueryEvent(ctx, ¬if.QueryEvent{
73
- Type: notif.Value,
74
- ID: p,
75
- })
76
-
77
- err := dht.putValueToPeer(ctx, p, key, rec)
78
- if err != nil {
79
- log.Debugf("failed putting value to peer: %s", err)
80
- }
81
- }(p)
82
- }
83
- wg.Wait()
84
- return nil
85
-}
86
-
87
-// GetValue searches for the value corresponding to given Key.
88
-func (dht *IpfsDHT) GetValue(ctx context.Context, key key.Key) ([]byte, error) {
89
- ctx, cancel := context.WithTimeout(ctx, time.Minute)
90
- defer cancel()
91
-
92
- vals, err := dht.GetValues(ctx, key, 16)
93
- if err != nil {
94
- return nil, err
95
- }
96
-
97
- var recs [][]byte
98
- for _, v := range vals {
99
- if v.Val != nil {
100
- recs = append(recs, v.Val)
101
- }
102
- }
103
-
104
- i, err := dht.Selector.BestRecord(key, recs)
105
- if err != nil {
106
- return nil, err
107
- }
108
-
109
- best := recs[i]
110
- log.Debugf("GetValue %v %v", key, best)
111
- if best == nil {
112
- log.Errorf("GetValue yielded correct record with nil value.")
113
- return nil, routing.ErrNotFound
114
- }
115
-
116
- fixupRec, err := record.MakePutRecord(dht.peerstore.PrivKey(dht.self), key, best, true)
117
- if err != nil {
118
- // probably shouldnt actually 'error' here as we have found a value we like,
119
- // but this call failing probably isnt something we want to ignore
120
- return nil, err
121
- }
122
-
123
- for _, v := range vals {
124
- // if someone sent us a different 'less-valid' record, lets correct them
125
- if !bytes.Equal(v.Val, best) {
126
- go func(v routing.RecvdVal) {
127
- if v.From == dht.self {
128
- err := dht.putLocal(key, fixupRec)
129
- if err != nil {
130
- log.Error("Error correcting local dht entry:", err)
131
- }
132
- return
133
- }
134
- ctx, cancel := context.WithTimeout(dht.Context(), time.Second*30)
135
- defer cancel()
136
- err := dht.putValueToPeer(ctx, v.From, key, fixupRec)
137
- if err != nil {
138
- log.Error("Error correcting DHT entry: ", err)
139
- }
140
- }(v)
141
- }
142
- }
143
-
144
- return best, nil
145
-}
146
-
147
-func (dht *IpfsDHT) GetValues(ctx context.Context, key key.Key, nvals int) ([]routing.RecvdVal, error) {
148
- var vals []routing.RecvdVal
149
- var valslock sync.Mutex
150
-
151
- // If we have it local, dont bother doing an RPC!
152
- lrec, err := dht.getLocal(key)
153
- if err == nil {
154
- // TODO: this is tricky, we dont always want to trust our own value
155
- // what if the authoritative source updated it?
156
- log.Debug("have it locally")
157
- vals = append(vals, routing.RecvdVal{
158
- Val: lrec.GetValue(),
159
- From: dht.self,
160
- })
161
-
162
- if nvals <= 1 {
163
- return vals, nil
164
- }
165
- } else if nvals == 0 {
166
- return nil, err
167
- }
168
-
169
- // get closest peers in the routing table
170
- rtp := dht.routingTable.NearestPeers(kb.ConvertKey(key), KValue)
171
- log.Debugf("peers in rt: %s", len(rtp), rtp)
172
- if len(rtp) == 0 {
173
- log.Warning("No peers from routing table!")
174
- return nil, kb.ErrLookupFailure
175
- }
176
-
177
- // setup the Query
178
- parent := ctx
179
- query := dht.newQuery(key, func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
180
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
181
- Type: notif.SendingQuery,
182
- ID: p,
183
- })
184
-
185
- rec, peers, err := dht.getValueOrPeers(ctx, p, key)
186
- switch err {
187
- case routing.ErrNotFound:
188
- // in this case, they responded with nothing,
189
- // still send a notification so listeners can know the
190
- // request has completed 'successfully'
191
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
192
- Type: notif.PeerResponse,
193
- ID: p,
194
- })
195
- return nil, err
196
- default:
197
- return nil, err
198
-
199
- case nil, errInvalidRecord:
200
- // in either of these cases, we want to keep going
201
- }
202
-
203
- res := &dhtQueryResult{closerPeers: peers}
204
-
205
- if rec.GetValue() != nil || err == errInvalidRecord {
206
- rv := routing.RecvdVal{
207
- Val: rec.GetValue(),
208
- From: p,
209
- }
210
- valslock.Lock()
211
- vals = append(vals, rv)
212
-
213
- // If weve collected enough records, we're done
214
- if len(vals) >= nvals {
215
- res.success = true
216
- }
217
- valslock.Unlock()
218
- }
219
-
220
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
221
- Type: notif.PeerResponse,
222
- ID: p,
223
- Responses: pointerizePeerInfos(peers),
224
- })
225
-
226
- return res, nil
227
- })
228
-
229
- // run it!
230
- _, err = query.Run(ctx, rtp)
231
- if len(vals) == 0 {
232
- if err != nil {
233
- return nil, err
234
- }
235
- }
236
-
237
- return vals, nil
238
-
239
-}
240
-
241
-// Value provider layer of indirection.
242
-// This is what DSHTs (Coral and MainlineDHT) do to store large values in a DHT.
243
-
244
-// Provide makes this node announce that it can provide a value for the given key
245
-func (dht *IpfsDHT) Provide(ctx context.Context, key key.Key) error {
246
- defer log.EventBegin(ctx, "provide", &key).Done()
247
-
248
- // add self locally
249
- dht.providers.AddProvider(ctx, key, dht.self)
250
-
251
- peers, err := dht.GetClosestPeers(ctx, key)
252
- if err != nil {
253
- return err
254
- }
255
-
256
- mes, err := dht.makeProvRecord(key)
257
- if err != nil {
258
- return err
259
- }
260
-
261
- wg := sync.WaitGroup{}
262
- for p := range peers {
263
- wg.Add(1)
264
- go func(p peer.ID) {
265
- defer wg.Done()
266
- log.Debugf("putProvider(%s, %s)", key, p)
267
- notif.PublishQueryEvent(ctx, ¬if.QueryEvent{
268
- Type: notif.FinalPeer,
269
- ID: p,
270
- })
271
- err := dht.sendMessage(ctx, p, mes)
272
- if err != nil {
273
- log.Debug(err)
274
- }
275
- }(p)
276
- }
277
- wg.Wait()
278
- return nil
279
-}
280
-
281
-func (dht *IpfsDHT) makeProvRecord(skey key.Key) (*pb.Message, error) {
282
- pi := pstore.PeerInfo{
283
- ID: dht.self,
284
- Addrs: dht.host.Addrs(),
285
- }
286
-
287
- // // only share WAN-friendly addresses ??
288
- // pi.Addrs = addrutil.WANShareableAddrs(pi.Addrs)
289
- if len(pi.Addrs) < 1 {
290
- return nil, fmt.Errorf("no known addresses for self. cannot put provider.")
291
- }
292
-
293
- pmes := pb.NewMessage(pb.Message_ADD_PROVIDER, string(skey), 0)
294
- pmes.ProviderPeers = pb.RawPeerInfosToPBPeers([]pstore.PeerInfo{pi})
295
- return pmes, nil
296
-}
297
-
298
-// FindProviders searches until the context expires.
299
-func (dht *IpfsDHT) FindProviders(ctx context.Context, key key.Key) ([]pstore.PeerInfo, error) {
300
- var providers []pstore.PeerInfo
301
- for p := range dht.FindProvidersAsync(ctx, key, KValue) {
302
- providers = append(providers, p)
303
- }
304
- return providers, nil
305
-}
306
-
307
-// FindProvidersAsync is the same thing as FindProviders, but returns a channel.
308
-// Peers will be returned on the channel as soon as they are found, even before
309
-// the search query completes.
310
-func (dht *IpfsDHT) FindProvidersAsync(ctx context.Context, key key.Key, count int) <-chan pstore.PeerInfo {
311
- log.Event(ctx, "findProviders", &key)
312
- peerOut := make(chan pstore.PeerInfo, count)
313
- go dht.findProvidersAsyncRoutine(ctx, key, count, peerOut)
314
- return peerOut
315
-}
316
-
317
-func (dht *IpfsDHT) findProvidersAsyncRoutine(ctx context.Context, key key.Key, count int, peerOut chan pstore.PeerInfo) {
318
- defer log.EventBegin(ctx, "findProvidersAsync", &key).Done()
319
- defer close(peerOut)
320
-
321
- ps := pset.NewLimited(count)
322
- provs := dht.providers.GetProviders(ctx, key)
323
- for _, p := range provs {
324
- // NOTE: Assuming that this list of peers is unique
325
- if ps.TryAdd(p) {
326
- select {
327
- case peerOut <- dht.peerstore.PeerInfo(p):
328
- case <-ctx.Done():
329
- return
330
- }
331
- }
332
-
333
- // If we have enough peers locally, dont bother with remote RPC
334
- if ps.Size() >= count {
335
- return
336
- }
337
- }
338
-
339
- // setup the Query
340
- parent := ctx
341
- query := dht.newQuery(key, func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
342
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
343
- Type: notif.SendingQuery,
344
- ID: p,
345
- })
346
- pmes, err := dht.findProvidersSingle(ctx, p, key)
347
- if err != nil {
348
- return nil, err
349
- }
350
-
351
- log.Debugf("%d provider entries", len(pmes.GetProviderPeers()))
352
- provs := pb.PBPeersToPeerInfos(pmes.GetProviderPeers())
353
- log.Debugf("%d provider entries decoded", len(provs))
354
-
355
- // Add unique providers from request, up to 'count'
356
- for _, prov := range provs {
357
- log.Debugf("got provider: %s", prov)
358
- if ps.TryAdd(prov.ID) {
359
- log.Debugf("using provider: %s", prov)
360
- select {
361
- case peerOut <- prov:
362
- case <-ctx.Done():
363
- log.Debug("context timed out sending more providers")
364
- return nil, ctx.Err()
365
- }
366
- }
367
- if ps.Size() >= count {
368
- log.Debugf("got enough providers (%d/%d)", ps.Size(), count)
369
- return &dhtQueryResult{success: true}, nil
370
- }
371
- }
372
-
373
- // Give closer peers back to the query to be queried
374
- closer := pmes.GetCloserPeers()
375
- clpeers := pb.PBPeersToPeerInfos(closer)
376
- log.Debugf("got closer peers: %d %s", len(clpeers), clpeers)
377
-
378
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
379
- Type: notif.PeerResponse,
380
- ID: p,
381
- Responses: pointerizePeerInfos(clpeers),
382
- })
383
- return &dhtQueryResult{closerPeers: clpeers}, nil
384
- })
385
-
386
- peers := dht.routingTable.NearestPeers(kb.ConvertKey(key), KValue)
387
- _, err := query.Run(ctx, peers)
388
- if err != nil {
389
- log.Debugf("Query error: %s", err)
390
- // Special handling for issue: https://github.com/ipfs/go-ipfs/issues/3032
391
- if fmt.Sprint(err) == "<nil>" {
392
- log.Error("reproduced bug 3032:")
393
- log.Errorf("Errors type information: %#v", err)
394
- log.Errorf("go version: %s", runtime.Version())
395
- log.Error("please report this information to: https://github.com/ipfs/go-ipfs/issues/3032")
396
-
397
- // replace problematic error with something that won't crash the daemon
398
- err = fmt.Errorf("<nil>")
399
- }
400
- notif.PublishQueryEvent(ctx, ¬if.QueryEvent{
401
- Type: notif.QueryError,
402
- Extra: err.Error(),
403
- })
404
- }
405
-}
406
-
407
-// FindPeer searches for a peer with given ID.
408
-func (dht *IpfsDHT) FindPeer(ctx context.Context, id peer.ID) (pstore.PeerInfo, error) {
409
- defer log.EventBegin(ctx, "FindPeer", id).Done()
410
-
411
- // Check if were already connected to them
412
- if pi := dht.FindLocal(id); pi.ID != "" {
413
- return pi, nil
414
- }
415
-
416
- peers := dht.routingTable.NearestPeers(kb.ConvertPeerID(id), KValue)
417
- if len(peers) == 0 {
418
- return pstore.PeerInfo{}, kb.ErrLookupFailure
419
- }
420
-
421
- // Sanity...
422
- for _, p := range peers {
423
- if p == id {
424
- log.Debug("found target peer in list of closest peers...")
425
- return dht.peerstore.PeerInfo(p), nil
426
- }
427
- }
428
-
429
- // setup the Query
430
- parent := ctx
431
- query := dht.newQuery(key.Key(id), func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
432
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
433
- Type: notif.SendingQuery,
434
- ID: p,
435
- })
436
-
437
- pmes, err := dht.findPeerSingle(ctx, p, id)
438
- if err != nil {
439
- return nil, err
440
- }
441
-
442
- closer := pmes.GetCloserPeers()
443
- clpeerInfos := pb.PBPeersToPeerInfos(closer)
444
-
445
- // see it we got the peer here
446
- for _, npi := range clpeerInfos {
447
- if npi.ID == id {
448
- return &dhtQueryResult{
449
- peer: npi,
450
- success: true,
451
- }, nil
452
- }
453
- }
454
-
455
- notif.PublishQueryEvent(parent, ¬if.QueryEvent{
456
- Type: notif.PeerResponse,
457
- Responses: pointerizePeerInfos(clpeerInfos),
458
- })
459
-
460
- return &dhtQueryResult{closerPeers: clpeerInfos}, nil
461
- })
462
-
463
- // run it!
464
- result, err := query.Run(ctx, peers)
465
- if err != nil {
466
- return pstore.PeerInfo{}, err
467
- }
468
-
469
- log.Debugf("FindPeer %v %v", id, result.success)
470
- if result.peer.ID == "" {
471
- return pstore.PeerInfo{}, routing.ErrNotFound
472
- }
473
-
474
- return result.peer, nil
475
-}
476
-
477
-// FindPeersConnectedToPeer searches for peers directly connected to a given peer.
478
-func (dht *IpfsDHT) FindPeersConnectedToPeer(ctx context.Context, id peer.ID) (<-chan pstore.PeerInfo, error) {
479
-
480
- peerchan := make(chan pstore.PeerInfo, asyncQueryBuffer)
481
- peersSeen := make(map[peer.ID]struct{})
482
-
483
- peers := dht.routingTable.NearestPeers(kb.ConvertPeerID(id), KValue)
484
- if len(peers) == 0 {
485
- return nil, kb.ErrLookupFailure
486
- }
487
-
488
- // setup the Query
489
- query := dht.newQuery(key.Key(id), func(ctx context.Context, p peer.ID) (*dhtQueryResult, error) {
490
-
491
- pmes, err := dht.findPeerSingle(ctx, p, id)
492
- if err != nil {
493
- return nil, err
494
- }
495
-
496
- var clpeers []pstore.PeerInfo
497
- closer := pmes.GetCloserPeers()
498
- for _, pbp := range closer {
499
- pi := pb.PBPeerToPeerInfo(pbp)
500
-
501
- // skip peers already seen
502
- if _, found := peersSeen[pi.ID]; found {
503
- continue
504
- }
505
- peersSeen[pi.ID] = struct{}{}
506
-
507
- // if peer is connected, send it to our client.
508
- if pb.Connectedness(*pbp.Connection) == inet.Connected {
509
- select {
510
- case <-ctx.Done():
511
- return nil, ctx.Err()
512
- case peerchan <- pi:
513
- }
514
- }
515
-
516
- // if peer is the peer we're looking for, don't bother querying it.
517
- // TODO maybe query it?
518
- if pb.Connectedness(*pbp.Connection) != inet.Connected {
519
- clpeers = append(clpeers, pi)
520
- }
521
- }
522
-
523
- return &dhtQueryResult{closerPeers: clpeers}, nil
524
- })
525
-
526
- // run it! run it asynchronously to gen peers as results are found.
527
- // this does no error checking
528
- go func() {
529
- if _, err := query.Run(ctx, peers); err != nil {
530
- log.Debug(err)
531
- }
532
-
533
- // close the peerchan channel when done.
534
- close(peerchan)
535
- }()
536
-
537
- return peerchan, nil
538
-}
routing/dht/util.go
deleted
-39
@@ -1,39 +0,0 @@
1
-package dht
2
-
3
-import (
4
- "sync"
5
-)
6
-
7
-// Pool size is the number of nodes used for group find/set RPC calls
8
-var PoolSize = 6
9
-
10
-// K is the maximum number of requests to perform before returning failure.
11
-var KValue = 20
12
-
13
-// Alpha is the concurrency factor for asynchronous requests.
14
-var AlphaValue = 3
15
-
16
-// A counter for incrementing a variable across multiple threads
17
-type counter struct {
18
- n int
19
- mut sync.Mutex
20
-}
21
-
22
-func (c *counter) Increment() {
23
- c.mut.Lock()
24
- c.n++
25
- c.mut.Unlock()
26
-}
27
-
28
-func (c *counter) Decrement() {
29
- c.mut.Lock()
30
- c.n--
31
- c.mut.Unlock()
32
-}
33
-
34
-func (c *counter) Size() (s int) {
35
- c.mut.Lock()
36
- s = c.n
37
- c.mut.Unlock()
38
- return
39
-}
routing/kbucket/bucket.go
deleted
-108
@@ -1,108 +0,0 @@
1
-package kbucket
2
-
3
-import (
4
- "container/list"
5
- "sync"
6
-
7
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
8
-)
9
-
10
-// Bucket holds a list of peers.
11
-type Bucket struct {
12
- lk sync.RWMutex
13
- list *list.List
14
-}
15
-
16
-func newBucket() *Bucket {
17
- b := new(Bucket)
18
- b.list = list.New()
19
- return b
20
-}
21
-
22
-func (b *Bucket) Peers() []peer.ID {
23
- b.lk.RLock()
24
- defer b.lk.RUnlock()
25
- ps := make([]peer.ID, 0, b.list.Len())
26
- for e := b.list.Front(); e != nil; e = e.Next() {
27
- id := e.Value.(peer.ID)
28
- ps = append(ps, id)
29
- }
30
- return ps
31
-}
32
-
33
-func (b *Bucket) Has(id peer.ID) bool {
34
- b.lk.RLock()
35
- defer b.lk.RUnlock()
36
- for e := b.list.Front(); e != nil; e = e.Next() {
37
- if e.Value.(peer.ID) == id {
38
- return true
39
- }
40
- }
41
- return false
42
-}
43
-
44
-func (b *Bucket) Remove(id peer.ID) {
45
- b.lk.Lock()
46
- defer b.lk.Unlock()
47
- for e := b.list.Front(); e != nil; e = e.Next() {
48
- if e.Value.(peer.ID) == id {
49
- b.list.Remove(e)
50
- }
51
- }
52
-}
53
-
54
-func (b *Bucket) MoveToFront(id peer.ID) {
55
- b.lk.Lock()
56
- defer b.lk.Unlock()
57
- for e := b.list.Front(); e != nil; e = e.Next() {
58
- if e.Value.(peer.ID) == id {
59
- b.list.MoveToFront(e)
60
- }
61
- }
62
-}
63
-
64
-func (b *Bucket) PushFront(p peer.ID) {
65
- b.lk.Lock()
66
- b.list.PushFront(p)
67
- b.lk.Unlock()
68
-}
69
-
70
-func (b *Bucket) PopBack() peer.ID {
71
- b.lk.Lock()
72
- defer b.lk.Unlock()
73
- last := b.list.Back()
74
- b.list.Remove(last)
75
- return last.Value.(peer.ID)
76
-}
77
-
78
-func (b *Bucket) Len() int {
79
- b.lk.RLock()
80
- defer b.lk.RUnlock()
81
- return b.list.Len()
82
-}
83
-
84
-// Split splits a buckets peers into two buckets, the methods receiver will have
85
-// peers with CPL equal to cpl, the returned bucket will have peers with CPL
86
-// greater than cpl (returned bucket has closer peers)
87
-func (b *Bucket) Split(cpl int, target ID) *Bucket {
88
- b.lk.Lock()
89
- defer b.lk.Unlock()
90
-
91
- out := list.New()
92
- newbuck := newBucket()
93
- newbuck.list = out
94
- e := b.list.Front()
95
- for e != nil {
96
- peerID := ConvertPeerID(e.Value.(peer.ID))
97
- peerCPL := commonPrefixLen(peerID, target)
98
- if peerCPL > cpl {
99
- cur := e
100
- out.PushBack(e.Value)
101
- e = e.Next()
102
- b.list.Remove(cur)
103
- continue
104
- }
105
- e = e.Next()
106
- }
107
- return newbuck
108
-}
routing/kbucket/sorting.go
deleted
-55
@@ -1,55 +0,0 @@
1
-package kbucket
2
-
3
-import (
4
- "container/list"
5
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
6
- "sort"
7
-)
8
-
9
-// A helper struct to sort peers by their distance to the local node
10
-type peerDistance struct {
11
- p peer.ID
12
- distance ID
13
-}
14
-
15
-// peerSorterArr implements sort.Interface to sort peers by xor distance
16
-type peerSorterArr []*peerDistance
17
-
18
-func (p peerSorterArr) Len() int { return len(p) }
19
-func (p peerSorterArr) Swap(a, b int) { p[a], p[b] = p[b], p[a] }
20
-func (p peerSorterArr) Less(a, b int) bool {
21
- return p[a].distance.less(p[b].distance)
22
-}
23
-
24
-//
25
-
26
-func copyPeersFromList(target ID, peerArr peerSorterArr, peerList *list.List) peerSorterArr {
27
- for e := peerList.Front(); e != nil; e = e.Next() {
28
- p := e.Value.(peer.ID)
29
- pID := ConvertPeerID(p)
30
- pd := peerDistance{
31
- p: p,
32
- distance: xor(target, pID),
33
- }
34
- peerArr = append(peerArr, &pd)
35
- }
36
- return peerArr
37
-}
38
-
39
-func SortClosestPeers(peers []peer.ID, target ID) []peer.ID {
40
- var psarr peerSorterArr
41
- for _, p := range peers {
42
- pID := ConvertPeerID(p)
43
- pd := &peerDistance{
44
- p: p,
45
- distance: xor(target, pID),
46
- }
47
- psarr = append(psarr, pd)
48
- }
49
- sort.Sort(psarr)
50
- var out []peer.ID
51
- for _, p := range psarr {
52
- out = append(out, p.p)
53
- }
54
- return out
55
-}
routing/kbucket/table.go
deleted
-225
@@ -1,225 +0,0 @@
1
-// package kbucket implements a kademlia 'k-bucket' routing table.
2
-package kbucket
3
-
4
-import (
5
- "fmt"
6
- "sort"
7
- "sync"
8
- "time"
9
-
10
- logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
11
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
12
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
13
-)
14
-
15
-var log = logging.Logger("table")
16
-
17
-// RoutingTable defines the routing table.
18
-type RoutingTable struct {
19
-
20
- // ID of the local peer
21
- local ID
22
-
23
- // Blanket lock, refine later for better performance
24
- tabLock sync.RWMutex
25
-
26
- // latency metrics
27
- metrics pstore.Metrics
28
-
29
- // Maximum acceptable latency for peers in this cluster
30
- maxLatency time.Duration
31
-
32
- // kBuckets define all the fingers to other nodes.
33
- Buckets []*Bucket
34
- bucketsize int
35
-}
36
-
37
-// NewRoutingTable creates a new routing table with a given bucketsize, local ID, and latency tolerance.
38
-func NewRoutingTable(bucketsize int, localID ID, latency time.Duration, m pstore.Metrics) *RoutingTable {
39
- rt := new(RoutingTable)
40
- rt.Buckets = []*Bucket{newBucket()}
41
- rt.bucketsize = bucketsize
42
- rt.local = localID
43
- rt.maxLatency = latency
44
- rt.metrics = m
45
- return rt
46
-}
47
-
48
-// Update adds or moves the given peer to the front of its respective bucket
49
-// If a peer gets removed from a bucket, it is returned
50
-func (rt *RoutingTable) Update(p peer.ID) {
51
- peerID := ConvertPeerID(p)
52
- cpl := commonPrefixLen(peerID, rt.local)
53
-
54
- rt.tabLock.Lock()
55
- defer rt.tabLock.Unlock()
56
- bucketID := cpl
57
- if bucketID >= len(rt.Buckets) {
58
- bucketID = len(rt.Buckets) - 1
59
- }
60
-
61
- bucket := rt.Buckets[bucketID]
62
- if bucket.Has(p) {
63
- // If the peer is already in the table, move it to the front.
64
- // This signifies that it it "more active" and the less active nodes
65
- // Will as a result tend towards the back of the list
66
- bucket.MoveToFront(p)
67
- return
68
- }
69
-
70
- if rt.metrics.LatencyEWMA(p) > rt.maxLatency {
71
- // Connection doesnt meet requirements, skip!
72
- return
73
- }
74
-
75
- // New peer, add to bucket
76
- bucket.PushFront(p)
77
-
78
- // Are we past the max bucket size?
79
- if bucket.Len() > rt.bucketsize {
80
- // If this bucket is the rightmost bucket, and its full
81
- // we need to split it and create a new bucket
82
- if bucketID == len(rt.Buckets)-1 {
83
- rt.nextBucket()
84
- return
85
- } else {
86
- // If the bucket cant split kick out least active node
87
- bucket.PopBack()
88
- return
89
- }
90
- }
91
-}
92
-
93
-// Remove deletes a peer from the routing table. This is to be used
94
-// when we are sure a node has disconnected completely.
95
-func (rt *RoutingTable) Remove(p peer.ID) {
96
- rt.tabLock.Lock()
97
- defer rt.tabLock.Unlock()
98
- peerID := ConvertPeerID(p)
99
- cpl := commonPrefixLen(peerID, rt.local)
100
-
101
- bucketID := cpl
102
- if bucketID >= len(rt.Buckets) {
103
- bucketID = len(rt.Buckets) - 1
104
- }
105
-
106
- bucket := rt.Buckets[bucketID]
107
- bucket.Remove(p)
108
-}
109
-
110
-func (rt *RoutingTable) nextBucket() peer.ID {
111
- bucket := rt.Buckets[len(rt.Buckets)-1]
112
- newBucket := bucket.Split(len(rt.Buckets)-1, rt.local)
113
- rt.Buckets = append(rt.Buckets, newBucket)
114
- if newBucket.Len() > rt.bucketsize {
115
- return rt.nextBucket()
116
- }
117
-
118
- // If all elements were on left side of split...
119
- if bucket.Len() > rt.bucketsize {
120
- return bucket.PopBack()
121
- }
122
- return ""
123
-}
124
-
125
-// Find a specific peer by ID or return nil
126
-func (rt *RoutingTable) Find(id peer.ID) peer.ID {
127
- srch := rt.NearestPeers(ConvertPeerID(id), 1)
128
- if len(srch) == 0 || srch[0] != id {
129
- return ""
130
- }
131
- return srch[0]
132
-}
133
-
134
-// NearestPeer returns a single peer that is nearest to the given ID
135
-func (rt *RoutingTable) NearestPeer(id ID) peer.ID {
136
- peers := rt.NearestPeers(id, 1)
137
- if len(peers) > 0 {
138
- return peers[0]
139
- }
140
-
141
- log.Debugf("NearestPeer: Returning nil, table size = %d", rt.Size())
142
- return ""
143
-}
144
-
145
-// NearestPeers returns a list of the 'count' closest peers to the given ID
146
-func (rt *RoutingTable) NearestPeers(id ID, count int) []peer.ID {
147
- cpl := commonPrefixLen(id, rt.local)
148
-
149
- rt.tabLock.RLock()
150
-
151
- // Get bucket at cpl index or last bucket
152
- var bucket *Bucket
153
- if cpl >= len(rt.Buckets) {
154
- cpl = len(rt.Buckets) - 1
155
- }
156
- bucket = rt.Buckets[cpl]
157
-
158
- var peerArr peerSorterArr
159
- peerArr = copyPeersFromList(id, peerArr, bucket.list)
160
- if len(peerArr) < count {
161
- // In the case of an unusual split, one bucket may be short or empty.
162
- // if this happens, search both surrounding buckets for nearby peers
163
- if cpl > 0 {
164
- plist := rt.Buckets[cpl-1].list
165
- peerArr = copyPeersFromList(id, peerArr, plist)
166
- }
167
-
168
- if cpl < len(rt.Buckets)-1 {
169
- plist := rt.Buckets[cpl+1].list
170
- peerArr = copyPeersFromList(id, peerArr, plist)
171
- }
172
- }
173
- rt.tabLock.RUnlock()
174
-
175
- // Sort by distance to local peer
176
- sort.Sort(peerArr)
177
-
178
- var out []peer.ID
179
- for i := 0; i < count && i < peerArr.Len(); i++ {
180
- out = append(out, peerArr[i].p)
181
- }
182
-
183
- return out
184
-}
185
-
186
-// Size returns the total number of peers in the routing table
187
-func (rt *RoutingTable) Size() int {
188
- var tot int
189
- rt.tabLock.RLock()
190
- for _, buck := range rt.Buckets {
191
- tot += buck.Len()
192
- }
193
- rt.tabLock.RUnlock()
194
- return tot
195
-}
196
-
197
-// ListPeers takes a RoutingTable and returns a list of all peers from all buckets in the table.
198
-// NOTE: This is potentially unsafe... use at your own risk
199
-func (rt *RoutingTable) ListPeers() []peer.ID {
200
- var peers []peer.ID
201
- rt.tabLock.RLock()
202
- for _, buck := range rt.Buckets {
203
- peers = append(peers, buck.Peers()...)
204
- }
205
- rt.tabLock.RUnlock()
206
- return peers
207
-}
208
-
209
-// Print prints a descriptive statement about the provided RoutingTable
210
-func (rt *RoutingTable) Print() {
211
- fmt.Printf("Routing Table, bs = %d, Max latency = %d\n", rt.bucketsize, rt.maxLatency)
212
- rt.tabLock.RLock()
213
-
214
- for i, b := range rt.Buckets {
215
- fmt.Printf("\tbucket: %d\n", i)
216
-
217
- b.lk.RLock()
218
- for e := b.list.Front(); e != nil; e = e.Next() {
219
- p := e.Value.(peer.ID)
220
- fmt.Printf("\t\t- %s %s\n", p.Pretty(), rt.metrics.LatencyEWMA(p).String())
221
- }
222
- b.lk.RUnlock()
223
- }
224
- rt.tabLock.RUnlock()
225
-}
routing/kbucket/table_test.go
deleted
-187
@@ -1,187 +0,0 @@
1
-package kbucket
2
-
3
-import (
4
- "math/rand"
5
- "testing"
6
- "time"
7
-
8
- tu "github.com/ipfs/go-ipfs/thirdparty/testutil"
9
-
10
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
11
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
12
-)
13
-
14
-// Test basic features of the bucket struct
15
-func TestBucket(t *testing.T) {
16
- b := newBucket()
17
-
18
- peers := make([]peer.ID, 100)
19
- for i := 0; i < 100; i++ {
20
- peers[i] = tu.RandPeerIDFatal(t)
21
- b.PushFront(peers[i])
22
- }
23
-
24
- local := tu.RandPeerIDFatal(t)
25
- localID := ConvertPeerID(local)
26
-
27
- i := rand.Intn(len(peers))
28
- if !b.Has(peers[i]) {
29
- t.Errorf("Failed to find peer: %v", peers[i])
30
- }
31
-
32
- spl := b.Split(0, ConvertPeerID(local))
33
- llist := b.list
34
- for e := llist.Front(); e != nil; e = e.Next() {
35
- p := ConvertPeerID(e.Value.(peer.ID))
36
- cpl := commonPrefixLen(p, localID)
37
- if cpl > 0 {
38
- t.Fatalf("Split failed. found id with cpl > 0 in 0 bucket")
39
- }
40
- }
41
-
42
- rlist := spl.list
43
- for e := rlist.Front(); e != nil; e = e.Next() {
44
- p := ConvertPeerID(e.Value.(peer.ID))
45
- cpl := commonPrefixLen(p, localID)
46
- if cpl == 0 {
47
- t.Fatalf("Split failed. found id with cpl == 0 in non 0 bucket")
48
- }
49
- }
50
-}
51
-
52
-// Right now, this just makes sure that it doesnt hang or crash
53
-func TestTableUpdate(t *testing.T) {
54
- local := tu.RandPeerIDFatal(t)
55
- m := pstore.NewMetrics()
56
- rt := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m)
57
-
58
- peers := make([]peer.ID, 100)
59
- for i := 0; i < 100; i++ {
60
- peers[i] = tu.RandPeerIDFatal(t)
61
- }
62
-
63
- // Testing Update
64
- for i := 0; i < 10000; i++ {
65
- rt.Update(peers[rand.Intn(len(peers))])
66
- }
67
-
68
- for i := 0; i < 100; i++ {
69
- id := ConvertPeerID(tu.RandPeerIDFatal(t))
70
- ret := rt.NearestPeers(id, 5)
71
- if len(ret) == 0 {
72
- t.Fatal("Failed to find node near ID.")
73
- }
74
- }
75
-}
76
-
77
-func TestTableFind(t *testing.T) {
78
- local := tu.RandPeerIDFatal(t)
79
- m := pstore.NewMetrics()
80
- rt := NewRoutingTable(10, ConvertPeerID(local), time.Hour, m)
81
-
82
- peers := make([]peer.ID, 100)
83
- for i := 0; i < 5; i++ {
84
- peers[i] = tu.RandPeerIDFatal(t)
85
- rt.Update(peers[i])
86
- }
87
-
88
- t.Logf("Searching for peer: '%s'", peers[2])
89
- found := rt.NearestPeer(ConvertPeerID(peers[2]))
90
- if !(found == peers[2]) {
91
- t.Fatalf("Failed to lookup known node...")
92
- }
93
-}
94
-
95
-func TestTableFindMultiple(t *testing.T) {
96
- local := tu.RandPeerIDFatal(t)
97
- m := pstore.NewMetrics()
98
- rt := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m)
99
-
100
- peers := make([]peer.ID, 100)
101
- for i := 0; i < 18; i++ {
102
- peers[i] = tu.RandPeerIDFatal(t)
103
- rt.Update(peers[i])
104
- }
105
-
106
- t.Logf("Searching for peer: '%s'", peers[2])
107
- found := rt.NearestPeers(ConvertPeerID(peers[2]), 15)
108
- if len(found) != 15 {
109
- t.Fatalf("Got back different number of peers than we expected.")
110
- }
111
-}
112
-
113
-// Looks for race conditions in table operations. For a more 'certain'
114
-// test, increase the loop counter from 1000 to a much higher number
115
-// and set GOMAXPROCS above 1
116
-func TestTableMultithreaded(t *testing.T) {
117
- local := peer.ID("localPeer")
118
- m := pstore.NewMetrics()
119
- tab := NewRoutingTable(20, ConvertPeerID(local), time.Hour, m)
120
- var peers []peer.ID
121
- for i := 0; i < 500; i++ {
122
- peers = append(peers, tu.RandPeerIDFatal(t))
123
- }
124
-
125
- done := make(chan struct{})
126
- go func() {
127
- for i := 0; i < 1000; i++ {
128
- n := rand.Intn(len(peers))
129
- tab.Update(peers[n])
130
- }
131
- done <- struct{}{}
132
- }()
133
-
134
- go func() {
135
- for i := 0; i < 1000; i++ {
136
- n := rand.Intn(len(peers))
137
- tab.Update(peers[n])
138
- }
139
- done <- struct{}{}
140
- }()
141
-
142
- go func() {
143
- for i := 0; i < 1000; i++ {
144
- n := rand.Intn(len(peers))
145
- tab.Find(peers[n])
146
- }
147
- done <- struct{}{}
148
- }()
149
- <-done
150
- <-done
151
- <-done
152
-}
153
-
154
-func BenchmarkUpdates(b *testing.B) {
155
- b.StopTimer()
156
- local := ConvertKey("localKey")
157
- m := pstore.NewMetrics()
158
- tab := NewRoutingTable(20, local, time.Hour, m)
159
-
160
- var peers []peer.ID
161
- for i := 0; i < b.N; i++ {
162
- peers = append(peers, tu.RandPeerIDFatal(b))
163
- }
164
-
165
- b.StartTimer()
166
- for i := 0; i < b.N; i++ {
167
- tab.Update(peers[i])
168
- }
169
-}
170
-
171
-func BenchmarkFinds(b *testing.B) {
172
- b.StopTimer()
173
- local := ConvertKey("localKey")
174
- m := pstore.NewMetrics()
175
- tab := NewRoutingTable(20, local, time.Hour, m)
176
-
177
- var peers []peer.ID
178
- for i := 0; i < b.N; i++ {
179
- peers = append(peers, tu.RandPeerIDFatal(b))
180
- tab.Update(peers[i])
181
- }
182
-
183
- b.StartTimer()
184
- for i := 0; i < b.N; i++ {
185
- tab.Find(peers[i])
186
- }
187
-}
routing/kbucket/util.go
deleted
-63
@@ -1,63 +0,0 @@
1
-package kbucket
2
-
3
-import (
4
- "bytes"
5
- "crypto/sha256"
6
- "errors"
7
-
8
- ks "github.com/ipfs/go-ipfs/routing/keyspace"
9
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
10
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
11
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
12
-)
13
-
14
-// Returned if a routing table query returns no results. This is NOT expected
15
-// behaviour
16
-var ErrLookupFailure = errors.New("failed to find any peer in table")
17
-
18
-// ID for IpfsDHT is in the XORKeySpace
19
-//
20
-// The type dht.ID signifies that its contents have been hashed from either a
21
-// peer.ID or a util.Key. This unifies the keyspace
22
-type ID []byte
23
-
24
-func (id ID) equal(other ID) bool {
25
- return bytes.Equal(id, other)
26
-}
27
-
28
-func (id ID) less(other ID) bool {
29
- a := ks.Key{Space: ks.XORKeySpace, Bytes: id}
30
- b := ks.Key{Space: ks.XORKeySpace, Bytes: other}
31
- return a.Less(b)
32
-}
33
-
34
-func xor(a, b ID) ID {
35
- return ID(u.XOR(a, b))
36
-}
37
-
38
-func commonPrefixLen(a, b ID) int {
39
- return ks.ZeroPrefixLen(u.XOR(a, b))
40
-}
41
-
42
-// ConvertPeerID creates a DHT ID by hashing a Peer ID (Multihash)
43
-func ConvertPeerID(id peer.ID) ID {
44
- hash := sha256.Sum256([]byte(id))
45
- return hash[:]
46
-}
47
-
48
-// ConvertKey creates a DHT ID by hashing a local key (String)
49
-func ConvertKey(id key.Key) ID {
50
- hash := sha256.Sum256([]byte(id))
51
- return hash[:]
52
-}
53
-
54
-// Closer returns true if a is closer to key than b is
55
-func Closer(a, b peer.ID, key key.Key) bool {
56
- aid := ConvertPeerID(a)
57
- bid := ConvertPeerID(b)
58
- tgt := ConvertKey(key)
59
- adist := xor(aid, tgt)
60
- bdist := xor(bid, tgt)
61
-
62
- return adist.less(bdist)
63
-}
routing/keyspace/keyspace.go
deleted
-97
@@ -1,97 +0,0 @@
1
-package keyspace
2
-
3
-import (
4
- "sort"
5
-
6
- "math/big"
7
-)
8
-
9
-// Key represents an identifier in a KeySpace. It holds a reference to the
10
-// associated KeySpace, as well references to both the Original identifier,
11
-// as well as the new, KeySpace Bytes one.
12
-type Key struct {
13
-
14
- // Space is the KeySpace this Key is related to.
15
- Space KeySpace
16
-
17
- // Original is the original value of the identifier
18
- Original []byte
19
-
20
- // Bytes is the new value of the identifier, in the KeySpace.
21
- Bytes []byte
22
-}
23
-
24
-// Equal returns whether this key is equal to another.
25
-func (k1 Key) Equal(k2 Key) bool {
26
- if k1.Space != k2.Space {
27
- panic("k1 and k2 not in same key space.")
28
- }
29
- return k1.Space.Equal(k1, k2)
30
-}
31
-
32
-// Less returns whether this key comes before another.
33
-func (k1 Key) Less(k2 Key) bool {
34
- if k1.Space != k2.Space {
35
- panic("k1 and k2 not in same key space.")
36
- }
37
- return k1.Space.Less(k1, k2)
38
-}
39
-
40
-// Distance returns this key's distance to another
41
-func (k1 Key) Distance(k2 Key) *big.Int {
42
- if k1.Space != k2.Space {
43
- panic("k1 and k2 not in same key space.")
44
- }
45
- return k1.Space.Distance(k1, k2)
46
-}
47
-
48
-// KeySpace is an object used to do math on identifiers. Each keyspace has its
49
-// own properties and rules. See XorKeySpace.
50
-type KeySpace interface {
51
-
52
- // Key converts an identifier into a Key in this space.
53
- Key([]byte) Key
54
-
55
- // Equal returns whether keys are equal in this key space
56
- Equal(Key, Key) bool
57
-
58
- // Distance returns the distance metric in this key space
59
- Distance(Key, Key) *big.Int
60
-
61
- // Less returns whether the first key is smaller than the second.
62
- Less(Key, Key) bool
63
-}
64
-
65
-// byDistanceToCenter is a type used to sort Keys by proximity to a center.
66
-type byDistanceToCenter struct {
67
- Center Key
68
- Keys []Key
69
-}
70
-
71
-func (s byDistanceToCenter) Len() int {
72
- return len(s.Keys)
73
-}
74
-
75
-func (s byDistanceToCenter) Swap(i, j int) {
76
- s.Keys[i], s.Keys[j] = s.Keys[j], s.Keys[i]
77
-}
78
-
79
-func (s byDistanceToCenter) Less(i, j int) bool {
80
- a := s.Center.Distance(s.Keys[i])
81
- b := s.Center.Distance(s.Keys[j])
82
- return a.Cmp(b) == -1
83
-}
84
-
85
-// SortByDistance takes a KeySpace, a center Key, and a list of Keys toSort.
86
-// It returns a new list, where the Keys toSort have been sorted by their
87
-// distance to the center Key.
88
-func SortByDistance(sp KeySpace, center Key, toSort []Key) []Key {
89
- toSortCopy := make([]Key, len(toSort))
90
- copy(toSortCopy, toSort)
91
- bdtc := &byDistanceToCenter{
92
- Center: center,
93
- Keys: toSortCopy, // copy
94
- }
95
- sort.Sort(bdtc)
96
- return bdtc.Keys
97
-}
routing/keyspace/xor.go
deleted
-67
@@ -1,67 +0,0 @@
1
-package keyspace
2
-
3
-import (
4
- "bytes"
5
- "crypto/sha256"
6
- "math/big"
7
-
8
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
9
-)
10
-
11
-// XORKeySpace is a KeySpace which:
12
-// - normalizes identifiers using a cryptographic hash (sha256)
13
-// - measures distance by XORing keys together
14
-var XORKeySpace = &xorKeySpace{}
15
-var _ KeySpace = XORKeySpace // ensure it conforms
16
-
17
-type xorKeySpace struct{}
18
-
19
-// Key converts an identifier into a Key in this space.
20
-func (s *xorKeySpace) Key(id []byte) Key {
21
- hash := sha256.Sum256(id)
22
- key := hash[:]
23
- return Key{
24
- Space: s,
25
- Original: id,
26
- Bytes: key,
27
- }
28
-}
29
-
30
-// Equal returns whether keys are equal in this key space
31
-func (s *xorKeySpace) Equal(k1, k2 Key) bool {
32
- return bytes.Equal(k1.Bytes, k2.Bytes)
33
-}
34
-
35
-// Distance returns the distance metric in this key space
36
-func (s *xorKeySpace) Distance(k1, k2 Key) *big.Int {
37
- // XOR the keys
38
- k3 := u.XOR(k1.Bytes, k2.Bytes)
39
-
40
- // interpret it as an integer
41
- dist := big.NewInt(0).SetBytes(k3)
42
- return dist
43
-}
44
-
45
-// Less returns whether the first key is smaller than the second.
46
-func (s *xorKeySpace) Less(k1, k2 Key) bool {
47
- a := k1.Bytes
48
- b := k2.Bytes
49
- for i := 0; i < len(a); i++ {
50
- if a[i] != b[i] {
51
- return a[i] < b[i]
52
- }
53
- }
54
- return true
55
-}
56
-
57
-// ZeroPrefixLen returns the number of consecutive zeroes in a byte slice.
58
-func ZeroPrefixLen(id []byte) int {
59
- for i := 0; i < len(id); i++ {
60
- for j := 0; j < 8; j++ {
61
- if (id[i]>>uint8(7-j))&0x1 != 0 {
62
- return i*8 + j
63
- }
64
- }
65
- }
66
- return len(id) * 8
67
-}
routing/keyspace/xor_test.go
deleted
-122
@@ -1,122 +0,0 @@
1
-package keyspace
2
-
3
-import (
4
- "bytes"
5
- "math/big"
6
- "testing"
7
-
8
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
9
-)
10
-
11
-func TestPrefixLen(t *testing.T) {
12
- cases := [][]byte{
13
- {0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00},
14
- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
15
- {0x00, 0x58, 0xFF, 0x80, 0x00, 0x00, 0xF0},
16
- }
17
- lens := []int{24, 56, 9}
18
-
19
- for i, c := range cases {
20
- r := ZeroPrefixLen(c)
21
- if r != lens[i] {
22
- t.Errorf("ZeroPrefixLen failed: %v != %v", r, lens[i])
23
- }
24
- }
25
-
26
-}
27
-
28
-func TestXorKeySpace(t *testing.T) {
29
-
30
- ids := [][]byte{
31
- {0xFF, 0xFF, 0xFF, 0xFF},
32
- {0x00, 0x00, 0x00, 0x00},
33
- {0xFF, 0xFF, 0xFF, 0xF0},
34
- }
35
-
36
- ks := [][2]Key{
37
- {XORKeySpace.Key(ids[0]), XORKeySpace.Key(ids[0])},
38
- {XORKeySpace.Key(ids[1]), XORKeySpace.Key(ids[1])},
39
- {XORKeySpace.Key(ids[2]), XORKeySpace.Key(ids[2])},
40
- }
41
-
42
- for i, set := range ks {
43
- if !set[0].Equal(set[1]) {
44
- t.Errorf("Key not eq. %v != %v", set[0], set[1])
45
- }
46
-
47
- if !bytes.Equal(set[0].Bytes, set[1].Bytes) {
48
- t.Errorf("Key gen failed. %v != %v", set[0].Bytes, set[1].Bytes)
49
- }
50
-
51
- if !bytes.Equal(set[0].Original, ids[i]) {
52
- t.Errorf("ptrs to original. %v != %v", set[0].Original, ids[i])
53
- }
54
-
55
- if len(set[0].Bytes) != 32 {
56
- t.Errorf("key length incorrect. 32 != %d", len(set[0].Bytes))
57
- }
58
- }
59
-
60
- for i := 1; i < len(ks); i++ {
61
- if ks[i][0].Less(ks[i-1][0]) == ks[i-1][0].Less(ks[i][0]) {
62
- t.Errorf("less should be different.")
63
- }
64
-
65
- if ks[i][0].Distance(ks[i-1][0]).Cmp(ks[i-1][0].Distance(ks[i][0])) != 0 {
66
- t.Errorf("distance should be the same.")
67
- }
68
-
69
- if ks[i][0].Equal(ks[i-1][0]) {
70
- t.Errorf("Keys should not be eq. %v != %v", ks[i][0], ks[i-1][0])
71
- }
72
- }
73
-}
74
-
75
-func TestDistancesAndCenterSorting(t *testing.T) {
76
-
77
- adjs := [][]byte{
78
- {173, 149, 19, 27, 192, 183, 153, 192, 177, 175, 71, 127, 177, 79, 207, 38, 166, 169, 247, 96, 121, 228, 139, 240, 144, 172, 183, 232, 54, 123, 253, 14},
79
- {223, 63, 97, 152, 4, 169, 47, 219, 64, 87, 25, 45, 196, 61, 215, 72, 234, 119, 138, 220, 82, 188, 73, 140, 232, 5, 36, 192, 20, 184, 17, 25},
80
- {73, 176, 221, 176, 149, 143, 22, 42, 129, 124, 213, 114, 232, 95, 189, 154, 18, 3, 122, 132, 32, 199, 53, 185, 58, 157, 117, 78, 52, 146, 157, 127},
81
- {73, 176, 221, 176, 149, 143, 22, 42, 129, 124, 213, 114, 232, 95, 189, 154, 18, 3, 122, 132, 32, 199, 53, 185, 58, 157, 117, 78, 52, 146, 157, 127},
82
- {73, 176, 221, 176, 149, 143, 22, 42, 129, 124, 213, 114, 232, 95, 189, 154, 18, 3, 122, 132, 32, 199, 53, 185, 58, 157, 117, 78, 52, 146, 157, 126},
83
- {73, 0, 221, 176, 149, 143, 22, 42, 129, 124, 213, 114, 232, 95, 189, 154, 18, 3, 122, 132, 32, 199, 53, 185, 58, 157, 117, 78, 52, 146, 157, 127},
84
- }
85
-
86
- keys := make([]Key, len(adjs))
87
- for i, a := range adjs {
88
- keys[i] = Key{Space: XORKeySpace, Bytes: a}
89
- }
90
-
91
- cmp := func(a int64, b *big.Int) int {
92
- return big.NewInt(a).Cmp(b)
93
- }
94
-
95
- if 0 != cmp(0, keys[2].Distance(keys[3])) {
96
- t.Errorf("distance calculation wrong: %v", keys[2].Distance(keys[3]))
97
- }
98
-
99
- if 0 != cmp(1, keys[2].Distance(keys[4])) {
100
- t.Errorf("distance calculation wrong: %v", keys[2].Distance(keys[4]))
101
- }
102
-
103
- d1 := keys[2].Distance(keys[5])
104
- d2 := u.XOR(keys[2].Bytes, keys[5].Bytes)
105
- d2 = d2[len(keys[2].Bytes)-len(d1.Bytes()):] // skip empty space for big
106
- if !bytes.Equal(d1.Bytes(), d2) {
107
- t.Errorf("bytes should be the same. %v == %v", d1.Bytes(), d2)
108
- }
109
-
110
- if -1 != cmp(2<<32, keys[2].Distance(keys[5])) {
111
- t.Errorf("2<<32 should be smaller")
112
- }
113
-
114
- keys2 := SortByDistance(XORKeySpace, keys[2], keys)
115
- order := []int{2, 3, 4, 5, 1, 0}
116
- for i, o := range order {
117
- if !bytes.Equal(keys[o].Bytes, keys2[i].Bytes) {
118
- t.Errorf("order is wrong. %d?? %v == %v", o, keys[o], keys2[i])
119
- }
120
- }
121
-
122
-}
routing/mock/centralized_client.go
+4
-4
@@ -4,11 +4,7 @@ import (
4
"errors"
5
"time"
6
7
- routing "github.com/ipfs/go-ipfs/routing"
8
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
7
"github.com/ipfs/go-ipfs/thirdparty/testutil"
10
- ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
11
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
8
9
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
10
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
@@ -16,7 +12,11 @@ import (
12
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
13
u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
14
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
15
+ ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
16
+ key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
17
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
18
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
19
+ dhtpb "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record/pb"
20
)
21
22
var log = logging.Logger("mockrouter")
routing/mock/dht.go
+1
-1
@@ -1,9 +1,9 @@
1
package mockrouting
2
3
import (
4
- dht "github.com/ipfs/go-ipfs/routing/dht"
4
"github.com/ipfs/go-ipfs/thirdparty/testutil"
5
mocknet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net/mock"
6
+ dht "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht"
7
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
8
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
9
sync "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore/sync"
routing/mock/interface.go
+2
-1
@@ -5,13 +5,14 @@
5
package mockrouting
6
7
import (
8
- routing "github.com/ipfs/go-ipfs/routing"
8
delay "github.com/ipfs/go-ipfs/thirdparty/delay"
9
"github.com/ipfs/go-ipfs/thirdparty/testutil"
10
+
11
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
12
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
13
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
14
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
15
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
16
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
17
)
18
routing/none/none_client.go
+1
-1
@@ -4,12 +4,12 @@ import (
4
"errors"
5
6
repo "github.com/ipfs/go-ipfs/repo"
7
- routing "github.com/ipfs/go-ipfs/routing"
7
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
8
p2phost "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/host"
9
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
10
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
11
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
12
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
13
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
14
)
15
routing/offline/offline.go
+3
-3
@@ -4,11 +4,11 @@ import (
4
"errors"
5
"time"
6
7
- routing "github.com/ipfs/go-ipfs/routing"
8
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
9
- record "github.com/ipfs/go-ipfs/routing/record"
7
ds "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
8
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
9
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
10
+ record "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record"
11
+ pb "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record/pb"
12
13
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
14
ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
routing/record/record.go
deleted
-48
@@ -1,48 +0,0 @@
1
-package record
2
-
3
-import (
4
- "bytes"
5
-
6
- proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
7
-
8
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
9
- logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
10
- ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
11
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
12
-)
13
-
14
-var log = logging.Logger("routing/record")
15
-
16
-// MakePutRecord creates and signs a dht record for the given key/value pair
17
-func MakePutRecord(sk ci.PrivKey, key key.Key, value []byte, sign bool) (*pb.Record, error) {
18
- record := new(pb.Record)
19
-
20
- record.Key = proto.String(string(key))
21
- record.Value = value
22
-
23
- pkh, err := sk.GetPublic().Hash()
24
- if err != nil {
25
- return nil, err
26
- }
27
-
28
- record.Author = proto.String(string(pkh))
29
- if sign {
30
- blob := RecordBlobForSig(record)
31
-
32
- sig, err := sk.Sign(blob)
33
- if err != nil {
34
- return nil, err
35
- }
36
-
37
- record.Signature = sig
38
- }
39
- return record, nil
40
-}
41
-
42
-// RecordBlobForSig returns the blob protected by the record signature
43
-func RecordBlobForSig(r *pb.Record) []byte {
44
- k := []byte(r.GetKey())
45
- v := []byte(r.GetValue())
46
- a := []byte(r.GetAuthor())
47
- return bytes.Join([][]byte{k, v, a}, []byte{})
48
-}
routing/record/selection.go
deleted
-40
@@ -1,40 +0,0 @@
1
-package record
2
-
3
-import (
4
- "errors"
5
-
6
- path "github.com/ipfs/go-ipfs/path"
7
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
8
-)
9
-
10
-// A SelectorFunc selects the best value for the given key from
11
-// a slice of possible values and returns the index of the chosen one
12
-type SelectorFunc func(key.Key, [][]byte) (int, error)
13
-
14
-type Selector map[string]SelectorFunc
15
-
16
-func (s Selector) BestRecord(k key.Key, recs [][]byte) (int, error) {
17
- if len(recs) == 0 {
18
- return 0, errors.New("no records given!")
19
- }
20
-
21
- parts := path.SplitList(string(k))
22
- if len(parts) < 3 {
23
- log.Infof("Record key does not have selectorfunc: %s", k)
24
- return 0, errors.New("record key does not have selectorfunc")
25
- }
26
-
27
- sel, ok := s[parts[1]]
28
- if !ok {
29
- log.Infof("Unrecognized key prefix: %s", parts[1])
30
- return 0, ErrInvalidRecordType
31
- }
32
-
33
- return sel(k, recs)
34
-}
35
-
36
-// PublicKeySelector just selects the first entry.
37
-// All valid public key records will be equivalent.
38
-func PublicKeySelector(k key.Key, vals [][]byte) (int, error) {
39
- return 0, nil
40
-}
routing/record/validation.go
deleted
-114
@@ -1,114 +0,0 @@
1
-package record
2
-
3
-import (
4
- "bytes"
5
- "errors"
6
- "fmt"
7
-
8
- path "github.com/ipfs/go-ipfs/path"
9
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
10
- ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
11
- mh "gx/ipfs/QmYf7ng2hG5XBtJA3tN34DQ2GUN5HNksEw1rLDkmr6vGku/go-multihash"
12
- u "gx/ipfs/QmZNVWh8LLjAavuQ2JXuFmuYH3C11xo988vSgp7UQrTRj1/go-ipfs-util"
13
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
14
-)
15
-
16
-// ValidatorFunc is a function that is called to validate a given
17
-// type of DHTRecord.
18
-type ValidatorFunc func(key.Key, []byte) error
19
-
20
-// ErrBadRecord is returned any time a dht record is found to be
21
-// incorrectly formatted or signed.
22
-var ErrBadRecord = errors.New("bad dht record")
23
-
24
-// ErrInvalidRecordType is returned if a DHTRecord keys prefix
25
-// is not found in the Validator map of the DHT.
26
-var ErrInvalidRecordType = errors.New("invalid record keytype")
27
-
28
-// Validator is an object that helps ensure routing records are valid.
29
-// It is a collection of validator functions, each of which implements
30
-// its own notion of validity.
31
-type Validator map[string]*ValidChecker
32
-
33
-type ValidChecker struct {
34
- Func ValidatorFunc
35
- Sign bool
36
-}
37
-
38
-// VerifyRecord checks a record and ensures it is still valid.
39
-// It runs needed validators
40
-func (v Validator) VerifyRecord(r *pb.Record) error {
41
- // Now, check validity func
42
- parts := path.SplitList(r.GetKey())
43
- if len(parts) < 3 {
44
- log.Infof("Record key does not have validator: %s", key.Key(r.GetKey()))
45
- return nil
46
- }
47
-
48
- val, ok := v[parts[1]]
49
- if !ok {
50
- log.Infof("Unrecognized key prefix: %s", parts[1])
51
- return ErrInvalidRecordType
52
- }
53
-
54
- return val.Func(key.Key(r.GetKey()), r.GetValue())
55
-}
56
-
57
-func (v Validator) IsSigned(k key.Key) (bool, error) {
58
- // Now, check validity func
59
- parts := path.SplitList(string(k))
60
- if len(parts) < 3 {
61
- log.Infof("Record key does not have validator: %s", k)
62
- return false, nil
63
- }
64
-
65
- val, ok := v[parts[1]]
66
- if !ok {
67
- log.Infof("Unrecognized key prefix: %s", parts[1])
68
- return false, ErrInvalidRecordType
69
- }
70
-
71
- return val.Sign, nil
72
-}
73
-
74
-// ValidatePublicKeyRecord implements ValidatorFunc and
75
-// verifies that the passed in record value is the PublicKey
76
-// that matches the passed in key.
77
-func ValidatePublicKeyRecord(k key.Key, val []byte) error {
78
- if len(k) < 5 {
79
- return errors.New("invalid public key record key")
80
- }
81
-
82
- prefix := string(k[:4])
83
- if prefix != "/pk/" {
84
- return errors.New("key was not prefixed with /pk/")
85
- }
86
-
87
- keyhash := []byte(k[4:])
88
- if _, err := mh.Cast(keyhash); err != nil {
89
- return fmt.Errorf("key did not contain valid multihash: %s", err)
90
- }
91
-
92
- pkh := u.Hash(val)
93
- if !bytes.Equal(keyhash, pkh) {
94
- return errors.New("public key does not match storage key")
95
- }
96
- return nil
97
-}
98
-
99
-var PublicKeyValidator = &ValidChecker{
100
- Func: ValidatePublicKeyRecord,
101
- Sign: false,
102
-}
103
-
104
-func CheckRecordSig(r *pb.Record, pk ci.PubKey) error {
105
- blob := RecordBlobForSig(r)
106
- good, err := pk.Verify(blob, r.Signature)
107
- if err != nil {
108
- return nil
109
- }
110
- if !good {
111
- return errors.New("invalid record signature")
112
- }
113
- return nil
114
-}
routing/record/validation_test.go
deleted
-35
@@ -1,35 +0,0 @@
1
-package record
2
-
3
-import (
4
- "encoding/base64"
5
- "testing"
6
-
7
- ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
8
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
9
-)
10
-
11
-var OffensiveKey = "CAASXjBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDjXAQQMal4SB2tSnX6NJIPmC69/BT8A8jc7/gDUZNkEhdhYHvc7k7S4vntV/c92nJGxNdop9fKJyevuNMuXhhHAgMBAAE="
12
-
13
-func TestValidatePublicKey(t *testing.T) {
14
- pkb, err := base64.StdEncoding.DecodeString(OffensiveKey)
15
- if err != nil {
16
- t.Fatal(err)
17
- }
18
-
19
- pubk, err := ci.UnmarshalPublicKey(pkb)
20
- if err != nil {
21
- t.Fatal(err)
22
- }
23
-
24
- pkh, err := pubk.Hash()
25
- if err != nil {
26
- t.Fatal(err)
27
- }
28
-
29
- k := key.Key("/pk/" + string(pkh))
30
-
31
- err = ValidatePublicKeyRecord(k, pkb)
32
- if err != nil {
33
- t.Fatal(err)
34
- }
35
-}
routing/routing.go
deleted
-105
@@ -1,105 +0,0 @@
1
-// package routing defines the interface for a routing system used by ipfs.
2
-package routing
3
-
4
-import (
5
- "errors"
6
-
7
- ci "gx/ipfs/QmVoi5es8D5fNHZDqoW6DgDAEPEV5hQp8GBz161vZXiwpQ/go-libp2p-crypto"
8
- peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
9
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
10
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
11
- pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
12
-)
13
-
14
-// ErrNotFound is returned when a search fails to find anything
15
-var ErrNotFound = errors.New("routing: not found")
16
-
17
-// ContentRouting is a value provider layer of indirection. It is used to find
18
-// information about who has what content.
19
-type ContentRouting interface {
20
- // Announce that this node can provide value for given key
21
- Provide(context.Context, key.Key) error
22
-
23
- // Search for peers who are able to provide a given key
24
- FindProvidersAsync(context.Context, key.Key, int) <-chan pstore.PeerInfo
25
-}
26
-
27
-// PeerRouting is a way to find information about certain peers.
28
-// This can be implemented by a simple lookup table, a tracking server,
29
-// or even a DHT.
30
-type PeerRouting interface {
31
- // Find specific Peer
32
- // FindPeer searches for a peer with given ID, returns a pstore.PeerInfo
33
- // with relevant addresses.
34
- FindPeer(context.Context, peer.ID) (pstore.PeerInfo, error)
35
-}
36
-
37
-type ValueStore interface {
38
- // Basic Put/Get
39
-
40
- // PutValue adds value corresponding to given Key.
41
- PutValue(context.Context, key.Key, []byte) error
42
-
43
- // GetValue searches for the value corresponding to given Key.
44
- GetValue(context.Context, key.Key) ([]byte, error)
45
-
46
- // GetValues searches for values corresponding to given Key.
47
- //
48
- // Passing a value of '0' for the count argument will cause the
49
- // routing interface to return values only from cached or local storage
50
- // and return an error if no cached value is found.
51
- //
52
- // Passing a value of '1' will return a local value if found, and query
53
- // the network for the first value it finds otherwise.
54
- // As a result, a value of '1' is mostly useful for cases where the record
55
- // in question has only one valid value (such as public keys)
56
- GetValues(c context.Context, k key.Key, count int) ([]RecvdVal, error)
57
-}
58
-
59
-// IpfsRouting is the combination of different routing types that ipfs
60
-// uses. It can be satisfied by a single item (such as a DHT) or multiple
61
-// different pieces that are more optimized to each task.
62
-type IpfsRouting interface {
63
- ContentRouting
64
- PeerRouting
65
- ValueStore
66
-
67
- // Bootstrap allows callers to hint to the routing system to get into a
68
- // Boostrapped state
69
- Bootstrap(context.Context) error
70
-
71
- // TODO expose io.Closer or plain-old Close error
72
-}
73
-
74
-// RecvdVal represents a dht value record that has been received from a given peer
75
-// it is used to track peers with expired records in order to correct them.
76
-type RecvdVal struct {
77
- From peer.ID
78
- Val []byte
79
-}
80
-
81
-type PubKeyFetcher interface {
82
- GetPublicKey(context.Context, peer.ID) (ci.PubKey, error)
83
-}
84
-
85
-// KeyForPublicKey returns the key used to retrieve public keys
86
-// from the dht.
87
-func KeyForPublicKey(id peer.ID) key.Key {
88
- return key.Key("/pk/" + string(id))
89
-}
90
-
91
-func GetPublicKey(r ValueStore, ctx context.Context, pkhash []byte) (ci.PubKey, error) {
92
- if dht, ok := r.(PubKeyFetcher); ok {
93
- // If we have a DHT as our routing system, use optimized fetcher
94
- return dht.GetPublicKey(ctx, peer.ID(pkhash))
95
- } else {
96
- key := key.Key("/pk/" + string(pkhash))
97
- pkval, err := r.GetValue(ctx, key)
98
- if err != nil {
99
- return nil, err
100
- }
101
-
102
- // get PublicKey from node.Data
103
- return ci.UnmarshalPublicKey(pkval)
104
- }
105
-}
routing/supernode/client.go
+15
-15
@@ -5,19 +5,19 @@ import (
5
"errors"
6
"time"
7
8
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
9
-
10
- routing "github.com/ipfs/go-ipfs/routing"
11
- pb "github.com/ipfs/go-ipfs/routing/dht/pb"
8
proxy "github.com/ipfs/go-ipfs/routing/supernode/proxy"
13
- loggables "gx/ipfs/QmYrv4LgCC8FhG2Ab4bwuq5DqBdwMtx3hMb3KKJDZcr2d7/go-libp2p-loggables"
9
10
logging "gx/ipfs/QmSpJByNKFX1sCsHBEp3R73FL4NF6FnQTEGyNAXHm2GS52/go-log"
11
"gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/host"
12
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
13
+ loggables "gx/ipfs/QmYrv4LgCC8FhG2Ab4bwuq5DqBdwMtx3hMb3KKJDZcr2d7/go-libp2p-loggables"
14
+ dhtpb "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht/pb"
15
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
16
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
17
+ key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
18
+ routing "gx/ipfs/QmcoQiBzRaaVv1DZbbXoDWiEtvDN94Ca1DcwnQKK2tP92s/go-libp2p-routing"
19
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
20
+ pb "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record/pb"
21
)
22
23
var log = logging.Logger("supernode")
@@ -45,13 +45,13 @@ func (c *Client) FindProvidersAsync(ctx context.Context, k key.Key, max int) <-c
45
ch := make(chan pstore.PeerInfo)
46
go func() {
47
defer close(ch)
48
- request := pb.NewMessage(pb.Message_GET_PROVIDERS, string(k), 0)
48
+ request := dhtpb.NewMessage(dhtpb.Message_GET_PROVIDERS, string(k), 0)
49
response, err := c.proxy.SendRequest(ctx, request)
50
if err != nil {
51
log.Debug(err)
52
return
53
}
54
- for _, p := range pb.PBPeersToPeerInfos(response.GetProviderPeers()) {
54
+ for _, p := range dhtpb.PBPeersToPeerInfos(response.GetProviderPeers()) {
55
select {
56
case <-ctx.Done():
57
log.Debug(ctx.Err())
@@ -69,14 +69,14 @@ func (c *Client) PutValue(ctx context.Context, k key.Key, v []byte) error {
69
if err != nil {
70
return err
71
}
72
- pmes := pb.NewMessage(pb.Message_PUT_VALUE, string(k), 0)
72
+ pmes := dhtpb.NewMessage(dhtpb.Message_PUT_VALUE, string(k), 0)
73
pmes.Record = r
74
return c.proxy.SendMessage(ctx, pmes) // wrap to hide the remote
75
}
76
77
func (c *Client) GetValue(ctx context.Context, k key.Key) ([]byte, error) {
78
defer log.EventBegin(ctx, "getValue", &k).Done()
79
- msg := pb.NewMessage(pb.Message_GET_VALUE, string(k), 0)
79
+ msg := dhtpb.NewMessage(dhtpb.Message_GET_VALUE, string(k), 0)
80
response, err := c.proxy.SendRequest(ctx, msg) // TODO wrap to hide the remote
81
if err != nil {
82
return nil, err
@@ -86,7 +86,7 @@ func (c *Client) GetValue(ctx context.Context, k key.Key) ([]byte, error) {
86
87
func (c *Client) GetValues(ctx context.Context, k key.Key, _ int) ([]routing.RecvdVal, error) {
88
defer log.EventBegin(ctx, "getValue", &k).Done()
89
- msg := pb.NewMessage(pb.Message_GET_VALUE, string(k), 0)
89
+ msg := dhtpb.NewMessage(dhtpb.Message_GET_VALUE, string(k), 0)
90
response, err := c.proxy.SendRequest(ctx, msg) // TODO wrap to hide the remote
91
if err != nil {
92
return nil, err
@@ -102,9 +102,9 @@ func (c *Client) GetValues(ctx context.Context, k key.Key, _ int) ([]routing.Rec
102
103
func (c *Client) Provide(ctx context.Context, k key.Key) error {
104
defer log.EventBegin(ctx, "provide", &k).Done()
105
- msg := pb.NewMessage(pb.Message_ADD_PROVIDER, string(k), 0)
105
+ msg := dhtpb.NewMessage(dhtpb.Message_ADD_PROVIDER, string(k), 0)
106
// FIXME how is connectedness defined for the local node
107
- pri := []pb.PeerRoutingInfo{
107
+ pri := []dhtpb.PeerRoutingInfo{
108
{
109
PeerInfo: pstore.PeerInfo{
110
ID: c.local,
@@ -112,18 +112,18 @@ func (c *Client) Provide(ctx context.Context, k key.Key) error {
112
},
113
},
114
}
115
- msg.ProviderPeers = pb.PeerRoutingInfosToPBPeers(pri)
115
+ msg.ProviderPeers = dhtpb.PeerRoutingInfosToPBPeers(pri)
116
return c.proxy.SendMessage(ctx, msg) // TODO wrap to hide remote
117
}
118
119
func (c *Client) FindPeer(ctx context.Context, id peer.ID) (pstore.PeerInfo, error) {
120
defer log.EventBegin(ctx, "findPeer", id).Done()
121
- request := pb.NewMessage(pb.Message_FIND_NODE, string(id), 0)
121
+ request := dhtpb.NewMessage(dhtpb.Message_FIND_NODE, string(id), 0)
122
response, err := c.proxy.SendRequest(ctx, request) // hide remote
123
if err != nil {
124
return pstore.PeerInfo{}, err
125
}
126
- for _, p := range pb.PBPeersToPeerInfos(response.GetCloserPeers()) {
126
+ for _, p := range dhtpb.PBPeersToPeerInfos(response.GetCloserPeers()) {
127
if p.ID == id {
128
return p, nil
129
}
routing/supernode/proxy/loopback.go
+3
-4
@@ -1,12 +1,11 @@
1
package proxy
2
3
import (
4
- ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io"
5
- context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
6
-
7
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
4
inet "gx/ipfs/QmUuwQUJmtvC6ReYcu7xaYKEUM3pD46H18dFn3LBhVt2Di/go-libp2p/p2p/net"
5
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
6
+ dhtpb "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht/pb"
7
+ ggio "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/io"
8
+ context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
9
)
10
11
// RequestHandler handles routing requests locally
routing/supernode/proxy/standard.go
+2
-2
@@ -14,9 +14,9 @@ import (
14
15
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
16
17
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
18
- kbucket "github.com/ipfs/go-ipfs/routing/kbucket"
17
+ kbucket "gx/ipfs/QmTZsN8hysGnbakvK6mS8rwDQ9uwokxmWFBv94pig6zGd1/go-libp2p-kbucket"
18
loggables "gx/ipfs/QmYrv4LgCC8FhG2Ab4bwuq5DqBdwMtx3hMb3KKJDZcr2d7/go-libp2p-loggables"
19
+ dhtpb "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht/pb"
20
)
21
22
const ProtocolSNR = "/ipfs/supernoderouting"
routing/supernode/server.go
+9
-8
@@ -4,16 +4,17 @@ import (
4
"errors"
5
"fmt"
6
7
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
8
- record "github.com/ipfs/go-ipfs/routing/record"
7
proxy "github.com/ipfs/go-ipfs/routing/supernode/proxy"
10
- datastore "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
11
- key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
8
9
peer "gx/ipfs/QmWXjJo15p4pzT7cayEwZi2sWgJqLnGDof6ZGMh9xBgU1p/go-libp2p-peer"
10
+ dhtpb "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht/pb"
11
proto "gx/ipfs/QmZ4Qi3GaRbjcx28Sme5eMH7RQjGkt8wHxt2a65oLaeFEV/gogo-protobuf/proto"
12
context "gx/ipfs/QmZy2y8t9zQH2a1b8q2ZSLKp17ATuJoCNxxyMFG5qFExpt/go-net/context"
13
+ datastore "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
14
+ key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
15
pstore "gx/ipfs/QmdMfSLMDBDYhtc4oF3NYGCZr5dy4wQb6Ji26N4D4mdxa2/go-libp2p-peerstore"
16
+ record "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record"
17
+ pb "gx/ipfs/Qme7D9iKHYxwq28p6PzCymywsYSRBx9uyGzW7qNB3s9VbC/go-libp2p-record/pb"
18
)
19
20
// Server handles routing queries using a database backend
@@ -115,7 +116,7 @@ func (s *Server) handleMessage(
116
var _ proxy.RequestHandler = &Server{}
117
var _ proxy.Proxy = &Server{}
118
118
-func getRoutingRecord(ds datastore.Datastore, k key.Key) (*dhtpb.Record, error) {
119
+func getRoutingRecord(ds datastore.Datastore, k key.Key) (*pb.Record, error) {
120
dskey := k.DsKey()
121
val, err := ds.Get(dskey)
122
if err != nil {
@@ -125,14 +126,14 @@ func getRoutingRecord(ds datastore.Datastore, k key.Key) (*dhtpb.Record, error)
126
if !ok {
127
return nil, fmt.Errorf("datastore had non byte-slice value for %v", dskey)
128
}
128
- var record dhtpb.Record
129
+ var record pb.Record
130
if err := proto.Unmarshal(recordBytes, &record); err != nil {
131
return nil, errors.New("failed to unmarshal dht record from datastore")
132
}
133
return &record, nil
134
}
135
135
-func putRoutingRecord(ds datastore.Datastore, k key.Key, value *dhtpb.Record) error {
136
+func putRoutingRecord(ds datastore.Datastore, k key.Key, value *pb.Record) error {
137
data, err := proto.Marshal(value)
138
if err != nil {
139
return err
@@ -204,7 +205,7 @@ func providerKey(k key.Key) datastore.Key {
205
return datastore.KeyWithNamespaces([]string{"routing", "providers", k.String()})
206
}
207
207
-func verify(ps pstore.Peerstore, r *dhtpb.Record) error {
208
+func verify(ps pstore.Peerstore, r *pb.Record) error {
209
v := make(record.Validator)
210
v["pk"] = record.PublicKeyValidator
211
p := peer.ID(r.GetAuthor())
routing/supernode/server_test.go
+1
-1
@@ -3,7 +3,7 @@ package supernode
3
import (
4
"testing"
5
6
- dhtpb "github.com/ipfs/go-ipfs/routing/dht/pb"
6
+ dhtpb "gx/ipfs/QmYvLYkYiVEi5LBHP2uFqiUaHqH7zWnEuRqoNEuGLNG6JB/go-libp2p-kad-dht/pb"
7
datastore "gx/ipfs/QmbzuUusHqaLLoNTDEVLcSF6vZDHZDLPC7p4bztRvvkXxU/go-datastore"
8
key "gx/ipfs/Qmce4Y4zg3sYr7xKM5UueS67vhNni6EeWgCRnb7MbLJMew/go-key"
9
)