master
go 177 lines 4.08 KB
Raw
1 package name
2
3 import (
4 "fmt"
5 "io"
6 "strings"
7
8 cmds "github.com/ipfs/go-ipfs-cmds"
9 "github.com/ipfs/kubo/core/commands/cmdenv"
10 ke "github.com/ipfs/kubo/core/commands/keyencode"
11 record "github.com/libp2p/go-libp2p-record"
12 "github.com/libp2p/go-libp2p/core/peer"
13 )
14
15 type ipnsPubsubState struct {
16 Enabled bool
17 }
18
19 type ipnsPubsubCancel struct {
20 Canceled bool
21 }
22
23 type stringList struct {
24 Strings []string
25 }
26
27 // IpnsPubsubCmd is the subcommand that allows us to manage the IPNS pubsub system
28 var IpnsPubsubCmd = &cmds.Command{
29 Status: cmds.Experimental,
30 Helptext: cmds.HelpText{
31 Tagline: "IPNS pubsub management",
32 ShortDescription: `
33 Manage and inspect the state of the IPNS pubsub resolver.
34
35 Note: this command is experimental and subject to change as the system is refined
36 `,
37 },
38 Subcommands: map[string]*cmds.Command{
39 "state": ipnspsStateCmd,
40 "subs": ipnspsSubsCmd,
41 "cancel": ipnspsCancelCmd,
42 },
43 }
44
45 var ipnspsStateCmd = &cmds.Command{
46 Status: cmds.Experimental,
47 Helptext: cmds.HelpText{
48 Tagline: "Query the state of IPNS pubsub.",
49 },
50 Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
51 n, err := cmdenv.GetNode(env)
52 if err != nil {
53 return err
54 }
55
56 return cmds.EmitOnce(res, &ipnsPubsubState{n.PSRouter != nil})
57 },
58 Type: ipnsPubsubState{},
59 Encoders: cmds.EncoderMap{
60 cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ips *ipnsPubsubState) error {
61 var state string
62 if ips.Enabled {
63 state = "enabled"
64 } else {
65 state = "disabled"
66 }
67
68 _, err := fmt.Fprintln(w, state)
69 return err
70 }),
71 },
72 }
73
74 var ipnspsSubsCmd = &cmds.Command{
75 Status: cmds.Experimental,
76 Helptext: cmds.HelpText{
77 Tagline: "Show current name subscriptions.",
78 },
79 Options: []cmds.Option{
80 ke.OptionIPNSBase,
81 },
82 Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
83 keyEnc, err := ke.KeyEncoderFromString(req.Options[ke.OptionIPNSBase.Name()].(string))
84 if err != nil {
85 return err
86 }
87
88 n, err := cmdenv.GetNode(env)
89 if err != nil {
90 return err
91 }
92
93 if n.PSRouter == nil {
94 return cmds.Errorf(cmds.ErrClient, "IPNS pubsub subsystem is not enabled")
95 }
96 var paths []string
97 for _, key := range n.PSRouter.GetSubscriptions() {
98 ns, k, err := record.SplitKey(key)
99 if err != nil || ns != "ipns" {
100 // Not necessarily an error.
101 continue
102 }
103 pid, err := peer.IDFromBytes([]byte(k))
104 if err != nil {
105 log.Errorf("ipns key not a valid peer ID: %s", err)
106 continue
107 }
108 paths = append(paths, "/ipns/"+keyEnc.FormatID(pid))
109 }
110
111 return cmds.EmitOnce(res, &stringList{paths})
112 },
113 Type: stringList{},
114 Encoders: cmds.EncoderMap{
115 cmds.Text: stringListEncoder(),
116 },
117 }
118
119 var ipnspsCancelCmd = &cmds.Command{
120 Status: cmds.Experimental,
121 Helptext: cmds.HelpText{
122 Tagline: "Cancel a name subscription.",
123 },
124 Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error {
125 n, err := cmdenv.GetNode(env)
126 if err != nil {
127 return err
128 }
129
130 if n.PSRouter == nil {
131 return cmds.Errorf(cmds.ErrClient, "IPNS pubsub subsystem is not enabled")
132 }
133
134 name := req.Arguments[0]
135 name = strings.TrimPrefix(name, "/ipns/")
136 pid, err := peer.Decode(name)
137 if err != nil {
138 return cmds.Errorf(cmds.ErrClient, "not a valid IPNS name: %s", err)
139 }
140
141 ok, err := n.PSRouter.Cancel("/ipns/" + string(pid))
142 if err != nil {
143 return err
144 }
145 return cmds.EmitOnce(res, &ipnsPubsubCancel{ok})
146 },
147 Arguments: []cmds.Argument{
148 cmds.StringArg("name", true, false, "Name to cancel the subscription for."),
149 },
150 Type: ipnsPubsubCancel{},
151 Encoders: cmds.EncoderMap{
152 cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, ipc *ipnsPubsubCancel) error {
153 var state string
154 if ipc.Canceled {
155 state = "canceled"
156 } else {
157 state = "no subscription"
158 }
159
160 _, err := fmt.Fprintln(w, state)
161 return err
162 }),
163 },
164 }
165
166 func stringListEncoder() cmds.EncoderFunc {
167 return cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, list *stringList) error {
168 for _, s := range list.Strings {
169 _, err := fmt.Fprintln(w, s)
170 if err != nil {
171 return err
172 }
173 }
174
175 return nil
176 })
177 }