code: func (sw *Switch) AddPeer(peer *Peer) error {
  	if err := sw.FilterConnByAddr(peer.Addr()); err != nil {
  		return err
  	}
  
  	if err := sw.FilterConnByPubKey(peer.PubKey()); err != nil {
  		return err
  	}
  
  	if err := peer.HandshakeTimeout(sw.nodeInfo, time.Duration(sw.config.GetInt(configKeyHandshakeTimeoutSeconds))*time.Second); err != nil {
  		return err
  	}
  
  	// Avoid self
  	if sw.nodeInfo.PubKey.Equals(peer.PubKey()) {
  		return errors.New("Ignoring connection from self")
  	}
  
  	// Check version, chain id
  	if err := sw.nodeInfo.CompatibleWith(peer.NodeInfo); err != nil {
  		return err
  	}
  
  	// Add the peer to .peers
  	// ignore if duplicate or if we already have too many for that IP range
  	if err := sw.peers.Add(peer); err != nil {
  		log.Notice("Ignoring peer", "error", err, "peer", peer)
  		peer.Stop()
  		return err
  	}
  
  	// Start peer
  	if sw.IsRunning() {
  		sw.startInitPeer(peer)
  	}
  
  	log.Notice("Added peer", "peer", peer)
  	return nil
  }
docs: // NOTE: This performs a blocking handshake before the peer is added.
  // CONTRACT: If error is returned, peer is nil, and conn is immediately closed.