github.com/nxtrace/NTrace-core@v1.3.1-0.20240513132635-39169291e8c9/printer/realtime_printer.go (about)

     1  package printer
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/nxtrace/NTrace-core/util"
     6  	"net"
     7  	"strconv"
     8  	"strings"
     9  
    10  	"github.com/fatih/color"
    11  	"github.com/nxtrace/NTrace-core/trace"
    12  )
    13  
    14  func RealtimePrinter(res *trace.Result, ttl int) {
    15  	fmt.Printf("%s  ", color.New(color.FgHiYellow, color.Bold).Sprintf("%-2d", ttl+1))
    16  	// 去重
    17  	var latestIP string
    18  	tmpMap := make(map[string][]string)
    19  	for i, v := range res.Hops[ttl] {
    20  		if v.Address == nil && latestIP != "" {
    21  			tmpMap[latestIP] = append(tmpMap[latestIP], fmt.Sprintf("%s ms", "*"))
    22  			continue
    23  		} else if v.Address == nil {
    24  			continue
    25  		}
    26  
    27  		if _, exist := tmpMap[v.Address.String()]; !exist {
    28  			tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], strconv.Itoa(i))
    29  			// 首次进入
    30  			if latestIP == "" {
    31  				for j := 0; j < i; j++ {
    32  					tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], fmt.Sprintf("%s ms", "*"))
    33  				}
    34  			}
    35  			latestIP = v.Address.String()
    36  		}
    37  
    38  		tmpMap[v.Address.String()] = append(tmpMap[v.Address.String()], fmt.Sprintf("%.2f ms", v.RTT.Seconds()*1000))
    39  	}
    40  
    41  	if latestIP == "" {
    42  		fmt.Fprintf(color.Output, "%s\n",
    43  			color.New(color.FgWhite, color.Bold).Sprintf("*"),
    44  		)
    45  		return
    46  	}
    47  
    48  	var blockDisplay = false
    49  	for ip, v := range tmpMap {
    50  		if blockDisplay {
    51  			fmt.Printf("%4s", "")
    52  		}
    53  		if net.ParseIP(ip).To4() == nil {
    54  			if util.EnableHidDstIP == "" || ip != util.DestIP {
    55  				fmt.Fprintf(color.Output, "%s",
    56  					color.New(color.FgWhite, color.Bold).Sprintf("%-25s", ip),
    57  				)
    58  			} else {
    59  				fmt.Fprintf(color.Output, "%s",
    60  					color.New(color.FgWhite, color.Bold).Sprintf("%-25s", util.HideIPPart(ip)),
    61  				)
    62  			}
    63  		} else {
    64  			if util.EnableHidDstIP == "" || ip != util.DestIP {
    65  				fmt.Fprintf(color.Output, "%s",
    66  					color.New(color.FgWhite, color.Bold).Sprintf("%-15s", ip),
    67  				)
    68  			} else {
    69  				fmt.Fprintf(color.Output, "%s",
    70  					color.New(color.FgWhite, color.Bold).Sprintf("%-15s", util.HideIPPart(ip)),
    71  				)
    72  			}
    73  		}
    74  
    75  		i, _ := strconv.Atoi(v[0])
    76  		if res.Hops[ttl][i].Geo.Asnumber != "" {
    77  			/*** CMIN2, CUG, CN2, CUII, CTG 改为壕金色高亮
    78  			/* 小孩子不懂事加着玩的
    79  			/* 此处的高亮不代表任何线路质量
    80  			/* 仅代表走了这部分的ASN
    81  			/* 如果使用这些ASN的IP同样会被高亮
    82  			***/
    83  			switch {
    84  			case res.Hops[ttl][i].Geo.Asnumber == "58807":
    85  				fallthrough
    86  			case res.Hops[ttl][i].Geo.Asnumber == "10099":
    87  				fallthrough
    88  			case res.Hops[ttl][i].Geo.Asnumber == "4809":
    89  				fallthrough
    90  			case res.Hops[ttl][i].Geo.Asnumber == "9929":
    91  				fallthrough
    92  			case res.Hops[ttl][i].Geo.Asnumber == "23764":
    93  				fallthrough
    94  			case res.Hops[ttl][i].Geo.Whois == "CTG-CN":
    95  				fallthrough
    96  			case res.Hops[ttl][i].Geo.Whois == "[CNC-BACKBONE]":
    97  				fallthrough
    98  			case res.Hops[ttl][i].Geo.Whois == "[CUG-BACKBONE]":
    99  				fallthrough
   100  			case res.Hops[ttl][i].Geo.Whois == "CMIN2-NET":
   101  				fallthrough
   102  			case strings.HasPrefix(res.Hops[ttl][i].Address.String(), "59.43."):
   103  				fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber))
   104  			default:
   105  				fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("AS%-6s", res.Hops[ttl][i].Geo.Asnumber))
   106  			}
   107  
   108  		} else {
   109  			fmt.Printf(" %-8s", "*")
   110  		}
   111  
   112  		if net.ParseIP(ip).To4() != nil {
   113  			whoisFormat := strings.Split(res.Hops[ttl][i].Geo.Whois, "-")
   114  			if len(whoisFormat) > 1 {
   115  				whoisFormat[0] = strings.Join(whoisFormat[:2], "-")
   116  			}
   117  
   118  			if whoisFormat[0] != "" {
   119  				//如果以RFC或DOD开头那么为空
   120  				if !(strings.HasPrefix(whoisFormat[0], "RFC") ||
   121  					strings.HasPrefix(whoisFormat[0], "DOD")) {
   122  					whoisFormat[0] = "[" + whoisFormat[0] + "]"
   123  				} else {
   124  					whoisFormat[0] = ""
   125  				}
   126  			}
   127  
   128  			// CMIN2, CUII, CN2, CUG 改为壕金色高亮
   129  			switch {
   130  			case res.Hops[ttl][i].Geo.Asnumber == "58807":
   131  				fallthrough
   132  			case res.Hops[ttl][i].Geo.Asnumber == "10099":
   133  				fallthrough
   134  			case res.Hops[ttl][i].Geo.Asnumber == "4809":
   135  				fallthrough
   136  			case res.Hops[ttl][i].Geo.Asnumber == "9929":
   137  				fallthrough
   138  			case res.Hops[ttl][i].Geo.Asnumber == "23764":
   139  				fallthrough
   140  			case whoisFormat[0] == "[CTG-CN]":
   141  				fallthrough
   142  			case whoisFormat[0] == "[CNC-BACKBONE]":
   143  				fallthrough
   144  			case whoisFormat[0] == "[CUG-BACKBONE]":
   145  				fallthrough
   146  			case whoisFormat[0] == "[CMIN2-NET]":
   147  				fallthrough
   148  			case strings.HasPrefix(res.Hops[ttl][i].Address.String(), "59.43."):
   149  				fmt.Fprintf(color.Output, " %s", color.New(color.FgHiYellow, color.Bold).Sprintf("%-16s", whoisFormat[0]))
   150  			default:
   151  				fmt.Fprintf(color.Output, " %s", color.New(color.FgHiGreen, color.Bold).Sprintf("%-16s", whoisFormat[0]))
   152  			}
   153  		}
   154  
   155  		applyLangSetting(&res.Hops[ttl][i]) // 应用语言设置
   156  
   157  		if net.ParseIP(ip).To4() != nil {
   158  
   159  			fmt.Fprintf(color.Output, " %s %s %s %s %s\n    %s   ",
   160  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country),
   161  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov),
   162  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City),
   163  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.District),
   164  				fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner),
   165  				color.New(color.FgHiBlack, color.Bold).Sprintf("%-39s", res.Hops[ttl][i].Hostname),
   166  			)
   167  		} else {
   168  			fmt.Fprintf(color.Output, " %s %s %s %s %s\n    %s   ",
   169  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Country),
   170  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.Prov),
   171  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.City),
   172  				color.New(color.FgWhite, color.Bold).Sprintf("%s", res.Hops[ttl][i].Geo.District),
   173  				fmt.Sprintf("%-6s", res.Hops[ttl][i].Geo.Owner),
   174  				color.New(color.FgHiBlack, color.Bold).Sprintf("%-32s", res.Hops[ttl][i].Hostname),
   175  			)
   176  		}
   177  
   178  		for j := 1; j < len(v); j++ {
   179  			if len(v) == 2 || j == 1 {
   180  				fmt.Fprintf(color.Output, "%s",
   181  					color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]),
   182  				)
   183  			} else {
   184  				fmt.Fprintf(color.Output, " / %s",
   185  					color.New(color.FgHiCyan, color.Bold).Sprintf("%s", v[j]),
   186  				)
   187  			}
   188  		}
   189  		for _, v := range res.Hops[ttl][i].MPLS {
   190  			fmt.Fprintf(color.Output, "%s",
   191  				color.New(color.FgHiBlack, color.Bold).Sprintf("\n    %s", v),
   192  			)
   193  		}
   194  		fmt.Println()
   195  		blockDisplay = true
   196  	}
   197  }