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  }