@@ -471,6 +471,43 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
471471 return &it->second ;
472472}
473473
474+ /* *
475+ * Data structure for an individual peer. This struct is not protected by
476+ * cs_main since it does not contain validation-critical data.
477+ *
478+ * Memory is owned by shared pointers and this object is destructed when
479+ * the refcount drops to zero.
480+ *
481+ * TODO: move most members from CNodeState to this structure.
482+ * TODO: move remaining application-layer data members from CNode to this structure.
483+ */
484+ struct Peer {
485+ /* * Same id as the CNode object for this peer */
486+ const NodeId m_id{0 };
487+
488+ Peer (NodeId id) : m_id(id) {}
489+ };
490+
491+ using PeerRef = std::shared_ptr<Peer>;
492+
493+ /* *
494+ * Map of all Peer objects, keyed by peer id. This map is protected
495+ * by the global g_peer_mutex. Once a shared pointer reference is
496+ * taken, the lock may be released. Individual fields are protected by
497+ * their own locks.
498+ */
499+ Mutex g_peer_mutex;
500+ static std::map<NodeId, PeerRef> g_peer_map GUARDED_BY (g_peer_mutex);
501+
502+ /* * Get a shared pointer to the Peer object.
503+ * May return nullptr if the Peer object can't be found. */
504+ static PeerRef GetPeerRef (NodeId id)
505+ {
506+ LOCK (g_peer_mutex);
507+ auto it = g_peer_map.find (id);
508+ return it != g_peer_map.end () ? it->second : nullptr ;
509+ }
510+
474511static void UpdatePreferredDownload (const CNode& node, CNodeState* state) EXCLUSIVE_LOCKS_REQUIRED(cs_main)
475512{
476513 nPreferredDownload -= state->fPreferredDownload ;
@@ -838,6 +875,11 @@ void PeerLogicValidation::InitializeNode(CNode *pnode) {
838875 LOCK (cs_main);
839876 mapNodeState.emplace_hint (mapNodeState.end (), std::piecewise_construct, std::forward_as_tuple (nodeid), std::forward_as_tuple (addr, pnode->IsInboundConn (), pnode->IsManualConn ()));
840877 }
878+ {
879+ PeerRef peer = std::make_shared<Peer>(nodeid);
880+ LOCK (g_peer_mutex);
881+ g_peer_map.emplace_hint (g_peer_map.end (), nodeid, std::move (peer));
882+ }
841883 if (!pnode->IsInboundConn ())
842884 PushNodeVersion (*pnode, *connman, GetTime ());
843885}
@@ -865,6 +907,10 @@ void PeerLogicValidation::ReattemptInitialBroadcast(CScheduler& scheduler) const
865907void PeerLogicValidation::FinalizeNode (NodeId nodeid, bool & fUpdateConnectionTime ) {
866908 fUpdateConnectionTime = false ;
867909 LOCK (cs_main);
910+ {
911+ LOCK (g_peer_mutex);
912+ g_peer_map.erase (nodeid);
913+ }
868914 CNodeState *state = State (nodeid);
869915 assert (state != nullptr );
870916
0 commit comments