mirror of
https://github.com/nxtrace/NTrace-core.git
synced 2025-08-12 06:26:39 +00:00
105 lines
3.2 KiB
Go
105 lines
3.2 KiB
Go
package printer
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/nxtrace/NTrace-core/trace"
|
|
)
|
|
|
|
type HopInfo int
|
|
|
|
const (
|
|
General HopInfo = 0
|
|
IXP HopInfo = 1
|
|
Peer HopInfo = 2
|
|
PoP HopInfo = 3
|
|
Aboard HopInfo = 4
|
|
)
|
|
|
|
func findLatestAvailableHop(res *trace.Result, ttl int, probesIndex int) int {
|
|
for ttl > 0 {
|
|
// 查找上一个跃点是不是有效结果
|
|
ttl--
|
|
// 判断此TTL跃点是否有效并判断地理位置结构体是否已经初始化
|
|
if len(res.Hops[ttl]) != 0 && res.Hops[ttl][probesIndex].Success && res.Hops[ttl][probesIndex].Geo != nil {
|
|
// TTL虽有效,但地理位置API没有能够正确返回数据,依旧不能视为有效数据
|
|
if res.Hops[ttl][probesIndex].Geo.Country == "" {
|
|
// 跳过继续寻找上一个有效跃点
|
|
continue
|
|
}
|
|
return ttl
|
|
}
|
|
}
|
|
// 没找到
|
|
return -1
|
|
}
|
|
|
|
func unifyName(name string) string {
|
|
if name == "China" || name == "CN" {
|
|
return "中国"
|
|
} else if name == "Hong kong" || name == "香港" || name == "Central and Western" {
|
|
return "中国香港"
|
|
} else if name == "Taiwan" || name == "台湾" {
|
|
return "中国台湾"
|
|
} else {
|
|
return name
|
|
}
|
|
}
|
|
|
|
func chinaISPPeer(hostname string) bool {
|
|
var keyWords = []string{"china", "ct", "cu", "cm", "cnc", "4134", "4837", "4809", "9929"}
|
|
for _, k := range keyWords {
|
|
if strings.Contains(strings.ToLower(hostname), k) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func chinaMainland(h trace.Hop) bool {
|
|
if unifyName(h.Geo.Country) == "中国" && unifyName(h.Geo.Prov) != "中国香港" && unifyName(h.Geo.Prov) != "中国台湾" {
|
|
return true
|
|
} else {
|
|
return false
|
|
}
|
|
}
|
|
|
|
func makeHopsType(res *trace.Result, ttl int) map[int]HopInfo {
|
|
// 创建一个字典,存放所有当前TTL的跃点类型集合
|
|
hopProbesMap := make(map[int]HopInfo)
|
|
for i := range res.Hops[ttl] {
|
|
// 判断是否res.Hops[ttl][i]是一个有效的跃点并且地理位置信息已经初始化
|
|
if res.Hops[ttl][i].Success && res.Hops[ttl][i].Geo != nil {
|
|
if availableTTL := findLatestAvailableHop(res, ttl, i); availableTTL != -1 {
|
|
switch {
|
|
case strings.Contains(res.Hops[ttl][i].Geo.District, "IXP") || strings.Contains(strings.ToLower(res.Hops[ttl][i].Hostname), "ix"):
|
|
hopProbesMap[i] = IXP
|
|
case strings.Contains(res.Hops[ttl][i].Geo.District, "Peer") || chinaISPPeer(res.Hops[ttl][i].Hostname):
|
|
hopProbesMap[i] = Peer
|
|
case strings.Contains(res.Hops[ttl][i].Geo.District, "PoP"):
|
|
hopProbesMap[i] = PoP
|
|
// 2个有效跃点必须都为有效数据,如果当前跳没有地理位置信息或者为局域网,不能视为有效节点
|
|
case res.Hops[availableTTL][i].Geo.Country != "LAN Address" && res.Hops[ttl][i].Geo.Country != "LAN Address" && res.Hops[ttl][i].Geo.Country != "" &&
|
|
// 一个跃点在中国大陆,另外一个跃点在其他地区,则可以推断出数据包跨境
|
|
chinaMainland(res.Hops[availableTTL][i]) != chinaMainland(res.Hops[ttl][i]):
|
|
// TODO: 将先后2跳跃点信息汇报给API,以完善相关数据
|
|
hopProbesMap[i] = Aboard
|
|
}
|
|
} else {
|
|
hopProbesMap[i] = General
|
|
}
|
|
}
|
|
}
|
|
|
|
return hopProbesMap
|
|
}
|
|
|
|
func ClassicPrinter(res *trace.Result, ttl int) {
|
|
fmt.Print(ttl + 1)
|
|
hopsTypeMap := makeHopsType(res, ttl)
|
|
for i := range res.Hops[ttl] {
|
|
HopPrinter(res.Hops[ttl][i], hopsTypeMap[i])
|
|
}
|
|
}
|