337 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			337 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package cli
 | |
| 
 | |
| import (
 | |
| 	"encoding/json"
 | |
| 	"fmt"
 | |
| 	"os"
 | |
| 	"sort"
 | |
| 	"strings"
 | |
| 	"text/tabwriter"
 | |
| 
 | |
| 	"github.com/libp2p/go-libp2p-core/peer"
 | |
| 	protocol "github.com/libp2p/go-libp2p-core/protocol"
 | |
| 
 | |
| 	"github.com/dustin/go-humanize"
 | |
| 	"github.com/urfave/cli/v2"
 | |
| 
 | |
| 	"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]",
 | |
| 	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 {
 | |
| 			return err
 | |
| 		}
 | |
| 
 | |
| 		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()
 | |
| 
 | |
| 	},
 | |
| }
 |