github.com/n1ghtfa1l/go-vnt@v0.6.4-alpha.6/vntp2p/server.go (about)

     1  // Copyright 2019 The go-vnt Authors
     2  // This file is part of the go-vnt library.
     3  //
     4  // The go-vnt library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-vnt library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-vnt library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package vntp2p
    18  
    19  import (
    20  	"context"
    21  	"crypto/ecdsa"
    22  	"errors"
    23  	"fmt"
    24  	"net"
    25  	"sync"
    26  
    27  	libp2p "github.com/libp2p/go-libp2p"
    28  	p2phost "github.com/libp2p/go-libp2p-host"
    29  	inet "github.com/libp2p/go-libp2p-net"
    30  	protocol "github.com/libp2p/go-libp2p-protocol"
    31  	"github.com/vntchain/go-vnt/event"
    32  	"github.com/vntchain/go-vnt/log"
    33  
    34  	// inet "github.com/libp2p/go-libp2p-net"
    35  	peer "github.com/libp2p/go-libp2p-peer"
    36  	peerstore "github.com/libp2p/go-libp2p-peerstore"
    37  	ma "github.com/multiformats/go-multiaddr"
    38  	// kb "github.com/libp2p/go-libp2p-kbucket"
    39  )
    40  
    41  const (
    42  	maxActiveDialTasks = 16
    43  	defaultDialRatio   = 3
    44  )
    45  
    46  var errServerStopped = errors.New("server stopped")
    47  
    48  type dialFlag int
    49  
    50  const (
    51  	dynDialedDail dialFlag = 1 << iota
    52  	staticDialedDail
    53  )
    54  
    55  type Config struct {
    56  	PrivateKey      *ecdsa.PrivateKey `toml:"-"`
    57  	MaxPeers        int
    58  	MaxPendingPeers int `toml:",omitempty"`
    59  	DialRatio       int `toml:",omitempty"`
    60  	NoDiscovery     bool
    61  	Name            string `toml:"-"`
    62  
    63  	BootstrapNodes []*Node
    64  	StaticNodes    []*Node
    65  	TrustedNodes   []*Node
    66  
    67  	NetRestrict  []*net.IPNet `toml:",omitempty"`
    68  	NodeDatabase string       `toml:",omitempty"`
    69  	Protocols    []Protocol   `toml:"-"`
    70  	ListenAddr   string
    71  	NAT          libp2p.Option `toml:"-"`
    72  	// Dialer NodeDialer `toml:"-"`
    73  	// NoDial bool `toml:",omitempty"`
    74  
    75  	EnableMsgEvents bool
    76  	Logger          log.Logger `toml:",omitempty"`
    77  }
    78  
    79  type Server struct {
    80  	Config
    81  	table   DhtTable
    82  	host    p2phost.Host
    83  	running bool
    84  
    85  	peerFeed event.Feed
    86  	loopWG   sync.WaitGroup
    87  	cancel   context.CancelFunc
    88  
    89  	lock sync.Mutex
    90  
    91  	quit         chan struct{}
    92  	addstatic    chan *Node
    93  	removestatic chan *Node
    94  
    95  	addpeer chan *Stream
    96  	delpeer chan peerDrop
    97  
    98  	peerOp     chan peerOpFunc
    99  	peerOpDone chan struct{}
   100  
   101  	protomap map[string][]Protocol
   102  }
   103  
   104  type peerOpFunc func(map[peer.ID]*Peer)
   105  
   106  // func NewServer() (*Server, error) {
   107  // 	return newServer()
   108  // }
   109  
   110  // func newServer() (*Server, error) {
   111  // 	return &Server{}, nil
   112  // }
   113  
   114  type peerDrop struct {
   115  	*Peer
   116  	err       error
   117  	requested bool // true if signaled by the peer
   118  }
   119  
   120  // close server.quit to broadcast the server shutdown
   121  func (server *Server) Close() {
   122  	log.Info("P2P server is being closed...")
   123  	close(server.quit)
   124  }
   125  
   126  func (server *Server) Start() error {
   127  	log.Trace("P2P server starting...", "protocols", server.Protocols)
   128  	if server.running {
   129  		return errors.New("server already running")
   130  	}
   131  
   132  	server.lock.Lock()
   133  	defer server.lock.Unlock()
   134  
   135  	server.addpeer = make(chan *Stream)
   136  	server.delpeer = make(chan peerDrop)
   137  	server.addstatic = make(chan *Node)
   138  	server.removestatic = make(chan *Node)
   139  	server.quit = make(chan struct{})
   140  	server.peerOp = make(chan peerOpFunc)
   141  	server.peerOpDone = make(chan struct{})
   142  
   143  	// 协议映射初始化
   144  	server.protomap = make(map[string][]Protocol)
   145  
   146  	server.protomap[PID] = server.Protocols
   147  
   148  	// Listen
   149  	// run
   150  	if server.ListenAddr == "" {
   151  		return fmt.Errorf("P2P Server can't start for no listening")
   152  	}
   153  
   154  	listenPort := server.Config.ListenAddr[1:]
   155  	ctx, cancel := context.WithCancel(context.Background())
   156  	server.cancel = cancel
   157  
   158  	d := server.NodeDatabase
   159  	vdht, host, err := ConstructDHT(ctx, MakePort(listenPort), nil, d, server.Config.NetRestrict, server.Config.NAT)
   160  	if err != nil {
   161  		log.Error("ConstructDHT failed", "error", err)
   162  		return err
   163  	}
   164  
   165  	// setStreamHandler can only handle request message
   166  	// it can not hear response
   167  	host.SetStreamHandler(PID, server.HandleStream)
   168  
   169  	server.table = NewDHTTable(vdht, host.ID())
   170  	server.host = host
   171  
   172  	bootnodes := server.LoadConfig(ctx)
   173  
   174  	maxdials := server.maxDialedConns()
   175  
   176  	taskState := newTaskState(maxdials, bootnodes, server.table)
   177  
   178  	server.loopWG.Add(1)
   179  	go server.run(ctx, taskState)
   180  
   181  	server.running = true
   182  	return nil
   183  }
   184  
   185  func (server *Server) LoadConfig(ctx context.Context) []peer.ID {
   186  	// 创建初始连接
   187  
   188  	bootnodes := []peer.ID{}
   189  
   190  	for _, bootnode := range server.Config.BootstrapNodes {
   191  		server.host.Peerstore().AddAddrs(bootnode.Id, []ma.Multiaddr{bootnode.Addr}, peerstore.PermanentAddrTTL)
   192  		_ = server.table.Update(ctx, bootnode.Id)
   193  
   194  		bootnodes = append(bootnodes, bootnode.Id)
   195  	}
   196  
   197  	return bootnodes
   198  
   199  }
   200  
   201  func (server *Server) run(ctx context.Context, tasker taskworker) {
   202  	// run the blacklist daemon to handle mismatched peers
   203  	go blacklist.run()
   204  
   205  	defer server.loopWG.Done()
   206  	_ = server.table.Start(ctx)
   207  	var (
   208  		runningTasks []task
   209  		queuedTasks  []task
   210  		taskdone     = make(chan task, maxActiveDialTasks)
   211  		peers        = make(map[peer.ID]*Peer)
   212  	)
   213  
   214  	delTask := func(t task) {
   215  		for i := range runningTasks {
   216  			if runningTasks[i] == t {
   217  				runningTasks = append(runningTasks[:i], runningTasks[i+1:]...)
   218  				break
   219  			}
   220  		}
   221  	}
   222  	startTasks := func(ts []task) (rest []task) {
   223  		i := 0
   224  		for ; len(runningTasks) < maxActiveDialTasks && i < len(ts); i++ {
   225  			t := ts[i]
   226  			go func() { t.Do(ctx, server); taskdone <- t }()
   227  			runningTasks = append(runningTasks, t)
   228  		}
   229  		return ts[i:]
   230  	}
   231  	scheduleTasks := func() {
   232  		queuedTasks = append(queuedTasks[:0], startTasks(queuedTasks)...)
   233  		if len(runningTasks) < maxActiveDialTasks {
   234  			// fmt.Println("begin new task")
   235  			nt := tasker.newTasks(peers)
   236  			queuedTasks = append(queuedTasks, startTasks(nt)...)
   237  		}
   238  	}
   239  
   240  	for {
   241  		scheduleTasks()
   242  
   243  		select {
   244  		case t := <-taskdone:
   245  			tasker.taskDone(t)
   246  			delTask(t)
   247  
   248  		case t := <-server.addpeer:
   249  			remoteID := t.stream.Conn().RemotePeer()
   250  			log.Debug("Adding peer", "peer id", remoteID)
   251  			if p, ok := peers[remoteID]; ok {
   252  				p.log.Debug("Already exist peer")
   253  				break
   254  			}
   255  			p := newPeer(t, server)
   256  
   257  			if server.EnableMsgEvents {
   258  				p.events = &server.peerFeed
   259  			}
   260  			go server.runPeer(p)
   261  			peers[p.RemoteID()] = p
   262  			p.log.Debug("Added peer", "peers", peers)
   263  
   264  		case t := <-server.addstatic:
   265  			log.Debug("Adding static", "peer id", t.Id)
   266  			tasker.addStatic(t)
   267  			log.Debug("Added static", "peer id", t.Id)
   268  		case t := <-server.removestatic:
   269  			tasker.removeStatic(t)
   270  			if p, ok := peers[t.Id]; ok {
   271  				p.Disconnect(DiscRequested)
   272  			}
   273  
   274  		case op := <-server.peerOp:
   275  			// This channel is used by Peers and PeerCount.
   276  			op(peers)
   277  			server.peerOpDone <- struct{}{}
   278  
   279  		case pd := <-server.delpeer:
   280  			// A peer disconnected.
   281  			pid := pd.RemoteID()
   282  			log.Info("Removing p2p peer", "peer", pid.ToString(), "error", pd.err)
   283  			if _, ok := peers[pid]; ok {
   284  				delete(peers, pid)
   285  			}
   286  		}
   287  	}
   288  }
   289  
   290  func (server *Server) Stop() {
   291  	log.Info("Server is Stopping!")
   292  	defer server.cancel()
   293  }
   294  
   295  func (server *Server) AddPeer(ctx context.Context, node *Node) {
   296  	if blacklist.exists(node.Id) {
   297  		log.Trace("node is blacklisted", "pid", node.Id)
   298  		return
   299  	}
   300  	server.host.Peerstore().AddAddrs(node.Id, []ma.Multiaddr{node.Addr}, peerstore.PermanentAddrTTL)
   301  	_ = server.table.Update(ctx, node.Id)
   302  
   303  	select {
   304  	case <-server.quit:
   305  	case server.addstatic <- node:
   306  	}
   307  }
   308  
   309  func (server *Server) RemovePeer(node *Node) {
   310  	select {
   311  	case <-server.quit:
   312  	case server.removestatic <- node:
   313  	}
   314  }
   315  
   316  func (server *Server) SubscribeEvents(ch chan *PeerEvent) event.Subscription {
   317  	return server.peerFeed.Subscribe(ch)
   318  }
   319  
   320  func (server *Server) PeersInfo() []*PeerInfo {
   321  	infos := make([]*PeerInfo, 0, server.PeerCount())
   322  
   323  	for _, peer := range server.Peers() {
   324  		if peer != nil {
   325  			infos = append(infos, peer.Info())
   326  		}
   327  	}
   328  	for i := 0; i < len(infos); i++ {
   329  		for j := i + 1; j < len(infos); j++ {
   330  			if infos[i].ID > infos[j].ID {
   331  				infos[i], infos[j] = infos[j], infos[i]
   332  			}
   333  		}
   334  	}
   335  	return infos
   336  }
   337  
   338  func (server *Server) Self() *Node {
   339  	server.lock.Lock()
   340  	defer server.lock.Unlock()
   341  
   342  	if !server.running {
   343  		return &Node{}
   344  	}
   345  
   346  	// hostAddr, _ := ma.NewMultiaddr(fmt.Sprintf("/ipfs/%s", server.host.ID().Pretty()))
   347  
   348  	addr := server.host.Addrs()[0]
   349  	// fullAddr := addr.Encapsulate(hostAddr)
   350  
   351  	return &Node{Addr: addr, Id: server.host.ID()}
   352  }
   353  
   354  // GetPeerByRemoteID get specific peer by remoteID
   355  // if it doesn't exist, new it
   356  // this function guarantee get the wanted peer
   357  func (server *Server) GetPeerByRemoteID(s inet.Stream) *Peer {
   358  	var p *Peer
   359  
   360  	// always try to new this peer
   361  	err := server.dispatch(&Stream{stream: s, Protocols: server.protomap[PID]}, server.addpeer)
   362  	if err != nil {
   363  		log.Error("GetPeerByRemoteID()", "new peer error", err)
   364  		return nil
   365  	}
   366  
   367  	select {
   368  	case <-server.quit:
   369  	case server.peerOp <- func(peers map[peer.ID]*Peer) {
   370  		remoteID := s.Conn().RemotePeer()
   371  		if val, ok := peers[remoteID]; ok {
   372  			p = val
   373  		}
   374  	}:
   375  		<-server.peerOpDone
   376  	}
   377  
   378  	pid := s.Conn().RemotePeer()
   379  	log.Debug("Got peer by remote id", "peerid", pid, "peer got", p)
   380  
   381  	return p
   382  }
   383  
   384  func (server *Server) Peers() []*Peer {
   385  	var ps []*Peer
   386  	select {
   387  	case <-server.quit:
   388  	case server.peerOp <- func(peers map[peer.ID]*Peer) {
   389  		for _, p := range peers {
   390  			ps = append(ps, p)
   391  		}
   392  	}:
   393  		<-server.peerOpDone
   394  	}
   395  	return ps
   396  }
   397  
   398  func (server *Server) PeerCount() int {
   399  	var count int
   400  	select {
   401  	case <-server.quit:
   402  	case server.peerOp <- func(ps map[peer.ID]*Peer) { count = len(ps) }:
   403  		<-server.peerOpDone
   404  	}
   405  	return count
   406  }
   407  
   408  func (server *Server) maxDialedConns() int {
   409  	r := server.DialRatio
   410  	if r == 0 {
   411  		r = defaultDialRatio
   412  	}
   413  	return server.MaxPeers / r
   414  }
   415  
   416  // SetupStream 主动发起连接
   417  func (server *Server) SetupStream(ctx context.Context, target peer.ID, pid string) error {
   418  	s, err := server.host.NewStream(ctx, target, protocol.ID(pid))
   419  	if err != nil {
   420  		// fmt.Println("SetupStream NewStream Error: ", err)
   421  		return err
   422  	}
   423  
   424  	// handle response message
   425  	go server.HandleStream(s)
   426  	/* rw := bufio.NewReadWriter(bufio.NewReader(s), bufio.NewWriter(s))
   427  	vntMessenger := &VNTMsger{
   428  		protocol: Protocol{},
   429  		in:       make(chan Msg),
   430  		w:        rw,
   431  	}
   432  
   433  	their, err := doProtocolHandshake(vntMessenger, server.ourHandshake)
   434  	if err != nil {
   435  		log.Error("SetupStream()", "failed protocolHandshake", err)
   436  		return err
   437  	} */
   438  
   439  	err = server.dispatch(&Stream{stream: s, Protocols: server.protomap[pid]}, server.addpeer)
   440  	if err != nil {
   441  		fmt.Println("SetupStream dispatch Error: ", err)
   442  		return err
   443  	}
   444  	return nil
   445  }
   446  
   447  func (server *Server) runPeer(p *Peer) {
   448  	// broadcast peer add
   449  	server.peerFeed.Send(&PeerEvent{
   450  		Type: PeerEventTypeAdd,
   451  		Peer: p.RemoteID(),
   452  	})
   453  
   454  	// run the protocol
   455  	remoteRequested, err := p.run()
   456  	if err != nil {
   457  		log.Debug("Run peer failed", "peer id", p.RemoteID(), "peer addr", p.RemoteAddr())
   458  	}
   459  
   460  	// broadcast peer drop
   461  	server.peerFeed.Send(&PeerEvent{
   462  		Type:  PeerEventTypeDrop,
   463  		Peer:  p.RemoteID(),
   464  		Error: err.Error(),
   465  	})
   466  
   467  	// Note: run waits for existing peers to be sent on srv.delpeer
   468  	// before returning, so this send should not select on srv.quit.
   469  	server.delpeer <- peerDrop{p, err, remoteRequested}
   470  }
   471  
   472  func (server *Server) dispatch(s *Stream, stage chan<- *Stream) error {
   473  	select {
   474  	case <-server.quit:
   475  		return errServerStopped
   476  	case stage <- s:
   477  	}
   478  	return nil
   479  }
   480  
   481  type NodeInfo struct {
   482  	ID      string `json:"id"`    // Unique node identifier (also the encryption key)
   483  	Name    string `json:"name"`  // Name of the node, including client type, version, OS, custom data
   484  	VNTNode string `json:"vnode"` // Vnode URL for adding this peer from remote peers
   485  	IP      string `json:"ip"`    // IP address of the node
   486  	Ports   struct {
   487  		Discovery int `json:"discovery"` // UDP listening port for discovery protocol
   488  		Listener  int `json:"listener"`  // TCP listening port for RLPx
   489  	} `json:"ports"`
   490  	ListenAddr string                 `json:"listenAddr"`
   491  	Protocols  map[string]interface{} `json:"protocols"`
   492  }
   493  
   494  func (server *Server) NodeInfo() *NodeInfo {
   495  	node := server.Self()
   496  
   497  	info := &NodeInfo{
   498  		ID:         node.Id.ToString(),
   499  		VNTNode:    node.String(),
   500  		Name:       server.Name,
   501  		IP:         GetIPfromAddr(node.Addr),
   502  		ListenAddr: server.ListenAddr,
   503  		Protocols:  make(map[string]interface{}),
   504  	}
   505  
   506  	// for _, proto := range server.Protocols {
   507  	// 	if _, ok := info.Protocols[proto.Name]; !ok {
   508  	// 		nodeInfo := interface{}("unknown")
   509  	// 		if query := proto.NodeInfo; query != nil {
   510  	// 			nodeInfo = proto.NodeInfo()
   511  	// 		}
   512  	// 		info.Protocols[proto.Name] = nodeInfo
   513  	// 	}
   514  	// }
   515  	return info
   516  }
   517  
   518  type taskworker interface {
   519  	newTasks(map[peer.ID]*Peer) []task
   520  	addStatic(n *Node)
   521  	removeStatic(n *Node)
   522  	taskDone(t task)
   523  }