master
go 134 lines 3.11 KB
Raw
1 package rpc
2
3 import (
4 "context"
5 "encoding/json"
6 "fmt"
7 "io"
8
9 "github.com/ipfs/boxo/ipns"
10 "github.com/ipfs/boxo/namesys"
11 "github.com/ipfs/boxo/path"
12 iface "github.com/ipfs/kubo/core/coreiface"
13 caopts "github.com/ipfs/kubo/core/coreiface/options"
14 )
15
16 type NameAPI HttpApi
17
18 type ipnsEntry struct {
19 Name string `json:"Name"`
20 Value string `json:"Value"`
21 }
22
23 func (api *NameAPI) Publish(ctx context.Context, p path.Path, opts ...caopts.NamePublishOption) (ipns.Name, error) {
24 options, err := caopts.NamePublishOptions(opts...)
25 if err != nil {
26 return ipns.Name{}, err
27 }
28
29 req := api.core().Request("name/publish", p.String()).
30 Option("key", options.Key).
31 Option("allow-offline", options.AllowOffline).
32 Option("lifetime", options.ValidTime).
33 Option("resolve", false)
34
35 if options.TTL != nil {
36 req.Option("ttl", options.TTL)
37 }
38
39 var out ipnsEntry
40 if err := req.Exec(ctx, &out); err != nil {
41 return ipns.Name{}, err
42 }
43 return ipns.NameFromString(out.Name)
44 }
45
46 func (api *NameAPI) Search(ctx context.Context, name string, opts ...caopts.NameResolveOption) (<-chan iface.IpnsResult, error) {
47 options, err := caopts.NameResolveOptions(opts...)
48 if err != nil {
49 return nil, err
50 }
51
52 ropts := namesys.ProcessResolveOptions(options.ResolveOpts)
53 if ropts.Depth != namesys.DefaultDepthLimit && ropts.Depth != 1 {
54 return nil, fmt.Errorf("Name.Resolve: depth other than 1 or %d not supported", namesys.DefaultDepthLimit)
55 }
56
57 req := api.core().Request("name/resolve", name).
58 Option("nocache", !options.Cache).
59 Option("recursive", ropts.Depth != 1).
60 Option("dht-record-count", ropts.DhtRecordCount).
61 Option("dht-timeout", ropts.DhtTimeout).
62 Option("stream", true)
63 resp, err := req.Send(ctx)
64 if err != nil {
65 return nil, err
66 }
67 if resp.Error != nil {
68 return nil, resp.Error
69 }
70
71 res := make(chan iface.IpnsResult)
72
73 go func() {
74 defer close(res)
75 defer resp.Close()
76
77 dec := json.NewDecoder(resp.Output)
78
79 for {
80 var out struct{ Path string }
81 err := dec.Decode(&out)
82 if err == io.EOF {
83 return
84 }
85 var ires iface.IpnsResult
86 if err == nil {
87 p, err := path.NewPath(out.Path)
88 if err != nil {
89 return
90 }
91 ires.Path = p
92 }
93
94 select {
95 case res <- ires:
96 case <-ctx.Done():
97 }
98 if err != nil {
99 return
100 }
101 }
102 }()
103
104 return res, nil
105 }
106
107 func (api *NameAPI) Resolve(ctx context.Context, name string, opts ...caopts.NameResolveOption) (path.Path, error) {
108 options, err := caopts.NameResolveOptions(opts...)
109 if err != nil {
110 return nil, err
111 }
112
113 ropts := namesys.ProcessResolveOptions(options.ResolveOpts)
114 if ropts.Depth != namesys.DefaultDepthLimit && ropts.Depth != 1 {
115 return nil, fmt.Errorf("Name.Resolve: depth other than 1 or %d not supported", namesys.DefaultDepthLimit)
116 }
117
118 req := api.core().Request("name/resolve", name).
119 Option("nocache", !options.Cache).
120 Option("recursive", ropts.Depth != 1).
121 Option("dht-record-count", ropts.DhtRecordCount).
122 Option("dht-timeout", ropts.DhtTimeout)
123
124 var out struct{ Path string }
125 if err := req.Exec(ctx, &out); err != nil {
126 return nil, err
127 }
128
129 return path.NewPath(out.Path)
130 }
131
132 func (api *NameAPI) core() *HttpApi {
133 return (*HttpApi)(api)
134 }