2010-08-29 18:58:15 +02:00
|
|
|
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
2015-12-13 14:51:43 +01:00
|
|
|
// Copyright (c) 2009-2015 The Bitcoin Core developers
|
2014-12-13 05:09:33 +01:00
|
|
|
// Distributed under the MIT software license, see the accompanying
|
2012-05-18 16:02:28 +02:00
|
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
#ifndef BITCOIN_NET_H
|
|
|
|
#define BITCOIN_NET_H
|
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
#include "addrdb.h"
|
|
|
|
#include "addrman.h"
|
2016-03-21 18:02:47 +01:00
|
|
|
#include "amount.h"
|
2013-04-13 07:13:08 +02:00
|
|
|
#include "bloom.h"
|
|
|
|
#include "compat.h"
|
|
|
|
#include "limitedmap.h"
|
2017-09-03 15:29:10 +02:00
|
|
|
#include "netaddress.h"
|
2013-04-13 07:13:08 +02:00
|
|
|
#include "protocol.h"
|
2014-06-26 14:41:53 +02:00
|
|
|
#include "random.h"
|
2014-10-22 21:08:30 +02:00
|
|
|
#include "streams.h"
|
2013-04-13 07:13:08 +02:00
|
|
|
#include "sync.h"
|
|
|
|
#include "uint256.h"
|
2016-12-04 21:33:39 +01:00
|
|
|
#include "util.h"
|
2017-08-09 18:06:31 +02:00
|
|
|
#include "threadinterrupt.h"
|
2013-04-13 07:13:08 +02:00
|
|
|
|
2017-07-12 22:08:18 +02:00
|
|
|
#include <atomic>
|
2011-05-15 09:11:04 +02:00
|
|
|
#include <deque>
|
2013-04-13 07:13:08 +02:00
|
|
|
#include <stdint.h>
|
2017-08-09 18:06:31 +02:00
|
|
|
#include <thread>
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
#include <memory>
|
2017-08-09 18:06:31 +02:00
|
|
|
#include <condition_variable>
|
2011-05-15 09:11:04 +02:00
|
|
|
|
2011-10-07 17:02:21 +02:00
|
|
|
#ifndef WIN32
|
2011-05-15 09:11:04 +02:00
|
|
|
#include <arpa/inet.h>
|
|
|
|
#endif
|
2010-08-29 18:58:15 +02:00
|
|
|
|
Split up util.cpp/h
Split up util.cpp/h into:
- string utilities (hex, base32, base64): no internal dependencies, no dependency on boost (apart from foreach)
- money utilities (parsesmoney, formatmoney)
- time utilities (gettime*, sleep, format date):
- and the rest (logging, argument parsing, config file parsing)
The latter is basically the environment and OS handling,
and is stripped of all utility functions, so we may want to
rename it to something else than util.cpp/h for clarity (Matt suggested
osinterface).
Breaks dependency of sha256.cpp on all the things pulled in by util.
2014-08-21 16:11:09 +02:00
|
|
|
#include <boost/filesystem/path.hpp>
|
2013-04-13 07:13:08 +02:00
|
|
|
#include <boost/foreach.hpp>
|
|
|
|
#include <boost/signals2/signal.hpp>
|
2013-06-06 09:04:33 +02:00
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
class CAddrMan;
|
2015-04-02 18:04:59 +02:00
|
|
|
class CScheduler;
|
2013-04-13 07:13:08 +02:00
|
|
|
class CNode;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
namespace boost {
|
|
|
|
class thread_group;
|
2014-06-24 14:17:43 +02:00
|
|
|
} // namespace boost
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2013-10-15 00:34:20 +02:00
|
|
|
/** Time between pings automatically sent out for latency probing and keepalive (in seconds). */
|
|
|
|
static const int PING_INTERVAL = 2 * 60;
|
|
|
|
/** Time after which to disconnect, after waiting for a ping response (or inactivity). */
|
|
|
|
static const int TIMEOUT_INTERVAL = 20 * 60;
|
2017-01-19 20:06:32 +01:00
|
|
|
/** Minimum time between warnings printed to log. */
|
|
|
|
static const int WARNING_INTERVAL = 10 * 60;
|
2017-07-17 12:39:12 +02:00
|
|
|
/** Run the feeler connection loop once every 2 minutes or 120 seconds. **/
|
|
|
|
static const int FEELER_INTERVAL = 120;
|
2013-04-13 07:13:08 +02:00
|
|
|
/** The maximum number of entries in an 'inv' protocol message */
|
|
|
|
static const unsigned int MAX_INV_SZ = 50000;
|
2014-11-21 12:22:11 +01:00
|
|
|
/** The maximum number of new addresses to accumulate before announcing. */
|
|
|
|
static const unsigned int MAX_ADDR_TO_SEND = 1000;
|
2017-09-14 13:42:37 +02:00
|
|
|
/** Maximum length of incoming protocol messages (no message over 3 MiB is currently acceptable). */
|
|
|
|
static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 3 * 1024 * 1024;
|
2015-07-31 18:05:42 +02:00
|
|
|
/** Maximum length of strSubVer in `version` message */
|
|
|
|
static const unsigned int MAX_SUBVERSION_LENGTH = 256;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
/** Maximum number of outgoing nodes */
|
|
|
|
static const int MAX_OUTBOUND_CONNECTIONS = 8;
|
|
|
|
/** Maximum number if outgoing masternodes */
|
|
|
|
static const int MAX_OUTBOUND_MASTERNODE_CONNECTIONS = 20;
|
2014-05-29 13:02:22 +02:00
|
|
|
/** -listen default */
|
|
|
|
static const bool DEFAULT_LISTEN = true;
|
2014-05-05 21:06:14 +02:00
|
|
|
/** -upnp default */
|
|
|
|
#ifdef USE_UPNP
|
|
|
|
static const bool DEFAULT_UPNP = USE_UPNP;
|
|
|
|
#else
|
|
|
|
static const bool DEFAULT_UPNP = false;
|
|
|
|
#endif
|
2014-09-09 09:18:05 +02:00
|
|
|
/** The maximum number of entries in mapAskFor */
|
|
|
|
static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ;
|
2015-11-23 02:54:23 +01:00
|
|
|
/** The maximum number of entries in setAskFor (larger due to getdata latency)*/
|
|
|
|
static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ;
|
2015-08-01 19:41:21 +02:00
|
|
|
/** The maximum number of peer connections to maintain. */
|
|
|
|
static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125;
|
2015-11-06 00:05:06 +01:00
|
|
|
/** The default for -maxuploadtarget. 0 = Unlimited */
|
|
|
|
static const uint64_t DEFAULT_MAX_UPLOAD_TARGET = 0;
|
2015-11-14 13:47:53 +01:00
|
|
|
/** Default for blocks only*/
|
|
|
|
static const bool DEFAULT_BLOCKSONLY = false;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2015-06-27 21:21:41 +02:00
|
|
|
static const bool DEFAULT_FORCEDNSSEED = false;
|
|
|
|
static const size_t DEFAULT_MAXRECEIVEBUFFER = 5 * 1000;
|
|
|
|
static const size_t DEFAULT_MAXSENDBUFFER = 1 * 1000;
|
|
|
|
|
2017-07-05 05:45:23 +02:00
|
|
|
static const ServiceFlags REQUIRED_SERVICES = NODE_NETWORK;
|
|
|
|
|
2015-06-27 21:21:41 +02:00
|
|
|
// NOTE: When adjusting this, update rpcnet:setban's help ("24h")
|
|
|
|
static const unsigned int DEFAULT_MISBEHAVING_BANTIME = 60 * 60 * 24; // Default 24-hour ban
|
2010-08-29 18:58:15 +02:00
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
typedef int NodeId;
|
|
|
|
|
|
|
|
struct AddedNodeInfo
|
|
|
|
{
|
|
|
|
std::string strAddedNode;
|
|
|
|
CService resolvedAddress;
|
|
|
|
bool fConnected;
|
|
|
|
bool fInbound;
|
|
|
|
};
|
|
|
|
|
|
|
|
class CTransaction;
|
|
|
|
class CNodeStats;
|
|
|
|
class CClientUIInterface;
|
|
|
|
|
|
|
|
class CConnman
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
|
|
|
|
enum NumConnections {
|
|
|
|
CONNECTIONS_NONE = 0,
|
|
|
|
CONNECTIONS_IN = (1U << 0),
|
|
|
|
CONNECTIONS_OUT = (1U << 1),
|
|
|
|
CONNECTIONS_ALL = (CONNECTIONS_IN | CONNECTIONS_OUT),
|
|
|
|
};
|
|
|
|
|
|
|
|
struct Options
|
|
|
|
{
|
|
|
|
ServiceFlags nLocalServices = NODE_NONE;
|
|
|
|
ServiceFlags nRelevantServices = NODE_NONE;
|
|
|
|
int nMaxConnections = 0;
|
|
|
|
int nMaxOutbound = 0;
|
|
|
|
int nMaxFeeler = 0;
|
|
|
|
int nBestHeight = 0;
|
|
|
|
CClientUIInterface* uiInterface = nullptr;
|
|
|
|
unsigned int nSendBufferMaxSize = 0;
|
|
|
|
unsigned int nReceiveFloodSize = 0;
|
|
|
|
};
|
|
|
|
CConnman();
|
|
|
|
~CConnman();
|
2017-08-09 18:06:31 +02:00
|
|
|
bool Start(CScheduler& scheduler, std::string& strNodeError, Options options);
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
void Stop();
|
2017-08-09 18:06:31 +02:00
|
|
|
void Interrupt();
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
|
2017-09-11 15:38:14 +02:00
|
|
|
bool GetNetworkActive() const { return fNetworkActive; };
|
|
|
|
void SetNetworkActive(bool active);
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false, bool fFeeler = false);
|
|
|
|
bool CheckIncomingNonce(uint64_t nonce);
|
|
|
|
|
|
|
|
// fConnectToMasternode should be 'true' only if you want this node to allow to connect to itself
|
|
|
|
// and/or you want it to be disconnected on CMasternodeMan::ProcessMasternodeConnections()
|
|
|
|
// Unfortunately, can't make this method private like in Bitcoin,
|
|
|
|
// because it's used in many Dash-specific places (masternode, privatesend).
|
|
|
|
CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL, bool fConnectToMasternode = false);
|
|
|
|
|
2017-08-17 20:37:22 +02:00
|
|
|
struct CFullyConnectedOnly {
|
|
|
|
bool operator() (const CNode* pnode) const {
|
|
|
|
return NodeFullyConnected(pnode);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr static const CFullyConnectedOnly FullyConnectedOnly{};
|
|
|
|
|
|
|
|
struct CAllNodes {
|
|
|
|
bool operator() (const CNode*) const {return true;}
|
|
|
|
};
|
|
|
|
|
|
|
|
constexpr static const CAllNodes AllNodes{};
|
|
|
|
|
|
|
|
bool ForNode(NodeId id, std::function<bool(const CNode* pnode)> cond, std::function<bool(CNode* pnode)> func);
|
|
|
|
bool ForNode(const CService& addr, std::function<bool(const CNode* pnode)> cond, std::function<bool(CNode* pnode)> func);
|
|
|
|
|
|
|
|
template<typename Callable>
|
|
|
|
bool ForNode(const CService& addr, Callable&& func)
|
|
|
|
{
|
|
|
|
return ForNode(addr, FullyConnectedOnly, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Callable>
|
|
|
|
bool ForNode(NodeId id, Callable&& func)
|
|
|
|
{
|
|
|
|
return ForNode(id, FullyConnectedOnly, func);
|
|
|
|
}
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
|
2017-07-27 16:28:05 +02:00
|
|
|
template <typename... Args>
|
|
|
|
void PushMessageWithVersionAndFlag(CNode* pnode, int nVersion, int flag, const std::string& sCommand, Args&&... args)
|
|
|
|
{
|
|
|
|
auto msg(BeginMessage(pnode, nVersion, flag, sCommand));
|
|
|
|
::SerializeMany(msg, msg.nType, msg.nVersion, std::forward<Args>(args)...);
|
|
|
|
EndMessage(msg);
|
|
|
|
PushMessage(pnode, msg, sCommand);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
void PushMessageWithFlag(CNode* pnode, int flag, const std::string& sCommand, Args&&... args)
|
|
|
|
{
|
|
|
|
PushMessageWithVersionAndFlag(pnode, 0, flag, sCommand, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
void PushMessageWithVersion(CNode* pnode, int nVersion, const std::string& sCommand, Args&&... args)
|
|
|
|
{
|
|
|
|
PushMessageWithVersionAndFlag(pnode, nVersion, 0, sCommand, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename... Args>
|
|
|
|
void PushMessage(CNode* pnode, const std::string& sCommand, Args&&... args)
|
|
|
|
{
|
|
|
|
PushMessageWithVersionAndFlag(pnode, 0, 0, sCommand, std::forward<Args>(args)...);
|
|
|
|
}
|
|
|
|
|
2017-08-17 20:37:22 +02:00
|
|
|
template<typename Condition, typename Callable>
|
|
|
|
bool ForEachNodeContinueIf(const Condition& cond, Callable&& func)
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_vNodes);
|
|
|
|
for (auto&& node : vNodes)
|
2017-08-17 20:37:22 +02:00
|
|
|
if (cond(node))
|
|
|
|
if(!func(node))
|
|
|
|
return false;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Callable>
|
2017-08-17 20:37:22 +02:00
|
|
|
bool ForEachNodeContinueIf(Callable&& func)
|
|
|
|
{
|
|
|
|
return ForEachNodeContinueIf(FullyConnectedOnly, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Condition, typename Callable>
|
|
|
|
bool ForEachNodeContinueIf(const Condition& cond, Callable&& func) const
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_vNodes);
|
|
|
|
for (const auto& node : vNodes)
|
2017-08-17 20:37:22 +02:00
|
|
|
if (cond(node))
|
|
|
|
if(!func(node))
|
|
|
|
return false;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
return true;
|
|
|
|
};
|
|
|
|
|
2017-08-17 20:37:22 +02:00
|
|
|
template<typename Callable>
|
|
|
|
bool ForEachNodeContinueIf(Callable&& func) const
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
2017-08-17 20:37:22 +02:00
|
|
|
return ForEachNodeContinueIf(FullyConnectedOnly, func);
|
|
|
|
}
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
|
2017-08-17 20:37:22 +02:00
|
|
|
template<typename Condition, typename Callable>
|
|
|
|
void ForEachNode(const Condition& cond, Callable&& func)
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_vNodes);
|
2017-08-17 20:37:22 +02:00
|
|
|
for (auto&& node : vNodes) {
|
|
|
|
if (cond(node))
|
|
|
|
func(node);
|
|
|
|
}
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Callable>
|
|
|
|
void ForEachNode(Callable&& func)
|
2017-08-17 20:37:22 +02:00
|
|
|
{
|
|
|
|
ForEachNode(FullyConnectedOnly, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Condition, typename Callable>
|
|
|
|
void ForEachNode(const Condition& cond, Callable&& func) const
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_vNodes);
|
2017-08-17 20:37:22 +02:00
|
|
|
for (auto&& node : vNodes) {
|
|
|
|
if (cond(node))
|
|
|
|
func(node);
|
|
|
|
}
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Callable>
|
|
|
|
void ForEachNode(Callable&& func) const
|
2017-08-17 20:37:22 +02:00
|
|
|
{
|
|
|
|
ForEachNode(FullyConnectedOnly, func);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Condition, typename Callable, typename CallableAfter>
|
|
|
|
void ForEachNodeThen(const Condition& cond, Callable&& pre, CallableAfter&& post)
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_vNodes);
|
2017-08-17 20:37:22 +02:00
|
|
|
for (auto&& node : vNodes) {
|
|
|
|
if (cond(node))
|
|
|
|
pre(node);
|
|
|
|
}
|
|
|
|
post();
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Callable, typename CallableAfter>
|
|
|
|
void ForEachNodeThen(Callable&& pre, CallableAfter&& post)
|
2017-08-17 20:37:22 +02:00
|
|
|
{
|
|
|
|
ForEachNodeThen(FullyConnectedOnly, pre, post);
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename Condition, typename Callable, typename CallableAfter>
|
|
|
|
void ForEachNodeThen(const Condition& cond, Callable&& pre, CallableAfter&& post) const
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_vNodes);
|
2017-08-17 20:37:22 +02:00
|
|
|
for (auto&& node : vNodes) {
|
|
|
|
if (cond(node))
|
|
|
|
pre(node);
|
|
|
|
}
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
post();
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename Callable, typename CallableAfter>
|
|
|
|
void ForEachNodeThen(Callable&& pre, CallableAfter&& post) const
|
|
|
|
{
|
2017-08-17 20:37:22 +02:00
|
|
|
ForEachNodeThen(FullyConnectedOnly, pre, post);
|
|
|
|
}
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
|
|
|
|
std::vector<CNode*> CopyNodeVector();
|
|
|
|
void ReleaseNodeVector(const std::vector<CNode*>& vecNodes);
|
|
|
|
|
2016-05-16 22:47:29 +02:00
|
|
|
void RelayTransaction(const CTransaction& tx);
|
|
|
|
void RelayTransaction(const CTransaction& tx, const CDataStream& ss);
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
void RelayInv(CInv &inv, const int minProtoVersion = MIN_PEER_PROTO_VERSION);
|
|
|
|
|
|
|
|
// Addrman functions
|
|
|
|
size_t GetAddressCount() const;
|
|
|
|
void SetServices(const CService &addr, ServiceFlags nServices);
|
|
|
|
void MarkAddressGood(const CAddress& addr);
|
|
|
|
void AddNewAddress(const CAddress& addr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
|
|
|
void AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty = 0);
|
|
|
|
std::vector<CAddress> GetAddresses();
|
|
|
|
void AddressCurrentlyConnected(const CService& addr);
|
|
|
|
|
|
|
|
// Denial-of-service detection/prevention
|
|
|
|
// The idea is to detect peers that are behaving
|
|
|
|
// badly and disconnect/ban them, but do it in a
|
|
|
|
// one-coding-mistake-won't-shatter-the-entire-network
|
|
|
|
// way.
|
|
|
|
// IMPORTANT: There should be nothing I can give a
|
|
|
|
// node that it will forward on that will make that
|
|
|
|
// node's peers drop it. If there is, an attacker
|
|
|
|
// can isolate a node and/or try to split the network.
|
|
|
|
// Dropping a node for sending stuff that is invalid
|
|
|
|
// now but might be valid in a later version is also
|
|
|
|
// dangerous, because it can cause a network split
|
|
|
|
// between nodes running old code and nodes running
|
|
|
|
// new code.
|
|
|
|
void Ban(const CNetAddr& netAddr, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
|
|
|
|
void Ban(const CSubNet& subNet, const BanReason& reason, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false);
|
|
|
|
void ClearBanned(); // needed for unit testing
|
|
|
|
bool IsBanned(CNetAddr ip);
|
|
|
|
bool IsBanned(CSubNet subnet);
|
|
|
|
bool Unban(const CNetAddr &ip);
|
|
|
|
bool Unban(const CSubNet &ip);
|
|
|
|
void GetBanned(banmap_t &banmap);
|
|
|
|
void SetBanned(const banmap_t &banmap);
|
|
|
|
|
|
|
|
void AddOneShot(const std::string& strDest);
|
|
|
|
|
|
|
|
bool AddNode(const std::string& node);
|
|
|
|
bool RemoveAddedNode(const std::string& node);
|
|
|
|
std::vector<AddedNodeInfo> GetAddedNodeInfo();
|
|
|
|
|
|
|
|
size_t GetNodeCount(NumConnections num);
|
|
|
|
void GetNodeStats(std::vector<CNodeStats>& vstats);
|
|
|
|
bool DisconnectNode(const std::string& node);
|
|
|
|
bool DisconnectNode(NodeId id);
|
|
|
|
|
|
|
|
unsigned int GetSendBufferSize() const;
|
|
|
|
|
|
|
|
void AddWhitelistedRange(const CSubNet &subnet);
|
|
|
|
|
|
|
|
ServiceFlags GetLocalServices() const;
|
|
|
|
|
|
|
|
//!set the max outbound target in bytes
|
|
|
|
void SetMaxOutboundTarget(uint64_t limit);
|
|
|
|
uint64_t GetMaxOutboundTarget();
|
|
|
|
|
|
|
|
//!set the timeframe for the max outbound target
|
|
|
|
void SetMaxOutboundTimeframe(uint64_t timeframe);
|
|
|
|
uint64_t GetMaxOutboundTimeframe();
|
|
|
|
|
|
|
|
//!check if the outbound target is reached
|
|
|
|
// if param historicalBlockServingLimit is set true, the function will
|
|
|
|
// response true if the limit for serving historical blocks has been reached
|
|
|
|
bool OutboundTargetReached(bool historicalBlockServingLimit);
|
|
|
|
|
|
|
|
//!response the bytes left in the current max outbound cycle
|
|
|
|
// in case of no limit, it will always response 0
|
|
|
|
uint64_t GetOutboundTargetBytesLeft();
|
|
|
|
|
|
|
|
//!response the time in second left in the current max outbound cycle
|
|
|
|
// in case of no limit, it will always response 0
|
|
|
|
uint64_t GetMaxOutboundTimeLeftInCycle();
|
|
|
|
|
|
|
|
uint64_t GetTotalBytesRecv();
|
|
|
|
uint64_t GetTotalBytesSent();
|
|
|
|
|
|
|
|
void SetBestHeight(int height);
|
|
|
|
int GetBestHeight() const;
|
|
|
|
|
|
|
|
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
unsigned int GetReceiveFloodSize() const;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
private:
|
|
|
|
struct ListenSocket {
|
|
|
|
SOCKET socket;
|
|
|
|
bool whitelisted;
|
|
|
|
|
|
|
|
ListenSocket(SOCKET socket_, bool whitelisted_) : socket(socket_), whitelisted(whitelisted_) {}
|
|
|
|
};
|
|
|
|
|
|
|
|
void ThreadOpenAddedConnections();
|
|
|
|
void ProcessOneShot();
|
|
|
|
void ThreadOpenConnections();
|
|
|
|
void ThreadMessageHandler();
|
|
|
|
void AcceptConnection(const ListenSocket& hListenSocket);
|
|
|
|
void ThreadSocketHandler();
|
|
|
|
void ThreadDNSAddressSeed();
|
|
|
|
void ThreadMnbRequestConnections();
|
|
|
|
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
void WakeMessageHandler();
|
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
CNode* FindNode(const CNetAddr& ip);
|
|
|
|
CNode* FindNode(const CSubNet& subNet);
|
|
|
|
CNode* FindNode(const std::string& addrName);
|
|
|
|
CNode* FindNode(const CService& addr);
|
|
|
|
|
|
|
|
bool AttemptToEvictConnection();
|
|
|
|
bool IsWhitelistedRange(const CNetAddr &addr);
|
|
|
|
|
|
|
|
void DeleteNode(CNode* pnode);
|
|
|
|
|
|
|
|
NodeId GetNewNodeId();
|
|
|
|
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
size_t SocketSendData(CNode *pnode);
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
//!check is the banlist has unwritten changes
|
|
|
|
bool BannedSetIsDirty();
|
|
|
|
//!set the "dirty" flag for the banlist
|
|
|
|
void SetBannedSetDirty(bool dirty=true);
|
|
|
|
//!clean unused entries (if bantime has expired)
|
|
|
|
void SweepBanned();
|
|
|
|
void DumpAddresses();
|
|
|
|
void DumpData();
|
|
|
|
void DumpBanlist();
|
|
|
|
|
2017-07-27 16:28:05 +02:00
|
|
|
CDataStream BeginMessage(CNode* node, int nVersion, int flags, const std::string& sCommand);
|
|
|
|
void PushMessage(CNode* pnode, CDataStream& strm, const std::string& sCommand);
|
|
|
|
void EndMessage(CDataStream& strm);
|
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
// Network stats
|
|
|
|
void RecordBytesRecv(uint64_t bytes);
|
|
|
|
void RecordBytesSent(uint64_t bytes);
|
|
|
|
|
2017-08-17 20:37:22 +02:00
|
|
|
// Whether the node should be passed out in ForEach* callbacks
|
|
|
|
static bool NodeFullyConnected(const CNode* pnode);
|
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
// Network usage totals
|
|
|
|
CCriticalSection cs_totalBytesRecv;
|
|
|
|
CCriticalSection cs_totalBytesSent;
|
|
|
|
uint64_t nTotalBytesRecv;
|
|
|
|
uint64_t nTotalBytesSent;
|
|
|
|
|
|
|
|
// outbound limit & stats
|
|
|
|
uint64_t nMaxOutboundTotalBytesSentInCycle;
|
|
|
|
uint64_t nMaxOutboundCycleStartTime;
|
|
|
|
uint64_t nMaxOutboundLimit;
|
|
|
|
uint64_t nMaxOutboundTimeframe;
|
|
|
|
|
|
|
|
// Whitelisted ranges. Any node connecting from these is automatically
|
|
|
|
// whitelisted (as well as those connecting to whitelisted binds).
|
|
|
|
std::vector<CSubNet> vWhitelistedRange;
|
|
|
|
CCriticalSection cs_vWhitelistedRange;
|
|
|
|
|
|
|
|
unsigned int nSendBufferMaxSize;
|
|
|
|
unsigned int nReceiveFloodSize;
|
|
|
|
|
|
|
|
std::vector<ListenSocket> vhListenSocket;
|
2017-09-11 15:38:14 +02:00
|
|
|
bool fNetworkActive;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
banmap_t setBanned;
|
|
|
|
CCriticalSection cs_setBanned;
|
|
|
|
bool setBannedIsDirty;
|
|
|
|
bool fAddressesInitialized;
|
|
|
|
CAddrMan addrman;
|
|
|
|
std::deque<std::string> vOneShots;
|
|
|
|
CCriticalSection cs_vOneShots;
|
|
|
|
std::vector<std::string> vAddedNodes;
|
|
|
|
CCriticalSection cs_vAddedNodes;
|
|
|
|
std::vector<CNode*> vNodes;
|
|
|
|
std::list<CNode*> vNodesDisconnected;
|
|
|
|
mutable CCriticalSection cs_vNodes;
|
|
|
|
std::atomic<NodeId> nLastNodeId;
|
|
|
|
|
|
|
|
/** Services this instance offers */
|
|
|
|
ServiceFlags nLocalServices;
|
|
|
|
|
|
|
|
/** Services this instance cares about */
|
|
|
|
ServiceFlags nRelevantServices;
|
|
|
|
|
|
|
|
CSemaphore *semOutbound;
|
|
|
|
CSemaphore *semMasternodeOutbound;
|
|
|
|
int nMaxConnections;
|
|
|
|
int nMaxOutbound;
|
|
|
|
int nMaxFeeler;
|
|
|
|
std::atomic<int> nBestHeight;
|
|
|
|
CClientUIInterface* clientInterface;
|
2017-08-09 18:06:31 +02:00
|
|
|
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
/** flag for waking the message processor. */
|
|
|
|
bool fMsgProcWake;
|
|
|
|
|
2017-08-09 18:06:31 +02:00
|
|
|
std::condition_variable condMsgProc;
|
|
|
|
std::mutex mutexMsgProc;
|
|
|
|
std::atomic<bool> flagInterruptMsgProc;
|
|
|
|
|
|
|
|
CThreadInterrupt interruptNet;
|
|
|
|
|
|
|
|
std::thread threadDNSAddressSeed;
|
|
|
|
std::thread threadSocketHandler;
|
|
|
|
std::thread threadOpenAddedConnections;
|
|
|
|
std::thread threadOpenConnections;
|
|
|
|
std::thread threadMnbRequestConnections;
|
|
|
|
std::thread threadMessageHandler;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
};
|
|
|
|
extern std::unique_ptr<CConnman> g_connman;
|
|
|
|
void Discover(boost::thread_group& threadGroup);
|
2013-03-07 04:31:26 +01:00
|
|
|
void MapPort(bool fUseUPnP);
|
2012-05-13 01:26:14 +02:00
|
|
|
unsigned short GetListenPort();
|
2014-06-21 13:34:36 +02:00
|
|
|
bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false);
|
2013-11-18 01:25:17 +01:00
|
|
|
|
2015-03-05 13:01:01 +01:00
|
|
|
struct CombinerAll
|
|
|
|
{
|
|
|
|
typedef bool result_type;
|
|
|
|
|
|
|
|
template<typename I>
|
|
|
|
bool operator()(I first, I last) const
|
|
|
|
{
|
|
|
|
while (first != last) {
|
|
|
|
if (!(*first)) return false;
|
|
|
|
++first;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-06-06 05:21:41 +02:00
|
|
|
// Signals for message handling
|
|
|
|
struct CNodeSignals
|
|
|
|
{
|
2017-08-09 18:06:31 +02:00
|
|
|
boost::signals2::signal<bool (CNode*, CConnman&, std::atomic<bool>&), CombinerAll> ProcessMessages;
|
|
|
|
boost::signals2::signal<bool (CNode*, CConnman&, std::atomic<bool>&), CombinerAll> SendMessages;
|
2017-07-27 16:28:05 +02:00
|
|
|
boost::signals2::signal<void (CNode*, CConnman&)> InitializeNode;
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
boost::signals2::signal<void (NodeId, bool&)> FinalizeNode;
|
2013-06-06 05:21:41 +02:00
|
|
|
};
|
|
|
|
|
2013-11-18 01:25:17 +01:00
|
|
|
|
2013-06-06 05:21:41 +02:00
|
|
|
CNodeSignals& GetNodeSignals();
|
2013-01-07 17:07:51 +01:00
|
|
|
|
|
|
|
|
2012-02-12 13:45:24 +01:00
|
|
|
enum
|
|
|
|
{
|
2012-05-10 20:35:13 +02:00
|
|
|
LOCAL_NONE, // unknown
|
|
|
|
LOCAL_IF, // address a local interface listens on
|
2012-05-11 15:28:59 +02:00
|
|
|
LOCAL_BIND, // address explicit bound to
|
2012-05-10 20:35:13 +02:00
|
|
|
LOCAL_UPNP, // address reported by UPnP
|
|
|
|
LOCAL_MANUAL, // address explicitly specified (-externalip=)
|
2012-02-19 20:44:35 +01:00
|
|
|
|
|
|
|
LOCAL_MAX
|
2012-02-12 13:45:24 +01:00
|
|
|
};
|
|
|
|
|
2014-07-21 08:32:25 +02:00
|
|
|
bool IsPeerAddrLocalGood(CNode *pnode);
|
2016-02-12 19:35:32 +01:00
|
|
|
void AdvertiseLocal(CNode *pnode);
|
2012-05-04 16:46:22 +02:00
|
|
|
void SetLimited(enum Network net, bool fLimited = true);
|
2012-05-14 17:15:58 +02:00
|
|
|
bool IsLimited(enum Network net);
|
2012-05-04 16:46:22 +02:00
|
|
|
bool IsLimited(const CNetAddr& addr);
|
2012-05-10 20:35:13 +02:00
|
|
|
bool AddLocal(const CService& addr, int nScore = LOCAL_NONE);
|
2012-05-13 01:26:14 +02:00
|
|
|
bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE);
|
2015-09-08 17:48:45 +02:00
|
|
|
bool RemoveLocal(const CService& addr);
|
2012-05-10 20:35:13 +02:00
|
|
|
bool SeenLocal(const CService& addr);
|
|
|
|
bool IsLocal(const CService& addr);
|
|
|
|
bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL);
|
2014-07-30 15:31:36 +02:00
|
|
|
bool IsReachable(enum Network net);
|
2012-04-10 20:22:04 +02:00
|
|
|
bool IsReachable(const CNetAddr &addr);
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices);
|
2012-02-12 13:45:24 +01:00
|
|
|
|
2012-04-10 20:22:04 +02:00
|
|
|
|
2012-05-24 19:02:21 +02:00
|
|
|
extern bool fDiscover;
|
2014-05-29 12:33:17 +02:00
|
|
|
extern bool fListen;
|
2017-07-21 20:31:47 +02:00
|
|
|
extern bool fRelayTxes;
|
2014-11-16 12:19:23 +01:00
|
|
|
|
2011-05-15 09:11:04 +02:00
|
|
|
extern std::map<CInv, CDataStream> mapRelay;
|
2013-04-13 07:13:08 +02:00
|
|
|
extern std::deque<std::pair<int64_t, CInv> > vRelayExpiration;
|
2010-08-29 18:58:15 +02:00
|
|
|
extern CCriticalSection cs_mapRelay;
|
2016-04-11 18:52:29 +02:00
|
|
|
extern limitedmap<uint256, int64_t> mapAlreadyAskedFor;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2015-07-31 18:05:42 +02:00
|
|
|
/** Subversion as sent to the P2P network in `version` messages */
|
|
|
|
extern std::string strSubVersion;
|
|
|
|
|
2014-05-05 13:22:28 +02:00
|
|
|
struct LocalServiceInfo {
|
|
|
|
int nScore;
|
|
|
|
int nPort;
|
|
|
|
};
|
|
|
|
|
|
|
|
extern CCriticalSection cs_mapLocalHost;
|
2014-06-04 12:52:15 +02:00
|
|
|
extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost;
|
2017-06-29 03:51:10 +02:00
|
|
|
typedef std::map<std::string, uint64_t> mapMsgCmdSize; //command, total bytes
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2012-06-29 23:24:53 +02:00
|
|
|
class CNodeStats
|
|
|
|
{
|
|
|
|
public:
|
2013-11-18 01:25:17 +01:00
|
|
|
NodeId nodeid;
|
2017-07-05 05:45:23 +02:00
|
|
|
ServiceFlags nServices;
|
2015-11-21 00:51:44 +01:00
|
|
|
bool fRelayTxes;
|
2013-04-13 07:13:08 +02:00
|
|
|
int64_t nLastSend;
|
|
|
|
int64_t nLastRecv;
|
|
|
|
int64_t nTimeConnected;
|
2014-12-15 11:06:15 +01:00
|
|
|
int64_t nTimeOffset;
|
2012-06-29 23:24:53 +02:00
|
|
|
std::string addrName;
|
|
|
|
int nVersion;
|
2013-11-26 12:52:21 +01:00
|
|
|
std::string cleanSubVer;
|
2012-06-29 23:24:53 +02:00
|
|
|
bool fInbound;
|
|
|
|
int nStartingHeight;
|
2013-04-13 07:13:08 +02:00
|
|
|
uint64_t nSendBytes;
|
2017-06-29 03:51:10 +02:00
|
|
|
mapMsgCmdSize mapSendBytesPerMsgCmd;
|
2013-04-13 07:13:08 +02:00
|
|
|
uint64_t nRecvBytes;
|
2017-06-29 03:51:10 +02:00
|
|
|
mapMsgCmdSize mapRecvBytesPerMsgCmd;
|
2014-06-21 13:34:36 +02:00
|
|
|
bool fWhitelisted;
|
2013-08-22 13:34:33 +02:00
|
|
|
double dPingTime;
|
|
|
|
double dPingWait;
|
2017-09-09 09:04:02 +02:00
|
|
|
double dMinPing;
|
2013-08-22 07:50:19 +02:00
|
|
|
std::string addrLocal;
|
2017-09-09 09:04:02 +02:00
|
|
|
CAddress addr;
|
2012-06-29 23:24:53 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2012-11-16 01:41:12 +01:00
|
|
|
class CNetMessage {
|
|
|
|
public:
|
|
|
|
bool in_data; // parsing header (false) or data (true)
|
|
|
|
|
|
|
|
CDataStream hdrbuf; // partially received header
|
|
|
|
CMessageHeader hdr; // complete header
|
|
|
|
unsigned int nHdrPos;
|
|
|
|
|
|
|
|
CDataStream vRecv; // received message data
|
|
|
|
unsigned int nDataPos;
|
|
|
|
|
2014-07-06 16:06:46 +02:00
|
|
|
int64_t nTime; // time (in microseconds) of message receipt.
|
|
|
|
|
2014-10-28 01:24:31 +01:00
|
|
|
CNetMessage(const CMessageHeader::MessageStartChars& pchMessageStartIn, int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), hdr(pchMessageStartIn), vRecv(nTypeIn, nVersionIn) {
|
2012-11-16 01:41:12 +01:00
|
|
|
hdrbuf.resize(24);
|
|
|
|
in_data = false;
|
|
|
|
nHdrPos = 0;
|
|
|
|
nDataPos = 0;
|
2014-07-06 16:06:46 +02:00
|
|
|
nTime = 0;
|
2012-11-16 01:41:12 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool complete() const
|
|
|
|
{
|
|
|
|
if (!in_data)
|
|
|
|
return false;
|
|
|
|
return (hdr.nMessageSize == nDataPos);
|
|
|
|
}
|
|
|
|
|
|
|
|
void SetVersion(int nVersionIn)
|
|
|
|
{
|
|
|
|
hdrbuf.SetVersion(nVersionIn);
|
|
|
|
vRecv.SetVersion(nVersionIn);
|
|
|
|
}
|
|
|
|
|
|
|
|
int readHeader(const char *pch, unsigned int nBytes);
|
|
|
|
int readData(const char *pch, unsigned int nBytes);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2012-03-26 16:48:23 +02:00
|
|
|
/** Information about a peer */
|
2010-08-29 18:58:15 +02:00
|
|
|
class CNode
|
|
|
|
{
|
2017-07-27 16:28:05 +02:00
|
|
|
friend class CConnman;
|
2010-08-29 18:58:15 +02:00
|
|
|
public:
|
|
|
|
// socket
|
2017-07-05 05:45:23 +02:00
|
|
|
ServiceFlags nServices;
|
|
|
|
ServiceFlags nServicesExpected;
|
2010-08-29 18:58:15 +02:00
|
|
|
SOCKET hSocket;
|
2013-03-24 16:52:24 +01:00
|
|
|
size_t nSendSize; // total size of all vSendMsg entries
|
|
|
|
size_t nSendOffset; // offset inside the first vSendMsg already sent
|
2013-04-13 07:13:08 +02:00
|
|
|
uint64_t nSendBytes;
|
2013-03-24 16:52:24 +01:00
|
|
|
std::deque<CSerializeData> vSendMsg;
|
2010-08-29 18:58:15 +02:00
|
|
|
CCriticalSection cs_vSend;
|
2012-11-16 01:41:12 +01:00
|
|
|
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
CCriticalSection cs_vProcessMsg;
|
|
|
|
std::list<CNetMessage> vProcessMsg;
|
|
|
|
size_t nProcessQueueSize;
|
|
|
|
|
2013-03-29 23:49:38 +01:00
|
|
|
std::deque<CInv> vRecvGetData;
|
2013-04-13 07:13:08 +02:00
|
|
|
uint64_t nRecvBytes;
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
std::atomic<int> nRecvVersion;
|
2012-11-16 01:41:12 +01:00
|
|
|
|
2013-04-13 07:13:08 +02:00
|
|
|
int64_t nLastSend;
|
|
|
|
int64_t nLastRecv;
|
|
|
|
int64_t nTimeConnected;
|
2014-12-15 11:06:15 +01:00
|
|
|
int64_t nTimeOffset;
|
2017-01-19 20:06:32 +01:00
|
|
|
int64_t nLastWarningTime;
|
2010-08-29 18:58:15 +02:00
|
|
|
CAddress addr;
|
2012-04-19 17:38:03 +02:00
|
|
|
std::string addrName;
|
2012-05-10 20:35:13 +02:00
|
|
|
CService addrLocal;
|
2017-01-19 20:06:32 +01:00
|
|
|
int nNumWarningsSkipped;
|
2017-08-17 20:37:22 +02:00
|
|
|
std::atomic<int> nVersion;
|
2014-01-11 18:14:29 +01:00
|
|
|
// strSubVer is whatever byte array we read from the wire. However, this field is intended
|
2013-11-26 12:52:21 +01:00
|
|
|
// to be printed out, displayed to humans in various forms and so on. So we sanitize it and
|
|
|
|
// store the sanitized version in cleanSubVer. The original should be used when dealing with
|
|
|
|
// the network or wire types and the cleaned string used when displayed or logged.
|
|
|
|
std::string strSubVer, cleanSubVer;
|
2014-06-21 13:34:36 +02:00
|
|
|
bool fWhitelisted; // This peer can bypass DoS banning.
|
2017-07-17 12:39:12 +02:00
|
|
|
bool fFeeler; // If true this node is being used as a short lived feeler.
|
2012-04-24 02:15:00 +02:00
|
|
|
bool fOneShot;
|
2010-08-29 18:58:15 +02:00
|
|
|
bool fClient;
|
|
|
|
bool fInbound;
|
|
|
|
bool fNetworkNode;
|
2017-08-17 20:37:22 +02:00
|
|
|
std::atomic_bool fSuccessfullyConnected;
|
2010-08-29 18:58:15 +02:00
|
|
|
bool fDisconnect;
|
2012-08-21 03:10:25 +02:00
|
|
|
// We use fRelayTxes for two purposes -
|
|
|
|
// a) it allows us to not relay tx invs before receiving the peer's version message
|
2015-04-28 16:48:28 +02:00
|
|
|
// b) the peer may tell us in its version message that we should not relay tx invs
|
2015-11-14 14:12:31 +01:00
|
|
|
// unless it loads a bloom filter.
|
2016-05-05 13:14:29 +02:00
|
|
|
bool fRelayTxes; //protected by cs_filter
|
2016-04-15 09:02:41 +02:00
|
|
|
bool fSentAddr;
|
2016-07-30 13:05:41 +02:00
|
|
|
// If 'true' this node will be disconnected on CMasternodeMan::ProcessMasternodeConnections()
|
|
|
|
bool fMasternode;
|
2012-05-10 18:44:07 +02:00
|
|
|
CSemaphoreGrant grantOutbound;
|
2017-01-21 20:03:55 +01:00
|
|
|
CSemaphoreGrant grantMasternodeOutbound;
|
2012-08-13 05:26:29 +02:00
|
|
|
CCriticalSection cs_filter;
|
|
|
|
CBloomFilter* pfilter;
|
2010-08-29 18:58:15 +02:00
|
|
|
int nRefCount;
|
2013-11-18 01:25:17 +01:00
|
|
|
NodeId id;
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
|
|
|
|
std::atomic_bool fPauseRecv;
|
|
|
|
std::atomic_bool fPauseSend;
|
2013-03-29 00:43:31 +01:00
|
|
|
protected:
|
2011-09-06 22:09:04 +02:00
|
|
|
|
2017-06-29 03:51:10 +02:00
|
|
|
mapMsgCmdSize mapSendBytesPerMsgCmd;
|
|
|
|
mapMsgCmdSize mapRecvBytesPerMsgCmd;
|
|
|
|
|
2010-08-29 18:58:15 +02:00
|
|
|
public:
|
|
|
|
uint256 hashContinue;
|
|
|
|
int nStartingHeight;
|
|
|
|
|
|
|
|
// flood relay
|
2011-05-15 09:11:04 +02:00
|
|
|
std::vector<CAddress> vAddrToSend;
|
2015-04-25 22:25:44 +02:00
|
|
|
CRollingBloomFilter addrKnown;
|
2010-08-29 18:58:15 +02:00
|
|
|
bool fGetAddr;
|
2011-05-15 09:11:04 +02:00
|
|
|
std::set<uint256> setKnown;
|
2015-04-08 20:20:00 +02:00
|
|
|
int64_t nNextAddrSend;
|
|
|
|
int64_t nNextLocalAddrSend;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
// inventory based relay
|
2015-11-26 06:25:30 +01:00
|
|
|
CRollingBloomFilter filterInventoryKnown;
|
2016-05-05 13:14:29 +02:00
|
|
|
// Set of transaction ids we still have to announce.
|
|
|
|
// They are sorted by the mempool before relay, so the order is not important.
|
|
|
|
std::set<uint256> setInventoryTxToSend;
|
|
|
|
// List of block ids we still have announce.
|
|
|
|
// There is no final sorting before sending, as they are always sent immediately
|
|
|
|
// and in the order requested.
|
|
|
|
std::vector<uint256> vInventoryBlockToSend;
|
2017-09-21 23:45:10 +02:00
|
|
|
// List of non-tx/non-block inventory items
|
|
|
|
std::vector<CInv> vInventoryOtherToSend;
|
2010-08-29 18:58:15 +02:00
|
|
|
CCriticalSection cs_inventory;
|
2014-07-16 23:31:41 +02:00
|
|
|
std::set<uint256> setAskFor;
|
2013-04-13 07:13:08 +02:00
|
|
|
std::multimap<int64_t, CInv> mapAskFor;
|
2015-04-08 20:20:00 +02:00
|
|
|
int64_t nNextInvSend;
|
2014-11-18 22:16:32 +01:00
|
|
|
// Used for headers announcements - unfiltered blocks to relay
|
|
|
|
// Also protected by cs_inventory
|
|
|
|
std::vector<uint256> vBlockHashesToAnnounce;
|
2017-09-04 08:10:52 +02:00
|
|
|
// Blocks received by INV while headers chain was too far behind. These are used to delay GETHEADERS messages
|
|
|
|
// Also protected by cs_inventory
|
|
|
|
std::vector<uint256> vBlockHashesFromINV;
|
2016-05-05 13:14:29 +02:00
|
|
|
// Used for BIP35 mempool sending, also protected by cs_inventory
|
|
|
|
bool fSendMempool;
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2017-07-12 13:13:38 +02:00
|
|
|
// Block and TXN accept times
|
|
|
|
std::atomic<int64_t> nLastBlockTime;
|
|
|
|
std::atomic<int64_t> nLastTXTime;
|
|
|
|
|
2013-10-15 00:34:20 +02:00
|
|
|
// Ping time measurement:
|
|
|
|
// The pong reply we're expecting, or 0 if no pong expected.
|
2013-04-13 07:13:08 +02:00
|
|
|
uint64_t nPingNonceSent;
|
2013-10-15 00:34:20 +02:00
|
|
|
// Time (in usec) the last ping was sent, or 0 if no ping was ever sent.
|
2013-04-13 07:13:08 +02:00
|
|
|
int64_t nPingUsecStart;
|
2013-10-15 00:34:20 +02:00
|
|
|
// Last measured round-trip time.
|
2013-04-13 07:13:08 +02:00
|
|
|
int64_t nPingUsecTime;
|
2015-08-13 11:31:46 +02:00
|
|
|
// Best measured round-trip time.
|
|
|
|
int64_t nMinPingUsecTime;
|
2013-10-15 00:34:20 +02:00
|
|
|
// Whether a ping is requested.
|
2013-08-22 13:34:33 +02:00
|
|
|
bool fPingQueued;
|
2016-03-21 18:02:47 +01:00
|
|
|
// Minimum fee rate with which to filter inv's to this node
|
|
|
|
CAmount minFeeFilter;
|
|
|
|
CCriticalSection cs_feeFilter;
|
|
|
|
CAmount lastSentFeeFilter;
|
|
|
|
int64_t nextSendTimeFeeFilter;
|
2014-01-11 18:14:29 +01:00
|
|
|
|
2017-03-13 07:29:16 +01:00
|
|
|
std::vector<unsigned char> vchKeyedNetGroup;
|
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
CNode(NodeId id, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false, bool fNetworkNodeIn = false);
|
2014-08-21 05:17:21 +02:00
|
|
|
~CNode();
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
private:
|
2017-03-13 07:29:16 +01:00
|
|
|
// Secret key for computing keyed net groups
|
|
|
|
static std::vector<unsigned char> vchSecretKey;
|
|
|
|
|
2017-02-05 17:45:36 +01:00
|
|
|
CCriticalSection cs_nRefCount;
|
|
|
|
|
2010-08-29 18:58:15 +02:00
|
|
|
CNode(const CNode&);
|
|
|
|
void operator=(const CNode&);
|
2013-08-22 18:09:32 +02:00
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
uint64_t nLocalHostNonce;
|
|
|
|
ServiceFlags nLocalServices;
|
|
|
|
int nMyStartingHeight;
|
2017-07-27 16:28:05 +02:00
|
|
|
int nSendVersion;
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
std::list<CNetMessage> vRecvMsg; // Used only by SocketHandler thread
|
2010-08-29 18:58:15 +02:00
|
|
|
public:
|
|
|
|
|
2013-11-18 01:25:17 +01:00
|
|
|
NodeId GetId() const {
|
|
|
|
return id;
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
uint64_t GetLocalNonce() const {
|
|
|
|
return nLocalHostNonce;
|
|
|
|
}
|
|
|
|
|
2017-07-27 16:28:05 +02:00
|
|
|
int GetMyStartingHeight() const {
|
|
|
|
return nMyStartingHeight;
|
|
|
|
}
|
|
|
|
|
2010-08-29 18:58:15 +02:00
|
|
|
int GetRefCount()
|
|
|
|
{
|
2017-02-05 17:45:36 +01:00
|
|
|
LOCK(cs_nRefCount);
|
2013-03-29 00:43:31 +01:00
|
|
|
assert(nRefCount >= 0);
|
|
|
|
return nRefCount;
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
bool ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete);
|
2012-11-16 01:41:12 +01:00
|
|
|
|
|
|
|
void SetRecvVersion(int nVersionIn)
|
|
|
|
{
|
|
|
|
nRecvVersion = nVersionIn;
|
Backport Bitcoin PR#9441: Net: Massive speedup. Net locks overhaul (#1586)
* net: fix typo causing the wrong receive buffer size
Surprisingly this hasn't been causing me any issues while testing, probably
because it requires lots of large blocks to be flying around.
Send/Recv corks need tests!
* net: make vRecvMsg a list so that we can use splice()
* net: make GetReceiveFloodSize public
This will be needed so that the message processor can cork incoming messages
* net: only disconnect if fDisconnect has been set
These conditions are problematic to check without locking, and we shouldn't be
relying on the refcount to disconnect.
* net: wait until the node is destroyed to delete its recv buffer
when vRecvMsg becomes a private buffer, it won't make sense to allow other
threads to mess with it anymore.
* net: set message deserialization version when it's actually time to deserialize
We'll soon no longer have access to vRecvMsg, and this is more intuitive anyway.
* net: handle message accounting in ReceiveMsgBytes
This allows locking to be pushed down to only where it's needed
Also reuse the current time rather than checking multiple times.
* net: record bytes written before notifying the message processor
* net: Add a simple function for waking the message handler
This may be used publicly in the future
* net: remove useless comments
* net: remove redundant max sendbuffer size check
This is left-over from before there was proper accounting. Hitting 2x the
sendbuffer size should not be possible.
* net: rework the way that the messagehandler sleeps
In order to sleep accurately, the message handler needs to know if _any_ node
has more processing that it should do before the entire thread sleeps.
Rather than returning a value that represents whether ProcessMessages
encountered a message that should trigger a disconnnect, interpret the return
value as whether or not that node has more work to do.
Also, use a global fProcessWake value that can be set by other threads,
which takes precedence (for one cycle) over the messagehandler's decision.
Note that the previous behavior was to only process one message per loop
(except in the case of a bad checksum or invalid header). That was changed in
PR #3180.
The only change here in that regard is that the current node now falls to the
back of the processing queue for the bad checksum/invalid header cases.
* net: add a new message queue for the message processor
This separates the storage of messages from the net and queued messages for
processing, allowing the locks to be split.
* net: add a flag to indicate when a node's process queue is full
Messages are dumped very quickly from the socket handler to the processor, so
it's the depth of the processing queue that's interesting.
The socket handler checks the process queue's size during the brief message
hand-off and pauses if necessary, and the processor possibly unpauses each time
a message is popped off of its queue.
* net: add a flag to indicate when a node's send buffer is full
Similar to the recv flag, but this one indicates whether or not the net's send
buffer is full.
The socket handler checks the send queue when a new message is added and pauses
if necessary, and possibly unpauses after each message is drained from its buffer.
* net: remove cs_vRecvMsg
vRecvMsg is now only touched by the socket handler thread.
The accounting vars (nRecvBytes/nLastRecv/mapRecvBytesPerMsgCmd) are also
only used by the socket handler thread, with the exception of queries from
rpc/gui. These accesses are not threadsafe, but they never were. This needs to
be addressed separately.
Also, update comment describing data flow
2017-08-23 16:20:43 +02:00
|
|
|
}
|
|
|
|
int GetRecvVersion()
|
|
|
|
{
|
|
|
|
return nRecvVersion;
|
2012-11-16 01:41:12 +01:00
|
|
|
}
|
2017-08-17 20:37:22 +02:00
|
|
|
void SetSendVersion(int nVersionIn);
|
|
|
|
int GetSendVersion() const;
|
2012-11-16 01:41:12 +01:00
|
|
|
|
2013-03-29 00:43:31 +01:00
|
|
|
CNode* AddRef()
|
2010-08-29 18:58:15 +02:00
|
|
|
{
|
2017-02-05 17:45:36 +01:00
|
|
|
LOCK(cs_nRefCount);
|
2013-03-29 00:43:31 +01:00
|
|
|
nRefCount++;
|
2010-08-29 18:58:15 +02:00
|
|
|
return this;
|
|
|
|
}
|
|
|
|
|
|
|
|
void Release()
|
|
|
|
{
|
2017-02-05 17:45:36 +01:00
|
|
|
LOCK(cs_nRefCount);
|
2010-08-29 18:58:15 +02:00
|
|
|
nRefCount--;
|
2017-02-04 19:47:38 +01:00
|
|
|
assert(nRefCount >= 0);
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void AddAddressKnown(const CAddress& addr)
|
|
|
|
{
|
2015-04-25 22:25:44 +02:00
|
|
|
addrKnown.insert(addr.GetKey());
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void PushAddress(const CAddress& addr)
|
|
|
|
{
|
|
|
|
// Known checking here is only to save space from duplicates.
|
|
|
|
// SendMessages will filter it again for knowns that were added
|
|
|
|
// after addresses were pushed.
|
2015-04-25 22:25:44 +02:00
|
|
|
if (addr.IsValid() && !addrKnown.contains(addr.GetKey())) {
|
2014-11-21 12:22:11 +01:00
|
|
|
if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) {
|
|
|
|
vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr;
|
|
|
|
} else {
|
|
|
|
vAddrToSend.push_back(addr);
|
|
|
|
}
|
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void AddInventoryKnown(const CInv& inv)
|
|
|
|
{
|
2012-04-06 18:39:12 +02:00
|
|
|
{
|
|
|
|
LOCK(cs_inventory);
|
2015-11-26 06:25:30 +01:00
|
|
|
filterInventoryKnown.insert(inv.hash);
|
2012-04-06 18:39:12 +02:00
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void PushInventory(const CInv& inv)
|
|
|
|
{
|
2016-05-05 13:14:29 +02:00
|
|
|
LOCK(cs_inventory);
|
|
|
|
if (inv.type == MSG_TX) {
|
|
|
|
if (!filterInventoryKnown.contains(inv.hash)) {
|
2016-12-04 21:33:39 +01:00
|
|
|
LogPrint("net", "PushInventory -- filtered inv: %s peer=%d\n", inv.ToString(), id);
|
2016-05-05 13:14:29 +02:00
|
|
|
setInventoryTxToSend.insert(inv.hash);
|
2016-12-04 21:33:39 +01:00
|
|
|
}
|
2016-05-05 13:14:29 +02:00
|
|
|
} else if (inv.type == MSG_BLOCK) {
|
2016-12-04 21:33:39 +01:00
|
|
|
LogPrint("net", "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id);
|
2016-05-05 13:14:29 +02:00
|
|
|
vInventoryBlockToSend.push_back(inv.hash);
|
2017-09-21 23:45:10 +02:00
|
|
|
} else {
|
|
|
|
LogPrint("net", "PushInventory -- inv: %s peer=%d\n", inv.ToString(), id);
|
|
|
|
vInventoryOtherToSend.push_back(inv);
|
2012-04-06 18:39:12 +02:00
|
|
|
}
|
2010-08-29 18:58:15 +02:00
|
|
|
}
|
|
|
|
|
2014-11-18 22:16:32 +01:00
|
|
|
void PushBlockHash(const uint256 &hash)
|
|
|
|
{
|
|
|
|
LOCK(cs_inventory);
|
|
|
|
vBlockHashesToAnnounce.push_back(hash);
|
|
|
|
}
|
|
|
|
|
2017-09-04 08:10:52 +02:00
|
|
|
void PushBlockHashFromINV(const uint256 &hash)
|
|
|
|
{
|
|
|
|
LOCK(cs_inventory);
|
|
|
|
vBlockHashesFromINV.push_back(hash);
|
|
|
|
}
|
|
|
|
|
2014-08-21 05:17:21 +02:00
|
|
|
void AskFor(const CInv& inv);
|
2010-08-29 18:58:15 +02:00
|
|
|
|
|
|
|
void CloseSocketDisconnect();
|
2011-09-06 22:09:04 +02:00
|
|
|
|
2012-06-29 23:24:53 +02:00
|
|
|
void copyStats(CNodeStats &stats);
|
2013-08-22 18:09:32 +02:00
|
|
|
|
Backport Bitcoin PR#8085: p2p: Begin encapsulation (#1537)
* net: move CBanDB and CAddrDB out of net.h/cpp
This will eventually solve a circular dependency
* net: Create CConnman to encapsulate p2p connections
* net: Move socket binding into CConnman
* net: move OpenNetworkConnection into CConnman
* net: move ban and addrman functions into CConnman
* net: Add oneshot functions to CConnman
* net: move added node functions to CConnman
* net: Add most functions needed for vNodes to CConnman
* net: handle nodesignals in CConnman
* net: Pass CConnection to wallet rather than using the global
* net: Add rpc error for missing/disabled p2p functionality
* net: Pass CConnman around as needed
* gui: add NodeID to the peer table
* net: create generic functor accessors and move vNodes to CConnman
* net: move whitelist functions into CConnman
* net: move nLastNodeId to CConnman
* net: move nLocalHostNonce to CConnman
This behavior seems to have been quite racy and broken.
Move nLocalHostNonce into CNode, and check received nonces against all
non-fully-connected nodes. If there's a match, assume we've connected
to ourself.
* net: move messageHandlerCondition to CConnman
* net: move send/recv statistics to CConnman
* net: move SendBufferSize/ReceiveFloodSize to CConnman
* net: move nLocalServices/nRelevantServices to CConnman
These are in-turn passed to CNode at connection time. This allows us to offer
different services to different peers (or test the effects of doing so).
* net: move semOutbound and semMasternodeOutbound to CConnman
* net: SocketSendData returns written size
* net: move max/max-outbound to CConnman
* net: Pass best block known height into CConnman
CConnman then passes the current best height into CNode at creation time.
This way CConnman/CNode have no dependency on main for height, and the signals
only move in one direction.
This also helps to prevent identity leakage a tiny bit. Before this change, an
attacker could theoretically make 2 connections on different interfaces. They
would connect fully on one, and only establish the initial connection on the
other. Once they receive a new block, they would relay it to your first
connection, and immediately commence the version handshake on the second. Since
the new block height is reflected immediately, they could attempt to learn
whether the two connections were correlated.
This is, of course, incredibly unlikely to work due to the small timings
involved and receipt from other senders. But it doesn't hurt to lock-in
nBestHeight at the time of connection, rather than letting the remote choose
the time.
* net: pass CClientUIInterface into CConnman
* net: Drop StartNode/StopNode and use CConnman directly
* net: Introduce CConnection::Options to avoid passing so many params
* net: add nSendBufferMaxSize/nReceiveFloodSize to CConnection::Options
* net: move vNodesDisconnected into CConnman
* Made the ForEachNode* functions in src/net.cpp more pragmatic and self documenting
* Convert ForEachNode* functions to take a templated function argument rather than a std::function to eliminate std::function overhead
* net: move MAX_FEELER_CONNECTIONS into connman
2017-07-21 11:35:19 +02:00
|
|
|
ServiceFlags GetLocalServices() const
|
|
|
|
{
|
|
|
|
return nLocalServices;
|
|
|
|
}
|
2017-03-13 07:29:16 +01:00
|
|
|
|
|
|
|
static std::vector<unsigned char> CalculateKeyedNetGroup(CAddress& address);
|
2010-08-29 18:58:15 +02:00
|
|
|
};
|
|
|
|
|
2015-05-25 22:59:38 +02:00
|
|
|
class CExplicitNetCleanup
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static void callCleanup();
|
|
|
|
};
|
2010-08-29 18:58:15 +02:00
|
|
|
|
2013-11-29 16:33:34 +01:00
|
|
|
|
2015-06-19 15:27:37 +02:00
|
|
|
|
2015-04-08 20:20:00 +02:00
|
|
|
/** Return a timestamp in the future (in microseconds) for exponentially distributed events. */
|
|
|
|
int64_t PoissonNextSend(int64_t nNow, int average_interval_seconds);
|
|
|
|
|
2014-08-28 22:21:03 +02:00
|
|
|
#endif // BITCOIN_NET_H
|