github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/p2p/netutil/iptrack.go (about) 1 2 //<developer> 3 // <name>linapex 曹一峰</name> 4 // <email>linapex@163.com</email> 5 // <wx>superexc</wx> 6 // <qqgroup>128148617</qqgroup> 7 // <url>https://jsq.ink</url> 8 // <role>pku engineer</role> 9 // <date>2019-03-16 19:16:41</date> 10 //</624450105306517504> 11 12 13 package netutil 14 15 import ( 16 "time" 17 18 "github.com/ethereum/go-ethereum/common/mclock" 19 ) 20 21 //IPtracker预测本地主机的外部端点,即IP地址和端口 22 //基于其他主机的语句。 23 type IPTracker struct { 24 window time.Duration 25 contactWindow time.Duration 26 minStatements int 27 clock mclock.Clock 28 statements map[string]ipStatement 29 contact map[string]mclock.AbsTime 30 lastStatementGC mclock.AbsTime 31 lastContactGC mclock.AbsTime 32 } 33 34 type ipStatement struct { 35 endpoint string 36 time mclock.AbsTime 37 } 38 39 //newiptracker创建一个IP跟踪器。 40 // 41 //窗口参数配置保留的过去网络事件的数量。这个 42 //minStatements参数强制执行必须记录的最小语句数 43 //在做出任何预测之前。这些参数的值越高,则“拍打”越小。 44 //网络条件变化时的预测。窗口持续时间值通常应在 45 //分钟的范围。 46 func NewIPTracker(window, contactWindow time.Duration, minStatements int) *IPTracker { 47 return &IPTracker{ 48 window: window, 49 contactWindow: contactWindow, 50 statements: make(map[string]ipStatement), 51 minStatements: minStatements, 52 contact: make(map[string]mclock.AbsTime), 53 clock: mclock.System{}, 54 } 55 } 56 57 //PredictTfullconenat检查本地主机是否位于全锥NAT之后。它预测 58 //正在检查是否已从以前未联系的节点接收到任何语句 59 //声明已作出。 60 func (it *IPTracker) PredictFullConeNAT() bool { 61 now := it.clock.Now() 62 it.gcContact(now) 63 it.gcStatements(now) 64 for host, st := range it.statements { 65 if c, ok := it.contact[host]; !ok || c > st.time { 66 return true 67 } 68 } 69 return false 70 } 71 72 //PredictEndPoint返回外部终结点的当前预测。 73 func (it *IPTracker) PredictEndpoint() string { 74 it.gcStatements(it.clock.Now()) 75 76 //当前的策略很简单:使用大多数语句查找端点。 77 counts := make(map[string]int) 78 maxcount, max := 0, "" 79 for _, s := range it.statements { 80 c := counts[s.endpoint] + 1 81 counts[s.endpoint] = c 82 if c > maxcount && c >= it.minStatements { 83 maxcount, max = c, s.endpoint 84 } 85 } 86 return max 87 } 88 89 //addStatement记录某个主机认为我们的外部端点是给定的端点。 90 func (it *IPTracker) AddStatement(host, endpoint string) { 91 now := it.clock.Now() 92 it.statements[host] = ipStatement{endpoint, now} 93 if time.Duration(now-it.lastStatementGC) >= it.window { 94 it.gcStatements(now) 95 } 96 } 97 98 //addcontact记录包含端点信息的数据包已发送到 99 //某些宿主。 100 func (it *IPTracker) AddContact(host string) { 101 now := it.clock.Now() 102 it.contact[host] = now 103 if time.Duration(now-it.lastContactGC) >= it.contactWindow { 104 it.gcContact(now) 105 } 106 } 107 108 func (it *IPTracker) gcStatements(now mclock.AbsTime) { 109 it.lastStatementGC = now 110 cutoff := now.Add(-it.window) 111 for host, s := range it.statements { 112 if s.time < cutoff { 113 delete(it.statements, host) 114 } 115 } 116 } 117 118 func (it *IPTracker) gcContact(now mclock.AbsTime) { 119 it.lastContactGC = now 120 cutoff := now.Add(-it.contactWindow) 121 for host, ct := range it.contact { 122 if ct < cutoff { 123 delete(it.contact, host) 124 } 125 } 126 } 127