Branch data Line data Source code
# 1 : : // Copyright (c) 2009-2010 Satoshi Nakamoto
# 2 : : // Copyright (c) 2009-2020 The Bitcoin Core developers
# 3 : : // Distributed under the MIT software license, see the accompanying
# 4 : : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
# 5 : :
# 6 : : #if defined(HAVE_CONFIG_H)
# 7 : : #include <config/bitcoin-config.h>
# 8 : : #endif
# 9 : :
# 10 : : #include <net.h>
# 11 : :
# 12 : : #include <banman.h>
# 13 : : #include <chainparams.h>
# 14 : : #include <clientversion.h>
# 15 : : #include <consensus/consensus.h>
# 16 : : #include <crypto/sha256.h>
# 17 : : #include <net_permissions.h>
# 18 : : #include <netbase.h>
# 19 : : #include <node/ui_interface.h>
# 20 : : #include <protocol.h>
# 21 : : #include <random.h>
# 22 : : #include <scheduler.h>
# 23 : : #include <util/strencodings.h>
# 24 : : #include <util/translation.h>
# 25 : :
# 26 : : #ifdef WIN32
# 27 : : #include <string.h>
# 28 : : #else
# 29 : : #include <fcntl.h>
# 30 : : #endif
# 31 : :
# 32 : : #ifdef USE_POLL
# 33 : : #include <poll.h>
# 34 : : #endif
# 35 : :
# 36 : : #ifdef USE_UPNP
# 37 : : #include <miniupnpc/miniupnpc.h>
# 38 : : #include <miniupnpc/upnpcommands.h>
# 39 : : #include <miniupnpc/upnperrors.h>
# 40 : : // The minimum supported miniUPnPc API version is set to 10. This keeps compatibility
# 41 : : // with Ubuntu 16.04 LTS and Debian 8 libminiupnpc-dev packages.
# 42 : : static_assert(MINIUPNPC_API_VERSION >= 10, "miniUPnPc API version >= 10 assumed");
# 43 : : #endif
# 44 : :
# 45 : : #include <cstdint>
# 46 : : #include <unordered_map>
# 47 : :
# 48 : : #include <math.h>
# 49 : :
# 50 : : // How often to dump addresses to peers.dat
# 51 : : static constexpr std::chrono::minutes DUMP_PEERS_INTERVAL{15};
# 52 : :
# 53 : : /** Number of DNS seeds to query when the number of connections is low. */
# 54 : : static constexpr int DNSSEEDS_TO_QUERY_AT_ONCE = 3;
# 55 : :
# 56 : : /** How long to delay before querying DNS seeds
# 57 : : *
# 58 : : * If we have more than THRESHOLD entries in addrman, then it's likely
# 59 : : * that we got those addresses from having previously connected to the P2P
# 60 : : * network, and that we'll be able to successfully reconnect to the P2P
# 61 : : * network via contacting one of them. So if that's the case, spend a
# 62 : : * little longer trying to connect to known peers before querying the
# 63 : : * DNS seeds.
# 64 : : */
# 65 : : static constexpr std::chrono::seconds DNSSEEDS_DELAY_FEW_PEERS{11};
# 66 : : static constexpr std::chrono::minutes DNSSEEDS_DELAY_MANY_PEERS{5};
# 67 : : static constexpr int DNSSEEDS_DELAY_PEER_THRESHOLD = 1000; // "many" vs "few" peers
# 68 : :
# 69 : : // We add a random period time (0 to 1 seconds) to feeler connections to prevent synchronization.
# 70 : 0 : #define FEELER_SLEEP_WINDOW 1
# 71 : :
# 72 : : // MSG_NOSIGNAL is not available on some platforms, if it doesn't exist define it as 0
# 73 : : #if !defined(MSG_NOSIGNAL)
# 74 : : #define MSG_NOSIGNAL 0
# 75 : : #endif
# 76 : :
# 77 : : // MSG_DONTWAIT is not available on some platforms, if it doesn't exist define it as 0
# 78 : : #if !defined(MSG_DONTWAIT)
# 79 : : #define MSG_DONTWAIT 0
# 80 : : #endif
# 81 : :
# 82 : : /** Used to pass flags to the Bind() function */
# 83 : : enum BindFlags {
# 84 : : BF_NONE = 0,
# 85 : : BF_EXPLICIT = (1U << 0),
# 86 : : BF_REPORT_ERROR = (1U << 1),
# 87 : : };
# 88 : :
# 89 : : // The set of sockets cannot be modified while waiting
# 90 : : // The sleep time needs to be small to avoid new sockets stalling
# 91 : : static const uint64_t SELECT_TIMEOUT_MILLISECONDS = 50;
# 92 : :
# 93 : : const std::string NET_MESSAGE_COMMAND_OTHER = "*other*";
# 94 : :
# 95 : : static const uint64_t RANDOMIZER_ID_NETGROUP = 0x6c0edd8036ef4036ULL; // SHA256("netgroup")[0:8]
# 96 : : static const uint64_t RANDOMIZER_ID_LOCALHOSTNONCE = 0xd93e69e2bbfa5735ULL; // SHA256("localhostnonce")[0:8]
# 97 : : //
# 98 : : // Global state variables
# 99 : : //
# 100 : : bool fDiscover = true;
# 101 : : bool fListen = true;
# 102 : : bool g_relay_txes = !DEFAULT_BLOCKSONLY;
# 103 : : RecursiveMutex cs_mapLocalHost;
# 104 : : std::map<CNetAddr, LocalServiceInfo> mapLocalHost GUARDED_BY(cs_mapLocalHost);
# 105 : : static bool vfLimited[NET_MAX] GUARDED_BY(cs_mapLocalHost) = {};
# 106 : : std::string strSubVersion;
# 107 : :
# 108 : : void CConnman::AddAddrFetch(const std::string& strDest)
# 109 : 0 : {
# 110 : 0 : LOCK(m_addr_fetches_mutex);
# 111 : 0 : m_addr_fetches.push_back(strDest);
# 112 : 0 : }
# 113 : :
# 114 : : uint16_t GetListenPort()
# 115 : 1300 : {
# 116 : 1300 : return (uint16_t)(gArgs.GetArg("-port", Params().GetDefaultPort()));
# 117 : 1300 : }
# 118 : :
# 119 : : // find 'best' local address for a particular peer
# 120 : : bool GetLocal(CService& addr, const CNetAddr *paddrPeer)
# 121 : 794 : {
# 122 : 794 : if (!fListen)
# 123 : 0 : return false;
# 124 : 794 :
# 125 : 794 : int nBestScore = -1;
# 126 : 794 : int nBestReachability = -1;
# 127 : 794 : {
# 128 : 794 : LOCK(cs_mapLocalHost);
# 129 : 794 : for (const auto& entry : mapLocalHost)
# 130 : 2 : {
# 131 : 2 : int nScore = entry.second.nScore;
# 132 : 2 : int nReachability = entry.first.GetReachabilityFrom(paddrPeer);
# 133 : 2 : if (nReachability > nBestReachability || (nReachability == nBestReachability && nScore > nBestScore))
# 134 : 2 : {
# 135 : 2 : addr = CService(entry.first, entry.second.nPort);
# 136 : 2 : nBestReachability = nReachability;
# 137 : 2 : nBestScore = nScore;
# 138 : 2 : }
# 139 : 2 : }
# 140 : 794 : }
# 141 : 794 : return nBestScore >= 0;
# 142 : 794 : }
# 143 : :
# 144 : : //! Convert the pnSeed6 array into usable address objects.
# 145 : : static std::vector<CAddress> convertSeed6(const std::vector<SeedSpec6> &vSeedsIn)
# 146 : 18 : {
# 147 : 18 : // It'll only connect to one or two seed nodes because once it connects,
# 148 : 18 : // it'll get a pile of addresses with newer timestamps.
# 149 : 18 : // Seed nodes are given a random 'last seen time' of between one and two
# 150 : 18 : // weeks ago.
# 151 : 18 : const int64_t nOneWeek = 7*24*60*60;
# 152 : 18 : std::vector<CAddress> vSeedsOut;
# 153 : 18 : vSeedsOut.reserve(vSeedsIn.size());
# 154 : 18 : FastRandomContext rng;
# 155 : 18 : for (const auto& seed_in : vSeedsIn) {
# 156 : 0 : struct in6_addr ip;
# 157 : 0 : memcpy(&ip, seed_in.addr, sizeof(ip));
# 158 : 0 : CAddress addr(CService(ip, seed_in.port), GetDesirableServiceFlags(NODE_NONE));
# 159 : 0 : addr.nTime = GetTime() - rng.randrange(nOneWeek) - nOneWeek;
# 160 : 0 : vSeedsOut.push_back(addr);
# 161 : 0 : }
# 162 : 18 : return vSeedsOut;
# 163 : 18 : }
# 164 : :
# 165 : : // get best local address for a particular peer as a CAddress
# 166 : : // Otherwise, return the unroutable 0.0.0.0 but filled in with
# 167 : : // the normal parameters, since the IP may be changed to a useful
# 168 : : // one by discovery.
# 169 : : CAddress GetLocalAddress(const CNetAddr *paddrPeer, ServiceFlags nLocalServices)
# 170 : 794 : {
# 171 : 794 : CAddress ret(CService(CNetAddr(),GetListenPort()), nLocalServices);
# 172 : 794 : CService addr;
# 173 : 794 : if (GetLocal(addr, paddrPeer))
# 174 : 2 : {
# 175 : 2 : ret = CAddress(addr, nLocalServices);
# 176 : 2 : }
# 177 : 794 : ret.nTime = GetAdjustedTime();
# 178 : 794 : return ret;
# 179 : 794 : }
# 180 : :
# 181 : : static int GetnScore(const CService& addr)
# 182 : 0 : {
# 183 : 0 : LOCK(cs_mapLocalHost);
# 184 : 0 : if (mapLocalHost.count(addr) == 0) return 0;
# 185 : 0 : return mapLocalHost[addr].nScore;
# 186 : 0 : }
# 187 : :
# 188 : : // Is our peer's addrLocal potentially useful as an external IP source?
# 189 : : bool IsPeerAddrLocalGood(CNode *pnode)
# 190 : 794 : {
# 191 : 794 : CService addrLocal = pnode->GetAddrLocal();
# 192 : 794 : return fDiscover && pnode->addr.IsRoutable() && addrLocal.IsRoutable() &&
# 193 : 794 : IsReachable(addrLocal.GetNetwork());
# 194 : 794 : }
# 195 : :
# 196 : : // pushes our own address to a peer
# 197 : : void AdvertiseLocal(CNode *pnode)
# 198 : 645 : {
# 199 : 645 : if (fListen && pnode->fSuccessfullyConnected)
# 200 : 645 : {
# 201 : 645 : CAddress addrLocal = GetLocalAddress(&pnode->addr, pnode->GetLocalServices());
# 202 : 645 : if (gArgs.GetBoolArg("-addrmantest", false)) {
# 203 : 5 : // use IPv4 loopback during addrmantest
# 204 : 5 : addrLocal = CAddress(CService(LookupNumeric("127.0.0.1", GetListenPort())), pnode->GetLocalServices());
# 205 : 5 : }
# 206 : 645 : // If discovery is enabled, sometimes give our peer the address it
# 207 : 645 : // tells us that it sees us as in case it has a better idea of our
# 208 : 645 : // address than we do.
# 209 : 645 : FastRandomContext rng;
# 210 : 645 : if (IsPeerAddrLocalGood(pnode) && (!addrLocal.IsRoutable() ||
# 211 : 2 : rng.randbits((GetnScore(addrLocal) > LOCAL_MANUAL) ? 3 : 1) == 0))
# 212 : 2 : {
# 213 : 2 : addrLocal.SetIP(pnode->GetAddrLocal());
# 214 : 2 : }
# 215 : 645 : if (addrLocal.IsRoutable() || gArgs.GetBoolArg("-addrmantest", false))
# 216 : 7 : {
# 217 : 7 : LogPrint(BCLog::NET, "AdvertiseLocal: advertising address %s\n", addrLocal.ToString());
# 218 : 7 : pnode->PushAddress(addrLocal, rng);
# 219 : 7 : }
# 220 : 645 : }
# 221 : 645 : }
# 222 : :
# 223 : : // learn a new local address
# 224 : : bool AddLocal(const CService& addr, int nScore)
# 225 : 2 : {
# 226 : 2 : if (!addr.IsRoutable())
# 227 : 0 : return false;
# 228 : 2 :
# 229 : 2 : if (!fDiscover && nScore < LOCAL_MANUAL)
# 230 : 0 : return false;
# 231 : 2 :
# 232 : 2 : if (!IsReachable(addr))
# 233 : 0 : return false;
# 234 : 2 :
# 235 : 2 : LogPrintf("AddLocal(%s,%i)\n", addr.ToString(), nScore);
# 236 : 2 :
# 237 : 2 : {
# 238 : 2 : LOCK(cs_mapLocalHost);
# 239 : 2 : bool fAlready = mapLocalHost.count(addr) > 0;
# 240 : 2 : LocalServiceInfo &info = mapLocalHost[addr];
# 241 : 2 : if (!fAlready || nScore >= info.nScore) {
# 242 : 2 : info.nScore = nScore + (fAlready ? 1 : 0);
# 243 : 2 : info.nPort = addr.GetPort();
# 244 : 2 : }
# 245 : 2 : }
# 246 : 2 :
# 247 : 2 : return true;
# 248 : 2 : }
# 249 : :
# 250 : : bool AddLocal(const CNetAddr &addr, int nScore)
# 251 : 0 : {
# 252 : 0 : return AddLocal(CService(addr, GetListenPort()), nScore);
# 253 : 0 : }
# 254 : :
# 255 : : void RemoveLocal(const CService& addr)
# 256 : 2 : {
# 257 : 2 : LOCK(cs_mapLocalHost);
# 258 : 2 : LogPrintf("RemoveLocal(%s)\n", addr.ToString());
# 259 : 2 : mapLocalHost.erase(addr);
# 260 : 2 : }
# 261 : :
# 262 : : void SetReachable(enum Network net, bool reachable)
# 263 : 530 : {
# 264 : 530 : if (net == NET_UNROUTABLE || net == NET_INTERNAL)
# 265 : 4 : return;
# 266 : 526 : LOCK(cs_mapLocalHost);
# 267 : 526 : vfLimited[net] = !reachable;
# 268 : 526 : }
# 269 : :
# 270 : : bool IsReachable(enum Network net)
# 271 : 686 : {
# 272 : 686 : LOCK(cs_mapLocalHost);
# 273 : 686 : return !vfLimited[net];
# 274 : 686 : }
# 275 : :
# 276 : : bool IsReachable(const CNetAddr &addr)
# 277 : 376 : {
# 278 : 376 : return IsReachable(addr.GetNetwork());
# 279 : 376 : }
# 280 : :
# 281 : : /** vote for a local address */
# 282 : : bool SeenLocal(const CService& addr)
# 283 : 0 : {
# 284 : 0 : {
# 285 : 0 : LOCK(cs_mapLocalHost);
# 286 : 0 : if (mapLocalHost.count(addr) == 0)
# 287 : 0 : return false;
# 288 : 0 : mapLocalHost[addr].nScore++;
# 289 : 0 : }
# 290 : 0 : return true;
# 291 : 0 : }
# 292 : :
# 293 : :
# 294 : : /** check whether a given address is potentially local */
# 295 : : bool IsLocal(const CService& addr)
# 296 : 110 : {
# 297 : 110 : LOCK(cs_mapLocalHost);
# 298 : 110 : return mapLocalHost.count(addr) > 0;
# 299 : 110 : }
# 300 : :
# 301 : : CNode* CConnman::FindNode(const CNetAddr& ip)
# 302 : 2 : {
# 303 : 2 : LOCK(cs_vNodes);
# 304 : 5 : for (CNode* pnode : vNodes) {
# 305 : 5 : if (static_cast<CNetAddr>(pnode->addr) == ip) {
# 306 : 0 : return pnode;
# 307 : 0 : }
# 308 : 5 : }
# 309 : 2 : return nullptr;
# 310 : 2 : }
# 311 : :
# 312 : : CNode* CConnman::FindNode(const CSubNet& subNet)
# 313 : 0 : {
# 314 : 0 : LOCK(cs_vNodes);
# 315 : 0 : for (CNode* pnode : vNodes) {
# 316 : 0 : if (subNet.Match(static_cast<CNetAddr>(pnode->addr))) {
# 317 : 0 : return pnode;
# 318 : 0 : }
# 319 : 0 : }
# 320 : 0 : return nullptr;
# 321 : 0 : }
# 322 : :
# 323 : : CNode* CConnman::FindNode(const std::string& addrName)
# 324 : 253 : {
# 325 : 253 : LOCK(cs_vNodes);
# 326 : 253 : for (CNode* pnode : vNodes) {
# 327 : 134 : if (pnode->GetAddrName() == addrName) {
# 328 : 3 : return pnode;
# 329 : 3 : }
# 330 : 134 : }
# 331 : 253 : return nullptr;
# 332 : 253 : }
# 333 : :
# 334 : : CNode* CConnman::FindNode(const CService& addr)
# 335 : 245 : {
# 336 : 245 : LOCK(cs_vNodes);
# 337 : 245 : for (CNode* pnode : vNodes) {
# 338 : 118 : if (static_cast<CService>(pnode->addr) == addr) {
# 339 : 0 : return pnode;
# 340 : 0 : }
# 341 : 118 : }
# 342 : 245 : return nullptr;
# 343 : 245 : }
# 344 : :
# 345 : : bool CConnman::CheckIncomingNonce(uint64_t nonce)
# 346 : 448 : {
# 347 : 448 : LOCK(cs_vNodes);
# 348 : 976 : for (const CNode* pnode : vNodes) {
# 349 : 976 : if (!pnode->fSuccessfullyConnected && !pnode->IsInboundConn() && pnode->GetLocalNonce() == nonce)
# 350 : 0 : return false;
# 351 : 976 : }
# 352 : 448 : return true;
# 353 : 448 : }
# 354 : :
# 355 : : /** Get the bind address for a socket as CAddress */
# 356 : : static CAddress GetBindAddress(SOCKET sock)
# 357 : 698 : {
# 358 : 698 : CAddress addr_bind;
# 359 : 698 : struct sockaddr_storage sockaddr_bind;
# 360 : 698 : socklen_t sockaddr_bind_len = sizeof(sockaddr_bind);
# 361 : 698 : if (sock != INVALID_SOCKET) {
# 362 : 698 : if (!getsockname(sock, (struct sockaddr*)&sockaddr_bind, &sockaddr_bind_len)) {
# 363 : 698 : addr_bind.SetSockAddr((const struct sockaddr*)&sockaddr_bind);
# 364 : 698 : } else {
# 365 : 0 : LogPrint(BCLog::NET, "Warning: getsockname failed\n");
# 366 : 0 : }
# 367 : 698 : }
# 368 : 698 : return addr_bind;
# 369 : 698 : }
# 370 : :
# 371 : : CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCountFailure, ConnectionType conn_type)
# 372 : 249 : {
# 373 : 249 : assert(conn_type != ConnectionType::INBOUND);
# 374 : 249 :
# 375 : 249 : if (pszDest == nullptr) {
# 376 : 2 : if (IsLocal(addrConnect))
# 377 : 0 : return nullptr;
# 378 : 2 :
# 379 : 2 : // Look for an existing connection
# 380 : 2 : CNode* pnode = FindNode(static_cast<CService>(addrConnect));
# 381 : 2 : if (pnode)
# 382 : 0 : {
# 383 : 0 : LogPrintf("Failed to open new connection, already connected\n");
# 384 : 0 : return nullptr;
# 385 : 0 : }
# 386 : 249 : }
# 387 : 249 :
# 388 : 249 : /// debug print
# 389 : 249 : LogPrint(BCLog::NET, "trying connection %s lastseen=%.1fhrs\n",
# 390 : 249 : pszDest ? pszDest : addrConnect.ToString(),
# 391 : 249 : pszDest ? 0.0 : (double)(GetAdjustedTime() - addrConnect.nTime)/3600.0);
# 392 : 249 :
# 393 : 249 : // Resolve
# 394 : 249 : const int default_port = Params().GetDefaultPort();
# 395 : 249 : if (pszDest) {
# 396 : 247 : std::vector<CService> resolved;
# 397 : 247 : if (Lookup(pszDest, resolved, default_port, fNameLookup && !HaveNameProxy(), 256) && !resolved.empty()) {
# 398 : 243 : addrConnect = CAddress(resolved[GetRand(resolved.size())], NODE_NONE);
# 399 : 243 : if (!addrConnect.IsValid()) {
# 400 : 0 : LogPrint(BCLog::NET, "Resolver returned invalid address %s for %s\n", addrConnect.ToString(), pszDest);
# 401 : 0 : return nullptr;
# 402 : 0 : }
# 403 : 243 : // It is possible that we already have a connection to the IP/port pszDest resolved to.
# 404 : 243 : // In that case, drop the connection that was just created, and return the existing CNode instead.
# 405 : 243 : // Also store the name we used to connect in that CNode, so that future FindNode() calls to that
# 406 : 243 : // name catch this early.
# 407 : 243 : LOCK(cs_vNodes);
# 408 : 243 : CNode* pnode = FindNode(static_cast<CService>(addrConnect));
# 409 : 243 : if (pnode)
# 410 : 0 : {
# 411 : 0 : pnode->MaybeSetAddrName(std::string(pszDest));
# 412 : 0 : LogPrintf("Failed to open new connection, already connected\n");
# 413 : 0 : return nullptr;
# 414 : 0 : }
# 415 : 249 : }
# 416 : 247 : }
# 417 : 249 :
# 418 : 249 : // Connect
# 419 : 249 : bool connected = false;
# 420 : 249 : SOCKET hSocket = INVALID_SOCKET;
# 421 : 249 : proxyType proxy;
# 422 : 249 : if (addrConnect.IsValid()) {
# 423 : 245 : bool proxyConnectionFailed = false;
# 424 : 245 :
# 425 : 245 : if (GetProxy(addrConnect.GetNetwork(), proxy)) {
# 426 : 6 : hSocket = CreateSocket(proxy.proxy);
# 427 : 6 : if (hSocket == INVALID_SOCKET) {
# 428 : 0 : return nullptr;
# 429 : 0 : }
# 430 : 6 : connected = ConnectThroughProxy(proxy, addrConnect.ToStringIP(), addrConnect.GetPort(), hSocket, nConnectTimeout, proxyConnectionFailed);
# 431 : 239 : } else {
# 432 : 239 : // no proxy needed (none set for target network)
# 433 : 239 : hSocket = CreateSocket(addrConnect);
# 434 : 239 : if (hSocket == INVALID_SOCKET) {
# 435 : 0 : return nullptr;
# 436 : 0 : }
# 437 : 239 : connected = ConnectSocketDirectly(addrConnect, hSocket, nConnectTimeout, conn_type == ConnectionType::MANUAL);
# 438 : 239 : }
# 439 : 245 : if (!proxyConnectionFailed) {
# 440 : 245 : // If a connection to the node was attempted, and failure (if any) is not caused by a problem connecting to
# 441 : 245 : // the proxy, mark this as an attempt.
# 442 : 245 : addrman.Attempt(addrConnect, fCountFailure);
# 443 : 245 : }
# 444 : 245 : } else if (pszDest && GetNameProxy(proxy)) {
# 445 : 3 : hSocket = CreateSocket(proxy.proxy);
# 446 : 3 : if (hSocket == INVALID_SOCKET) {
# 447 : 0 : return nullptr;
# 448 : 0 : }
# 449 : 3 : std::string host;
# 450 : 3 : int port = default_port;
# 451 : 3 : SplitHostPort(std::string(pszDest), port, host);
# 452 : 3 : bool proxyConnectionFailed;
# 453 : 3 : connected = ConnectThroughProxy(proxy, host, port, hSocket, nConnectTimeout, proxyConnectionFailed);
# 454 : 3 : }
# 455 : 249 : if (!connected) {
# 456 : 4 : CloseSocket(hSocket);
# 457 : 4 : return nullptr;
# 458 : 4 : }
# 459 : 245 :
# 460 : 245 : // Add node
# 461 : 245 : NodeId id = GetNewNodeId();
# 462 : 245 : uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
# 463 : 245 : CAddress addr_bind = GetBindAddress(hSocket);
# 464 : 245 : CNode* pnode = new CNode(id, nLocalServices, GetBestHeight(), hSocket, addrConnect, CalculateKeyedNetGroup(addrConnect), nonce, addr_bind, pszDest ? pszDest : "", conn_type);
# 465 : 245 : pnode->AddRef();
# 466 : 245 :
# 467 : 245 : // We're making a new connection, harvest entropy from the time (and our peer count)
# 468 : 245 : RandAddEvent((uint32_t)id);
# 469 : 245 :
# 470 : 245 : return pnode;
# 471 : 245 : }
# 472 : :
# 473 : : void CNode::CloseSocketDisconnect()
# 474 : 890 : {
# 475 : 890 : fDisconnect = true;
# 476 : 890 : LOCK(cs_hSocket);
# 477 : 890 : if (hSocket != INVALID_SOCKET)
# 478 : 890 : {
# 479 : 698 : LogPrint(BCLog::NET, "disconnecting peer=%d\n", id);
# 480 : 698 : CloseSocket(hSocket);
# 481 : 698 : }
# 482 : 890 : }
# 483 : :
# 484 : 454 : void CConnman::AddWhitelistPermissionFlags(NetPermissionFlags& flags, const CNetAddr &addr) const {
# 485 : 454 : for (const auto& subnet : vWhitelistedRange) {
# 486 : 67 : if (subnet.m_subnet.Match(addr)) NetPermissions::AddFlag(flags, subnet.m_flags);
# 487 : 67 : }
# 488 : 454 : }
# 489 : :
# 490 : 9549 : std::string CNode::GetAddrName() const {
# 491 : 9549 : LOCK(cs_addrName);
# 492 : 9549 : return addrName;
# 493 : 9549 : }
# 494 : :
# 495 : 0 : void CNode::MaybeSetAddrName(const std::string& addrNameIn) {
# 496 : 0 : LOCK(cs_addrName);
# 497 : 0 : if (addrName.empty()) {
# 498 : 0 : addrName = addrNameIn;
# 499 : 0 : }
# 500 : 0 : }
# 501 : :
# 502 : 6102 : CService CNode::GetAddrLocal() const {
# 503 : 6102 : LOCK(cs_addrLocal);
# 504 : 6102 : return addrLocal;
# 505 : 6102 : }
# 506 : :
# 507 : 685 : void CNode::SetAddrLocal(const CService& addrLocalIn) {
# 508 : 685 : LOCK(cs_addrLocal);
# 509 : 685 : if (addrLocal.IsValid()) {
# 510 : 0 : error("Addr local already set for node: %i. Refusing to change from %s to %s", id, addrLocal.ToString(), addrLocalIn.ToString());
# 511 : 685 : } else {
# 512 : 685 : addrLocal = addrLocalIn;
# 513 : 685 : }
# 514 : 685 : }
# 515 : :
# 516 : : #undef X
# 517 : 84896 : #define X(name) stats.name = name
# 518 : : void CNode::copyStats(CNodeStats &stats, const std::vector<bool> &m_asmap)
# 519 : 5306 : {
# 520 : 5306 : stats.nodeid = this->GetId();
# 521 : 5306 : X(nServices);
# 522 : 5306 : X(addr);
# 523 : 5306 : X(addrBind);
# 524 : 5306 : stats.m_mapped_as = addr.GetMappedAS(m_asmap);
# 525 : 5306 : if (m_tx_relay != nullptr) {
# 526 : 5306 : LOCK(m_tx_relay->cs_filter);
# 527 : 5306 : stats.fRelayTxes = m_tx_relay->fRelayTxes;
# 528 : 5306 : } else {
# 529 : 0 : stats.fRelayTxes = false;
# 530 : 0 : }
# 531 : 5306 : X(nLastSend);
# 532 : 5306 : X(nLastRecv);
# 533 : 5306 : X(nTimeConnected);
# 534 : 5306 : X(nTimeOffset);
# 535 : 5306 : stats.addrName = GetAddrName();
# 536 : 5306 : X(nVersion);
# 537 : 5306 : {
# 538 : 5306 : LOCK(cs_SubVer);
# 539 : 5306 : X(cleanSubVer);
# 540 : 5306 : }
# 541 : 5306 : stats.fInbound = IsInboundConn();
# 542 : 5306 : stats.m_manual_connection = IsManualConn();
# 543 : 5306 : X(nStartingHeight);
# 544 : 5306 : {
# 545 : 5306 : LOCK(cs_vSend);
# 546 : 5306 : X(mapSendBytesPerMsgCmd);
# 547 : 5306 : X(nSendBytes);
# 548 : 5306 : }
# 549 : 5306 : {
# 550 : 5306 : LOCK(cs_vRecv);
# 551 : 5306 : X(mapRecvBytesPerMsgCmd);
# 552 : 5306 : X(nRecvBytes);
# 553 : 5306 : }
# 554 : 5306 : X(m_legacyWhitelisted);
# 555 : 5306 : X(m_permissionFlags);
# 556 : 5306 : if (m_tx_relay != nullptr) {
# 557 : 5306 : LOCK(m_tx_relay->cs_feeFilter);
# 558 : 5306 : stats.minFeeFilter = m_tx_relay->minFeeFilter;
# 559 : 5306 : } else {
# 560 : 0 : stats.minFeeFilter = 0;
# 561 : 0 : }
# 562 : 5306 :
# 563 : 5306 : // It is common for nodes with good ping times to suddenly become lagged,
# 564 : 5306 : // due to a new block arriving or other large transfer.
# 565 : 5306 : // Merely reporting pingtime might fool the caller into thinking the node was still responsive,
# 566 : 5306 : // since pingtime does not update until the ping is complete, which might take a while.
# 567 : 5306 : // So, if a ping is taking an unusually long time in flight,
# 568 : 5306 : // the caller can immediately detect that this is happening.
# 569 : 5306 : std::chrono::microseconds ping_wait{0};
# 570 : 5306 : if ((0 != nPingNonceSent) && (0 != m_ping_start.load().count())) {
# 571 : 18 : ping_wait = GetTime<std::chrono::microseconds>() - m_ping_start.load();
# 572 : 18 : }
# 573 : 5306 :
# 574 : 5306 : // Raw ping time is in microseconds, but show it to user as whole seconds (Bitcoin users should be well used to small numbers with many decimal places by now :)
# 575 : 5306 : stats.m_ping_usec = nPingUsecTime;
# 576 : 5306 : stats.m_min_ping_usec = nMinPingUsecTime;
# 577 : 5306 : stats.m_ping_wait_usec = count_microseconds(ping_wait);
# 578 : 5306 :
# 579 : 5306 : // Leave string empty if addrLocal invalid (not filled in yet)
# 580 : 5306 : CService addrLocalUnlocked = GetAddrLocal();
# 581 : 5306 : stats.addrLocal = addrLocalUnlocked.IsValid() ? addrLocalUnlocked.ToString() : "";
# 582 : 5306 : }
# 583 : : #undef X
# 584 : :
# 585 : : bool CNode::ReceiveMsgBytes(const char *pch, unsigned int nBytes, bool& complete)
# 586 : 101691 : {
# 587 : 101691 : complete = false;
# 588 : 101691 : const auto time = GetTime<std::chrono::microseconds>();
# 589 : 101691 : LOCK(cs_vRecv);
# 590 : 101691 : nLastRecv = std::chrono::duration_cast<std::chrono::seconds>(time).count();
# 591 : 101691 : nRecvBytes += nBytes;
# 592 : 288146 : while (nBytes > 0) {
# 593 : 186456 : // absorb network data
# 594 : 186456 : int handled = m_deserializer->Read(pch, nBytes);
# 595 : 186456 : if (handled < 0) return false;
# 596 : 186455 :
# 597 : 186455 : pch += handled;
# 598 : 186455 : nBytes -= handled;
# 599 : 186455 :
# 600 : 186455 : if (m_deserializer->Complete()) {
# 601 : 83291 : // decompose a transport agnostic CNetMessage from the deserializer
# 602 : 83291 : CNetMessage msg = m_deserializer->GetMessage(Params().MessageStart(), time);
# 603 : 83291 :
# 604 : 83291 : //store received bytes per message command
# 605 : 83291 : //to prevent a memory DOS, only allow valid commands
# 606 : 83291 : mapMsgCmdSize::iterator i = mapRecvBytesPerMsgCmd.find(msg.m_command);
# 607 : 83291 : if (i == mapRecvBytesPerMsgCmd.end())
# 608 : 83 : i = mapRecvBytesPerMsgCmd.find(NET_MESSAGE_COMMAND_OTHER);
# 609 : 83291 : assert(i != mapRecvBytesPerMsgCmd.end());
# 610 : 83291 : i->second += msg.m_raw_message_size;
# 611 : 83291 :
# 612 : 83291 : // push the message to the process queue,
# 613 : 83291 : vRecvMsg.push_back(std::move(msg));
# 614 : 83291 :
# 615 : 83291 : complete = true;
# 616 : 83291 : }
# 617 : 186455 : }
# 618 : 101691 :
# 619 : 101691 : return true;
# 620 : 101691 : }
# 621 : :
# 622 : : void CNode::SetSendVersion(int nVersionIn)
# 623 : 709 : {
# 624 : 709 : // Send version may only be changed in the version message, and
# 625 : 709 : // only one version message is allowed per session. We can therefore
# 626 : 709 : // treat this value as const and even atomic as long as it's only used
# 627 : 709 : // once a version message has been successfully processed. Any attempt to
# 628 : 709 : // set this twice is an error.
# 629 : 709 : if (nSendVersion != 0) {
# 630 : 0 : error("Send version already set for node: %i. Refusing to change from %i to %i", id, nSendVersion, nVersionIn);
# 631 : 709 : } else {
# 632 : 709 : nSendVersion = nVersionIn;
# 633 : 709 : }
# 634 : 709 : }
# 635 : :
# 636 : : int CNode::GetSendVersion() const
# 637 : 511313 : {
# 638 : 511313 : // The send version should always be explicitly set to
# 639 : 511313 : // INIT_PROTO_VERSION rather than using this value until SetSendVersion
# 640 : 511313 : // has been called.
# 641 : 511313 : if (nSendVersion == 0) {
# 642 : 0 : error("Requesting unset send version for node: %i. Using %i", id, INIT_PROTO_VERSION);
# 643 : 0 : return INIT_PROTO_VERSION;
# 644 : 0 : }
# 645 : 511313 : return nSendVersion;
# 646 : 511313 : }
# 647 : :
# 648 : : int V1TransportDeserializer::readHeader(const char *pch, unsigned int nBytes)
# 649 : 83293 : {
# 650 : 83293 : // copy data to temporary parsing buffer
# 651 : 83293 : unsigned int nRemaining = CMessageHeader::HEADER_SIZE - nHdrPos;
# 652 : 83293 : unsigned int nCopy = std::min(nRemaining, nBytes);
# 653 : 83293 :
# 654 : 83293 : memcpy(&hdrbuf[nHdrPos], pch, nCopy);
# 655 : 83293 : nHdrPos += nCopy;
# 656 : 83293 :
# 657 : 83293 : // if header incomplete, exit
# 658 : 83293 : if (nHdrPos < CMessageHeader::HEADER_SIZE)
# 659 : 1 : return nCopy;
# 660 : 83292 :
# 661 : 83292 : // deserialize to CMessageHeader
# 662 : 83292 : try {
# 663 : 83292 : hdrbuf >> hdr;
# 664 : 83292 : }
# 665 : 83292 : catch (const std::exception&) {
# 666 : 0 : return -1;
# 667 : 0 : }
# 668 : 83292 :
# 669 : 83292 : // reject messages larger than MAX_SIZE or MAX_PROTOCOL_MESSAGE_LENGTH
# 670 : 83292 : if (hdr.nMessageSize > MAX_SIZE || hdr.nMessageSize > MAX_PROTOCOL_MESSAGE_LENGTH) {
# 671 : 1 : return -1;
# 672 : 1 : }
# 673 : 83291 :
# 674 : 83291 : // switch state to reading message data
# 675 : 83291 : in_data = true;
# 676 : 83291 :
# 677 : 83291 : return nCopy;
# 678 : 83291 : }
# 679 : :
# 680 : : int V1TransportDeserializer::readData(const char *pch, unsigned int nBytes)
# 681 : 103163 : {
# 682 : 103163 : unsigned int nRemaining = hdr.nMessageSize - nDataPos;
# 683 : 103163 : unsigned int nCopy = std::min(nRemaining, nBytes);
# 684 : 103163 :
# 685 : 103163 : if (vRecv.size() < nDataPos + nCopy) {
# 686 : 85425 : // Allocate up to 256 KiB ahead, but never more than the total message size.
# 687 : 85425 : vRecv.resize(std::min(hdr.nMessageSize, nDataPos + nCopy + 256 * 1024));
# 688 : 85425 : }
# 689 : 103163 :
# 690 : 103163 : hasher.Write((const unsigned char*)pch, nCopy);
# 691 : 103163 : memcpy(&vRecv[nDataPos], pch, nCopy);
# 692 : 103163 : nDataPos += nCopy;
# 693 : 103163 :
# 694 : 103163 : return nCopy;
# 695 : 103163 : }
# 696 : :
# 697 : : const uint256& V1TransportDeserializer::GetMessageHash() const
# 698 : 83291 : {
# 699 : 83291 : assert(Complete());
# 700 : 83291 : if (data_hash.IsNull())
# 701 : 83291 : hasher.Finalize(data_hash.begin());
# 702 : 83291 : return data_hash;
# 703 : 83291 : }
# 704 : :
# 705 : : CNetMessage V1TransportDeserializer::GetMessage(const CMessageHeader::MessageStartChars& message_start, const std::chrono::microseconds time)
# 706 : 83291 : {
# 707 : 83291 : // decompose a single CNetMessage from the TransportDeserializer
# 708 : 83291 : CNetMessage msg(std::move(vRecv));
# 709 : 83291 :
# 710 : 83291 : // store state about valid header, netmagic and checksum
# 711 : 83291 : msg.m_valid_header = hdr.IsValid(message_start);
# 712 : 83291 : msg.m_valid_netmagic = (memcmp(hdr.pchMessageStart, message_start, CMessageHeader::MESSAGE_START_SIZE) == 0);
# 713 : 83291 : uint256 hash = GetMessageHash();
# 714 : 83291 :
# 715 : 83291 : // store command string, payload size
# 716 : 83291 : msg.m_command = hdr.GetCommand();
# 717 : 83291 : msg.m_message_size = hdr.nMessageSize;
# 718 : 83291 : msg.m_raw_message_size = hdr.nMessageSize + CMessageHeader::HEADER_SIZE;
# 719 : 83291 :
# 720 : 83291 : // We just received a message off the wire, harvest entropy from the time (and the message checksum)
# 721 : 83291 : RandAddEvent(ReadLE32(hash.begin()));
# 722 : 83291 :
# 723 : 83291 : msg.m_valid_checksum = (memcmp(hash.begin(), hdr.pchChecksum, CMessageHeader::CHECKSUM_SIZE) == 0);
# 724 : 83291 : if (!msg.m_valid_checksum) {
# 725 : 1 : LogPrint(BCLog::NET, "CHECKSUM ERROR (%s, %u bytes), expected %s was %s\n",
# 726 : 1 : SanitizeString(msg.m_command), msg.m_message_size,
# 727 : 1 : HexStr(hash.begin(), hash.begin()+CMessageHeader::CHECKSUM_SIZE),
# 728 : 1 : HexStr(hdr.pchChecksum, hdr.pchChecksum+CMessageHeader::CHECKSUM_SIZE));
# 729 : 1 : }
# 730 : 83291 :
# 731 : 83291 : // store receive time
# 732 : 83291 : msg.m_time = time;
# 733 : 83291 :
# 734 : 83291 : // reset the network deserializer (prepare for the next message)
# 735 : 83291 : Reset();
# 736 : 83291 : return msg;
# 737 : 83291 : }
# 738 : :
# 739 : 87627 : void V1TransportSerializer::prepareForTransport(CSerializedNetMsg& msg, std::vector<unsigned char>& header) {
# 740 : 87627 : // create dbl-sha256 checksum
# 741 : 87627 : uint256 hash = Hash(msg.data.begin(), msg.data.end());
# 742 : 87627 :
# 743 : 87627 : // create header
# 744 : 87627 : CMessageHeader hdr(Params().MessageStart(), msg.m_type.c_str(), msg.data.size());
# 745 : 87627 : memcpy(hdr.pchChecksum, hash.begin(), CMessageHeader::CHECKSUM_SIZE);
# 746 : 87627 :
# 747 : 87627 : // serialize header
# 748 : 87627 : header.reserve(CMessageHeader::HEADER_SIZE);
# 749 : 87627 : CVectorWriter{SER_NETWORK, INIT_PROTO_VERSION, header, 0, hdr};
# 750 : 87627 : }
# 751 : :
# 752 : : size_t CConnman::SocketSendData(CNode *pnode) const EXCLUSIVE_LOCKS_REQUIRED(pnode->cs_vSend)
# 753 : 87847 : {
# 754 : 87847 : auto it = pnode->vSendMsg.begin();
# 755 : 87847 : size_t nSentSize = 0;
# 756 : 87847 :
# 757 : 260740 : while (it != pnode->vSendMsg.end()) {
# 758 : 173244 : const auto &data = *it;
# 759 : 173244 : assert(data.size() > pnode->nSendOffset);
# 760 : 173244 : int nBytes = 0;
# 761 : 173244 : {
# 762 : 173244 : LOCK(pnode->cs_hSocket);
# 763 : 173244 : if (pnode->hSocket == INVALID_SOCKET)
# 764 : 173244 : break;
# 765 : 173218 : nBytes = send(pnode->hSocket, reinterpret_cast<const char*>(data.data()) + pnode->nSendOffset, data.size() - pnode->nSendOffset, MSG_NOSIGNAL | MSG_DONTWAIT);
# 766 : 173218 : }
# 767 : 173218 : if (nBytes > 0) {
# 768 : 173215 : pnode->nLastSend = GetSystemTimeInSeconds();
# 769 : 173215 : pnode->nSendBytes += nBytes;
# 770 : 173215 : pnode->nSendOffset += nBytes;
# 771 : 173215 : nSentSize += nBytes;
# 772 : 173215 : if (pnode->nSendOffset == data.size()) {
# 773 : 172893 : pnode->nSendOffset = 0;
# 774 : 172893 : pnode->nSendSize -= data.size();
# 775 : 172893 : pnode->fPauseSend = pnode->nSendSize > nSendBufferMaxSize;
# 776 : 172893 : it++;
# 777 : 172893 : } else {
# 778 : 322 : // could not send full message; stop sending more
# 779 : 322 : break;
# 780 : 322 : }
# 781 : 3 : } else {
# 782 : 3 : if (nBytes < 0) {
# 783 : 3 : // error
# 784 : 3 : int nErr = WSAGetLastError();
# 785 : 3 : if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
# 786 : 3 : {
# 787 : 3 : LogPrintf("socket send error %s\n", NetworkErrorString(nErr));
# 788 : 3 : pnode->CloseSocketDisconnect();
# 789 : 3 : }
# 790 : 3 : }
# 791 : 3 : // couldn't send anything at all
# 792 : 3 : break;
# 793 : 3 : }
# 794 : 173218 : }
# 795 : 87847 :
# 796 : 87847 : if (it == pnode->vSendMsg.end()) {
# 797 : 87496 : assert(pnode->nSendOffset == 0);
# 798 : 87496 : assert(pnode->nSendSize == 0);
# 799 : 87496 : }
# 800 : 87847 : pnode->vSendMsg.erase(pnode->vSendMsg.begin(), it);
# 801 : 87847 : return nSentSize;
# 802 : 87847 : }
# 803 : :
# 804 : : struct NodeEvictionCandidate
# 805 : : {
# 806 : : NodeId id;
# 807 : : int64_t nTimeConnected;
# 808 : : int64_t nMinPingUsecTime;
# 809 : : int64_t nLastBlockTime;
# 810 : : int64_t nLastTXTime;
# 811 : : bool fRelevantServices;
# 812 : : bool fRelayTxes;
# 813 : : bool fBloomFilter;
# 814 : : CAddress addr;
# 815 : : uint64_t nKeyedNetGroup;
# 816 : : bool prefer_evict;
# 817 : : };
# 818 : :
# 819 : : static bool ReverseCompareNodeMinPingTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
# 820 : 75 : {
# 821 : 75 : return a.nMinPingUsecTime > b.nMinPingUsecTime;
# 822 : 75 : }
# 823 : :
# 824 : : static bool ReverseCompareNodeTimeConnected(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
# 825 : 0 : {
# 826 : 0 : return a.nTimeConnected > b.nTimeConnected;
# 827 : 0 : }
# 828 : :
# 829 : 20 : static bool CompareNetGroupKeyed(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b) {
# 830 : 20 : return a.nKeyedNetGroup < b.nKeyedNetGroup;
# 831 : 20 : }
# 832 : :
# 833 : : static bool CompareNodeBlockTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
# 834 : 7 : {
# 835 : 7 : // There is a fall-through here because it is common for a node to have many peers which have not yet relayed a block.
# 836 : 7 : if (a.nLastBlockTime != b.nLastBlockTime) return a.nLastBlockTime < b.nLastBlockTime;
# 837 : 3 : if (a.fRelevantServices != b.fRelevantServices) return b.fRelevantServices;
# 838 : 3 : return a.nTimeConnected > b.nTimeConnected;
# 839 : 3 : }
# 840 : :
# 841 : : static bool CompareNodeTXTime(const NodeEvictionCandidate &a, const NodeEvictionCandidate &b)
# 842 : 21 : {
# 843 : 21 : // There is a fall-through here because it is common for a node to have more than a few peers that have not yet relayed txn.
# 844 : 21 : if (a.nLastTXTime != b.nLastTXTime) return a.nLastTXTime < b.nLastTXTime;
# 845 : 6 : if (a.fRelayTxes != b.fRelayTxes) return b.fRelayTxes;
# 846 : 6 : if (a.fBloomFilter != b.fBloomFilter) return a.fBloomFilter;
# 847 : 6 : return a.nTimeConnected > b.nTimeConnected;
# 848 : 6 : }
# 849 : :
# 850 : :
# 851 : : //! Sort an array by the specified comparator, then erase the last K elements.
# 852 : : template<typename T, typename Comparator>
# 853 : : static void EraseLastKElements(std::vector<T> &elements, Comparator comparator, size_t k)
# 854 : 5 : {
# 855 : 5 : std::sort(elements.begin(), elements.end(), comparator);
# 856 : 5 : size_t eraseSize = std::min(k, elements.size());
# 857 : 5 : elements.erase(elements.end() - eraseSize, elements.end());
# 858 : 5 : }
# 859 : :
# 860 : : /** Try to find a connection to evict when the node is full.
# 861 : : * Extreme care must be taken to avoid opening the node to attacker
# 862 : : * triggered network partitioning.
# 863 : : * The strategy used here is to protect a small number of peers
# 864 : : * for each of several distinct characteristics which are difficult
# 865 : : * to forge. In order to partition a node the attacker must be
# 866 : : * simultaneously better at all of them than honest peers.
# 867 : : */
# 868 : : bool CConnman::AttemptToEvictConnection()
# 869 : 1 : {
# 870 : 1 : std::vector<NodeEvictionCandidate> vEvictionCandidates;
# 871 : 1 : {
# 872 : 1 : LOCK(cs_vNodes);
# 873 : 1 :
# 874 : 21 : for (const CNode* node : vNodes) {
# 875 : 21 : if (node->HasPermission(PF_NOBAN))
# 876 : 0 : continue;
# 877 : 21 : if (!node->IsInboundConn())
# 878 : 0 : continue;
# 879 : 21 : if (node->fDisconnect)
# 880 : 0 : continue;
# 881 : 21 : bool peer_relay_txes = false;
# 882 : 21 : bool peer_filter_not_null = false;
# 883 : 21 : if (node->m_tx_relay != nullptr) {
# 884 : 21 : LOCK(node->m_tx_relay->cs_filter);
# 885 : 21 : peer_relay_txes = node->m_tx_relay->fRelayTxes;
# 886 : 21 : peer_filter_not_null = node->m_tx_relay->pfilter != nullptr;
# 887 : 21 : }
# 888 : 21 : NodeEvictionCandidate candidate = {node->GetId(), node->nTimeConnected, node->nMinPingUsecTime,
# 889 : 21 : node->nLastBlockTime, node->nLastTXTime,
# 890 : 21 : HasAllDesirableServiceFlags(node->nServices),
# 891 : 21 : peer_relay_txes, peer_filter_not_null, node->addr, node->nKeyedNetGroup,
# 892 : 21 : node->m_prefer_evict};
# 893 : 21 : vEvictionCandidates.push_back(candidate);
# 894 : 21 : }
# 895 : 1 : }
# 896 : 1 :
# 897 : 1 : // Protect connections with certain characteristics
# 898 : 1 :
# 899 : 1 : // Deterministically select 4 peers to protect by netgroup.
# 900 : 1 : // An attacker cannot predict which netgroups will be protected
# 901 : 1 : EraseLastKElements(vEvictionCandidates, CompareNetGroupKeyed, 4);
# 902 : 1 : // Protect the 8 nodes with the lowest minimum ping time.
# 903 : 1 : // An attacker cannot manipulate this metric without physically moving nodes closer to the target.
# 904 : 1 : EraseLastKElements(vEvictionCandidates, ReverseCompareNodeMinPingTime, 8);
# 905 : 1 : // Protect 4 nodes that most recently sent us transactions.
# 906 : 1 : // An attacker cannot manipulate this metric without performing useful work.
# 907 : 1 : EraseLastKElements(vEvictionCandidates, CompareNodeTXTime, 4);
# 908 : 1 : // Protect 4 nodes that most recently sent us blocks.
# 909 : 1 : // An attacker cannot manipulate this metric without performing useful work.
# 910 : 1 : EraseLastKElements(vEvictionCandidates, CompareNodeBlockTime, 4);
# 911 : 1 : // Protect the half of the remaining nodes which have been connected the longest.
# 912 : 1 : // This replicates the non-eviction implicit behavior, and precludes attacks that start later.
# 913 : 1 : EraseLastKElements(vEvictionCandidates, ReverseCompareNodeTimeConnected, vEvictionCandidates.size() / 2);
# 914 : 1 :
# 915 : 1 : if (vEvictionCandidates.empty()) return false;
# 916 : 1 :
# 917 : 1 : // If any remaining peers are preferred for eviction consider only them.
# 918 : 1 : // This happens after the other preferences since if a peer is really the best by other criteria (esp relaying blocks)
# 919 : 1 : // then we probably don't want to evict it no matter what.
# 920 : 1 : if (std::any_of(vEvictionCandidates.begin(),vEvictionCandidates.end(),[](NodeEvictionCandidate const &n){return n.prefer_evict;})) {
# 921 : 0 : vEvictionCandidates.erase(std::remove_if(vEvictionCandidates.begin(),vEvictionCandidates.end(),
# 922 : 0 : [](NodeEvictionCandidate const &n){return !n.prefer_evict;}),vEvictionCandidates.end());
# 923 : 0 : }
# 924 : 1 :
# 925 : 1 : // Identify the network group with the most connections and youngest member.
# 926 : 1 : // (vEvictionCandidates is already sorted by reverse connect time)
# 927 : 1 : uint64_t naMostConnections;
# 928 : 1 : unsigned int nMostConnections = 0;
# 929 : 1 : int64_t nMostConnectionsTime = 0;
# 930 : 1 : std::map<uint64_t, std::vector<NodeEvictionCandidate> > mapNetGroupNodes;
# 931 : 1 : for (const NodeEvictionCandidate &node : vEvictionCandidates) {
# 932 : 1 : std::vector<NodeEvictionCandidate> &group = mapNetGroupNodes[node.nKeyedNetGroup];
# 933 : 1 : group.push_back(node);
# 934 : 1 : int64_t grouptime = group[0].nTimeConnected;
# 935 : 1 :
# 936 : 1 : if (group.size() > nMostConnections || (group.size() == nMostConnections && grouptime > nMostConnectionsTime)) {
# 937 : 1 : nMostConnections = group.size();
# 938 : 1 : nMostConnectionsTime = grouptime;
# 939 : 1 : naMostConnections = node.nKeyedNetGroup;
# 940 : 1 : }
# 941 : 1 : }
# 942 : 1 :
# 943 : 1 : // Reduce to the network group with the most connections
# 944 : 1 : vEvictionCandidates = std::move(mapNetGroupNodes[naMostConnections]);
# 945 : 1 :
# 946 : 1 : // Disconnect from the network group with the most connections
# 947 : 1 : NodeId evicted = vEvictionCandidates.front().id;
# 948 : 1 : LOCK(cs_vNodes);
# 949 : 9 : for (CNode* pnode : vNodes) {
# 950 : 9 : if (pnode->GetId() == evicted) {
# 951 : 1 : pnode->fDisconnect = true;
# 952 : 1 : return true;
# 953 : 1 : }
# 954 : 9 : }
# 955 : 1 : return false;
# 956 : 1 : }
# 957 : :
# 958 : 454 : void CConnman::AcceptConnection(const ListenSocket& hListenSocket) {
# 959 : 454 : struct sockaddr_storage sockaddr;
# 960 : 454 : socklen_t len = sizeof(sockaddr);
# 961 : 454 : SOCKET hSocket = accept(hListenSocket.socket, (struct sockaddr*)&sockaddr, &len);
# 962 : 454 : CAddress addr;
# 963 : 454 : int nInbound = 0;
# 964 : 454 : int nMaxInbound = nMaxConnections - m_max_outbound;
# 965 : 454 :
# 966 : 454 : if (hSocket != INVALID_SOCKET) {
# 967 : 454 : if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) {
# 968 : 0 : LogPrintf("Warning: Unknown socket family\n");
# 969 : 0 : }
# 970 : 454 : }
# 971 : 454 :
# 972 : 454 : NetPermissionFlags permissionFlags = NetPermissionFlags::PF_NONE;
# 973 : 454 : hListenSocket.AddSocketPermissionFlags(permissionFlags);
# 974 : 454 : AddWhitelistPermissionFlags(permissionFlags, addr);
# 975 : 454 : bool legacyWhitelisted = false;
# 976 : 454 : if (NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::PF_ISIMPLICIT)) {
# 977 : 6 : NetPermissions::ClearFlag(permissionFlags, PF_ISIMPLICIT);
# 978 : 6 : if (gArgs.GetBoolArg("-whitelistforcerelay", DEFAULT_WHITELISTFORCERELAY)) NetPermissions::AddFlag(permissionFlags, PF_FORCERELAY);
# 979 : 6 : if (gArgs.GetBoolArg("-whitelistrelay", DEFAULT_WHITELISTRELAY)) NetPermissions::AddFlag(permissionFlags, PF_RELAY);
# 980 : 6 : NetPermissions::AddFlag(permissionFlags, PF_MEMPOOL);
# 981 : 6 : NetPermissions::AddFlag(permissionFlags, PF_NOBAN);
# 982 : 6 : legacyWhitelisted = true;
# 983 : 6 : }
# 984 : 454 :
# 985 : 454 : {
# 986 : 454 : LOCK(cs_vNodes);
# 987 : 534 : for (const CNode* pnode : vNodes) {
# 988 : 534 : if (pnode->IsInboundConn()) nInbound++;
# 989 : 534 : }
# 990 : 454 : }
# 991 : 454 :
# 992 : 454 : if (hSocket == INVALID_SOCKET)
# 993 : 454 : {
# 994 : 0 : int nErr = WSAGetLastError();
# 995 : 0 : if (nErr != WSAEWOULDBLOCK)
# 996 : 0 : LogPrintf("socket error accept failed: %s\n", NetworkErrorString(nErr));
# 997 : 0 : return;
# 998 : 0 : }
# 999 : 454 :
# 1000 : 454 : if (!fNetworkActive) {
# 1001 : 0 : LogPrintf("connection from %s dropped: not accepting new connections\n", addr.ToString());
# 1002 : 0 : CloseSocket(hSocket);
# 1003 : 0 : return;
# 1004 : 0 : }
# 1005 : 454 :
# 1006 : 454 : if (!IsSelectableSocket(hSocket))
# 1007 : 0 : {
# 1008 : 0 : LogPrintf("connection from %s dropped: non-selectable socket\n", addr.ToString());
# 1009 : 0 : CloseSocket(hSocket);
# 1010 : 0 : return;
# 1011 : 0 : }
# 1012 : 454 :
# 1013 : 454 : // According to the internet TCP_NODELAY is not carried into accepted sockets
# 1014 : 454 : // on all platforms. Set it again here just to be sure.
# 1015 : 454 : SetSocketNoDelay(hSocket);
# 1016 : 454 :
# 1017 : 454 : // Don't accept connections from banned peers.
# 1018 : 454 : bool banned = m_banman && m_banman->IsBanned(addr);
# 1019 : 454 : if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::PF_NOBAN) && banned)
# 1020 : 1 : {
# 1021 : 1 : LogPrint(BCLog::NET, "connection from %s dropped (banned)\n", addr.ToString());
# 1022 : 1 : CloseSocket(hSocket);
# 1023 : 1 : return;
# 1024 : 1 : }
# 1025 : 453 :
# 1026 : 453 : // Only accept connections from discouraged peers if our inbound slots aren't (almost) full.
# 1027 : 453 : bool discouraged = m_banman && m_banman->IsDiscouraged(addr);
# 1028 : 453 : if (!NetPermissions::HasFlag(permissionFlags, NetPermissionFlags::PF_NOBAN) && nInbound + 1 >= nMaxInbound && discouraged)
# 1029 : 0 : {
# 1030 : 0 : LogPrint(BCLog::NET, "connection from %s dropped (discouraged)\n", addr.ToString());
# 1031 : 0 : CloseSocket(hSocket);
# 1032 : 0 : return;
# 1033 : 0 : }
# 1034 : 453 :
# 1035 : 453 : if (nInbound >= nMaxInbound)
# 1036 : 1 : {
# 1037 : 1 : if (!AttemptToEvictConnection()) {
# 1038 : 0 : // No connection to evict, disconnect the new connection
# 1039 : 0 : LogPrint(BCLog::NET, "failed to find an eviction candidate - connection dropped (full)\n");
# 1040 : 0 : CloseSocket(hSocket);
# 1041 : 0 : return;
# 1042 : 0 : }
# 1043 : 453 : }
# 1044 : 453 :
# 1045 : 453 : NodeId id = GetNewNodeId();
# 1046 : 453 : uint64_t nonce = GetDeterministicRandomizer(RANDOMIZER_ID_LOCALHOSTNONCE).Write(id).Finalize();
# 1047 : 453 : CAddress addr_bind = GetBindAddress(hSocket);
# 1048 : 453 :
# 1049 : 453 : ServiceFlags nodeServices = nLocalServices;
# 1050 : 453 : if (NetPermissions::HasFlag(permissionFlags, PF_BLOOMFILTER)) {
# 1051 : 2 : nodeServices = static_cast<ServiceFlags>(nodeServices | NODE_BLOOM);
# 1052 : 2 : }
# 1053 : 453 : CNode* pnode = new CNode(id, nodeServices, GetBestHeight(), hSocket, addr, CalculateKeyedNetGroup(addr), nonce, addr_bind, "", ConnectionType::INBOUND);
# 1054 : 453 : pnode->AddRef();
# 1055 : 453 : pnode->m_permissionFlags = permissionFlags;
# 1056 : 453 : // If this flag is present, the user probably expect that RPC and QT report it as whitelisted (backward compatibility)
# 1057 : 453 : pnode->m_legacyWhitelisted = legacyWhitelisted;
# 1058 : 453 : pnode->m_prefer_evict = discouraged;
# 1059 : 453 : m_msgproc->InitializeNode(pnode);
# 1060 : 453 :
# 1061 : 453 : LogPrint(BCLog::NET, "connection from %s accepted\n", addr.ToString());
# 1062 : 453 :
# 1063 : 453 : {
# 1064 : 453 : LOCK(cs_vNodes);
# 1065 : 453 : vNodes.push_back(pnode);
# 1066 : 453 : }
# 1067 : 453 :
# 1068 : 453 : // We received a new connection, harvest entropy from the time (and our peer count)
# 1069 : 453 : RandAddEvent((uint32_t)id);
# 1070 : 453 : }
# 1071 : :
# 1072 : : void CConnman::DisconnectNodes()
# 1073 : 182663 : {
# 1074 : 182663 : {
# 1075 : 182663 : LOCK(cs_vNodes);
# 1076 : 182663 :
# 1077 : 182663 : if (!fNetworkActive) {
# 1078 : 27 : // Disconnect any connected nodes
# 1079 : 27 : for (CNode* pnode : vNodes) {
# 1080 : 3 : if (!pnode->fDisconnect) {
# 1081 : 3 : LogPrint(BCLog::NET, "Network not active, dropping peer=%d\n", pnode->GetId());
# 1082 : 3 : pnode->fDisconnect = true;
# 1083 : 3 : }
# 1084 : 3 : }
# 1085 : 27 : }
# 1086 : 182663 :
# 1087 : 182663 : // Disconnect unused nodes
# 1088 : 182663 : std::vector<CNode*> vNodesCopy = vNodes;
# 1089 : 182663 : for (CNode* pnode : vNodesCopy)
# 1090 : 291683 : {
# 1091 : 291683 : if (pnode->fDisconnect)
# 1092 : 335 : {
# 1093 : 335 : // remove from vNodes
# 1094 : 335 : vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
# 1095 : 335 :
# 1096 : 335 : // release outbound grant (if any)
# 1097 : 335 : pnode->grantOutbound.Release();
# 1098 : 335 :
# 1099 : 335 : // close socket and cleanup
# 1100 : 335 : pnode->CloseSocketDisconnect();
# 1101 : 335 :
# 1102 : 335 : // hold in disconnected pool until all refs are released
# 1103 : 335 : pnode->Release();
# 1104 : 335 : vNodesDisconnected.push_back(pnode);
# 1105 : 335 : }
# 1106 : 291683 : }
# 1107 : 182663 : }
# 1108 : 182663 : {
# 1109 : 182663 : // Delete disconnected nodes
# 1110 : 182663 : std::list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
# 1111 : 182663 : for (CNode* pnode : vNodesDisconnectedCopy)
# 1112 : 344 : {
# 1113 : 344 : // wait until threads are done using it
# 1114 : 344 : if (pnode->GetRefCount() <= 0) {
# 1115 : 335 : bool fDelete = false;
# 1116 : 335 : {
# 1117 : 335 : TRY_LOCK(pnode->cs_vSend, lockSend);
# 1118 : 335 : if (lockSend) {
# 1119 : 335 : fDelete = true;
# 1120 : 335 : }
# 1121 : 335 : }
# 1122 : 335 : if (fDelete) {
# 1123 : 335 : vNodesDisconnected.remove(pnode);
# 1124 : 335 : DeleteNode(pnode);
# 1125 : 335 : }
# 1126 : 335 : }
# 1127 : 344 : }
# 1128 : 182663 : }
# 1129 : 182663 : }
# 1130 : :
# 1131 : : void CConnman::NotifyNumConnectionsChanged()
# 1132 : 182663 : {
# 1133 : 182663 : size_t vNodesSize;
# 1134 : 182663 : {
# 1135 : 182663 : LOCK(cs_vNodes);
# 1136 : 182663 : vNodesSize = vNodes.size();
# 1137 : 182663 : }
# 1138 : 182663 : if(vNodesSize != nPrevNodeCount) {
# 1139 : 1010 : nPrevNodeCount = vNodesSize;
# 1140 : 1010 : if(clientInterface)
# 1141 : 1010 : clientInterface->NotifyNumConnectionsChanged(vNodesSize);
# 1142 : 1010 : }
# 1143 : 182663 : }
# 1144 : :
# 1145 : : void CConnman::InactivityCheck(CNode *pnode)
# 1146 : 291680 : {
# 1147 : 291680 : int64_t nTime = GetSystemTimeInSeconds();
# 1148 : 291680 : if (nTime - pnode->nTimeConnected > m_peer_connect_timeout)
# 1149 : 22436 : {
# 1150 : 22436 : if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
# 1151 : 2 : {
# 1152 : 2 : LogPrint(BCLog::NET, "socket no message in first %i seconds, %d %d from %d\n", m_peer_connect_timeout, pnode->nLastRecv != 0, pnode->nLastSend != 0, pnode->GetId());
# 1153 : 2 : pnode->fDisconnect = true;
# 1154 : 2 : }
# 1155 : 22434 : else if (nTime - pnode->nLastSend > TIMEOUT_INTERVAL)
# 1156 : 0 : {
# 1157 : 0 : LogPrintf("socket sending timeout: %is\n", nTime - pnode->nLastSend);
# 1158 : 0 : pnode->fDisconnect = true;
# 1159 : 0 : }
# 1160 : 22434 : else if (nTime - pnode->nLastRecv > (pnode->nVersion > BIP0031_VERSION ? TIMEOUT_INTERVAL : 90*60))
# 1161 : 0 : {
# 1162 : 0 : LogPrintf("socket receive timeout: %is\n", nTime - pnode->nLastRecv);
# 1163 : 0 : pnode->fDisconnect = true;
# 1164 : 0 : }
# 1165 : 22434 : else if (pnode->nPingNonceSent && pnode->m_ping_start.load() + std::chrono::seconds{TIMEOUT_INTERVAL} < GetTime<std::chrono::microseconds>())
# 1166 : 1 : {
# 1167 : 1 : LogPrintf("ping timeout: %fs\n", 0.000001 * count_microseconds(GetTime<std::chrono::microseconds>() - pnode->m_ping_start.load()));
# 1168 : 1 : pnode->fDisconnect = true;
# 1169 : 1 : }
# 1170 : 22433 : else if (!pnode->fSuccessfullyConnected)
# 1171 : 1 : {
# 1172 : 1 : LogPrint(BCLog::NET, "version handshake timeout from %d\n", pnode->GetId());
# 1173 : 1 : pnode->fDisconnect = true;
# 1174 : 1 : }
# 1175 : 22436 : }
# 1176 : 291680 : }
# 1177 : :
# 1178 : : bool CConnman::GenerateSelectSet(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
# 1179 : 182663 : {
# 1180 : 182671 : for (const ListenSocket& hListenSocket : vhListenSocket) {
# 1181 : 182671 : recv_set.insert(hListenSocket.socket);
# 1182 : 182671 : }
# 1183 : 182663 :
# 1184 : 182663 : {
# 1185 : 182663 : LOCK(cs_vNodes);
# 1186 : 182663 : for (CNode* pnode : vNodes)
# 1187 : 291348 : {
# 1188 : 291348 : // Implement the following logic:
# 1189 : 291348 : // * If there is data to send, select() for sending data. As this only
# 1190 : 291348 : // happens when optimistic write failed, we choose to first drain the
# 1191 : 291348 : // write buffer in this case before receiving more. This avoids
# 1192 : 291348 : // needlessly queueing received data, if the remote peer is not themselves
# 1193 : 291348 : // receiving data. This means properly utilizing TCP flow control signalling.
# 1194 : 291348 : // * Otherwise, if there is space left in the receive buffer, select() for
# 1195 : 291348 : // receiving data.
# 1196 : 291348 : // * Hand off all complete messages to the processor, to be handled without
# 1197 : 291348 : // blocking here.
# 1198 : 291348 :
# 1199 : 291348 : bool select_recv = !pnode->fPauseRecv;
# 1200 : 291348 : bool select_send;
# 1201 : 291348 : {
# 1202 : 291348 : LOCK(pnode->cs_vSend);
# 1203 : 291348 : select_send = !pnode->vSendMsg.empty();
# 1204 : 291348 : }
# 1205 : 291348 :
# 1206 : 291348 : LOCK(pnode->cs_hSocket);
# 1207 : 291348 : if (pnode->hSocket == INVALID_SOCKET)
# 1208 : 291348 : continue;
# 1209 : 291348 :
# 1210 : 291348 : error_set.insert(pnode->hSocket);
# 1211 : 291348 : if (select_send) {
# 1212 : 328 : send_set.insert(pnode->hSocket);
# 1213 : 328 : continue;
# 1214 : 328 : }
# 1215 : 291020 : if (select_recv) {
# 1216 : 291020 : recv_set.insert(pnode->hSocket);
# 1217 : 291020 : }
# 1218 : 291020 : }
# 1219 : 182663 : }
# 1220 : 182663 :
# 1221 : 182663 : return !recv_set.empty() || !send_set.empty() || !error_set.empty();
# 1222 : 182663 : }
# 1223 : :
# 1224 : : #ifdef USE_POLL
# 1225 : : void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
# 1226 : : {
# 1227 : : std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
# 1228 : : if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
# 1229 : : interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
# 1230 : : return;
# 1231 : : }
# 1232 : :
# 1233 : : std::unordered_map<SOCKET, struct pollfd> pollfds;
# 1234 : : for (SOCKET socket_id : recv_select_set) {
# 1235 : : pollfds[socket_id].fd = socket_id;
# 1236 : : pollfds[socket_id].events |= POLLIN;
# 1237 : : }
# 1238 : :
# 1239 : : for (SOCKET socket_id : send_select_set) {
# 1240 : : pollfds[socket_id].fd = socket_id;
# 1241 : : pollfds[socket_id].events |= POLLOUT;
# 1242 : : }
# 1243 : :
# 1244 : : for (SOCKET socket_id : error_select_set) {
# 1245 : : pollfds[socket_id].fd = socket_id;
# 1246 : : // These flags are ignored, but we set them for clarity
# 1247 : : pollfds[socket_id].events |= POLLERR|POLLHUP;
# 1248 : : }
# 1249 : :
# 1250 : : std::vector<struct pollfd> vpollfds;
# 1251 : : vpollfds.reserve(pollfds.size());
# 1252 : : for (auto it : pollfds) {
# 1253 : : vpollfds.push_back(std::move(it.second));
# 1254 : : }
# 1255 : :
# 1256 : : if (poll(vpollfds.data(), vpollfds.size(), SELECT_TIMEOUT_MILLISECONDS) < 0) return;
# 1257 : :
# 1258 : : if (interruptNet) return;
# 1259 : :
# 1260 : : for (struct pollfd pollfd_entry : vpollfds) {
# 1261 : : if (pollfd_entry.revents & POLLIN) recv_set.insert(pollfd_entry.fd);
# 1262 : : if (pollfd_entry.revents & POLLOUT) send_set.insert(pollfd_entry.fd);
# 1263 : : if (pollfd_entry.revents & (POLLERR|POLLHUP)) error_set.insert(pollfd_entry.fd);
# 1264 : : }
# 1265 : : }
# 1266 : : #else
# 1267 : : void CConnman::SocketEvents(std::set<SOCKET> &recv_set, std::set<SOCKET> &send_set, std::set<SOCKET> &error_set)
# 1268 : 182663 : {
# 1269 : 182663 : std::set<SOCKET> recv_select_set, send_select_set, error_select_set;
# 1270 : 182663 : if (!GenerateSelectSet(recv_select_set, send_select_set, error_select_set)) {
# 1271 : 0 : interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS));
# 1272 : 0 : return;
# 1273 : 0 : }
# 1274 : 182663 :
# 1275 : 182663 : //
# 1276 : 182663 : // Find which sockets have data to receive
# 1277 : 182663 : //
# 1278 : 182663 : struct timeval timeout;
# 1279 : 182663 : timeout.tv_sec = 0;
# 1280 : 182663 : timeout.tv_usec = SELECT_TIMEOUT_MILLISECONDS * 1000; // frequency to poll pnode->vSend
# 1281 : 182663 :
# 1282 : 182663 : fd_set fdsetRecv;
# 1283 : 182663 : fd_set fdsetSend;
# 1284 : 182663 : fd_set fdsetError;
# 1285 : 182663 : FD_ZERO(&fdsetRecv);
# 1286 : 182663 : FD_ZERO(&fdsetSend);
# 1287 : 182663 : FD_ZERO(&fdsetError);
# 1288 : 182663 : SOCKET hSocketMax = 0;
# 1289 : 182663 :
# 1290 : 473691 : for (SOCKET hSocket : recv_select_set) {
# 1291 : 473691 : FD_SET(hSocket, &fdsetRecv);
# 1292 : 473691 : hSocketMax = std::max(hSocketMax, hSocket);
# 1293 : 473691 : }
# 1294 : 182663 :
# 1295 : 182663 : for (SOCKET hSocket : send_select_set) {
# 1296 : 328 : FD_SET(hSocket, &fdsetSend);
# 1297 : 328 : hSocketMax = std::max(hSocketMax, hSocket);
# 1298 : 328 : }
# 1299 : 182663 :
# 1300 : 291348 : for (SOCKET hSocket : error_select_set) {
# 1301 : 291348 : FD_SET(hSocket, &fdsetError);
# 1302 : 291348 : hSocketMax = std::max(hSocketMax, hSocket);
# 1303 : 291348 : }
# 1304 : 182663 :
# 1305 : 182663 : int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
# 1306 : 182663 :
# 1307 : 182663 : if (interruptNet)
# 1308 : 494 : return;
# 1309 : 182169 :
# 1310 : 182169 : if (nSelect == SOCKET_ERROR)
# 1311 : 182169 : {
# 1312 : 0 : int nErr = WSAGetLastError();
# 1313 : 0 : LogPrintf("socket select error %s\n", NetworkErrorString(nErr));
# 1314 : 0 : for (unsigned int i = 0; i <= hSocketMax; i++)
# 1315 : 0 : FD_SET(i, &fdsetRecv);
# 1316 : 0 : FD_ZERO(&fdsetSend);
# 1317 : 0 : FD_ZERO(&fdsetError);
# 1318 : 0 : if (!interruptNet.sleep_for(std::chrono::milliseconds(SELECT_TIMEOUT_MILLISECONDS)))
# 1319 : 0 : return;
# 1320 : 182169 : }
# 1321 : 182169 :
# 1322 : 472833 : for (SOCKET hSocket : recv_select_set) {
# 1323 : 472833 : if (FD_ISSET(hSocket, &fdsetRecv)) {
# 1324 : 102333 : recv_set.insert(hSocket);
# 1325 : 102333 : }
# 1326 : 472833 : }
# 1327 : 182169 :
# 1328 : 182169 : for (SOCKET hSocket : send_select_set) {
# 1329 : 328 : if (FD_ISSET(hSocket, &fdsetSend)) {
# 1330 : 322 : send_set.insert(hSocket);
# 1331 : 322 : }
# 1332 : 328 : }
# 1333 : 182169 :
# 1334 : 290985 : for (SOCKET hSocket : error_select_set) {
# 1335 : 290985 : if (FD_ISSET(hSocket, &fdsetError)) {
# 1336 : 0 : error_set.insert(hSocket);
# 1337 : 0 : }
# 1338 : 290985 : }
# 1339 : 182169 : }
# 1340 : : #endif
# 1341 : :
# 1342 : : void CConnman::SocketHandler()
# 1343 : 182663 : {
# 1344 : 182663 : std::set<SOCKET> recv_set, send_set, error_set;
# 1345 : 182663 : SocketEvents(recv_set, send_set, error_set);
# 1346 : 182663 :
# 1347 : 182663 : if (interruptNet) return;
# 1348 : 182169 :
# 1349 : 182169 : //
# 1350 : 182169 : // Accept new connections
# 1351 : 182169 : //
# 1352 : 182169 : for (const ListenSocket& hListenSocket : vhListenSocket)
# 1353 : 182176 : {
# 1354 : 182176 : if (hListenSocket.socket != INVALID_SOCKET && recv_set.count(hListenSocket.socket) > 0)
# 1355 : 454 : {
# 1356 : 454 : AcceptConnection(hListenSocket);
# 1357 : 454 : }
# 1358 : 182176 : }
# 1359 : 182169 :
# 1360 : 182169 : //
# 1361 : 182169 : // Service each socket
# 1362 : 182169 : //
# 1363 : 182169 : std::vector<CNode*> vNodesCopy;
# 1364 : 182169 : {
# 1365 : 182169 : LOCK(cs_vNodes);
# 1366 : 182169 : vNodesCopy = vNodes;
# 1367 : 182169 : for (CNode* pnode : vNodesCopy)
# 1368 : 291683 : pnode->AddRef();
# 1369 : 182169 : }
# 1370 : 182169 : for (CNode* pnode : vNodesCopy)
# 1371 : 291683 : {
# 1372 : 291683 : if (interruptNet)
# 1373 : 0 : return;
# 1374 : 291683 :
# 1375 : 291683 : //
# 1376 : 291683 : // Receive
# 1377 : 291683 : //
# 1378 : 291683 : bool recvSet = false;
# 1379 : 291683 : bool sendSet = false;
# 1380 : 291683 : bool errorSet = false;
# 1381 : 291683 : {
# 1382 : 291683 : LOCK(pnode->cs_hSocket);
# 1383 : 291683 : if (pnode->hSocket == INVALID_SOCKET)
# 1384 : 291683 : continue;
# 1385 : 291680 : recvSet = recv_set.count(pnode->hSocket) > 0;
# 1386 : 291680 : sendSet = send_set.count(pnode->hSocket) > 0;
# 1387 : 291680 : errorSet = error_set.count(pnode->hSocket) > 0;
# 1388 : 291680 : }
# 1389 : 291680 : if (recvSet || errorSet)
# 1390 : 101879 : {
# 1391 : 101879 : // typical socket buffer is 8K-64K
# 1392 : 101879 : char pchBuf[0x10000];
# 1393 : 101879 : int nBytes = 0;
# 1394 : 101879 : {
# 1395 : 101879 : LOCK(pnode->cs_hSocket);
# 1396 : 101879 : if (pnode->hSocket == INVALID_SOCKET)
# 1397 : 101879 : continue;
# 1398 : 101879 : nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
# 1399 : 101879 : }
# 1400 : 101879 : if (nBytes > 0)
# 1401 : 101691 : {
# 1402 : 101691 : bool notify = false;
# 1403 : 101691 : if (!pnode->ReceiveMsgBytes(pchBuf, nBytes, notify))
# 1404 : 1 : pnode->CloseSocketDisconnect();
# 1405 : 101691 : RecordBytesRecv(nBytes);
# 1406 : 101691 : if (notify) {
# 1407 : 80121 : size_t nSizeAdded = 0;
# 1408 : 80121 : auto it(pnode->vRecvMsg.begin());
# 1409 : 163412 : for (; it != pnode->vRecvMsg.end(); ++it) {
# 1410 : 83291 : // vRecvMsg contains only completed CNetMessage
# 1411 : 83291 : // the single possible partially deserialized message are held by TransportDeserializer
# 1412 : 83291 : nSizeAdded += it->m_raw_message_size;
# 1413 : 83291 : }
# 1414 : 80121 : {
# 1415 : 80121 : LOCK(pnode->cs_vProcessMsg);
# 1416 : 80121 : pnode->vProcessMsg.splice(pnode->vProcessMsg.end(), pnode->vRecvMsg, pnode->vRecvMsg.begin(), it);
# 1417 : 80121 : pnode->nProcessQueueSize += nSizeAdded;
# 1418 : 80121 : pnode->fPauseRecv = pnode->nProcessQueueSize > nReceiveFloodSize;
# 1419 : 80121 : }
# 1420 : 80121 : WakeMessageHandler();
# 1421 : 80121 : }
# 1422 : 101691 : }
# 1423 : 188 : else if (nBytes == 0)
# 1424 : 181 : {
# 1425 : 181 : // socket closed gracefully
# 1426 : 181 : if (!pnode->fDisconnect) {
# 1427 : 181 : LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId());
# 1428 : 181 : }
# 1429 : 181 : pnode->CloseSocketDisconnect();
# 1430 : 181 : }
# 1431 : 7 : else if (nBytes < 0)
# 1432 : 7 : {
# 1433 : 7 : // error
# 1434 : 7 : int nErr = WSAGetLastError();
# 1435 : 7 : if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
# 1436 : 7 : {
# 1437 : 7 : if (!pnode->fDisconnect) {
# 1438 : 7 : LogPrint(BCLog::NET, "socket recv error for peer=%d: %s\n", pnode->GetId(), NetworkErrorString(nErr));
# 1439 : 7 : }
# 1440 : 7 : pnode->CloseSocketDisconnect();
# 1441 : 7 : }
# 1442 : 7 : }
# 1443 : 101879 : }
# 1444 : 291680 :
# 1445 : 291680 : //
# 1446 : 291680 : // Send
# 1447 : 291680 : //
# 1448 : 291680 : if (sendSet)
# 1449 : 322 : {
# 1450 : 322 : LOCK(pnode->cs_vSend);
# 1451 : 322 : size_t nBytes = SocketSendData(pnode);
# 1452 : 322 : if (nBytes) {
# 1453 : 322 : RecordBytesSent(nBytes);
# 1454 : 322 : }
# 1455 : 322 : }
# 1456 : 291680 :
# 1457 : 291680 : InactivityCheck(pnode);
# 1458 : 291680 : }
# 1459 : 182169 : {
# 1460 : 182169 : LOCK(cs_vNodes);
# 1461 : 182169 : for (CNode* pnode : vNodesCopy)
# 1462 : 291683 : pnode->Release();
# 1463 : 182169 : }
# 1464 : 182169 : }
# 1465 : :
# 1466 : : void CConnman::ThreadSocketHandler()
# 1467 : 494 : {
# 1468 : 183157 : while (!interruptNet)
# 1469 : 182663 : {
# 1470 : 182663 : DisconnectNodes();
# 1471 : 182663 : NotifyNumConnectionsChanged();
# 1472 : 182663 : SocketHandler();
# 1473 : 182663 : }
# 1474 : 494 : }
# 1475 : :
# 1476 : : void CConnman::WakeMessageHandler()
# 1477 : 114417 : {
# 1478 : 114417 : {
# 1479 : 114417 : LOCK(mutexMsgProc);
# 1480 : 114417 : fMsgProcWake = true;
# 1481 : 114417 : }
# 1482 : 114417 : condMsgProc.notify_one();
# 1483 : 114417 : }
# 1484 : :
# 1485 : :
# 1486 : :
# 1487 : :
# 1488 : :
# 1489 : :
# 1490 : : #ifdef USE_UPNP
# 1491 : : static CThreadInterrupt g_upnp_interrupt;
# 1492 : : static std::thread g_upnp_thread;
# 1493 : : static void ThreadMapPort()
# 1494 : 0 : {
# 1495 : 0 : std::string port = strprintf("%u", GetListenPort());
# 1496 : 0 : const char * multicastif = nullptr;
# 1497 : 0 : const char * minissdpdpath = nullptr;
# 1498 : 0 : struct UPNPDev * devlist = nullptr;
# 1499 : 0 : char lanaddr[64];
# 1500 : 0 :
# 1501 : 0 : int error = 0;
# 1502 : : #if MINIUPNPC_API_VERSION < 14
# 1503 : : devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error);
# 1504 : : #else
# 1505 : : devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, 2, &error);
# 1506 : 0 : #endif
# 1507 : 0 :
# 1508 : 0 : struct UPNPUrls urls;
# 1509 : 0 : struct IGDdatas data;
# 1510 : 0 : int r;
# 1511 : 0 :
# 1512 : 0 : r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr));
# 1513 : 0 : if (r == 1)
# 1514 : 0 : {
# 1515 : 0 : if (fDiscover) {
# 1516 : 0 : char externalIPAddress[40];
# 1517 : 0 : r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress);
# 1518 : 0 : if (r != UPNPCOMMAND_SUCCESS) {
# 1519 : 0 : LogPrintf("UPnP: GetExternalIPAddress() returned %d\n", r);
# 1520 : 0 : } else {
# 1521 : 0 : if (externalIPAddress[0]) {
# 1522 : 0 : CNetAddr resolved;
# 1523 : 0 : if (LookupHost(externalIPAddress, resolved, false)) {
# 1524 : 0 : LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString());
# 1525 : 0 : AddLocal(resolved, LOCAL_UPNP);
# 1526 : 0 : }
# 1527 : 0 : } else {
# 1528 : 0 : LogPrintf("UPnP: GetExternalIPAddress failed.\n");
# 1529 : 0 : }
# 1530 : 0 : }
# 1531 : 0 : }
# 1532 : 0 :
# 1533 : 0 : std::string strDesc = PACKAGE_NAME " " + FormatFullVersion();
# 1534 : 0 :
# 1535 : 0 : do {
# 1536 : 0 : r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, port.c_str(), port.c_str(), lanaddr, strDesc.c_str(), "TCP", 0, "0");
# 1537 : 0 :
# 1538 : 0 : if (r != UPNPCOMMAND_SUCCESS) {
# 1539 : 0 : LogPrintf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", port, port, lanaddr, r, strupnperror(r));
# 1540 : 0 : } else {
# 1541 : 0 : LogPrintf("UPnP Port Mapping successful.\n");
# 1542 : 0 : }
# 1543 : 0 : } while (g_upnp_interrupt.sleep_for(std::chrono::minutes(20)));
# 1544 : 0 :
# 1545 : 0 : r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port.c_str(), "TCP", 0);
# 1546 : 0 : LogPrintf("UPNP_DeletePortMapping() returned: %d\n", r);
# 1547 : 0 : freeUPNPDevlist(devlist); devlist = nullptr;
# 1548 : 0 : FreeUPNPUrls(&urls);
# 1549 : 0 : } else {
# 1550 : 0 : LogPrintf("No valid UPnP IGDs found\n");
# 1551 : 0 : freeUPNPDevlist(devlist); devlist = nullptr;
# 1552 : 0 : if (r != 0)
# 1553 : 0 : FreeUPNPUrls(&urls);
# 1554 : 0 : }
# 1555 : 0 : }
# 1556 : :
# 1557 : : void StartMapPort()
# 1558 : 0 : {
# 1559 : 0 : if (!g_upnp_thread.joinable()) {
# 1560 : 0 : assert(!g_upnp_interrupt);
# 1561 : 0 : g_upnp_thread = std::thread((std::bind(&TraceThread<void (*)()>, "upnp", &ThreadMapPort)));
# 1562 : 0 : }
# 1563 : 0 : }
# 1564 : :
# 1565 : : void InterruptMapPort()
# 1566 : 531 : {
# 1567 : 531 : if(g_upnp_thread.joinable()) {
# 1568 : 0 : g_upnp_interrupt();
# 1569 : 0 : }
# 1570 : 531 : }
# 1571 : :
# 1572 : : void StopMapPort()
# 1573 : 531 : {
# 1574 : 531 : if(g_upnp_thread.joinable()) {
# 1575 : 0 : g_upnp_thread.join();
# 1576 : 0 : g_upnp_interrupt.reset();
# 1577 : 0 : }
# 1578 : 531 : }
# 1579 : :
# 1580 : : #else
# 1581 : : void StartMapPort()
# 1582 : : {
# 1583 : : // Intentionally left blank.
# 1584 : : }
# 1585 : : void InterruptMapPort()
# 1586 : : {
# 1587 : : // Intentionally left blank.
# 1588 : : }
# 1589 : : void StopMapPort()
# 1590 : : {
# 1591 : : // Intentionally left blank.
# 1592 : : }
# 1593 : : #endif
# 1594 : :
# 1595 : :
# 1596 : :
# 1597 : :
# 1598 : :
# 1599 : :
# 1600 : : void CConnman::ThreadDNSAddressSeed()
# 1601 : 0 : {
# 1602 : 0 : FastRandomContext rng;
# 1603 : 0 : std::vector<std::string> seeds = Params().DNSSeeds();
# 1604 : 0 : Shuffle(seeds.begin(), seeds.end(), rng);
# 1605 : 0 : int seeds_right_now = 0; // Number of seeds left before testing if we have enough connections
# 1606 : 0 : int found = 0;
# 1607 : 0 :
# 1608 : 0 : if (gArgs.GetBoolArg("-forcednsseed", DEFAULT_FORCEDNSSEED)) {
# 1609 : 0 : // When -forcednsseed is provided, query all.
# 1610 : 0 : seeds_right_now = seeds.size();
# 1611 : 0 : } else if (addrman.size() == 0) {
# 1612 : 0 : // If we have no known peers, query all.
# 1613 : 0 : // This will occur on the first run, or if peers.dat has been
# 1614 : 0 : // deleted.
# 1615 : 0 : seeds_right_now = seeds.size();
# 1616 : 0 : }
# 1617 : 0 :
# 1618 : 0 : // goal: only query DNS seed if address need is acute
# 1619 : 0 : // * If we have a reasonable number of peers in addrman, spend
# 1620 : 0 : // some time trying them first. This improves user privacy by
# 1621 : 0 : // creating fewer identifying DNS requests, reduces trust by
# 1622 : 0 : // giving seeds less influence on the network topology, and
# 1623 : 0 : // reduces traffic to the seeds.
# 1624 : 0 : // * When querying DNS seeds query a few at once, this ensures
# 1625 : 0 : // that we don't give DNS seeds the ability to eclipse nodes
# 1626 : 0 : // that query them.
# 1627 : 0 : // * If we continue having problems, eventually query all the
# 1628 : 0 : // DNS seeds, and if that fails too, also try the fixed seeds.
# 1629 : 0 : // (done in ThreadOpenConnections)
# 1630 : 0 : const std::chrono::seconds seeds_wait_time = (addrman.size() >= DNSSEEDS_DELAY_PEER_THRESHOLD ? DNSSEEDS_DELAY_MANY_PEERS : DNSSEEDS_DELAY_FEW_PEERS);
# 1631 : 0 :
# 1632 : 0 : for (const std::string& seed : seeds) {
# 1633 : 0 : if (seeds_right_now == 0) {
# 1634 : 0 : seeds_right_now += DNSSEEDS_TO_QUERY_AT_ONCE;
# 1635 : 0 :
# 1636 : 0 : if (addrman.size() > 0) {
# 1637 : 0 : LogPrintf("Waiting %d seconds before querying DNS seeds.\n", seeds_wait_time.count());
# 1638 : 0 : std::chrono::seconds to_wait = seeds_wait_time;
# 1639 : 0 : while (to_wait.count() > 0) {
# 1640 : 0 : // if sleeping for the MANY_PEERS interval, wake up
# 1641 : 0 : // early to see if we have enough peers and can stop
# 1642 : 0 : // this thread entirely freeing up its resources
# 1643 : 0 : std::chrono::seconds w = std::min(DNSSEEDS_DELAY_FEW_PEERS, to_wait);
# 1644 : 0 : if (!interruptNet.sleep_for(w)) return;
# 1645 : 0 : to_wait -= w;
# 1646 : 0 :
# 1647 : 0 : int nRelevant = 0;
# 1648 : 0 : {
# 1649 : 0 : LOCK(cs_vNodes);
# 1650 : 0 : for (const CNode* pnode : vNodes) {
# 1651 : 0 : if (pnode->fSuccessfullyConnected && pnode->IsOutboundOrBlockRelayConn()) ++nRelevant;
# 1652 : 0 : }
# 1653 : 0 : }
# 1654 : 0 : if (nRelevant >= 2) {
# 1655 : 0 : if (found > 0) {
# 1656 : 0 : LogPrintf("%d addresses found from DNS seeds\n", found);
# 1657 : 0 : LogPrintf("P2P peers available. Finished DNS seeding.\n");
# 1658 : 0 : } else {
# 1659 : 0 : LogPrintf("P2P peers available. Skipped DNS seeding.\n");
# 1660 : 0 : }
# 1661 : 0 : return;
# 1662 : 0 : }
# 1663 : 0 : }
# 1664 : 0 : }
# 1665 : 0 : }
# 1666 : 0 :
# 1667 : 0 : if (interruptNet) return;
# 1668 : 0 :
# 1669 : 0 : // hold off on querying seeds if P2P network deactivated
# 1670 : 0 : if (!fNetworkActive) {
# 1671 : 0 : LogPrintf("Waiting for network to be reactivated before querying DNS seeds.\n");
# 1672 : 0 : do {
# 1673 : 0 : if (!interruptNet.sleep_for(std::chrono::seconds{1})) return;
# 1674 : 0 : } while (!fNetworkActive);
# 1675 : 0 : }
# 1676 : 0 :
# 1677 : 0 : LogPrintf("Loading addresses from DNS seed %s\n", seed);
# 1678 : 0 : if (HaveNameProxy()) {
# 1679 : 0 : AddAddrFetch(seed);
# 1680 : 0 : } else {
# 1681 : 0 : std::vector<CNetAddr> vIPs;
# 1682 : 0 : std::vector<CAddress> vAdd;
# 1683 : 0 : ServiceFlags requiredServiceBits = GetDesirableServiceFlags(NODE_NONE);
# 1684 : 0 : std::string host = strprintf("x%x.%s", requiredServiceBits, seed);
# 1685 : 0 : CNetAddr resolveSource;
# 1686 : 0 : if (!resolveSource.SetInternal(host)) {
# 1687 : 0 : continue;
# 1688 : 0 : }
# 1689 : 0 : unsigned int nMaxIPs = 256; // Limits number of IPs learned from a DNS seed
# 1690 : 0 : if (LookupHost(host, vIPs, nMaxIPs, true)) {
# 1691 : 0 : for (const CNetAddr& ip : vIPs) {
# 1692 : 0 : int nOneDay = 24*3600;
# 1693 : 0 : CAddress addr = CAddress(CService(ip, Params().GetDefaultPort()), requiredServiceBits);
# 1694 : 0 : addr.nTime = GetTime() - 3*nOneDay - rng.randrange(4*nOneDay); // use a random age between 3 and 7 days old
# 1695 : 0 : vAdd.push_back(addr);
# 1696 : 0 : found++;
# 1697 : 0 : }
# 1698 : 0 : addrman.Add(vAdd, resolveSource);
# 1699 : 0 : } else {
# 1700 : 0 : // We now avoid directly using results from DNS Seeds which do not support service bit filtering,
# 1701 : 0 : // instead using them as a addrfetch to get nodes with our desired service bits.
# 1702 : 0 : AddAddrFetch(seed);
# 1703 : 0 : }
# 1704 : 0 : }
# 1705 : 0 : --seeds_right_now;
# 1706 : 0 : }
# 1707 : 0 : LogPrintf("%d addresses found from DNS seeds\n", found);
# 1708 : 0 : }
# 1709 : :
# 1710 : : void CConnman::DumpAddresses()
# 1711 : 794 : {
# 1712 : 794 : int64_t nStart = GetTimeMillis();
# 1713 : 794 :
# 1714 : 794 : CAddrDB adb;
# 1715 : 794 : adb.Write(addrman);
# 1716 : 794 :
# 1717 : 794 : LogPrint(BCLog::NET, "Flushed %d addresses to peers.dat %dms\n",
# 1718 : 794 : addrman.size(), GetTimeMillis() - nStart);
# 1719 : 794 : }
# 1720 : :
# 1721 : : void CConnman::ProcessAddrFetch()
# 1722 : 9729 : {
# 1723 : 9729 : std::string strDest;
# 1724 : 9729 : {
# 1725 : 9729 : LOCK(m_addr_fetches_mutex);
# 1726 : 9729 : if (m_addr_fetches.empty())
# 1727 : 9729 : return;
# 1728 : 0 : strDest = m_addr_fetches.front();
# 1729 : 0 : m_addr_fetches.pop_front();
# 1730 : 0 : }
# 1731 : 0 : CAddress addr;
# 1732 : 0 : CSemaphoreGrant grant(*semOutbound, true);
# 1733 : 0 : if (grant) {
# 1734 : 0 : OpenNetworkConnection(addr, false, &grant, strDest.c_str(), ConnectionType::ADDR_FETCH);
# 1735 : 0 : }
# 1736 : 0 : }
# 1737 : :
# 1738 : : bool CConnman::GetTryNewOutboundPeer()
# 1739 : 34 : {
# 1740 : 34 : return m_try_another_outbound_peer;
# 1741 : 34 : }
# 1742 : :
# 1743 : : void CConnman::SetTryNewOutboundPeer(bool flag)
# 1744 : 671 : {
# 1745 : 671 : m_try_another_outbound_peer = flag;
# 1746 : 671 : LogPrint(BCLog::NET, "net: setting try another outbound peer=%s\n", flag ? "true" : "false");
# 1747 : 671 : }
# 1748 : :
# 1749 : : // Return the number of peers we have over our outbound connection limit
# 1750 : : // Exclude peers that are marked for disconnect, or are going to be
# 1751 : : // disconnected soon (eg one-shots and feelers)
# 1752 : : // Also exclude peers that haven't finished initial connection handshake yet
# 1753 : : // (so that we don't decide we're over our desired connection limit, and then
# 1754 : : // evict some peer that has finished the handshake)
# 1755 : : int CConnman::GetExtraOutboundCount()
# 1756 : 47 : {
# 1757 : 47 : int nOutbound = 0;
# 1758 : 47 : {
# 1759 : 47 : LOCK(cs_vNodes);
# 1760 : 117 : for (const CNode* pnode : vNodes) {
# 1761 : 117 : if (pnode->fSuccessfullyConnected && !pnode->fDisconnect && pnode->IsOutboundOrBlockRelayConn()) {
# 1762 : 68 : ++nOutbound;
# 1763 : 68 : }
# 1764 : 117 : }
# 1765 : 47 : }
# 1766 : 47 : return std::max(nOutbound - m_max_outbound_full_relay - m_max_outbound_block_relay, 0);
# 1767 : 47 : }
# 1768 : :
# 1769 : : void CConnman::ThreadOpenConnections(const std::vector<std::string> connect)
# 1770 : 494 : {
# 1771 : 494 : // Connect to specific addresses
# 1772 : 494 : if (!connect.empty())
# 1773 : 1 : {
# 1774 : 1 : for (int64_t nLoop = 0;; nLoop++)
# 1775 : 1 : {
# 1776 : 1 : ProcessAddrFetch();
# 1777 : 1 : for (const std::string& strAddr : connect)
# 1778 : 1 : {
# 1779 : 1 : CAddress addr(CService(), NODE_NONE);
# 1780 : 1 : OpenNetworkConnection(addr, false, nullptr, strAddr.c_str(), ConnectionType::MANUAL);
# 1781 : 1 : for (int i = 0; i < 10 && i < nLoop; i++)
# 1782 : 0 : {
# 1783 : 0 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 1784 : 0 : return;
# 1785 : 0 : }
# 1786 : 1 : }
# 1787 : 1 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 1788 : 1 : return;
# 1789 : 1 : }
# 1790 : 1 : }
# 1791 : 494 :
# 1792 : 494 : // Initiate network connections
# 1793 : 494 : int64_t nStart = GetTime();
# 1794 : 493 :
# 1795 : 493 : // Minimum time before next feeler connection (in microseconds).
# 1796 : 493 : int64_t nNextFeeler = PoissonNextSend(nStart*1000*1000, FEELER_INTERVAL);
# 1797 : 9730 : while (!interruptNet)
# 1798 : 9728 : {
# 1799 : 9728 : ProcessAddrFetch();
# 1800 : 9728 :
# 1801 : 9728 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 1802 : 491 : return;
# 1803 : 9237 :
# 1804 : 9237 : CSemaphoreGrant grant(*semOutbound);
# 1805 : 9237 : if (interruptNet)
# 1806 : 0 : return;
# 1807 : 9237 :
# 1808 : 9237 : // Add seed nodes if DNS seeds are all down (an infrastructure attack?).
# 1809 : 9237 : // Note that we only do this if we started with an empty peers.dat,
# 1810 : 9237 : // (in which case we will query DNS seeds immediately) *and* the DNS
# 1811 : 9237 : // seeds have not returned any results.
# 1812 : 9237 : if (addrman.size() == 0 && (GetTime() - nStart > 60)) {
# 1813 : 1470 : static bool done = false;
# 1814 : 1470 : if (!done) {
# 1815 : 18 : LogPrintf("Adding fixed seed nodes as DNS doesn't seem to be available.\n");
# 1816 : 18 : CNetAddr local;
# 1817 : 18 : local.SetInternal("fixedseeds");
# 1818 : 18 : addrman.Add(convertSeed6(Params().FixedSeeds()), local);
# 1819 : 18 : done = true;
# 1820 : 18 : }
# 1821 : 1470 : }
# 1822 : 9237 :
# 1823 : 9237 : //
# 1824 : 9237 : // Choose an address to connect to based on most recently seen
# 1825 : 9237 : //
# 1826 : 9237 : CAddress addrConnect;
# 1827 : 9237 :
# 1828 : 9237 : // Only connect out to one peer per network group (/16 for IPv4).
# 1829 : 9237 : int nOutboundFullRelay = 0;
# 1830 : 9237 : int nOutboundBlockRelay = 0;
# 1831 : 9237 : std::set<std::vector<unsigned char> > setConnected;
# 1832 : 9237 :
# 1833 : 9237 : {
# 1834 : 9237 : LOCK(cs_vNodes);
# 1835 : 13798 : for (const CNode* pnode : vNodes) {
# 1836 : 13798 : if (pnode->IsFullOutboundConn()) nOutboundFullRelay++;
# 1837 : 13798 : if (pnode->IsBlockOnlyConn()) nOutboundBlockRelay++;
# 1838 : 13798 :
# 1839 : 13798 : // Netgroups for inbound and manual peers are not excluded because our goal here
# 1840 : 13798 : // is to not use multiple of our limited outbound slots on a single netgroup
# 1841 : 13798 : // but inbound and manual peers do not use our outbound slots. Inbound peers
# 1842 : 13798 : // also have the added issue that they could be attacker controlled and used
# 1843 : 13798 : // to prevent us from connecting to particular hosts if we used them here.
# 1844 : 13798 : switch(pnode->m_conn_type){
# 1845 : 13798 : case ConnectionType::INBOUND:
# 1846 : 13798 : case ConnectionType::MANUAL:
# 1847 : 13798 : break;
# 1848 : 13798 : case ConnectionType::OUTBOUND:
# 1849 : 0 : case ConnectionType::BLOCK_RELAY:
# 1850 : 0 : case ConnectionType::ADDR_FETCH:
# 1851 : 0 : case ConnectionType::FEELER:
# 1852 : 0 : setConnected.insert(pnode->addr.GetGroup(addrman.m_asmap));
# 1853 : 13798 : }
# 1854 : 13798 : }
# 1855 : 9237 : }
# 1856 : 9237 :
# 1857 : 9237 : // Feeler Connections
# 1858 : 9237 : //
# 1859 : 9237 : // Design goals:
# 1860 : 9237 : // * Increase the number of connectable addresses in the tried table.
# 1861 : 9237 : //
# 1862 : 9237 : // Method:
# 1863 : 9237 : // * Choose a random address from new and attempt to connect to it if we can connect
# 1864 : 9237 : // successfully it is added to tried.
# 1865 : 9237 : // * Start attempting feeler connections only after node finishes making outbound
# 1866 : 9237 : // connections.
# 1867 : 9237 : // * Only make a feeler connection once every few minutes.
# 1868 : 9237 : //
# 1869 : 9237 : bool fFeeler = false;
# 1870 : 9237 :
# 1871 : 9237 : if (nOutboundFullRelay >= m_max_outbound_full_relay && nOutboundBlockRelay >= m_max_outbound_block_relay && !GetTryNewOutboundPeer()) {
# 1872 : 0 : int64_t nTime = GetTimeMicros(); // The current time right now (in microseconds).
# 1873 : 0 : if (nTime > nNextFeeler) {
# 1874 : 0 : nNextFeeler = PoissonNextSend(nTime, FEELER_INTERVAL);
# 1875 : 0 : fFeeler = true;
# 1876 : 0 : } else {
# 1877 : 0 : continue;
# 1878 : 0 : }
# 1879 : 9237 : }
# 1880 : 9237 :
# 1881 : 9237 : addrman.ResolveCollisions();
# 1882 : 9237 :
# 1883 : 9237 : int64_t nANow = GetAdjustedTime();
# 1884 : 9237 : int nTries = 0;
# 1885 : 9335 : while (!interruptNet)
# 1886 : 9335 : {
# 1887 : 9335 : CAddrInfo addr = addrman.SelectTriedCollision();
# 1888 : 9335 :
# 1889 : 9335 : // SelectTriedCollision returns an invalid address if it is empty.
# 1890 : 9335 : if (!fFeeler || !addr.IsValid()) {
# 1891 : 9335 : addr = addrman.Select(fFeeler);
# 1892 : 9335 : }
# 1893 : 9335 :
# 1894 : 9335 : // Require outbound connections, other than feelers, to be to distinct network groups
# 1895 : 9335 : if (!fFeeler && setConnected.count(addr.GetGroup(addrman.m_asmap))) {
# 1896 : 0 : break;
# 1897 : 0 : }
# 1898 : 9335 :
# 1899 : 9335 : // if we selected an invalid or local address, restart
# 1900 : 9335 : if (!addr.IsValid() || IsLocal(addr)) {
# 1901 : 9235 : break;
# 1902 : 9235 : }
# 1903 : 100 :
# 1904 : 100 : // If we didn't find an appropriate destination after trying 100 addresses fetched from addrman,
# 1905 : 100 : // stop this loop, and let the outer loop run again (which sleeps, adds seed nodes, recalculates
# 1906 : 100 : // already-connected network ranges, ...) before trying new addrman addresses.
# 1907 : 100 : nTries++;
# 1908 : 100 : if (nTries > 100)
# 1909 : 0 : break;
# 1910 : 100 :
# 1911 : 100 : if (!IsReachable(addr))
# 1912 : 0 : continue;
# 1913 : 100 :
# 1914 : 100 : // only consider very recently tried nodes after 30 failed attempts
# 1915 : 100 : if (nANow - addr.nLastTry < 600 && nTries < 30)
# 1916 : 0 : continue;
# 1917 : 100 :
# 1918 : 100 : // for non-feelers, require all the services we'll want,
# 1919 : 100 : // for feelers, only require they be a full node (only because most
# 1920 : 100 : // SPV clients don't have a good address DB available)
# 1921 : 100 : if (!fFeeler && !HasAllDesirableServiceFlags(addr.nServices)) {
# 1922 : 0 : continue;
# 1923 : 100 : } else if (fFeeler && !MayHaveUsefulAddressDB(addr.nServices)) {
# 1924 : 0 : continue;
# 1925 : 0 : }
# 1926 : 100 :
# 1927 : 100 : // do not allow non-default ports, unless after 50 invalid addresses selected already
# 1928 : 100 : if (addr.GetPort() != Params().GetDefaultPort() && nTries < 50)
# 1929 : 98 : continue;
# 1930 : 2 :
# 1931 : 2 : addrConnect = addr;
# 1932 : 2 : break;
# 1933 : 2 : }
# 1934 : 9237 :
# 1935 : 9237 : if (addrConnect.IsValid()) {
# 1936 : 2 :
# 1937 : 2 : if (fFeeler) {
# 1938 : 0 : // Add small amount of random noise before connection to avoid synchronization.
# 1939 : 0 : int randsleep = GetRandInt(FEELER_SLEEP_WINDOW * 1000);
# 1940 : 0 : if (!interruptNet.sleep_for(std::chrono::milliseconds(randsleep)))
# 1941 : 0 : return;
# 1942 : 0 : LogPrint(BCLog::NET, "Making feeler connection to %s\n", addrConnect.ToString());
# 1943 : 0 : }
# 1944 : 2 :
# 1945 : 2 : ConnectionType conn_type;
# 1946 : 2 : // Determine what type of connection to open. If fFeeler is not
# 1947 : 2 : // set, open OUTBOUND connections until we meet our full-relay
# 1948 : 2 : // capacity. Then open BLOCK_RELAY connections until we hit our
# 1949 : 2 : // block-relay peer limit. Otherwise, default to opening an
# 1950 : 2 : // OUTBOUND connection.
# 1951 : 2 : if (fFeeler) {
# 1952 : 0 : conn_type = ConnectionType::FEELER;
# 1953 : 2 : } else if (nOutboundFullRelay < m_max_outbound_full_relay) {
# 1954 : 2 : conn_type = ConnectionType::OUTBOUND;
# 1955 : 2 : } else if (nOutboundBlockRelay < m_max_outbound_block_relay) {
# 1956 : 0 : conn_type = ConnectionType::BLOCK_RELAY;
# 1957 : 0 : } else {
# 1958 : 0 : // GetTryNewOutboundPeer() is true
# 1959 : 0 : conn_type = ConnectionType::OUTBOUND;
# 1960 : 0 : }
# 1961 : 2 :
# 1962 : 2 : OpenNetworkConnection(addrConnect, (int)setConnected.size() >= std::min(nMaxConnections - 1, 2), &grant, nullptr, conn_type);
# 1963 : 2 : }
# 1964 : 9237 : }
# 1965 : 493 : }
# 1966 : :
# 1967 : : std::vector<AddedNodeInfo> CConnman::GetAddedNodeInfo()
# 1968 : 2670 : {
# 1969 : 2670 : std::vector<AddedNodeInfo> ret;
# 1970 : 2670 :
# 1971 : 2670 : std::list<std::string> lAddresses(0);
# 1972 : 2670 : {
# 1973 : 2670 : LOCK(cs_vAddedNodes);
# 1974 : 2670 : ret.reserve(vAddedNodes.size());
# 1975 : 2670 : std::copy(vAddedNodes.cbegin(), vAddedNodes.cend(), std::back_inserter(lAddresses));
# 1976 : 2670 : }
# 1977 : 2670 :
# 1978 : 2670 :
# 1979 : 2670 : // Build a map of all already connected addresses (by IP:port and by name) to inbound/outbound and resolved CService
# 1980 : 2670 : std::map<CService, bool> mapConnected;
# 1981 : 2670 : std::map<std::string, std::pair<bool, CService>> mapConnectedByName;
# 1982 : 2670 : {
# 1983 : 2670 : LOCK(cs_vNodes);
# 1984 : 3385 : for (const CNode* pnode : vNodes) {
# 1985 : 3385 : if (pnode->addr.IsValid()) {
# 1986 : 3385 : mapConnected[pnode->addr] = pnode->IsInboundConn();
# 1987 : 3385 : }
# 1988 : 3385 : std::string addrName = pnode->GetAddrName();
# 1989 : 3385 : if (!addrName.empty()) {
# 1990 : 3385 : mapConnectedByName[std::move(addrName)] = std::make_pair(pnode->IsInboundConn(), static_cast<const CService&>(pnode->addr));
# 1991 : 3385 : }
# 1992 : 3385 : }
# 1993 : 2670 : }
# 1994 : 2670 :
# 1995 : 2670 : for (const std::string& strAddNode : lAddresses) {
# 1996 : 3 : CService service(LookupNumeric(strAddNode, Params().GetDefaultPort()));
# 1997 : 3 : AddedNodeInfo addedNode{strAddNode, CService(), false, false};
# 1998 : 3 : if (service.IsValid()) {
# 1999 : 2 : // strAddNode is an IP:port
# 2000 : 2 : auto it = mapConnected.find(service);
# 2001 : 2 : if (it != mapConnected.end()) {
# 2002 : 0 : addedNode.resolvedAddress = service;
# 2003 : 0 : addedNode.fConnected = true;
# 2004 : 0 : addedNode.fInbound = it->second;
# 2005 : 0 : }
# 2006 : 2 : } else {
# 2007 : 1 : // strAddNode is a name
# 2008 : 1 : auto it = mapConnectedByName.find(strAddNode);
# 2009 : 1 : if (it != mapConnectedByName.end()) {
# 2010 : 0 : addedNode.resolvedAddress = it->second.second;
# 2011 : 0 : addedNode.fConnected = true;
# 2012 : 0 : addedNode.fInbound = it->second.first;
# 2013 : 0 : }
# 2014 : 1 : }
# 2015 : 3 : ret.emplace_back(std::move(addedNode));
# 2016 : 3 : }
# 2017 : 2670 :
# 2018 : 2670 : return ret;
# 2019 : 2670 : }
# 2020 : :
# 2021 : : void CConnman::ThreadOpenAddedConnections()
# 2022 : 494 : {
# 2023 : 2667 : while (true)
# 2024 : 2667 : {
# 2025 : 2667 : CSemaphoreGrant grant(*semAddnode);
# 2026 : 2667 : std::vector<AddedNodeInfo> vInfo = GetAddedNodeInfo();
# 2027 : 2667 : bool tried = false;
# 2028 : 2667 : for (const AddedNodeInfo& info : vInfo) {
# 2029 : 1 : if (!info.fConnected) {
# 2030 : 1 : if (!grant.TryAcquire()) {
# 2031 : 0 : // If we've used up our semaphore and need a new one, let's not wait here since while we are waiting
# 2032 : 0 : // the addednodeinfo state might change.
# 2033 : 0 : break;
# 2034 : 0 : }
# 2035 : 1 : tried = true;
# 2036 : 1 : CAddress addr(CService(), NODE_NONE);
# 2037 : 1 : OpenNetworkConnection(addr, false, &grant, info.strAddedNode.c_str(), ConnectionType::MANUAL);
# 2038 : 1 : if (!interruptNet.sleep_for(std::chrono::milliseconds(500)))
# 2039 : 1 : return;
# 2040 : 1 : }
# 2041 : 1 : }
# 2042 : 2667 : // Retry every 60 seconds if a connection was attempted, otherwise two seconds
# 2043 : 2667 : if (!interruptNet.sleep_for(std::chrono::seconds(tried ? 60 : 2)))
# 2044 : 493 : return;
# 2045 : 2666 : }
# 2046 : 494 : }
# 2047 : :
# 2048 : : // if successful, this moves the passed grant to the constructed node
# 2049 : : void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFailure, CSemaphoreGrant *grantOutbound, const char *pszDest, ConnectionType conn_type)
# 2050 : 251 : {
# 2051 : 251 : assert(conn_type != ConnectionType::INBOUND);
# 2052 : 251 :
# 2053 : 251 : //
# 2054 : 251 : // Initiate outbound network connection
# 2055 : 251 : //
# 2056 : 251 : if (interruptNet) {
# 2057 : 0 : return;
# 2058 : 0 : }
# 2059 : 251 : if (!fNetworkActive) {
# 2060 : 0 : return;
# 2061 : 0 : }
# 2062 : 251 : if (!pszDest) {
# 2063 : 2 : bool banned_or_discouraged = m_banman && (m_banman->IsDiscouraged(addrConnect) || m_banman->IsBanned(addrConnect));
# 2064 : 2 : if (IsLocal(addrConnect) || FindNode(static_cast<CNetAddr>(addrConnect)) || banned_or_discouraged || FindNode(addrConnect.ToStringIPPort())) {
# 2065 : 0 : return;
# 2066 : 0 : }
# 2067 : 249 : } else if (FindNode(std::string(pszDest)))
# 2068 : 2 : return;
# 2069 : 249 :
# 2070 : 249 : CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
# 2071 : 249 :
# 2072 : 249 : if (!pnode)
# 2073 : 4 : return;
# 2074 : 245 : if (grantOutbound)
# 2075 : 0 : grantOutbound->MoveTo(pnode->grantOutbound);
# 2076 : 245 :
# 2077 : 245 : m_msgproc->InitializeNode(pnode);
# 2078 : 245 : {
# 2079 : 245 : LOCK(cs_vNodes);
# 2080 : 245 : vNodes.push_back(pnode);
# 2081 : 245 : }
# 2082 : 245 : }
# 2083 : :
# 2084 : : void CConnman::ThreadMessageHandler()
# 2085 : 494 : {
# 2086 : 125595 : while (!flagInterruptMsgProc)
# 2087 : 125103 : {
# 2088 : 125103 : std::vector<CNode*> vNodesCopy;
# 2089 : 125103 : {
# 2090 : 125103 : LOCK(cs_vNodes);
# 2091 : 125103 : vNodesCopy = vNodes;
# 2092 : 192979 : for (CNode* pnode : vNodesCopy) {
# 2093 : 192979 : pnode->AddRef();
# 2094 : 192979 : }
# 2095 : 125103 : }
# 2096 : 125103 :
# 2097 : 125103 : bool fMoreWork = false;
# 2098 : 125103 :
# 2099 : 125103 : for (CNode* pnode : vNodesCopy)
# 2100 : 192978 : {
# 2101 : 192978 : if (pnode->fDisconnect)
# 2102 : 22 : continue;
# 2103 : 192956 :
# 2104 : 192956 : // Receive messages
# 2105 : 192956 : bool fMoreNodeWork = m_msgproc->ProcessMessages(pnode, flagInterruptMsgProc);
# 2106 : 192956 : fMoreWork |= (fMoreNodeWork && !pnode->fPauseSend);
# 2107 : 192956 : if (flagInterruptMsgProc)
# 2108 : 0 : return;
# 2109 : 192956 : // Send messages
# 2110 : 192956 : {
# 2111 : 192956 : LOCK(pnode->cs_sendProcessing);
# 2112 : 192956 : m_msgproc->SendMessages(pnode);
# 2113 : 192956 : }
# 2114 : 192956 :
# 2115 : 192956 : if (flagInterruptMsgProc)
# 2116 : 2 : return;
# 2117 : 192956 : }
# 2118 : 125103 :
# 2119 : 125103 : {
# 2120 : 125101 : LOCK(cs_vNodes);
# 2121 : 125101 : for (CNode* pnode : vNodesCopy)
# 2122 : 192976 : pnode->Release();
# 2123 : 125101 : }
# 2124 : 125101 :
# 2125 : 125101 : WAIT_LOCK(mutexMsgProc, lock);
# 2126 : 125101 : if (!fMoreWork) {
# 2127 : 169358 : condMsgProc.wait_until(lock, std::chrono::steady_clock::now() + std::chrono::milliseconds(100), [this]() EXCLUSIVE_LOCKS_REQUIRED(mutexMsgProc) { return fMsgProcWake; });
# 2128 : 91869 : }
# 2129 : 125101 : fMsgProcWake = false;
# 2130 : 125101 : }
# 2131 : 494 : }
# 2132 : :
# 2133 : : bool CConnman::BindListenPort(const CService& addrBind, bilingual_str& strError, NetPermissionFlags permissions)
# 2134 : 495 : {
# 2135 : 495 : int nOne = 1;
# 2136 : 495 :
# 2137 : 495 : // Create socket for listening for incoming connections
# 2138 : 495 : struct sockaddr_storage sockaddr;
# 2139 : 495 : socklen_t len = sizeof(sockaddr);
# 2140 : 495 : if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len))
# 2141 : 0 : {
# 2142 : 0 : strError = strprintf(Untranslated("Error: Bind address family for %s not supported"), addrBind.ToString());
# 2143 : 0 : LogPrintf("%s\n", strError.original);
# 2144 : 0 : return false;
# 2145 : 0 : }
# 2146 : 495 :
# 2147 : 495 : SOCKET hListenSocket = CreateSocket(addrBind);
# 2148 : 495 : if (hListenSocket == INVALID_SOCKET)
# 2149 : 495 : {
# 2150 : 0 : strError = strprintf(Untranslated("Error: Couldn't open socket for incoming connections (socket returned error %s)"), NetworkErrorString(WSAGetLastError()));
# 2151 : 0 : LogPrintf("%s\n", strError.original);
# 2152 : 0 : return false;
# 2153 : 0 : }
# 2154 : 495 :
# 2155 : 495 : // Allow binding if the port is still in TIME_WAIT state after
# 2156 : 495 : // the program was closed and restarted.
# 2157 : 495 : setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (sockopt_arg_type)&nOne, sizeof(int));
# 2158 : 495 :
# 2159 : 495 : // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option
# 2160 : 495 : // and enable it by default or not. Try to enable it, if possible.
# 2161 : 495 : if (addrBind.IsIPv6()) {
# 2162 : 1 : #ifdef IPV6_V6ONLY
# 2163 : 1 : setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (sockopt_arg_type)&nOne, sizeof(int));
# 2164 : 1 : #endif
# 2165 : : #ifdef WIN32
# 2166 : : int nProtLevel = PROTECTION_LEVEL_UNRESTRICTED;
# 2167 : : setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_PROTECTION_LEVEL, (const char*)&nProtLevel, sizeof(int));
# 2168 : : #endif
# 2169 : : }
# 2170 : 495 :
# 2171 : 495 : if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR)
# 2172 : 495 : {
# 2173 : 0 : int nErr = WSAGetLastError();
# 2174 : 0 : if (nErr == WSAEADDRINUSE)
# 2175 : 0 : strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
# 2176 : 0 : else
# 2177 : 0 : strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
# 2178 : 0 : LogPrintf("%s\n", strError.original);
# 2179 : 0 : CloseSocket(hListenSocket);
# 2180 : 0 : return false;
# 2181 : 0 : }
# 2182 : 495 : LogPrintf("Bound to %s\n", addrBind.ToString());
# 2183 : 495 :
# 2184 : 495 : // Listen for incoming connections
# 2185 : 495 : if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
# 2186 : 495 : {
# 2187 : 0 : strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
# 2188 : 0 : LogPrintf("%s\n", strError.original);
# 2189 : 0 : CloseSocket(hListenSocket);
# 2190 : 0 : return false;
# 2191 : 0 : }
# 2192 : 495 :
# 2193 : 495 : vhListenSocket.push_back(ListenSocket(hListenSocket, permissions));
# 2194 : 495 :
# 2195 : 495 : if (addrBind.IsRoutable() && fDiscover && (permissions & PF_NOBAN) == 0)
# 2196 : 0 : AddLocal(addrBind, LOCAL_BIND);
# 2197 : 495 :
# 2198 : 495 : return true;
# 2199 : 495 : }
# 2200 : :
# 2201 : : void Discover()
# 2202 : 497 : {
# 2203 : 497 : if (!fDiscover)
# 2204 : 497 : return;
# 2205 : 0 :
# 2206 : : #ifdef WIN32
# 2207 : : // Get local host IP
# 2208 : : char pszHostName[256] = "";
# 2209 : : if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
# 2210 : : {
# 2211 : : std::vector<CNetAddr> vaddr;
# 2212 : : if (LookupHost(pszHostName, vaddr, 0, true))
# 2213 : : {
# 2214 : : for (const CNetAddr &addr : vaddr)
# 2215 : : {
# 2216 : : if (AddLocal(addr, LOCAL_IF))
# 2217 : : LogPrintf("%s: %s - %s\n", __func__, pszHostName, addr.ToString());
# 2218 : : }
# 2219 : : }
# 2220 : : }
# 2221 : : #elif (HAVE_DECL_GETIFADDRS && HAVE_DECL_FREEIFADDRS)
# 2222 : : // Get local host ip
# 2223 : 0 : struct ifaddrs* myaddrs;
# 2224 : 0 : if (getifaddrs(&myaddrs) == 0)
# 2225 : 0 : {
# 2226 : 0 : for (struct ifaddrs* ifa = myaddrs; ifa != nullptr; ifa = ifa->ifa_next)
# 2227 : 0 : {
# 2228 : 0 : if (ifa->ifa_addr == nullptr) continue;
# 2229 : 0 : if ((ifa->ifa_flags & IFF_UP) == 0) continue;
# 2230 : 0 : if (strcmp(ifa->ifa_name, "lo") == 0) continue;
# 2231 : 0 : if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
# 2232 : 0 : if (ifa->ifa_addr->sa_family == AF_INET)
# 2233 : 0 : {
# 2234 : 0 : struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
# 2235 : 0 : CNetAddr addr(s4->sin_addr);
# 2236 : 0 : if (AddLocal(addr, LOCAL_IF))
# 2237 : 0 : LogPrintf("%s: IPv4 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
# 2238 : 0 : }
# 2239 : 0 : else if (ifa->ifa_addr->sa_family == AF_INET6)
# 2240 : 0 : {
# 2241 : 0 : struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
# 2242 : 0 : CNetAddr addr(s6->sin6_addr);
# 2243 : 0 : if (AddLocal(addr, LOCAL_IF))
# 2244 : 0 : LogPrintf("%s: IPv6 %s: %s\n", __func__, ifa->ifa_name, addr.ToString());
# 2245 : 0 : }
# 2246 : 0 : }
# 2247 : 0 : freeifaddrs(myaddrs);
# 2248 : 0 : }
# 2249 : 0 : #endif
# 2250 : 0 : }
# 2251 : :
# 2252 : : void CConnman::SetNetworkActive(bool active)
# 2253 : 672 : {
# 2254 : 672 : LogPrintf("%s: %s\n", __func__, active);
# 2255 : 672 :
# 2256 : 672 : if (fNetworkActive == active) {
# 2257 : 662 : return;
# 2258 : 662 : }
# 2259 : 10 :
# 2260 : 10 : fNetworkActive = active;
# 2261 : 10 :
# 2262 : 10 : uiInterface.NotifyNetworkActiveChanged(fNetworkActive);
# 2263 : 10 : }
# 2264 : :
# 2265 : : CConnman::CConnman(uint64_t nSeed0In, uint64_t nSeed1In, bool network_active)
# 2266 : : : nSeed0(nSeed0In), nSeed1(nSeed1In)
# 2267 : 665 : {
# 2268 : 665 : SetTryNewOutboundPeer(false);
# 2269 : 665 :
# 2270 : 665 : Options connOptions;
# 2271 : 665 : Init(connOptions);
# 2272 : 665 : SetNetworkActive(network_active);
# 2273 : 665 : }
# 2274 : :
# 2275 : : NodeId CConnman::GetNewNodeId()
# 2276 : 698 : {
# 2277 : 698 : return nLastNodeId.fetch_add(1, std::memory_order_relaxed);
# 2278 : 698 : }
# 2279 : :
# 2280 : :
# 2281 : 495 : bool CConnman::Bind(const CService &addr, unsigned int flags, NetPermissionFlags permissions) {
# 2282 : 495 : if (!(flags & BF_EXPLICIT) && !IsReachable(addr))
# 2283 : 0 : return false;
# 2284 : 495 : bilingual_str strError;
# 2285 : 495 : if (!BindListenPort(addr, strError, permissions)) {
# 2286 : 0 : if ((flags & BF_REPORT_ERROR) && clientInterface) {
# 2287 : 0 : clientInterface->ThreadSafeMessageBox(strError, "", CClientUIInterface::MSG_ERROR);
# 2288 : 0 : }
# 2289 : 0 : return false;
# 2290 : 0 : }
# 2291 : 495 : return true;
# 2292 : 495 : }
# 2293 : :
# 2294 : : bool CConnman::InitBinds(const std::vector<CService>& binds, const std::vector<NetWhitebindPermissions>& whiteBinds)
# 2295 : 494 : {
# 2296 : 494 : bool fBound = false;
# 2297 : 494 : for (const auto& addrBind : binds) {
# 2298 : 492 : fBound |= Bind(addrBind, (BF_EXPLICIT | BF_REPORT_ERROR), NetPermissionFlags::PF_NONE);
# 2299 : 492 : }
# 2300 : 494 : for (const auto& addrBind : whiteBinds) {
# 2301 : 1 : fBound |= Bind(addrBind.m_service, (BF_EXPLICIT | BF_REPORT_ERROR), addrBind.m_flags);
# 2302 : 1 : }
# 2303 : 494 : if (binds.empty() && whiteBinds.empty()) {
# 2304 : 1 : struct in_addr inaddr_any;
# 2305 : 1 : inaddr_any.s_addr = INADDR_ANY;
# 2306 : 1 : struct in6_addr inaddr6_any = IN6ADDR_ANY_INIT;
# 2307 : 1 : fBound |= Bind(CService(inaddr6_any, GetListenPort()), BF_NONE, NetPermissionFlags::PF_NONE);
# 2308 : 1 : fBound |= Bind(CService(inaddr_any, GetListenPort()), !fBound ? BF_REPORT_ERROR : BF_NONE, NetPermissionFlags::PF_NONE);
# 2309 : 1 : }
# 2310 : 494 : return fBound;
# 2311 : 494 : }
# 2312 : :
# 2313 : : bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
# 2314 : 494 : {
# 2315 : 494 : Init(connOptions);
# 2316 : 494 :
# 2317 : 494 : {
# 2318 : 494 : LOCK(cs_totalBytesRecv);
# 2319 : 494 : nTotalBytesRecv = 0;
# 2320 : 494 : }
# 2321 : 494 : {
# 2322 : 494 : LOCK(cs_totalBytesSent);
# 2323 : 494 : nTotalBytesSent = 0;
# 2324 : 494 : nMaxOutboundTotalBytesSentInCycle = 0;
# 2325 : 494 : nMaxOutboundCycleStartTime = 0;
# 2326 : 494 : }
# 2327 : 494 :
# 2328 : 494 : if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) {
# 2329 : 0 : if (clientInterface) {
# 2330 : 0 : clientInterface->ThreadSafeMessageBox(
# 2331 : 0 : _("Failed to listen on any port. Use -listen=0 if you want this."),
# 2332 : 0 : "", CClientUIInterface::MSG_ERROR);
# 2333 : 0 : }
# 2334 : 0 : return false;
# 2335 : 0 : }
# 2336 : 494 :
# 2337 : 494 : for (const auto& strDest : connOptions.vSeedNodes) {
# 2338 : 0 : AddAddrFetch(strDest);
# 2339 : 0 : }
# 2340 : 494 :
# 2341 : 494 : if (clientInterface) {
# 2342 : 494 : clientInterface->InitMessage(_("Loading P2P addresses...").translated);
# 2343 : 494 : }
# 2344 : 494 : // Load addresses from peers.dat
# 2345 : 494 : int64_t nStart = GetTimeMillis();
# 2346 : 494 : {
# 2347 : 494 : CAddrDB adb;
# 2348 : 494 : if (adb.Read(addrman))
# 2349 : 197 : LogPrintf("Loaded %i addresses from peers.dat %dms\n", addrman.size(), GetTimeMillis() - nStart);
# 2350 : 297 : else {
# 2351 : 297 : addrman.Clear(); // Addrman can be in an inconsistent state after failure, reset it
# 2352 : 297 : LogPrintf("Invalid or missing peers.dat; recreating\n");
# 2353 : 297 : DumpAddresses();
# 2354 : 297 : }
# 2355 : 494 : }
# 2356 : 494 :
# 2357 : 494 : uiInterface.InitMessage(_("Starting network threads...").translated);
# 2358 : 494 :
# 2359 : 494 : fAddressesInitialized = true;
# 2360 : 494 :
# 2361 : 494 : if (semOutbound == nullptr) {
# 2362 : 494 : // initialize semaphore
# 2363 : 494 : semOutbound = MakeUnique<CSemaphore>(std::min(m_max_outbound, nMaxConnections));
# 2364 : 494 : }
# 2365 : 494 : if (semAddnode == nullptr) {
# 2366 : 494 : // initialize semaphore
# 2367 : 494 : semAddnode = MakeUnique<CSemaphore>(nMaxAddnode);
# 2368 : 494 : }
# 2369 : 494 :
# 2370 : 494 : //
# 2371 : 494 : // Start threads
# 2372 : 494 : //
# 2373 : 494 : assert(m_msgproc);
# 2374 : 494 : InterruptSocks5(false);
# 2375 : 494 : interruptNet.reset();
# 2376 : 494 : flagInterruptMsgProc = false;
# 2377 : 494 :
# 2378 : 494 : {
# 2379 : 494 : LOCK(mutexMsgProc);
# 2380 : 494 : fMsgProcWake = false;
# 2381 : 494 : }
# 2382 : 494 :
# 2383 : 494 : // Send and receive from sockets, accept connections
# 2384 : 494 : threadSocketHandler = std::thread(&TraceThread<std::function<void()> >, "net", std::function<void()>(std::bind(&CConnman::ThreadSocketHandler, this)));
# 2385 : 494 :
# 2386 : 494 : if (!gArgs.GetBoolArg("-dnsseed", true))
# 2387 : 494 : LogPrintf("DNS seeding disabled\n");
# 2388 : 0 : else
# 2389 : 0 : threadDNSAddressSeed = std::thread(&TraceThread<std::function<void()> >, "dnsseed", std::function<void()>(std::bind(&CConnman::ThreadDNSAddressSeed, this)));
# 2390 : 494 :
# 2391 : 494 : // Initiate manual connections
# 2392 : 494 : threadOpenAddedConnections = std::thread(&TraceThread<std::function<void()> >, "addcon", std::function<void()>(std::bind(&CConnman::ThreadOpenAddedConnections, this)));
# 2393 : 494 :
# 2394 : 494 : if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
# 2395 : 0 : if (clientInterface) {
# 2396 : 0 : clientInterface->ThreadSafeMessageBox(
# 2397 : 0 : _("Cannot provide specific connections and have addrman find outgoing connections at the same."),
# 2398 : 0 : "", CClientUIInterface::MSG_ERROR);
# 2399 : 0 : }
# 2400 : 0 : return false;
# 2401 : 0 : }
# 2402 : 494 : if (connOptions.m_use_addrman_outgoing || !connOptions.m_specified_outgoing.empty())
# 2403 : 494 : threadOpenConnections = std::thread(&TraceThread<std::function<void()> >, "opencon", std::function<void()>(std::bind(&CConnman::ThreadOpenConnections, this, connOptions.m_specified_outgoing)));
# 2404 : 494 :
# 2405 : 494 : // Process messages
# 2406 : 494 : threadMessageHandler = std::thread(&TraceThread<std::function<void()> >, "msghand", std::function<void()>(std::bind(&CConnman::ThreadMessageHandler, this)));
# 2407 : 494 :
# 2408 : 494 : // Dump network addresses
# 2409 : 494 : scheduler.scheduleEvery([this] { DumpAddresses(); }, DUMP_PEERS_INTERVAL);
# 2410 : 494 :
# 2411 : 494 : return true;
# 2412 : 494 : }
# 2413 : :
# 2414 : : class CNetCleanup
# 2415 : : {
# 2416 : : public:
# 2417 : 559 : CNetCleanup() {}
# 2418 : :
# 2419 : : ~CNetCleanup()
# 2420 : 0 : {
# 2421 : : #ifdef WIN32
# 2422 : : // Shutdown Windows Sockets
# 2423 : : WSACleanup();
# 2424 : : #endif
# 2425 : : }
# 2426 : : };
# 2427 : : static CNetCleanup instance_of_cnetcleanup;
# 2428 : :
# 2429 : : void CConnman::Interrupt()
# 2430 : 1174 : {
# 2431 : 1174 : {
# 2432 : 1174 : LOCK(mutexMsgProc);
# 2433 : 1174 : flagInterruptMsgProc = true;
# 2434 : 1174 : }
# 2435 : 1174 : condMsgProc.notify_all();
# 2436 : 1174 :
# 2437 : 1174 : interruptNet();
# 2438 : 1174 : InterruptSocks5(true);
# 2439 : 1174 :
# 2440 : 1174 : if (semOutbound) {
# 2441 : 5928 : for (int i=0; i<m_max_outbound; i++) {
# 2442 : 5434 : semOutbound->post();
# 2443 : 5434 : }
# 2444 : 494 : }
# 2445 : 1174 :
# 2446 : 1174 : if (semAddnode) {
# 2447 : 4446 : for (int i=0; i<nMaxAddnode; i++) {
# 2448 : 3952 : semAddnode->post();
# 2449 : 3952 : }
# 2450 : 494 : }
# 2451 : 1174 : }
# 2452 : :
# 2453 : : void CConnman::StopThreads()
# 2454 : 1174 : {
# 2455 : 1174 : if (threadMessageHandler.joinable())
# 2456 : 494 : threadMessageHandler.join();
# 2457 : 1174 : if (threadOpenConnections.joinable())
# 2458 : 494 : threadOpenConnections.join();
# 2459 : 1174 : if (threadOpenAddedConnections.joinable())
# 2460 : 494 : threadOpenAddedConnections.join();
# 2461 : 1174 : if (threadDNSAddressSeed.joinable())
# 2462 : 0 : threadDNSAddressSeed.join();
# 2463 : 1174 : if (threadSocketHandler.joinable())
# 2464 : 494 : threadSocketHandler.join();
# 2465 : 1174 : }
# 2466 : :
# 2467 : : void CConnman::StopNodes()
# 2468 : 1174 : {
# 2469 : 1174 : if (fAddressesInitialized) {
# 2470 : 494 : DumpAddresses();
# 2471 : 494 : fAddressesInitialized = false;
# 2472 : 494 : }
# 2473 : 1174 :
# 2474 : 1174 : // Close sockets
# 2475 : 1174 : LOCK(cs_vNodes);
# 2476 : 1174 : for (CNode* pnode : vNodes)
# 2477 : 363 : pnode->CloseSocketDisconnect();
# 2478 : 1174 : for (ListenSocket& hListenSocket : vhListenSocket)
# 2479 : 495 : if (hListenSocket.socket != INVALID_SOCKET)
# 2480 : 495 : if (!CloseSocket(hListenSocket.socket))
# 2481 : 0 : LogPrintf("CloseSocket(hListenSocket) failed with error %s\n", NetworkErrorString(WSAGetLastError()));
# 2482 : 1174 :
# 2483 : 1174 : // clean up some globals (to help leak detection)
# 2484 : 1174 : for (CNode* pnode : vNodes) {
# 2485 : 363 : DeleteNode(pnode);
# 2486 : 363 : }
# 2487 : 1174 : for (CNode* pnode : vNodesDisconnected) {
# 2488 : 0 : DeleteNode(pnode);
# 2489 : 0 : }
# 2490 : 1174 : vNodes.clear();
# 2491 : 1174 : vNodesDisconnected.clear();
# 2492 : 1174 : vhListenSocket.clear();
# 2493 : 1174 : semOutbound.reset();
# 2494 : 1174 : semAddnode.reset();
# 2495 : 1174 : }
# 2496 : :
# 2497 : : void CConnman::DeleteNode(CNode* pnode)
# 2498 : 698 : {
# 2499 : 698 : assert(pnode);
# 2500 : 698 : bool fUpdateConnectionTime = false;
# 2501 : 698 : m_msgproc->FinalizeNode(pnode->GetId(), fUpdateConnectionTime);
# 2502 : 698 : if (fUpdateConnectionTime) {
# 2503 : 234 : addrman.Connected(pnode->addr);
# 2504 : 234 : }
# 2505 : 698 : delete pnode;
# 2506 : 698 : }
# 2507 : :
# 2508 : : CConnman::~CConnman()
# 2509 : 665 : {
# 2510 : 665 : Interrupt();
# 2511 : 665 : Stop();
# 2512 : 665 : }
# 2513 : :
# 2514 : : void CConnman::SetServices(const CService &addr, ServiceFlags nServices)
# 2515 : 235 : {
# 2516 : 235 : addrman.SetServices(addr, nServices);
# 2517 : 235 : }
# 2518 : :
# 2519 : : void CConnman::MarkAddressGood(const CAddress& addr)
# 2520 : 235 : {
# 2521 : 235 : addrman.Good(addr);
# 2522 : 235 : }
# 2523 : :
# 2524 : : void CConnman::AddNewAddresses(const std::vector<CAddress>& vAddr, const CAddress& addrFrom, int64_t nTimePenalty)
# 2525 : 4 : {
# 2526 : 4 : addrman.Add(vAddr, addrFrom, nTimePenalty);
# 2527 : 4 : }
# 2528 : :
# 2529 : : std::vector<CAddress> CConnman::GetAddresses()
# 2530 : 237 : {
# 2531 : 237 : return addrman.GetAddr();
# 2532 : 237 : }
# 2533 : :
# 2534 : : bool CConnman::AddNode(const std::string& strNode)
# 2535 : 1 : {
# 2536 : 1 : LOCK(cs_vAddedNodes);
# 2537 : 1 : for (const std::string& it : vAddedNodes) {
# 2538 : 0 : if (strNode == it) return false;
# 2539 : 0 : }
# 2540 : 1 :
# 2541 : 1 : vAddedNodes.push_back(strNode);
# 2542 : 1 : return true;
# 2543 : 1 : }
# 2544 : :
# 2545 : : bool CConnman::RemoveAddedNode(const std::string& strNode)
# 2546 : 0 : {
# 2547 : 0 : LOCK(cs_vAddedNodes);
# 2548 : 0 : for(std::vector<std::string>::iterator it = vAddedNodes.begin(); it != vAddedNodes.end(); ++it) {
# 2549 : 0 : if (strNode == *it) {
# 2550 : 0 : vAddedNodes.erase(it);
# 2551 : 0 : return true;
# 2552 : 0 : }
# 2553 : 0 : }
# 2554 : 0 : return false;
# 2555 : 0 : }
# 2556 : :
# 2557 : : size_t CConnman::GetNodeCount(NumConnections flags)
# 2558 : 69 : {
# 2559 : 69 : LOCK(cs_vNodes);
# 2560 : 69 : if (flags == CConnman::CONNECTIONS_ALL) // Shortcut if we want total
# 2561 : 69 : return vNodes.size();
# 2562 : 0 :
# 2563 : 0 : int nNum = 0;
# 2564 : 0 : for (const auto& pnode : vNodes) {
# 2565 : 0 : if (flags & (pnode->IsInboundConn() ? CONNECTIONS_IN : CONNECTIONS_OUT)) {
# 2566 : 0 : nNum++;
# 2567 : 0 : }
# 2568 : 0 : }
# 2569 : 0 :
# 2570 : 0 : return nNum;
# 2571 : 0 : }
# 2572 : :
# 2573 : : void CConnman::GetNodeStats(std::vector<CNodeStats>& vstats)
# 2574 : 3085 : {
# 2575 : 3085 : vstats.clear();
# 2576 : 3085 : LOCK(cs_vNodes);
# 2577 : 3085 : vstats.reserve(vNodes.size());
# 2578 : 5306 : for (CNode* pnode : vNodes) {
# 2579 : 5306 : vstats.emplace_back();
# 2580 : 5306 : pnode->copyStats(vstats.back(), addrman.m_asmap);
# 2581 : 5306 : }
# 2582 : 3085 : }
# 2583 : :
# 2584 : : bool CConnman::DisconnectNode(const std::string& strNode)
# 2585 : 2 : {
# 2586 : 2 : LOCK(cs_vNodes);
# 2587 : 2 : if (CNode* pnode = FindNode(strNode)) {
# 2588 : 1 : pnode->fDisconnect = true;
# 2589 : 1 : return true;
# 2590 : 1 : }
# 2591 : 1 : return false;
# 2592 : 1 : }
# 2593 : :
# 2594 : : bool CConnman::DisconnectNode(const CSubNet& subnet)
# 2595 : 27 : {
# 2596 : 27 : bool disconnected = false;
# 2597 : 27 : LOCK(cs_vNodes);
# 2598 : 27 : for (CNode* pnode : vNodes) {
# 2599 : 4 : if (subnet.Match(pnode->addr)) {
# 2600 : 4 : pnode->fDisconnect = true;
# 2601 : 4 : disconnected = true;
# 2602 : 4 : }
# 2603 : 4 : }
# 2604 : 27 : return disconnected;
# 2605 : 27 : }
# 2606 : :
# 2607 : : bool CConnman::DisconnectNode(const CNetAddr& addr)
# 2608 : 13 : {
# 2609 : 13 : return DisconnectNode(CSubNet(addr));
# 2610 : 13 : }
# 2611 : :
# 2612 : : bool CConnman::DisconnectNode(NodeId id)
# 2613 : 25 : {
# 2614 : 25 : LOCK(cs_vNodes);
# 2615 : 37 : for(CNode* pnode : vNodes) {
# 2616 : 37 : if (id == pnode->GetId()) {
# 2617 : 25 : pnode->fDisconnect = true;
# 2618 : 25 : return true;
# 2619 : 25 : }
# 2620 : 37 : }
# 2621 : 25 : return false;
# 2622 : 25 : }
# 2623 : :
# 2624 : : void CConnman::RecordBytesRecv(uint64_t bytes)
# 2625 : 101691 : {
# 2626 : 101691 : LOCK(cs_totalBytesRecv);
# 2627 : 101691 : nTotalBytesRecv += bytes;
# 2628 : 101691 : }
# 2629 : :
# 2630 : : void CConnman::RecordBytesSent(uint64_t bytes)
# 2631 : 87821 : {
# 2632 : 87821 : LOCK(cs_totalBytesSent);
# 2633 : 87821 : nTotalBytesSent += bytes;
# 2634 : 87821 :
# 2635 : 87821 : uint64_t now = GetTime();
# 2636 : 87821 : if (nMaxOutboundCycleStartTime + nMaxOutboundTimeframe < now)
# 2637 : 298 : {
# 2638 : 298 : // timeframe expired, reset cycle
# 2639 : 298 : nMaxOutboundCycleStartTime = now;
# 2640 : 298 : nMaxOutboundTotalBytesSentInCycle = 0;
# 2641 : 298 : }
# 2642 : 87821 :
# 2643 : 87821 : // TODO, exclude peers with download permission
# 2644 : 87821 : nMaxOutboundTotalBytesSentInCycle += bytes;
# 2645 : 87821 : }
# 2646 : :
# 2647 : : void CConnman::SetMaxOutboundTarget(uint64_t limit)
# 2648 : 0 : {
# 2649 : 0 : LOCK(cs_totalBytesSent);
# 2650 : 0 : nMaxOutboundLimit = limit;
# 2651 : 0 : }
# 2652 : :
# 2653 : : uint64_t CConnman::GetMaxOutboundTarget()
# 2654 : 8 : {
# 2655 : 8 : LOCK(cs_totalBytesSent);
# 2656 : 8 : return nMaxOutboundLimit;
# 2657 : 8 : }
# 2658 : :
# 2659 : : uint64_t CConnman::GetMaxOutboundTimeframe()
# 2660 : 8 : {
# 2661 : 8 : LOCK(cs_totalBytesSent);
# 2662 : 8 : return nMaxOutboundTimeframe;
# 2663 : 8 : }
# 2664 : :
# 2665 : : uint64_t CConnman::GetMaxOutboundTimeLeftInCycle()
# 2666 : 1110 : {
# 2667 : 1110 : LOCK(cs_totalBytesSent);
# 2668 : 1110 : if (nMaxOutboundLimit == 0)
# 2669 : 8 : return 0;
# 2670 : 1102 :
# 2671 : 1102 : if (nMaxOutboundCycleStartTime == 0)
# 2672 : 0 : return nMaxOutboundTimeframe;
# 2673 : 1102 :
# 2674 : 1102 : uint64_t cycleEndTime = nMaxOutboundCycleStartTime + nMaxOutboundTimeframe;
# 2675 : 1102 : uint64_t now = GetTime();
# 2676 : 1102 : return (cycleEndTime < now) ? 0 : cycleEndTime - GetTime();
# 2677 : 1102 : }
# 2678 : :
# 2679 : : void CConnman::SetMaxOutboundTimeframe(uint64_t timeframe)
# 2680 : 0 : {
# 2681 : 0 : LOCK(cs_totalBytesSent);
# 2682 : 0 : if (nMaxOutboundTimeframe != timeframe)
# 2683 : 0 : {
# 2684 : 0 : // reset measure-cycle in case of changing
# 2685 : 0 : // the timeframe
# 2686 : 0 : nMaxOutboundCycleStartTime = GetTime();
# 2687 : 0 : }
# 2688 : 0 : nMaxOutboundTimeframe = timeframe;
# 2689 : 0 : }
# 2690 : :
# 2691 : : bool CConnman::OutboundTargetReached(bool historicalBlockServingLimit)
# 2692 : 15664 : {
# 2693 : 15664 : LOCK(cs_totalBytesSent);
# 2694 : 15664 : if (nMaxOutboundLimit == 0)
# 2695 : 14562 : return false;
# 2696 : 1102 :
# 2697 : 1102 : if (historicalBlockServingLimit)
# 2698 : 1102 : {
# 2699 : 1102 : // keep a large enough buffer to at least relay each block once
# 2700 : 1102 : uint64_t timeLeftInCycle = GetMaxOutboundTimeLeftInCycle();
# 2701 : 1102 : uint64_t buffer = timeLeftInCycle / 600 * MAX_BLOCK_SERIALIZED_SIZE;
# 2702 : 1102 : if (buffer >= nMaxOutboundLimit || nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit - buffer)
# 2703 : 823 : return true;
# 2704 : 0 : }
# 2705 : 0 : else if (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit)
# 2706 : 0 : return true;
# 2707 : 279 :
# 2708 : 279 : return false;
# 2709 : 279 : }
# 2710 : :
# 2711 : : uint64_t CConnman::GetOutboundTargetBytesLeft()
# 2712 : 8 : {
# 2713 : 8 : LOCK(cs_totalBytesSent);
# 2714 : 8 : if (nMaxOutboundLimit == 0)
# 2715 : 8 : return 0;
# 2716 : 0 :
# 2717 : 0 : return (nMaxOutboundTotalBytesSentInCycle >= nMaxOutboundLimit) ? 0 : nMaxOutboundLimit - nMaxOutboundTotalBytesSentInCycle;
# 2718 : 0 : }
# 2719 : :
# 2720 : : uint64_t CConnman::GetTotalBytesRecv()
# 2721 : 8 : {
# 2722 : 8 : LOCK(cs_totalBytesRecv);
# 2723 : 8 : return nTotalBytesRecv;
# 2724 : 8 : }
# 2725 : :
# 2726 : : uint64_t CConnman::GetTotalBytesSent()
# 2727 : 8 : {
# 2728 : 8 : LOCK(cs_totalBytesSent);
# 2729 : 8 : return nTotalBytesSent;
# 2730 : 8 : }
# 2731 : :
# 2732 : : ServiceFlags CConnman::GetLocalServices() const
# 2733 : 47 : {
# 2734 : 47 : return nLocalServices;
# 2735 : 47 : }
# 2736 : :
# 2737 : : void CConnman::SetBestHeight(int height)
# 2738 : 38849 : {
# 2739 : 38849 : nBestHeight.store(height, std::memory_order_release);
# 2740 : 38849 : }
# 2741 : :
# 2742 : : int CConnman::GetBestHeight() const
# 2743 : 698 : {
# 2744 : 698 : return nBestHeight.load(std::memory_order_acquire);
# 2745 : 698 : }
# 2746 : :
# 2747 : 79087 : unsigned int CConnman::GetReceiveFloodSize() const { return nReceiveFloodSize; }
# 2748 : :
# 2749 : : CNode::CNode(NodeId idIn, ServiceFlags nLocalServicesIn, int nMyStartingHeightIn, SOCKET hSocketIn, const CAddress& addrIn, uint64_t nKeyedNetGroupIn, uint64_t nLocalHostNonceIn, const CAddress& addrBindIn, const std::string& addrNameIn, ConnectionType conn_type_in)
# 2750 : : : nTimeConnected(GetSystemTimeInSeconds()),
# 2751 : : addr(addrIn),
# 2752 : : addrBind(addrBindIn),
# 2753 : : nKeyedNetGroup(nKeyedNetGroupIn),
# 2754 : : // Don't relay addr messages to peers that we connect to as block-relay-only
# 2755 : : // peers (to prevent adversaries from inferring these links from addr
# 2756 : : // traffic).
# 2757 : : id(idIn),
# 2758 : : nLocalHostNonce(nLocalHostNonceIn),
# 2759 : : m_conn_type(conn_type_in),
# 2760 : : nLocalServices(nLocalServicesIn),
# 2761 : : nMyStartingHeight(nMyStartingHeightIn)
# 2762 : 730 : {
# 2763 : 730 : hSocket = hSocketIn;
# 2764 : 730 : addrName = addrNameIn == "" ? addr.ToStringIPPort() : addrNameIn;
# 2765 : 730 : hashContinue = uint256();
# 2766 : 730 : if (conn_type_in != ConnectionType::BLOCK_RELAY) {
# 2767 : 730 : m_tx_relay = MakeUnique<TxRelay>();
# 2768 : 730 : m_addr_known = MakeUnique<CRollingBloomFilter>(5000, 0.001);
# 2769 : 730 : }
# 2770 : 730 :
# 2771 : 730 : for (const std::string &msg : getAllNetMessageTypes())
# 2772 : 23360 : mapRecvBytesPerMsgCmd[msg] = 0;
# 2773 : 730 : mapRecvBytesPerMsgCmd[NET_MESSAGE_COMMAND_OTHER] = 0;
# 2774 : 730 :
# 2775 : 730 : if (fLogIPs) {
# 2776 : 2 : LogPrint(BCLog::NET, "Added connection to %s peer=%d\n", addrName, id);
# 2777 : 728 : } else {
# 2778 : 728 : LogPrint(BCLog::NET, "Added connection peer=%d\n", id);
# 2779 : 728 : }
# 2780 : 730 :
# 2781 : 730 : m_deserializer = MakeUnique<V1TransportDeserializer>(V1TransportDeserializer(Params().MessageStart(), SER_NETWORK, INIT_PROTO_VERSION));
# 2782 : 730 : m_serializer = MakeUnique<V1TransportSerializer>(V1TransportSerializer());
# 2783 : 730 : }
# 2784 : :
# 2785 : : CNode::~CNode()
# 2786 : 730 : {
# 2787 : 730 : CloseSocket(hSocket);
# 2788 : 730 : }
# 2789 : :
# 2790 : : bool CConnman::NodeFullyConnected(const CNode* pnode)
# 2791 : 121816 : {
# 2792 : 121816 : return pnode && pnode->fSuccessfullyConnected && !pnode->fDisconnect;
# 2793 : 121816 : }
# 2794 : :
# 2795 : : void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
# 2796 : 87627 : {
# 2797 : 87627 : size_t nMessageSize = msg.data.size();
# 2798 : 87627 : LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.m_type), nMessageSize, pnode->GetId());
# 2799 : 87627 :
# 2800 : 87627 : // make sure we use the appropriate network transport format
# 2801 : 87627 : std::vector<unsigned char> serializedHeader;
# 2802 : 87627 : pnode->m_serializer->prepareForTransport(msg, serializedHeader);
# 2803 : 87627 : size_t nTotalSize = nMessageSize + serializedHeader.size();
# 2804 : 87627 :
# 2805 : 87627 : size_t nBytesSent = 0;
# 2806 : 87627 : {
# 2807 : 87627 : LOCK(pnode->cs_vSend);
# 2808 : 87627 : bool optimisticSend(pnode->vSendMsg.empty());
# 2809 : 87627 :
# 2810 : 87627 : //log total amount of bytes per message type
# 2811 : 87627 : pnode->mapSendBytesPerMsgCmd[msg.m_type] += nTotalSize;
# 2812 : 87627 : pnode->nSendSize += nTotalSize;
# 2813 : 87627 :
# 2814 : 87627 : if (pnode->nSendSize > nSendBufferMaxSize)
# 2815 : 36 : pnode->fPauseSend = true;
# 2816 : 87627 : pnode->vSendMsg.push_back(std::move(serializedHeader));
# 2817 : 87627 : if (nMessageSize)
# 2818 : 85336 : pnode->vSendMsg.push_back(std::move(msg.data));
# 2819 : 87627 :
# 2820 : 87627 : // If write queue empty, attempt "optimistic write"
# 2821 : 87627 : if (optimisticSend == true)
# 2822 : 87525 : nBytesSent = SocketSendData(pnode);
# 2823 : 87627 : }
# 2824 : 87627 : if (nBytesSent)
# 2825 : 87499 : RecordBytesSent(nBytesSent);
# 2826 : 87627 : }
# 2827 : :
# 2828 : : bool CConnman::ForNode(NodeId id, std::function<bool(CNode* pnode)> func)
# 2829 : 186 : {
# 2830 : 186 : CNode* found = nullptr;
# 2831 : 186 : LOCK(cs_vNodes);
# 2832 : 283 : for (auto&& pnode : vNodes) {
# 2833 : 283 : if(pnode->GetId() == id) {
# 2834 : 184 : found = pnode;
# 2835 : 184 : break;
# 2836 : 184 : }
# 2837 : 283 : }
# 2838 : 186 : return found != nullptr && NodeFullyConnected(found) && func(found);
# 2839 : 186 : }
# 2840 : :
# 2841 : : int64_t CConnman::PoissonNextSendInbound(int64_t now, int average_interval_seconds)
# 2842 : 5445 : {
# 2843 : 5445 : if (m_next_send_inv_to_incoming < now) {
# 2844 : 747 : // If this function were called from multiple threads simultaneously
# 2845 : 747 : // it would possible that both update the next send variable, and return a different result to their caller.
# 2846 : 747 : // This is not possible in practice as only the net processing thread invokes this function.
# 2847 : 747 : m_next_send_inv_to_incoming = PoissonNextSend(now, average_interval_seconds);
# 2848 : 747 : }
# 2849 : 5445 : return m_next_send_inv_to_incoming;
# 2850 : 5445 : }
# 2851 : :
# 2852 : : int64_t PoissonNextSend(int64_t now, int average_interval_seconds)
# 2853 : 5189 : {
# 2854 : 5189 : return now + (int64_t)(log1p(GetRand(1ULL << 48) * -0.0000000000000035527136788 /* -1/2^48 */) * average_interval_seconds * -1000000.0 + 0.5);
# 2855 : 5189 : }
# 2856 : :
# 2857 : : CSipHasher CConnman::GetDeterministicRandomizer(uint64_t id) const
# 2858 : 1406 : {
# 2859 : 1406 : return CSipHasher(nSeed0, nSeed1).Write(id);
# 2860 : 1406 : }
# 2861 : :
# 2862 : : uint64_t CConnman::CalculateKeyedNetGroup(const CAddress& ad) const
# 2863 : 698 : {
# 2864 : 698 : std::vector<unsigned char> vchNetGroup(ad.GetGroup(addrman.m_asmap));
# 2865 : 698 :
# 2866 : 698 : return GetDeterministicRandomizer(RANDOMIZER_ID_NETGROUP).Write(vchNetGroup.data(), vchNetGroup.size()).Finalize();
# 2867 : 698 : }
|