@cryptotaxi247 / kubo / commits / 2e6e0f18e

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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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, &notif.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 )