Implement DHT Api
This commit was moved from ipfs/go-ipfs-http-client@c77355067a22300a8abe6b93b354de0ae0a3b548
Łukasz Magiera committed
Jan 15, 2019 at 17:01 UTC
ed9f2dd091693e914e9de072b2c23c2f991210a6
2 files changed
+99
-1
client/httpapi/api.go
+1
-1
@@ -158,7 +158,7 @@ func (api *HttpApi) Object() iface.ObjectAPI {
158
}
159
160
func (api *HttpApi) Dht() iface.DhtAPI {
161
- return nil
161
+ return (*DhtAPI)(api)
162
}
163
164
func (api *HttpApi) Swarm() iface.SwarmAPI {
client/httpapi/dht.go
new
+98
@@ -0,0 +1,98 @@
1
+package httpapi
2
+
3
+import (
4
+ "context"
5
+ "encoding/json"
6
+ "github.com/ipfs/go-ipfs/core/coreapi/interface"
7
+ caopts "github.com/ipfs/go-ipfs/core/coreapi/interface/options"
8
+
9
+ "github.com/libp2p/go-libp2p-peer"
10
+ "github.com/libp2p/go-libp2p-peerstore"
11
+ notif "github.com/libp2p/go-libp2p-routing/notifications"
12
+)
13
+
14
+type DhtAPI HttpApi
15
+
16
+func (api *DhtAPI) FindPeer(ctx context.Context, p peer.ID) (peerstore.PeerInfo, error) {
17
+ var out struct {
18
+ Type notif.QueryEventType
19
+ Responses []peerstore.PeerInfo
20
+ }
21
+ resp, err := api.core().request("dht/findpeer", p.Pretty()).Send(ctx)
22
+ if err != nil {
23
+ return peerstore.PeerInfo{}, err
24
+ }
25
+ if resp.Error != nil {
26
+ return peerstore.PeerInfo{}, resp.Error
27
+ }
28
+ defer resp.Close()
29
+ dec := json.NewDecoder(resp.Output)
30
+ for {
31
+ if err := dec.Decode(&out); err != nil {
32
+ return peerstore.PeerInfo{}, err
33
+ }
34
+ if out.Type == notif.FinalPeer {
35
+ return out.Responses[0], nil
36
+ }
37
+ }
38
+}
39
+
40
+func (api *DhtAPI) FindProviders(ctx context.Context, p iface.Path, opts ...caopts.DhtFindProvidersOption) (<-chan peerstore.PeerInfo, error) {
41
+ options, err := caopts.DhtFindProvidersOptions(opts...)
42
+ if err != nil {
43
+ return nil, err
44
+ }
45
+ resp, err := api.core().request("dht/findprovs", p.String()).
46
+ Option("num-providers", options.NumProviders).
47
+ Send(ctx)
48
+ if err != nil {
49
+ return nil, err
50
+ }
51
+ if resp.Error != nil {
52
+ return nil, resp.Error
53
+ }
54
+ res := make(chan peerstore.PeerInfo)
55
+
56
+ go func() {
57
+ defer resp.Close()
58
+ defer close(res)
59
+ dec := json.NewDecoder(resp.Output)
60
+
61
+ for {
62
+ var out struct {
63
+ Type notif.QueryEventType
64
+ Responses []peerstore.PeerInfo
65
+ }
66
+
67
+ if err := dec.Decode(&out); err != nil {
68
+ return // todo: handle this somehow
69
+ }
70
+ if out.Type == notif.Provider {
71
+ for _, pi := range out.Responses {
72
+ select {
73
+ case res <- pi:
74
+ case <-ctx.Done():
75
+ return
76
+ }
77
+ }
78
+ }
79
+ }
80
+ }()
81
+
82
+ return res, nil
83
+}
84
+
85
+func (api *DhtAPI) Provide(ctx context.Context, p iface.Path, opts ...caopts.DhtProvideOption) error {
86
+ options, err := caopts.DhtProvideOptions(opts...)
87
+ if err != nil {
88
+ return err
89
+ }
90
+
91
+ return api.core().request("dht/provide", p.String()).
92
+ Option("recursive", options.Recursive).
93
+ Exec(ctx, nil)
94
+}
95
+
96
+func (api *DhtAPI) core() *HttpApi {
97
+ return (*HttpApi)(api)
98
+}