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()
 | 
						|
 | 
						|
	},
 | 
						|
}
 |