text: // Copyright (c) 2009-2010 Satoshi Nakamoto
  // Copyright (c) 2009-2015 The Bitcoin Core developers
  // Distributed under the MIT software license, see the accompanying
  // file COPYING or http://www.opensource.org/licenses/mit-license.php.
  
  #ifndef BITCOIN_NET_PROCESSING_H
  #define BITCOIN_NET_PROCESSING_H
  
  #include "net.h"
  #include "validationinterface.h"
  
  
  struct CBlockReject {
      unsigned char chRejectCode;
      string strRejectReason;
      uint256 hashBlock;
  };
  
  /** Blocks that are in flight, and that are in the queue to be downloaded. Protected by cs_main. */
  struct QueuedBlock {
      uint256 hash;
      CBlockIndex* pindex;     //!< Optional.
      bool fValidatedHeaders;  //!< Whether this block has validated headers at the time of request.
  };
  
  
  /**
   * Maintain validation-specific state about nodes, protected by cs_main, instead
   * by CNode's own locks. This simplifies asynchronous operation, where
   * processing of incoming data is done after the ProcessMessage call returns,
   * and we're no longer holding the node's locks.
   */
  struct CNodeState {
      //! The peer's address
      const CService address;
      //! Whether we have a fully established connection.
      bool fCurrentlyConnected;
      //! Accumulated misbehaviour score for this peer.
      int nMisbehavior;
      //! Whether this peer should be disconnected and banned (unless whitelisted).
      bool fShouldBan;
      //! String name of this peer (debugging/logging purposes).
      const std::string name;
      //! List of asynchronously-determined block rejections to notify this peer about.
      std::vector<CBlockReject> rejects;
      //! The best known block we know this peer has announced.
      CBlockIndex *pindexBestKnownBlock;
      //! The hash of the last unknown block this peer has announced.
      uint256 hashLastUnknownBlock;
      //! The last full block we both have.
      CBlockIndex *pindexLastCommonBlock;
      //! The best header we have sent our peer.
      CBlockIndex *pindexBestHeaderSent;
      //! Whether we've started headers synchronization with this peer.
      bool fSyncStarted;
      //! When to potentially disconnect peer for stalling headers download
      int64_t nHeadersSyncTimeout;
      //! Since when we're stalling block download progress (in microseconds), or 0.
      int64_t nStallingSince;
      list<QueuedBlock> vBlocksInFlight;
      //! When the first entry in vBlocksInFlight started downloading. Don't care when vBlocksInFlight is empty.
      int64_t nDownloadingSince;
      int nBlocksInFlight;
      int nBlocksInFlightValidHeaders;
      //! Whether we consider this a preferred download peer.
      bool fPreferredDownload;
      //! Whether this peer wants invs or headers (when possible) for block announcements.
      bool fPreferHeaders;
  
      CNodeState(CAddress addrIn, std::string addrNameIn) : address(addrIn), name(addrNameIn) {
          fCurrentlyConnected = false;
          nMisbehavior = 0;
          fShouldBan = false;
          pindexBestKnownBlock = NULL;
          hashLastUnknownBlock.SetNull();
          pindexLastCommonBlock = NULL;
          pindexBestHeaderSent = NULL;
          fSyncStarted = false;
          nHeadersSyncTimeout = 0;
          nStallingSince = 0;
          nDownloadingSince = 0;
          nBlocksInFlight = 0;
          nBlocksInFlightValidHeaders = 0;
          fPreferredDownload = false;
          fPreferHeaders = false;
      }
  };
  
  
  /** Headers download timeout expressed in microseconds
   *  Timeout = base + per_header * (expected number of headers) */
  static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_BASE = 15 * 60 * 1000000; // 15 minutes
  static constexpr int64_t HEADERS_DOWNLOAD_TIMEOUT_PER_HEADER = 1000; // 1ms/header
  
  /** Register with a network node to receive its signals */
  void RegisterNodeSignals(CNodeSignals& nodeSignals);
  /** Unregister a network node */
  void UnregisterNodeSignals(CNodeSignals& nodeSignals);
  
  CNodeState *State(NodeId pnode);
  
  class PeerLogicValidation : public CValidationInterface {
  private:
      CConnman* connman;
  
  public:
      PeerLogicValidation(CConnman* connmanIn);
  
      virtual void UpdatedBlockTip(const CBlockIndex *pindexNew, const CBlockIndex *pindexFork, bool fInitialDownload);
      virtual void BlockChecked(const CBlock& block, const CValidationState& state);
  };
  
  struct CNodeStateStats {
      int nMisbehavior;
      int nSyncHeight;
      int nCommonHeight;
      std::vector<int> vHeightInFlight;
  };
  
  /** Get statistics from node state */
  bool GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats);
  /** Increase a node's misbehavior score. */
  void Misbehaving(NodeId nodeid, int howmuch);
  
  /** Process protocol messages received from a given node */
  bool ProcessMessages(CNode* pfrom, CConnman& connman, std::atomic<bool>& interrupt);
  /**
   * Send queued protocol messages to be sent to a give node.
   *
   * @param[in]   pto             The node which we are sending messages to.
   * @param[in]   connman         The connection manager for that node.
   * @param[in]   interrupt       Interrupt condition for processing threads
   * @return                      True if there is more work to be done
   */
  bool SendMessages(CNode* pto, CConnman& connman, std::atomic<bool>& interrupt);
  
  #endif // BITCOIN_NET_PROCESSING_H
  