github.com/turingchain2020/turingchain@v1.1.21/system/p2p/dht/protocol/peer/peerinfo.go (about)

     1  package peer
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  	"sync"
     9  	"sync/atomic"
    10  	"time"
    11  
    12  	"github.com/turingchain2020/turingchain/common/version"
    13  	"github.com/turingchain2020/turingchain/system/p2p/dht/protocol"
    14  	types2 "github.com/turingchain2020/turingchain/system/p2p/dht/types"
    15  	"github.com/turingchain2020/turingchain/types"
    16  	"github.com/libp2p/go-libp2p-core/network"
    17  	"github.com/libp2p/go-libp2p-core/peer"
    18  	"github.com/multiformats/go-multiaddr"
    19  )
    20  
    21  const diffHeightValue = 512
    22  
    23  func (p *Protocol) getLocalPeerInfo() *types.Peer {
    24  	msg := p.QueueClient.NewMessage(mempool, types.EventGetMempoolSize, nil)
    25  	err := p.QueueClient.Send(msg, true)
    26  	if err != nil {
    27  		return nil
    28  	}
    29  	resp, err := p.QueueClient.WaitTimeout(msg, time.Second*10)
    30  	if err != nil {
    31  		log.Error("getLocalPeerInfo", "mempool WaitTimeout", err)
    32  		return nil
    33  	}
    34  	var localPeer types.Peer
    35  	localPeer.MempoolSize = int32(resp.Data.(*types.MempoolSize).GetSize())
    36  
    37  	msg = p.QueueClient.NewMessage(blockchain, types.EventGetLastHeader, nil)
    38  	err = p.QueueClient.Send(msg, true)
    39  	if err != nil {
    40  		return nil
    41  	}
    42  	resp, err = p.QueueClient.WaitTimeout(msg, time.Second*10)
    43  	if err != nil {
    44  		log.Error("getLocalPeerInfo", "blockchain WaitTimeout", err)
    45  		return nil
    46  	}
    47  	localPeer.Header = resp.Data.(*types.Header)
    48  	localPeer.Name = p.Host.ID().Pretty()
    49  	ip, port := parseIPAndPort(p.getExternalAddr())
    50  	localPeer.Addr = ip
    51  	localPeer.Port = int32(port)
    52  	localPeer.Version = version.GetVersion() + "@" + version.GetAppVersion()
    53  	localPeer.StoreDBVersion = version.GetStoreDBVersion()
    54  	localPeer.LocalDBVersion = version.GetLocalDBVersion()
    55  	return &localPeer
    56  }
    57  
    58  func (p *Protocol) refreshPeerInfo() {
    59  	if !atomic.CompareAndSwapInt32(&p.refreshing, 0, 1) {
    60  		return
    61  	}
    62  	defer atomic.StoreInt32(&p.refreshing, 0)
    63  	var wg sync.WaitGroup
    64  	for _, remoteID := range p.ConnManager.FetchConnPeers() {
    65  		if p.checkDone() {
    66  			log.Warn("getPeerInfo", "process", "done+++++++")
    67  			return
    68  		}
    69  		if remoteID == p.Host.ID() {
    70  			continue
    71  		}
    72  		//修改为并发获取peerinfo信息
    73  		wg.Add(1)
    74  		go func(pid peer.ID) {
    75  			defer wg.Done()
    76  			pInfo, err := p.queryPeerInfoOld(pid)
    77  			if err != nil {
    78  				log.Error("refreshPeerInfo", "error", err, "pid", pid)
    79  				return
    80  			}
    81  			p.PeerInfoManager.Refresh(pInfo)
    82  		}(remoteID)
    83  	}
    84  	selfPeer := p.getLocalPeerInfo()
    85  	if selfPeer != nil {
    86  		selfPeer.Self = true
    87  		p.PeerInfoManager.Refresh(selfPeer)
    88  		p.checkOutBound(selfPeer.GetHeader().GetHeight())
    89  	}
    90  	wg.Wait()
    91  }
    92  
    93  func (p *Protocol) checkOutBound(height int64) {
    94  	for _, pinfo := range p.PeerInfoManager.FetchAll() {
    95  		if pinfo.GetHeader().GetHeight()+diffHeightValue < height {
    96  			pid, err := peer.Decode(pinfo.GetName())
    97  			if err != nil {
    98  				continue
    99  			}
   100  			// 断开向外的主动连接
   101  			for _, conn := range p.Host.Network().ConnsToPeer(pid) {
   102  				//判断是Inbound 还是Outbound
   103  				if conn.Stat().Direction == network.DirOutbound {
   104  					// 拉入连接黑名单
   105  					p.ConnBlackList.Add(pinfo.GetName(), 0)
   106  					_ = conn.Close()
   107  				}
   108  			}
   109  		}
   110  	}
   111  }
   112  
   113  func (p *Protocol) detectNodeAddr() {
   114  
   115  	// 通过bootstrap获取本节点公网ip
   116  	for _, bootstrap := range p.SubConfig.BootStraps {
   117  		if p.checkDone() {
   118  			break
   119  		}
   120  		addr, _ := multiaddr.NewMultiaddr(bootstrap)
   121  		peerInfo, err := peer.AddrInfoFromP2pAddr(addr)
   122  		if err != nil {
   123  			continue
   124  		}
   125  		err = p.queryVersionOld(peerInfo.ID)
   126  		if err != nil {
   127  			continue
   128  		}
   129  	}
   130  	var rangeCount int
   131  	for {
   132  		if p.checkDone() {
   133  			break
   134  		}
   135  		if p.RoutingTable.Size() == 0 {
   136  			time.Sleep(time.Second)
   137  			continue
   138  		}
   139  		//启动后间隔1分钟,以充分获得节点外网地址
   140  		rangeCount++
   141  		if rangeCount > 2 {
   142  			time.Sleep(time.Minute)
   143  		}
   144  		for _, pid := range p.RoutingTable.ListPeers() {
   145  			if p.containsPublicIP(pid) {
   146  				continue
   147  			}
   148  			err := p.queryVersionOld(pid)
   149  			if err != nil {
   150  				log.Error("detectNodeAddr", "queryVersion error", err, "pid", pid)
   151  				continue
   152  			}
   153  		}
   154  	}
   155  }
   156  
   157  func (p *Protocol) queryPeerInfoOld(pid peer.ID) (*types.Peer, error) {
   158  	ctx, cancel := context.WithTimeout(p.Ctx, time.Second*3)
   159  	defer cancel()
   160  	stream, err := p.Host.NewStream(ctx, pid, peerInfoOld)
   161  	if err != nil {
   162  		log.Error("refreshPeerInfo", "new stream error", err, "peer id", pid)
   163  		return nil, err
   164  	}
   165  	defer protocol.CloseStream(stream)
   166  	err = protocol.WriteStream(&types.MessagePeerInfoReq{}, stream)
   167  	if err != nil {
   168  		return nil, err
   169  	}
   170  	var resp types.MessagePeerInfoResp
   171  	err = protocol.ReadStream(&resp, stream)
   172  	if err != nil {
   173  		return nil, err
   174  	}
   175  	if resp.Message == nil {
   176  		return nil, types2.ErrInvalidResponse
   177  	}
   178  	pInfo := types.Peer{
   179  		Addr:           resp.Message.Addr,
   180  		Port:           resp.Message.Port,
   181  		Name:           resp.Message.Name,
   182  		MempoolSize:    resp.Message.MempoolSize,
   183  		Header:         resp.Message.Header,
   184  		Version:        resp.Message.Version,
   185  		LocalDBVersion: resp.Message.LocalDBVersion,
   186  		StoreDBVersion: resp.Message.StoreDBVersion,
   187  	}
   188  	return &pInfo, nil
   189  }
   190  
   191  func (p *Protocol) queryPeerInfo(pid peer.ID) (*types.Peer, error) {
   192  	ctx, cancel := context.WithTimeout(p.Ctx, time.Second*3)
   193  	defer cancel()
   194  	stream, err := p.Host.NewStream(ctx, pid, peerInfo)
   195  	if err != nil {
   196  		log.Error("refreshPeerInfo", "new stream error", err, "peer id", pid)
   197  		return nil, err
   198  	}
   199  	defer protocol.CloseStream(stream)
   200  	var resp types.Peer
   201  	err = protocol.ReadStream(&resp, stream)
   202  	if err != nil {
   203  		return nil, err
   204  	}
   205  	return &resp, nil
   206  }
   207  
   208  func (p *Protocol) queryVersionOld(pid peer.ID) error {
   209  	stream, err := p.Host.NewStream(p.Ctx, pid, peerVersionOld)
   210  	if err != nil {
   211  		log.Error("NewStream", "err", err, "remoteID", pid)
   212  		return err
   213  	}
   214  	defer protocol.CloseStream(stream)
   215  
   216  	req := types.MessageP2PVersionReq{
   217  		Message: &types.P2PVersion{
   218  			Version:  p.SubConfig.Channel,
   219  			AddrFrom: fmt.Sprintf("/ip4/%v/tcp/%d", p.getPublicIP(), p.SubConfig.Port),
   220  			AddrRecv: stream.Conn().RemoteMultiaddr().String(),
   221  		},
   222  	}
   223  	err = protocol.WriteStream(&req, stream)
   224  	if err != nil {
   225  		log.Error("queryVersion", "WriteStream err", err)
   226  		return err
   227  	}
   228  	var res types.MessageP2PVersionResp
   229  	err = protocol.ReadStream(&res, stream)
   230  	if err != nil {
   231  		log.Error("queryVersion", "ReadStream err", err)
   232  		return err
   233  	}
   234  	msg := res.Message
   235  	addr := msg.GetAddrRecv()
   236  	p.setExternalAddr(addr)
   237  	if !strings.Contains(msg.AddrFrom, "/ip4") {
   238  		_, port := parseIPAndPort(stream.Conn().RemoteMultiaddr().String())
   239  		msg.AddrFrom = fmt.Sprintf("/ip4/%s/tcp/%d", msg.AddrFrom, port)
   240  	}
   241  	if ip, _ := parseIPAndPort(msg.GetAddrFrom()); isPublicIP(ip) {
   242  		remoteMAddr, err := multiaddr.NewMultiaddr(msg.GetAddrFrom())
   243  		if err != nil {
   244  			return err
   245  		}
   246  		p.Host.Peerstore().AddAddr(pid, remoteMAddr, time.Hour*12)
   247  	}
   248  	return nil
   249  }
   250  
   251  func (p *Protocol) queryVersion(pid peer.ID) error {
   252  	stream, err := p.Host.NewStream(p.Ctx, pid, peerVersion)
   253  	if err != nil {
   254  		log.Error("NewStream", "err", err, "remoteID", pid)
   255  		return err
   256  	}
   257  	defer protocol.CloseStream(stream)
   258  
   259  	req := &types.P2PVersion{
   260  		Version:  p.SubConfig.Channel,
   261  		AddrFrom: fmt.Sprintf("/ip4/%v/tcp/%d", p.getPublicIP(), p.SubConfig.Port),
   262  		AddrRecv: stream.Conn().RemoteMultiaddr().String(),
   263  	}
   264  	err = protocol.WriteStream(req, stream)
   265  	if err != nil {
   266  		log.Error("queryVersion", "WriteStream err", err)
   267  		return err
   268  	}
   269  	var resp types.P2PVersion
   270  	err = protocol.ReadStream(&resp, stream)
   271  	if err != nil {
   272  		log.Error("queryVersion", "ReadStream err", err)
   273  		return err
   274  	}
   275  	addr := resp.GetAddrRecv()
   276  	p.setExternalAddr(addr)
   277  
   278  	if ip, _ := parseIPAndPort(resp.GetAddrFrom()); isPublicIP(ip) {
   279  		remoteMAddr, err := multiaddr.NewMultiaddr(resp.GetAddrFrom())
   280  		if err != nil {
   281  			return err
   282  		}
   283  		p.Host.Peerstore().AddAddr(pid, remoteMAddr, time.Hour*12)
   284  	}
   285  	return nil
   286  }
   287  
   288  func (p *Protocol) setExternalAddr(addr string) {
   289  	ip, _ := parseIPAndPort(addr)
   290  	if isPublicIP(ip) {
   291  		p.mutex.Lock()
   292  		p.externalAddr = addr
   293  		p.mutex.Unlock()
   294  		ma, _ := multiaddr.NewMultiaddr(addr)
   295  		p.Host.Peerstore().AddAddr(p.Host.ID(), ma, time.Hour*24)
   296  	}
   297  }
   298  
   299  func (p *Protocol) getExternalAddr() string {
   300  	p.mutex.Lock()
   301  	defer p.mutex.Unlock()
   302  	return p.externalAddr
   303  }
   304  
   305  func (p *Protocol) getPublicIP() string {
   306  	ip, _ := parseIPAndPort(p.getExternalAddr())
   307  	return ip
   308  }
   309  
   310  func (p *Protocol) containsPublicIP(pid peer.ID) bool {
   311  	for _, maddr := range p.Host.Peerstore().Addrs(pid) {
   312  		if ip, _ := parseIPAndPort(maddr.String()); isPublicIP(ip) {
   313  			return true
   314  		}
   315  	}
   316  	return false
   317  }
   318  
   319  func parseIPAndPort(multiAddr string) (ip string, port int) {
   320  	split := strings.Split(multiAddr, "/")
   321  	if len(split) < 5 {
   322  		return
   323  	}
   324  	port, err := strconv.Atoi(split[4])
   325  	if err != nil {
   326  		return
   327  	}
   328  	ip = split[2]
   329  	return
   330  }