diff --git a/core/commands/p2p.go b/core/commands/p2p.go index 9a65de5c48d0..a8ead6d4926f 100644 --- a/core/commands/p2p.go +++ b/core/commands/p2p.go @@ -1,7 +1,6 @@ package commands import ( - "bytes" "context" "errors" "fmt" @@ -11,15 +10,16 @@ import ( "text/tabwriter" "time" - cmds "github.com/ipfs/go-ipfs/commands" core "github.com/ipfs/go-ipfs/core" + cmdenv "github.com/ipfs/go-ipfs/core/commands/cmdenv" p2p "github.com/ipfs/go-ipfs/p2p" + cmds "gx/ipfs/QmSXUokcP4TJpFfqozT69AVAYRtzXVMUjzQVkYX41R9Svs/go-ipfs-cmds" ma "gx/ipfs/QmT4U94DnD8FRfqr21obWY32HLM5VExccPKMjQHofeYqr9/go-multiaddr" pstore "gx/ipfs/QmTTJcDL3gsnGDALjh2fDGg1onGRUdVgNL2hU2WEZcVrMX/go-libp2p-peerstore" - "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" - "gx/ipfs/QmZc5PLgxW61uTPG24TroxHDF6xzgbhZZQf5i53ciQC47Y/go-ipfs-addr" - "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit" + protocol "gx/ipfs/QmZNkThpqfVXs9GNbexPrfBbXSLNYeKrE7jwFM2oqHbyqN/go-libp2p-protocol" + ipfsaddr "gx/ipfs/QmZc5PLgxW61uTPG24TroxHDF6xzgbhZZQf5i53ciQC47Y/go-ipfs-addr" + cmdkit "gx/ipfs/Qmde5VP1qUkyQXKCfmEUA7bP64V2HAptbJ7phuPp7jXWwg/go-ipfs-cmdkit" madns "gx/ipfs/QmeHJXPqCNzSFbVkYM1uQLuM2L5FyJB9zukQ7EeqRP8ZC9/go-multiaddr-dns" ) @@ -69,8 +69,7 @@ are refined`, }, Subcommands: map[string]*cmds.Command{ - "stream": p2pStreamCmd, - + "stream": p2pStreamCmd, "forward": p2pForwardCmd, "listen": p2pListenCmd, "close": p2pCloseCmd, @@ -101,47 +100,35 @@ Example: Options: []cmdkit.Option{ cmdkit.BoolOption(allowCustomProtocolOptionName, "Don't require /x/ prefix"), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := p2pGetNode(req) + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := p2pGetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - protoOpt := req.Arguments()[0] - listenOpt := req.Arguments()[1] - targetOpt := req.Arguments()[2] + protoOpt := req.Arguments[0] + listenOpt := req.Arguments[1] + targetOpt := req.Arguments[2] proto := protocol.ID(protoOpt) listen, err := ma.NewMultiaddr(listenOpt) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } targets, err := parseIpfsAddr(targetOpt) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - allowCustom, _, err := req.Option(allowCustomProtocolOptionName).Bool() - if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } + allowCustom, _ := req.Options[allowCustomProtocolOptionName].(bool) if !allowCustom && !strings.HasPrefix(string(proto), P2PProtoPrefix) { - res.SetError(errors.New("protocol name must be within '"+P2PProtoPrefix+"' namespace"), cmdkit.ErrNormal) - return + return errors.New("protocol name must be within '" + P2PProtoPrefix + "' namespace") } - if err := forwardLocal(n.Context(), n.P2P, n.Peerstore, proto, listen, targets); err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - res.SetOutput(nil) + return forwardLocal(n.Context(), n.P2P, n.Peerstore, proto, listen, targets) }, } @@ -197,47 +184,37 @@ Example: Options: []cmdkit.Option{ cmdkit.BoolOption(allowCustomProtocolOptionName, "Don't require /x/ prefix"), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := p2pGetNode(req) + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := p2pGetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - protoOpt := req.Arguments()[0] - targetOpt := req.Arguments()[1] + protoOpt := req.Arguments[0] + targetOpt := req.Arguments[1] proto := protocol.ID(protoOpt) target, err := ma.NewMultiaddr(targetOpt) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } // port can't be 0 if err := checkPort(target); err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - allowCustom, _, err := req.Option(allowCustomProtocolOptionName).Bool() + allowCustom, _ := req.Options[allowCustomProtocolOptionName].(bool) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } if !allowCustom && !strings.HasPrefix(string(proto), P2PProtoPrefix) { - res.SetError(errors.New("protocol name must be within '"+P2PProtoPrefix+"' namespace"), cmdkit.ErrNormal) - return + return errors.New("protocol name must be within '" + P2PProtoPrefix + "' namespace") } - if err := forwardRemote(n.Context(), n.P2P, proto, target); err != nil { - res.SetError(err, cmdkit.ErrNormal) - return - } - - res.SetOutput(nil) + return forwardRemote(n.Context(), n.P2P, proto, target) }, } @@ -305,11 +282,10 @@ var p2pLsCmd = &cmds.Command{ Options: []cmdkit.Option{ cmdkit.BoolOption(p2pHeadersOptionName, "v", "Print table headers (Protocol, Listen, Target)."), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := p2pGetNode(req) + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := p2pGetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } output := &P2PLsOutput{} @@ -334,31 +310,24 @@ var p2pLsCmd = &cmds.Command{ } n.P2P.ListenersP2P.Unlock() - res.SetOutput(output) + return res.Emit(output) }, Type: P2PLsOutput{}, - Marshalers: cmds.MarshalerMap{ - cmds.Text: func(res cmds.Response) (io.Reader, error) { - v, err := unwrapOutput(res.Output()) - if err != nil { - return nil, err - } - - headers, _, _ := res.Request().Option(p2pHeadersOptionName).Bool() - list := v.(*P2PLsOutput) - buf := new(bytes.Buffer) - w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0) - for _, listener := range list.Listeners { + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *P2PLsOutput) error { + headers, _ := req.Options[p2pHeadersOptionName].(bool) + tw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0) + for _, listener := range out.Listeners { if headers { - fmt.Fprintln(w, "Protocol\tListen Address\tTarget Address") + fmt.Fprintln(tw, "Protocol\tListen Address\tTarget Address") } - fmt.Fprintf(w, "%s\t%s\t%s\n", listener.Protocol, listener.ListenAddress, listener.TargetAddress) + fmt.Fprintf(tw, "%s\t%s\t%s\n", listener.Protocol, listener.ListenAddress, listener.TargetAddress) } - w.Flush() + tw.Flush() - return buf, nil - }, + return nil + }), }, } @@ -379,40 +348,35 @@ var p2pCloseCmd = &cmds.Command{ cmdkit.StringOption(p2pListenAddressOptionName, "l", "Match listen address"), cmdkit.StringOption(p2pTargetAddressOptionName, "t", "Match target address"), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := p2pGetNode(req) + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := p2pGetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - closeAll, _, _ := req.Option(p2pAllOptionName).Bool() - protoOpt, p, _ := req.Option(p2pProtocolOptionName).String() - listenOpt, l, _ := req.Option(p2pListenAddressOptionName).String() - targetOpt, t, _ := req.Option(p2pTargetAddressOptionName).String() + closeAll, _ := req.Options[p2pAllOptionName].(bool) + protoOpt, p := req.Options[p2pProtocolOptionName].(string) + listenOpt, l := req.Options[p2pListenAddressOptionName].(string) + targetOpt, t := req.Options[p2pTargetAddressOptionName].(string) proto := protocol.ID(protoOpt) listen, err := ma.NewMultiaddr(listenOpt) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } target, err := ma.NewMultiaddr(targetOpt) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } if !(closeAll || p || l || t) { - res.SetError(errors.New("no matching options given"), cmdkit.ErrNormal) - return + return errors.New("no matching options given") } if closeAll && (p || l || t) { - res.SetError(errors.New("can't combine --all with other matching options"), cmdkit.ErrNormal) - return + return errors.New("can't combine --all with other matching options") } match := func(listener p2p.Listener) bool { @@ -434,22 +398,14 @@ var p2pCloseCmd = &cmds.Command{ done := n.P2P.ListenersLocal.Close(match) done += n.P2P.ListenersP2P.Close(match) - res.SetOutput(done) + return res.Emit(done) }, Type: int(0), - Marshalers: cmds.MarshalerMap{ - cmds.Text: func(res cmds.Response) (io.Reader, error) { - v, err := unwrapOutput(res.Output()) - if err != nil { - return nil, err - } - - closed := v.(int) - buf := new(bytes.Buffer) - fmt.Fprintf(buf, "Closed %d stream(s)\n", closed) - - return buf, nil - }, + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out int) error { + fmt.Fprintf(w, "Closed %d stream(s)\n", out) + return nil + }), }, } @@ -477,11 +433,10 @@ var p2pStreamLsCmd = &cmds.Command{ Options: []cmdkit.Option{ cmdkit.BoolOption(p2pHeadersOptionName, "v", "Print table headers (ID, Protocol, Local, Remote)."), }, - Run: func(req cmds.Request, res cmds.Response) { - n, err := p2pGetNode(req) + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := p2pGetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } output := &P2PStreamsOutput{} @@ -499,31 +454,24 @@ var p2pStreamLsCmd = &cmds.Command{ } n.P2P.Streams.Unlock() - res.SetOutput(output) + return res.Emit(output) }, Type: P2PStreamsOutput{}, - Marshalers: cmds.MarshalerMap{ - cmds.Text: func(res cmds.Response) (io.Reader, error) { - v, err := unwrapOutput(res.Output()) - if err != nil { - return nil, err - } - - headers, _, _ := res.Request().Option(p2pHeadersOptionName).Bool() - list := v.(*P2PStreamsOutput) - buf := new(bytes.Buffer) - w := tabwriter.NewWriter(buf, 1, 2, 1, ' ', 0) - for _, stream := range list.Streams { + Encoders: cmds.EncoderMap{ + cmds.Text: cmds.MakeTypedEncoder(func(req *cmds.Request, w io.Writer, out *P2PStreamsOutput) error { + headers, _ := req.Options[p2pHeadersOptionName].(bool) + tw := tabwriter.NewWriter(w, 1, 2, 1, ' ', 0) + for _, stream := range out.Streams { if headers { - fmt.Fprintln(w, "ID\tProtocol\tOrigin\tTarget") + fmt.Fprintln(tw, "ID\tProtocol\tOrigin\tTarget") } - fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", stream.HandlerID, stream.Protocol, stream.OriginAddress, stream.TargetAddress) + fmt.Fprintf(tw, "%s\t%s\t%s\t%s\n", stream.HandlerID, stream.Protocol, stream.OriginAddress, stream.TargetAddress) } - w.Flush() + tw.Flush() - return buf, nil - }, + return nil + }), }, } @@ -537,28 +485,23 @@ var p2pStreamCloseCmd = &cmds.Command{ Options: []cmdkit.Option{ cmdkit.BoolOption(p2pAllOptionName, "a", "Close all streams."), }, - Run: func(req cmds.Request, res cmds.Response) { - res.SetOutput(nil) - - n, err := p2pGetNode(req) + Run: func(req *cmds.Request, res cmds.ResponseEmitter, env cmds.Environment) error { + n, err := p2pGetNode(env) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } - closeAll, _, _ := req.Option(p2pAllOptionName).Bool() + closeAll, _ := req.Options[p2pAllOptionName].(bool) var handlerID uint64 if !closeAll { - if len(req.Arguments()) == 0 { - res.SetError(errors.New("no id specified"), cmdkit.ErrNormal) - return + if len(req.Arguments) == 0 { + return errors.New("no id specified") } - handlerID, err = strconv.ParseUint(req.Arguments()[0], 10, 64) + handlerID, err = strconv.ParseUint(req.Arguments[0], 10, 64) if err != nil { - res.SetError(err, cmdkit.ErrNormal) - return + return err } } @@ -578,16 +521,18 @@ var p2pStreamCloseCmd = &cmds.Command{ for _, s := range toClose { n.P2P.Streams.Reset(s) } + + return nil }, } -func p2pGetNode(req cmds.Request) (*core.IpfsNode, error) { - n, err := req.InvocContext().GetNode() +func p2pGetNode(env cmds.Environment) (*core.IpfsNode, error) { + nd, err := cmdenv.GetNode(env) if err != nil { return nil, err } - config, err := n.Repo.Config() + config, err := nd.Repo.Config() if err != nil { return nil, err } @@ -596,9 +541,9 @@ func p2pGetNode(req cmds.Request) (*core.IpfsNode, error) { return nil, errors.New("libp2p stream mounting not enabled") } - if !n.OnlineMode() { + if !nd.OnlineMode() { return nil, ErrNotOnline } - return n, nil + return nd, nil } diff --git a/core/commands/root.go b/core/commands/root.go index 5013d39de305..315e49bda2f4 100644 --- a/core/commands/root.go +++ b/core/commands/root.go @@ -137,7 +137,7 @@ var rootSubcommands = map[string]*cmds.Command{ "object": ocmd.ObjectCmd, "pin": lgc.NewCommand(PinCmd), "ping": lgc.NewCommand(PingCmd), - "p2p": lgc.NewCommand(P2PCmd), + "p2p": P2PCmd, "refs": lgc.NewCommand(RefsCmd), "resolve": ResolveCmd, "swarm": SwarmCmd,