378 lines
7.4 KiB
Go
378 lines
7.4 KiB
Go
package cli
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"sort"
|
|
"strings"
|
|
"text/tabwriter"
|
|
|
|
"github.com/dustin/go-humanize"
|
|
"github.com/urfave/cli/v2"
|
|
"golang.org/x/xerrors"
|
|
|
|
"github.com/libp2p/go-libp2p-core/peer"
|
|
protocol "github.com/libp2p/go-libp2p-core/protocol"
|
|
"github.com/multiformats/go-multiaddr"
|
|
|
|
"github.com/filecoin-project/go-address"
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
|
"github.com/filecoin-project/lotus/lib/addrutil"
|
|
)
|
|
|
|
var netCmd = &cli.Command{
|
|
Name: "net",
|
|
Usage: "Manage P2P Network",
|
|
Subcommands: []*cli.Command{
|
|
NetPeers,
|
|
netConnect,
|
|
NetListen,
|
|
NetId,
|
|
netFindPeer,
|
|
netScores,
|
|
NetReachability,
|
|
NetBandwidthCmd,
|
|
},
|
|
}
|
|
|
|
var NetPeers = &cli.Command{
|
|
Name: "peers",
|
|
Usage: "Print peers",
|
|
Flags: []cli.Flag{
|
|
&cli.BoolFlag{
|
|
Name: "agent",
|
|
Aliases: []string{"a"},
|
|
Usage: "Print agent name",
|
|
},
|
|
},
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
ctx := ReqContext(cctx)
|
|
peers, err := api.NetPeers(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
sort.Slice(peers, func(i, j int) bool {
|
|
return strings.Compare(string(peers[i].ID), string(peers[j].ID)) > 0
|
|
})
|
|
|
|
for _, peer := range peers {
|
|
var agent string
|
|
if cctx.Bool("agent") {
|
|
agent, err = api.NetAgentVersion(ctx, peer.ID)
|
|
if err != nil {
|
|
log.Warnf("getting agent version: %s", err)
|
|
} else {
|
|
agent = ", " + agent
|
|
}
|
|
}
|
|
|
|
fmt.Printf("%s, %s%s\n", peer.ID, peer.Addrs, agent)
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var netScores = &cli.Command{
|
|
Name: "scores",
|
|
Usage: "Print peers' pubsub scores",
|
|
Flags: []cli.Flag{
|
|
&cli.BoolFlag{
|
|
Name: "extended",
|
|
Usage: "print extended peer scores in json",
|
|
},
|
|
},
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
ctx := ReqContext(cctx)
|
|
scores, err := api.NetPubsubScores(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if cctx.Bool("extended") {
|
|
enc := json.NewEncoder(os.Stdout)
|
|
for _, peer := range scores {
|
|
err := enc.Encode(peer)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
} else {
|
|
for _, peer := range scores {
|
|
fmt.Printf("%s, %f\n", peer.ID, peer.Score.Score)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var NetListen = &cli.Command{
|
|
Name: "listen",
|
|
Usage: "List listen addresses",
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
ctx := ReqContext(cctx)
|
|
|
|
addrs, err := api.NetAddrsListen(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
for _, peer := range addrs.Addrs {
|
|
fmt.Printf("%s/p2p/%s\n", peer, addrs.ID)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var netConnect = &cli.Command{
|
|
Name: "connect",
|
|
Usage: "Connect to a peer",
|
|
ArgsUsage: "[peerMultiaddr|minerActorAddress]",
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
ctx := ReqContext(cctx)
|
|
|
|
pis, err := addrutil.ParseAddresses(ctx, cctx.Args().Slice())
|
|
if err != nil {
|
|
a, perr := address.NewFromString(cctx.Args().First())
|
|
if perr != nil {
|
|
return err
|
|
}
|
|
|
|
na, fc, err := GetFullNodeAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer fc()
|
|
|
|
mi, err := na.StateMinerInfo(ctx, a, types.EmptyTSK)
|
|
if err != nil {
|
|
return xerrors.Errorf("getting miner info: %w", err)
|
|
}
|
|
|
|
if mi.PeerId == nil {
|
|
return xerrors.Errorf("no PeerID for miner")
|
|
}
|
|
multiaddrs := make([]multiaddr.Multiaddr, 0, len(mi.Multiaddrs))
|
|
for i, a := range mi.Multiaddrs {
|
|
maddr, err := multiaddr.NewMultiaddrBytes(a)
|
|
if err != nil {
|
|
log.Warnf("parsing multiaddr %d (%x): %s", i, a, err)
|
|
continue
|
|
}
|
|
multiaddrs = append(multiaddrs, maddr)
|
|
}
|
|
|
|
pi := peer.AddrInfo{
|
|
ID: *mi.PeerId,
|
|
Addrs: multiaddrs,
|
|
}
|
|
|
|
fmt.Printf("%s -> %s\n", a, pi)
|
|
|
|
pis = append(pis, pi)
|
|
}
|
|
|
|
for _, pi := range pis {
|
|
fmt.Printf("connect %s: ", pi.ID.Pretty())
|
|
err := api.NetConnect(ctx, pi)
|
|
if err != nil {
|
|
fmt.Println("failure")
|
|
return err
|
|
}
|
|
fmt.Println("success")
|
|
}
|
|
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var NetId = &cli.Command{
|
|
Name: "id",
|
|
Usage: "Get node identity",
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
|
|
ctx := ReqContext(cctx)
|
|
|
|
pid, err := api.ID(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println(pid)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var netFindPeer = &cli.Command{
|
|
Name: "findpeer",
|
|
Usage: "Find the addresses of a given peerID",
|
|
ArgsUsage: "[peerId]",
|
|
Action: func(cctx *cli.Context) error {
|
|
if cctx.NArg() != 1 {
|
|
fmt.Println("Usage: findpeer [peer ID]")
|
|
return nil
|
|
}
|
|
|
|
pid, err := peer.Decode(cctx.Args().First())
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
|
|
ctx := ReqContext(cctx)
|
|
|
|
addrs, err := api.NetFindPeer(ctx, pid)
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println(addrs)
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var NetReachability = &cli.Command{
|
|
Name: "reachability",
|
|
Usage: "Print information about reachability from the internet",
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
|
|
ctx := ReqContext(cctx)
|
|
|
|
i, err := api.NetAutoNatStatus(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Println("AutoNAT status: ", i.Reachability.String())
|
|
if i.PublicAddr != "" {
|
|
fmt.Println("Public address: ", i.PublicAddr)
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
var NetBandwidthCmd = &cli.Command{
|
|
Name: "bandwidth",
|
|
Usage: "Print bandwidth usage information",
|
|
Flags: []cli.Flag{
|
|
&cli.BoolFlag{
|
|
Name: "by-peer",
|
|
Usage: "list bandwidth usage by peer",
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: "by-protocol",
|
|
Usage: "list bandwidth usage by protocol",
|
|
},
|
|
},
|
|
Action: func(cctx *cli.Context) error {
|
|
api, closer, err := GetAPI(cctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer closer()
|
|
|
|
ctx := ReqContext(cctx)
|
|
|
|
bypeer := cctx.Bool("by-peer")
|
|
byproto := cctx.Bool("by-protocol")
|
|
|
|
tw := tabwriter.NewWriter(os.Stdout, 4, 4, 2, ' ', 0)
|
|
|
|
fmt.Fprintf(tw, "Segment\tTotalIn\tTotalOut\tRateIn\tRateOut\n")
|
|
|
|
if bypeer {
|
|
bw, err := api.NetBandwidthStatsByPeer(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var peers []string
|
|
for p := range bw {
|
|
peers = append(peers, p)
|
|
}
|
|
|
|
sort.Slice(peers, func(i, j int) bool {
|
|
return peers[i] < peers[j]
|
|
})
|
|
|
|
for _, p := range peers {
|
|
s := bw[p]
|
|
fmt.Fprintf(tw, "%s\t%s\t%s\t%s/s\t%s/s\n", p, humanize.Bytes(uint64(s.TotalIn)), humanize.Bytes(uint64(s.TotalOut)), humanize.Bytes(uint64(s.RateIn)), humanize.Bytes(uint64(s.RateOut)))
|
|
}
|
|
} else if byproto {
|
|
bw, err := api.NetBandwidthStatsByProtocol(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var protos []protocol.ID
|
|
for p := range bw {
|
|
protos = append(protos, p)
|
|
}
|
|
|
|
sort.Slice(protos, func(i, j int) bool {
|
|
return protos[i] < protos[j]
|
|
})
|
|
|
|
for _, p := range protos {
|
|
s := bw[p]
|
|
if p == "" {
|
|
p = "<unknown>"
|
|
}
|
|
fmt.Fprintf(tw, "%s\t%s\t%s\t%s/s\t%s/s\n", p, humanize.Bytes(uint64(s.TotalIn)), humanize.Bytes(uint64(s.TotalOut)), humanize.Bytes(uint64(s.RateIn)), humanize.Bytes(uint64(s.RateOut)))
|
|
}
|
|
} else {
|
|
|
|
s, err := api.NetBandwidthStats(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
fmt.Fprintf(tw, "Total\t%s\t%s\t%s/s\t%s/s\n", humanize.Bytes(uint64(s.TotalIn)), humanize.Bytes(uint64(s.TotalOut)), humanize.Bytes(uint64(s.RateIn)), humanize.Bytes(uint64(s.RateOut)))
|
|
}
|
|
|
|
return tw.Flush()
|
|
|
|
},
|
|
}
|