github.com/yinchengtsinghua/golang-Eos-dpos-Ethereum@v0.0.0-20190121132951-92cc4225ed8e/p2p/netutil/net.go (about) 1 2 //此源码被清华学神尹成大魔王专业翻译分析并修改 3 //尹成QQ77025077 4 //尹成微信18510341407 5 //尹成所在QQ群721929980 6 //尹成邮箱 yinc13@mails.tsinghua.edu.cn 7 //尹成毕业于清华大学,微软区块链领域全球最有价值专家 8 //https://mvp.microsoft.com/zh-cn/PublicProfile/4033620 9 //版权所有2016 Go Ethereum作者 10 //此文件是Go以太坊库的一部分。 11 // 12 //Go-Ethereum库是免费软件:您可以重新分发它和/或修改 13 //根据GNU发布的较低通用公共许可证的条款 14 //自由软件基金会,或者许可证的第3版,或者 15 //(由您选择)任何更高版本。 16 // 17 //Go以太坊图书馆的发行目的是希望它会有用, 18 //但没有任何保证;甚至没有 19 //适销性或特定用途的适用性。见 20 //GNU较低的通用公共许可证,了解更多详细信息。 21 // 22 //你应该收到一份GNU较低级别的公共许可证副本 23 //以及Go以太坊图书馆。如果没有,请参见<http://www.gnu.org/licenses/>。 24 25 //包netutil包含对网络包的扩展。 26 package netutil 27 28 import ( 29 "bytes" 30 "errors" 31 "fmt" 32 "net" 33 "sort" 34 "strings" 35 ) 36 37 var lan4, lan6, special4, special6 Netlist 38 39 func init() { 40 //来自RFC 5735、RFC 5156的列表, 41 //https://www.iana.org/assignments/iana-ipv4-special-registry/ 42 lan4.Add("0.0.0.0/8") //“这个”网络 43 lan4.Add("10.0.0.0/8") //私人使用 44 lan4.Add("172.16.0.0/12") //私人使用 45 lan4.Add("192.168.0.0/16") //私人使用 46 lan6.Add("fe80::/10") //链路本地 47 lan6.Add("fc00::/7") //独特的地方 48 special4.Add("192.0.0.0/29") //IPv4服务连续性 49 special4.Add("192.0.0.9/32") //PCP选播 50 special4.Add("192.0.0.170/32") //NAT64/DNS64发现 51 special4.Add("192.0.0.171/32") //NAT64/DNS64发现 52 special4.Add("192.0.2.0/24") //测试网络-1 53 special4.Add("192.31.196.0/24") //AS112 54 special4.Add("192.52.193.0/24") //AMT 55 special4.Add("192.88.99.0/24") //6to4继电器选播 56 special4.Add("192.175.48.0/24") //AS112 57 special4.Add("198.18.0.0/15") //设备基准测试 58 special4.Add("198.51.100.0/24") //测试网NET-2 59 special4.Add("203.0.113.0/24") //测试网-3 60 special4.Add("255.255.255.255/32") //有限广播 61 62 //http://www.iana.org/assignments/iana-ipv6-special-registry/ 63 special6.Add("100::/64") 64 special6.Add("2001::/32") 65 special6.Add("2001:1::1/128") 66 special6.Add("2001:2::/48") 67 special6.Add("2001:3::/32") 68 special6.Add("2001:4:112::/48") 69 special6.Add("2001:5::/32") 70 special6.Add("2001:10::/28") 71 special6.Add("2001:20::/28") 72 special6.Add("2001:db8::/32") 73 special6.Add("2002::/16") 74 } 75 76 //netlist是IP网络的列表。 77 type Netlist []net.IPNet 78 79 //ParseNetList解析CIDR掩码的逗号分隔列表。 80 //空白和多余的逗号将被忽略。 81 func ParseNetlist(s string) (*Netlist, error) { 82 ws := strings.NewReplacer(" ", "", "\n", "", "\t", "") 83 masks := strings.Split(ws.Replace(s), ",") 84 l := make(Netlist, 0) 85 for _, mask := range masks { 86 if mask == "" { 87 continue 88 } 89 _, n, err := net.ParseCIDR(mask) 90 if err != nil { 91 return nil, err 92 } 93 l = append(l, *n) 94 } 95 return &l, nil 96 } 97 98 //marshaltoml实现toml.marshalerrec。 99 func (l Netlist) MarshalTOML() interface{} { 100 list := make([]string, 0, len(l)) 101 for _, net := range l { 102 list = append(list, net.String()) 103 } 104 return list 105 } 106 107 //unmarshaltoml实现toml.unmarshalerrec。 108 func (l *Netlist) UnmarshalTOML(fn func(interface{}) error) error { 109 var masks []string 110 if err := fn(&masks); err != nil { 111 return err 112 } 113 for _, mask := range masks { 114 _, n, err := net.ParseCIDR(mask) 115 if err != nil { 116 return err 117 } 118 *l = append(*l, *n) 119 } 120 return nil 121 } 122 123 //添加分析CIDR掩码并将其附加到列表中。它对无效的掩码感到恐慌,并且 124 //用于设置静态列表。 125 func (l *Netlist) Add(cidr string) { 126 _, n, err := net.ParseCIDR(cidr) 127 if err != nil { 128 panic(err) 129 } 130 *l = append(*l, *n) 131 } 132 133 //包含报告给定IP是否包含在列表中。 134 func (l *Netlist) Contains(ip net.IP) bool { 135 if l == nil { 136 return false 137 } 138 for _, net := range *l { 139 if net.Contains(ip) { 140 return true 141 } 142 } 143 return false 144 } 145 146 //islan报告IP是否为本地网络地址。 147 func IsLAN(ip net.IP) bool { 148 if ip.IsLoopback() { 149 return true 150 } 151 if v4 := ip.To4(); v4 != nil { 152 return lan4.Contains(v4) 153 } 154 return lan6.Contains(ip) 155 } 156 157 //IsSpecialNetwork报告IP是否位于专用网络范围内 158 //这包括广播、多播和文档地址。 159 func IsSpecialNetwork(ip net.IP) bool { 160 if ip.IsMulticast() { 161 return true 162 } 163 if v4 := ip.To4(); v4 != nil { 164 return special4.Contains(v4) 165 } 166 return special6.Contains(ip) 167 } 168 169 var ( 170 errInvalid = errors.New("invalid IP") 171 errUnspecified = errors.New("zero address") 172 errSpecial = errors.New("special network") 173 errLoopback = errors.New("loopback address from non-loopback host") 174 errLAN = errors.New("LAN address from WAN host") 175 ) 176 177 //checkrelayip报告是否从给定的发送方IP中继IP 178 //是有效的连接目标。 179 // 180 //有四条规则: 181 //-特殊网络地址永远无效。 182 //-如果由回送主机中继,则回送地址正常。 183 //-如果由LAN主机中继,则LAN地址正常。 184 //-所有其他地址始终可以接受。 185 func CheckRelayIP(sender, addr net.IP) error { 186 if len(addr) != net.IPv4len && len(addr) != net.IPv6len { 187 return errInvalid 188 } 189 if addr.IsUnspecified() { 190 return errUnspecified 191 } 192 if IsSpecialNetwork(addr) { 193 return errSpecial 194 } 195 if addr.IsLoopback() && !sender.IsLoopback() { 196 return errLoopback 197 } 198 if IsLAN(addr) && !IsLAN(sender) { 199 return errLAN 200 } 201 return nil 202 } 203 204 //Samenet报告两个IP地址是否具有相同的给定位长度前缀。 205 func SameNet(bits uint, ip, other net.IP) bool { 206 ip4, other4 := ip.To4(), other.To4() 207 switch { 208 case (ip4 == nil) != (other4 == nil): 209 return false 210 case ip4 != nil: 211 return sameNet(bits, ip4, other4) 212 default: 213 return sameNet(bits, ip.To16(), other.To16()) 214 } 215 } 216 217 func sameNet(bits uint, ip, other net.IP) bool { 218 nb := int(bits / 8) 219 mask := ^byte(0xFF >> (bits % 8)) 220 if mask != 0 && nb < len(ip) && ip[nb]&mask != other[nb]&mask { 221 return false 222 } 223 return nb <= len(ip) && bytes.Equal(ip[:nb], other[:nb]) 224 } 225 226 //DistinctNetset跟踪IP,确保最多N个IP 227 //属于同一网络范围。 228 type DistinctNetSet struct { 229 Subnet uint //公共前缀位数 230 Limit uint //每个子网中的最大IP数 231 232 members map[string]uint 233 buf net.IP 234 } 235 236 //添加将IP地址添加到集合中。如果 237 //定义范围内的现有IP数超过限制。 238 func (s *DistinctNetSet) Add(ip net.IP) bool { 239 key := s.key(ip) 240 n := s.members[string(key)] 241 if n < s.Limit { 242 s.members[string(key)] = n + 1 243 return true 244 } 245 return false 246 } 247 248 //移除从集合中移除IP。 249 func (s *DistinctNetSet) Remove(ip net.IP) { 250 key := s.key(ip) 251 if n, ok := s.members[string(key)]; ok { 252 if n == 1 { 253 delete(s.members, string(key)) 254 } else { 255 s.members[string(key)] = n - 1 256 } 257 } 258 } 259 260 //包含给定IP是否包含在集合中。 261 func (s DistinctNetSet) Contains(ip net.IP) bool { 262 key := s.key(ip) 263 _, ok := s.members[string(key)] 264 return ok 265 } 266 267 //len返回跟踪的IP数。 268 func (s DistinctNetSet) Len() int { 269 n := uint(0) 270 for _, i := range s.members { 271 n += i 272 } 273 return int(n) 274 } 275 276 //键将地址的映射键编码到临时缓冲区中。 277 // 278 //密钥的第一个字节是“4”或“6”,用于区分IPv4/IPv6地址类型。 279 //密钥的其余部分是IP,截断为位数。 280 func (s *DistinctNetSet) key(ip net.IP) net.IP { 281 //延迟初始化存储。 282 if s.members == nil { 283 s.members = make(map[string]uint) 284 s.buf = make(net.IP, 17) 285 } 286 //将IP和位规范化。 287 typ := byte('6') 288 if ip4 := ip.To4(); ip4 != nil { 289 typ, ip = '4', ip4 290 } 291 bits := s.Subnet 292 if bits > uint(len(ip)*8) { 293 bits = uint(len(ip) * 8) 294 } 295 //将前缀编码为s.buf。 296 nb := int(bits / 8) 297 mask := ^byte(0xFF >> (bits % 8)) 298 s.buf[0] = typ 299 buf := append(s.buf[:1], ip[:nb]...) 300 if nb < len(ip) && mask != 0 { 301 buf = append(buf, ip[nb]&mask) 302 } 303 return buf 304 } 305 306 //字符串实现fmt.stringer 307 func (s DistinctNetSet) String() string { 308 var buf bytes.Buffer 309 buf.WriteString("{") 310 keys := make([]string, 0, len(s.members)) 311 for k := range s.members { 312 keys = append(keys, k) 313 } 314 sort.Strings(keys) 315 for i, k := range keys { 316 var ip net.IP 317 if k[0] == '4' { 318 ip = make(net.IP, 4) 319 } else { 320 ip = make(net.IP, 16) 321 } 322 copy(ip, k[1:]) 323 fmt.Fprintf(&buf, "%v×%d", ip, s.members[k]) 324 if i != len(keys)-1 { 325 buf.WriteString(" ") 326 } 327 } 328 buf.WriteString("}") 329 return buf.String() 330 }