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 }