Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1002/// A ping-pong round trip has completed successfully. Update latest and minimum ping durations.1003void PongReceived(NodeClock::duration ping_time)1004{1005m_last_ping_time = ping_time;1006m_min_ping_time = std::min(m_min_ping_time.load(), ping_time);1007}1009private:1010const NodeId id;1011const uint64_t nLocalHostNonce;1012std::atomic<int> m_greatest_common_version{INIT_PROTO_VERSION};1014const size_t m_recv_flood_size;1015std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread1017Mutex m_msg_process_queue_mutex;1018std::list<CNetMessage> m_msg_process_queue GUARDED_BY(m_msg_process_queue_mutex);1019size_t m_msg_process_queue_size GUARDED_BY(m_msg_process_queue_mutex){0};1021// Our address, as reported by the peer1022CService m_addr_local GUARDED_BY(m_addr_local_mutex);1023mutable Mutex m_addr_local_mutex;1025mapMsgTypeSize mapSendBytesPerMsgType GUARDED_BY(cs_vSend);1026mapMsgTypeSize mapRecvBytesPerMsgType GUARDED_BY(cs_vRecv);1028/**1029* If an I2P session is created per connection (for outbound transient I2P1030* connections) then it is stored here so that it can be destroyed when the1031* socket is closed. I2P sessions involve a data/transport socket (in `m_sock`)1032* and a control socket (in `m_i2p_sam_session`). For transient sessions, once1033* the data socket is closed, the control socket is not going to be used anymore1034* and is just taking up resources. So better close it as soon as `m_sock` is1035* closed.1036* Otherwise this unique_ptr is empty.1037*/1038std::unique_ptr<i2p::sam::Session> m_i2p_sam_session GUARDED_BY(m_sock_mutex);1039};1041/**1042* Interface for message handling1043*/1044class NetEventsInterface1045{1046public:1047/** Mutex for anything that is only accessed via the msg processing thread */1048static Mutex g_msgproc_mutex;1050/** Initialize a peer (setup state) */1051virtual void InitializeNode(const CNode& node, ServiceFlags our_services) = 0;1053/** Handle removal of a peer (clear state) */1054virtual void FinalizeNode(const CNode& node) = 0;1056/**1057* Callback to determine whether the given set of service flags are sufficient1058* for a peer to be "relevant".1059*/1060virtual bool HasAllDesirableServiceFlags(ServiceFlags services) const = 0;1062/**1063* Process protocol messages received from a given node1064*1065* @param[in] node The node which we have received messages from.1066* @param[in] interrupt Interrupt condition for processing threads1067* @return True if there is more work to be done1068*/1069virtual bool ProcessMessages(CNode& node, std::atomic<bool>& interrupt) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) = 0;1071/**1072* Send queued protocol messages to a given node.1073*1074* @param[in] node The node which we are sending messages to.1075* @return True if there is more work to be done1076*/1077virtual bool SendMessages(CNode& node) EXCLUSIVE_LOCKS_REQUIRED(g_msgproc_mutex) = 0;1080protected:1081/**1082* Protected destructor so that instances can only be deleted by derived classes.1083* If that restriction is no longer desired, this should be made public and virtual.1084*/1085~NetEventsInterface() = default;1086};1088class CConnman1089{1090public:1092struct Options1093{1094ServiceFlags m_local_services = NODE_NONE;1095int m_max_automatic_connections = DEFAULT_MAX_PEER_CONNECTIONS;1096int m_full_relay_inbound_percent = DEFAULT_FULL_RELAY_INBOUND_PCT;1097CClientUIInterface* uiInterface = nullptr;1098NetEventsInterface* m_msgproc = nullptr;1099BanMan* m_banman = nullptr;1100unsigned int nSendBufferMaxSize = 0;1101unsigned int nReceiveFloodSize = 0;1102uint64_t nMaxOutboundLimit = 0;1103int64_t m_peer_connect_timeout = DEFAULT_PEER_CONNECT_TIMEOUT;1104std::vector<std::string> vSeedNodes;1105std::vector<NetWhitelistPermissions> vWhitelistedRangeIncoming;1106std::vector<NetWhitelistPermissions> vWhitelistedRangeOutgoing;1107std::vector<NetWhitebindPermissions> vWhiteBinds;1108std::vector<CService> vBinds;1109std::vector<CService> onion_binds;1110/// True if the user did not specify -bind= or -whitebind= and thus1111/// we should bind on `0.0.0.0` (IPv4) and `::` (IPv6).1112bool bind_on_any;1113bool m_use_addrman_outgoing = true;1114std::vector<std::string> m_specified_outgoing;1115std::vector<std::string> m_added_nodes;1116bool m_i2p_accept_incoming;1117bool whitelist_forcerelay = DEFAULT_WHITELISTFORCERELAY;1118bool whitelist_relay = DEFAULT_WHITELISTRELAY;1119bool m_capture_messages = false;1120};1122void Init(const Options& connOptions) EXCLUSIVE_LOCKS_REQUIRED(!m_added_nodes_mutex, !m_total_bytes_sent_mutex)1123{1124AssertLockNotHeld(m_total_bytes_sent_mutex);1126m_local_services = connOptions.m_local_services;1127m_max_automatic_connections = connOptions.m_max_automatic_connections;1128m_max_outbound_full_relay = std::min(MAX_OUTBOUND_FULL_RELAY_CONNECTIONS, m_max_automatic_connections);1129m_max_outbound_block_relay = std::min(MAX_BLOCK_RELAY_ONLY_CONNECTIONS, m_max_automatic_connections - m_max_outbound_full_relay);1130m_max_automatic_outbound = m_max_outbound_full_relay + m_max_outbound_block_relay + m_max_feeler;1131m_max_inbound = std::max(0, m_max_automatic_connections - m_max_automatic_outbound);1132m_max_inbound_full_relay = std::max(0, static_cast<int>(connOptions.m_full_relay_inbound_percent / 100.0 * m_max_inbound));1133m_use_addrman_outgoing = connOptions.m_use_addrman_outgoing;1134m_client_interface = connOptions.uiInterface;1135m_banman = connOptions.m_banman;1136m_msgproc = connOptions.m_msgproc;1137nSendBufferMaxSize = connOptions.nSendBufferMaxSize;1138nReceiveFloodSize = connOptions.nReceiveFloodSize;1139m_peer_connect_timeout = std::chrono::seconds{connOptions.m_peer_connect_timeout};1140{1141LOCK(m_total_bytes_sent_mutex);1142nMaxOutboundLimit = connOptions.nMaxOutboundLimit;1143}1144vWhitelistedRangeIncoming = connOptions.vWhitelistedRangeIncoming;1145vWhitelistedRangeOutgoing = connOptions.vWhitelistedRangeOutgoing;1146{1147LOCK(m_added_nodes_mutex);1148// Attempt v2 connection if we support v2 - we'll reconnect with v1 if our1149// peer doesn't support it or immediately disconnects us for another reason.1150const bool use_v2transport(GetLocalServices() & NODE_P2P_V2);1151for (const std::string& added_node : connOptions.m_added_nodes) {1152m_added_node_params.push_back({added_node, use_v2transport});1153}1154}1155m_onion_binds = connOptions.onion_binds;1156whitelist_forcerelay = connOptions.whitelist_forcerelay;1157whitelist_relay = connOptions.whitelist_relay;1158m_capture_messages = connOptions.m_capture_messages;1159}1161// test only1162void SetCaptureMessages(bool cap) { m_capture_messages = cap; }1164CConnman(uint64_t seed0,1165uint64_t seed1,1166AddrMan& addrman,1167const NetGroupManager& netgroupman,1168const CChainParams& params,1169bool network_active = true,1170std::shared_ptr<CThreadInterrupt> interrupt_net = std::make_shared<CThreadInterrupt>());1172~CConnman();1174bool Start(CScheduler& scheduler, const Options& options) EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex, !m_added_nodes_mutex, !m_addr_fetches_mutex, !mutexMsgProc);1176void StopThreads();1177void StopNodes() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_reconnections_mutex);1178void Stop() EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_reconnections_mutex)1179{1180AssertLockNotHeld(m_nodes_mutex);1181AssertLockNotHeld(m_reconnections_mutex);1182StopThreads();1183StopNodes();1184};1186void Interrupt() EXCLUSIVE_LOCKS_REQUIRED(!mutexMsgProc);1187bool GetNetworkActive() const { return fNetworkActive; };1188bool GetUseAddrmanOutgoing() const { return m_use_addrman_outgoing; };1189void SetNetworkActive(bool active);1191/**1192* Open a new P2P connection and initialize it with the PeerManager at `m_msgproc`.1193* @param[in] addrConnect Address to connect to, if `pszDest` is `nullptr`.1194* @param[in] fCountFailure Increment the number of connection attempts to this address in Addrman.1195* @param[in] grant_outbound Take ownership of this grant, to be released later when the connection is closed.1196* @param[in] pszDest Address to resolve and connect to.1197* @param[in] conn_type Type of the connection to open, must not be `ConnectionType::INBOUND`.1198* @param[in] use_v2transport Use P2P encryption, (aka V2 transport, BIP324).1199* @param[in] proxy_override Optional proxy to use and override normal proxy selection.1200* @retval true The connection was opened successfully.1201* @retval false The connection attempt failed.1202*/1203bool OpenNetworkConnection(const CAddress& addrConnect,1204bool fCountFailure,1205CountingSemaphoreGrant<>&& grant_outbound,1206const char* pszDest,1207ConnectionType conn_type,1208bool use_v2transport,1209const std::optional<Proxy>& proxy_override)1210EXCLUSIVE_LOCKS_REQUIRED(!m_nodes_mutex, !m_unused_i2p_sessions_mutex);1212/// Group of private broadcast related members.1213class PrivateBroadcast1214{1215public:1216/**1217* Remember if we ever established at least one outbound connection to a1218* Tor peer, including sending and receiving P2P messages. If this is1219* true then the Tor proxy indeed works and is a proxy to the Tor network,1220* not a misconfigured ordinary SOCKS5 proxy as -proxy or -onion. If that1221* is the case, then we assume that connecting to an IPv4 or IPv6 address1222* via that proxy will be done through the Tor network and a Tor exit node.1223*/1224std::atomic_bool m_outbound_tor_ok_at_least_once{false};1226/**1227* Semaphore used to guard against opening too many connections.1228* Opening private broadcast connections will be paused if this is equal to 0.1229*/1230std::counting_semaphore<> m_sem_conn_max{MAX_PRIVATE_BROADCAST_CONNECTIONS};1232/**1233* Choose a network to open a connection to.1234* @param[out] proxy Optional proxy to override the normal proxy selection.1235* Will be set if !std::nullopt is returned. Could be set to `std::nullopt`1236* if there is no need to override the proxy that would be used for connecting1237* to the returned network.1238* @retval std::nullopt No network could be selected.1239* @retval !std::nullopt The network was selected and `proxy` is set (maybe to `std::nullopt`).1240*/1241std::optional<Network> PickNetwork(std::optional<Proxy>& proxy) const;1243/// Get the pending number of connections to open.1244size_t NumToOpen() const;1246/**1247* Increment the number of new connections of type `ConnectionType::PRIVATE_BROADCAST`1248* to be opened by `CConnman::ThreadPrivateBroadcast()`.1249* @param[in] n Increment by this number.1250*/
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.