raw
experimental-genesis    1 //  /****************************\
experimental-genesis 2 // * EXPERIMENTAL BRANCH. *
experimental-genesis 3 // * FOR LABORATORY USE ONLY. *
experimental-genesis 4 // ********************************
experimental-genesis 5 // ************
experimental-genesis 6 // **************
experimental-genesis 7 // ****************
experimental-genesis 8 // **** **** ****
experimental-genesis 9 // *** *** ***
experimental-genesis 10 // *** *** ***
experimental-genesis 11 // *** * * **
experimental-genesis 12 // ******** ********
experimental-genesis 13 // ******* ******
experimental-genesis 14 // *** **
experimental-genesis 15 // * ******* **
experimental-genesis 16 // ** * * * * *
experimental-genesis 17 // ** * * ***
experimental-genesis 18 // **** * * * * ****
experimental-genesis 19 // **** *** * * ** ***
experimental-genesis 20 // **** ********* ******
experimental-genesis 21 // ******* ***** *******
experimental-genesis 22 // ********* ****** **
experimental-genesis 23 // ** ****** ******
experimental-genesis 24 // ** ******* **
experimental-genesis 25 // ** ******* ***
experimental-genesis 26 // **** ******** ************
experimental-genesis 27 // ************ ************
experimental-genesis 28 // ******** *******
experimental-genesis 29 // ****** ****
experimental-genesis 30 // *** ***
experimental-genesis 31 // ********************************
experimental-genesis 32 // Copyright (c) 2009-2010 Satoshi Nakamoto
experimental-genesis 33 // Copyright (c) 2009-2012 The Bitcoin developers
experimental-genesis 34 // Distributed under the MIT/X11 software license, see the accompanying
experimental-genesis 35 // file license.txt or http://www.opensource.org/licenses/mit-license.php.
experimental-genesis 36 #ifndef BITCOIN_NET_H
experimental-genesis 37 #define BITCOIN_NET_H
experimental-genesis 38
experimental-genesis 39 #include <deque>
experimental-genesis 40 #include <boost/array.hpp>
experimental-genesis 41 #include <boost/foreach.hpp>
experimental-genesis 42 #include <openssl/rand.h>
experimental-genesis 43
experimental-genesis 44 #ifndef WIN32
experimental-genesis 45 #include <arpa/inet.h>
experimental-genesis 46 #endif
experimental-genesis 47
experimental-genesis 48 #include "protocol.h"
experimental-genesis 49
experimental-genesis 50 class CAddrDB;
experimental-genesis 51 class CRequestTracker;
experimental-genesis 52 class CNode;
experimental-genesis 53 class CBlockIndex;
experimental-genesis 54 extern int nBestHeight;
experimental-genesis 55 extern int nConnectTimeout;
experimental-genesis 56
experimental-genesis 57
experimental-genesis 58
experimental-genesis 59 inline unsigned int ReceiveBufferSize() { return 1000*GetArg("-maxreceivebuffer", 10*1000); }
experimental-genesis 60 inline unsigned int SendBufferSize() { return 1000*GetArg("-maxsendbuffer", 10*1000); }
experimental-genesis 61 static const unsigned int PUBLISH_HOPS = 5;
experimental-genesis 62
experimental-genesis 63 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout=nConnectTimeout);
experimental-genesis 64 bool Lookup(const char *pszName, std::vector<CAddress>& vaddr, int nServices, int nMaxSolutions, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
experimental-genesis 65 bool Lookup(const char *pszName, CAddress& addr, int nServices, bool fAllowLookup = false, int portDefault = 0, bool fAllowPort = false);
experimental-genesis 66 bool GetMyExternalIP(unsigned int& ipRet);
experimental-genesis 67 bool AddAddress(CAddress addr, int64 nTimePenalty=0, CAddrDB *pAddrDB=NULL);
experimental-genesis 68 void AddressCurrentlyConnected(const CAddress& addr);
experimental-genesis 69 CNode* FindNode(unsigned int ip);
experimental-genesis 70 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout=0);
experimental-genesis 71 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1);
experimental-genesis 72 bool AnySubscribed(unsigned int nChannel);
experimental-genesis 73 void MapPort(bool fMapPort);
experimental-genesis 74 bool BindListenPort(std::string& strError=REF(std::string()));
experimental-genesis 75 void StartNode(void* parg);
experimental-genesis 76 bool StopNode();
experimental-genesis 77
experimental-genesis 78 enum
experimental-genesis 79 {
experimental-genesis 80 MSG_TX = 1,
experimental-genesis 81 MSG_BLOCK,
experimental-genesis 82 };
experimental-genesis 83
experimental-genesis 84 class CRequestTracker
experimental-genesis 85 {
experimental-genesis 86 public:
experimental-genesis 87 void (*fn)(void*, CDataStream&);
experimental-genesis 88 void* param1;
experimental-genesis 89
experimental-genesis 90 explicit CRequestTracker(void (*fnIn)(void*, CDataStream&)=NULL, void* param1In=NULL)
experimental-genesis 91 {
experimental-genesis 92 fn = fnIn;
experimental-genesis 93 param1 = param1In;
experimental-genesis 94 }
experimental-genesis 95
experimental-genesis 96 bool IsNull()
experimental-genesis 97 {
experimental-genesis 98 return fn == NULL;
experimental-genesis 99 }
experimental-genesis 100 };
experimental-genesis 101
experimental-genesis 102
experimental-genesis 103
experimental-genesis 104
experimental-genesis 105
experimental-genesis 106 extern bool fClient;
experimental-genesis 107 extern bool fAllowDNS;
experimental-genesis 108 extern uint64 nLocalServices;
experimental-genesis 109 extern CAddress addrLocalHost;
experimental-genesis 110 extern uint64 nLocalHostNonce;
experimental-genesis 111 extern boost::array<int, 10> vnThreadsRunning;
experimental-genesis 112
experimental-genesis 113 extern std::vector<CNode*> vNodes;
experimental-genesis 114 extern CCriticalSection cs_vNodes;
experimental-genesis 115 extern std::map<std::vector<unsigned char>, CAddress> mapAddresses;
experimental-genesis 116 extern CCriticalSection cs_mapAddresses;
experimental-genesis 117 extern std::map<CInv, CDataStream> mapRelay;
experimental-genesis 118 extern std::deque<std::pair<int64, CInv> > vRelayExpiration;
experimental-genesis 119 extern CCriticalSection cs_mapRelay;
experimental-genesis 120 extern std::map<CInv, int64> mapAlreadyAskedFor;
experimental-genesis 121
experimental-genesis 122 // Settings
experimental-genesis 123 extern int fUseProxy;
experimental-genesis 124 extern CAddress addrProxy;
experimental-genesis 125
experimental-genesis 126
experimental-genesis 127
experimental-genesis 128
experimental-genesis 129
experimental-genesis 130
experimental-genesis 131 class CNode
experimental-genesis 132 {
experimental-genesis 133 public:
experimental-genesis 134 // socket
experimental-genesis 135 uint64 nServices;
experimental-genesis 136 SOCKET hSocket;
experimental-genesis 137 CDataStream vSend;
experimental-genesis 138 CDataStream vRecv;
experimental-genesis 139 CCriticalSection cs_vSend;
experimental-genesis 140 CCriticalSection cs_vRecv;
experimental-genesis 141 int64 nLastSend;
experimental-genesis 142 int64 nLastRecv;
experimental-genesis 143 int64 nLastSendEmpty;
experimental-genesis 144 int64 nTimeConnected;
experimental-genesis 145 unsigned int nHeaderStart;
experimental-genesis 146 unsigned int nMessageStart;
experimental-genesis 147 CAddress addr;
experimental-genesis 148 int nVersion;
experimental-genesis 149 std::string strSubVer;
experimental-genesis 150 bool fClient;
experimental-genesis 151 bool fInbound;
experimental-genesis 152 bool fNetworkNode;
experimental-genesis 153 bool fSuccessfullyConnected;
experimental-genesis 154 bool fDisconnect;
experimental-genesis 155 protected:
experimental-genesis 156 int nRefCount;
experimental-genesis 157
experimental-genesis 158 // Denial-of-service detection/prevention
experimental-genesis 159 // Key is ip address, value is banned-until-time
experimental-genesis 160 static std::map<unsigned int, int64> setBanned;
experimental-genesis 161 static CCriticalSection cs_setBanned;
experimental-genesis 162 int nMisbehavior;
experimental-genesis 163
experimental-genesis 164 public:
experimental-genesis 165 int64 nReleaseTime;
experimental-genesis 166 std::map<uint256, CRequestTracker> mapRequests;
experimental-genesis 167 CCriticalSection cs_mapRequests;
experimental-genesis 168 uint256 hashContinue;
experimental-genesis 169 CBlockIndex* pindexLastGetBlocksBegin;
experimental-genesis 170 uint256 hashLastGetBlocksEnd;
experimental-genesis 171 int nStartingHeight;
experimental-genesis 172
experimental-genesis 173 // flood relay
experimental-genesis 174 std::vector<CAddress> vAddrToSend;
experimental-genesis 175 std::set<CAddress> setAddrKnown;
experimental-genesis 176 bool fGetAddr;
experimental-genesis 177 std::set<uint256> setKnown;
experimental-genesis 178
experimental-genesis 179 // inventory based relay
experimental-genesis 180 std::set<CInv> setInventoryKnown;
experimental-genesis 181 std::vector<CInv> vInventoryToSend;
experimental-genesis 182 CCriticalSection cs_inventory;
experimental-genesis 183 std::multimap<int64, CInv> mapAskFor;
experimental-genesis 184
experimental-genesis 185 // publish and subscription
experimental-genesis 186 std::vector<char> vfSubscribe;
experimental-genesis 187
experimental-genesis 188 CNode(SOCKET hSocketIn, CAddress addrIn, bool fInboundIn=false)
experimental-genesis 189 {
experimental-genesis 190 nServices = 0;
experimental-genesis 191 hSocket = hSocketIn;
experimental-genesis 192 vSend.SetType(SER_NETWORK);
experimental-genesis 193 vSend.SetVersion(0);
experimental-genesis 194 vRecv.SetType(SER_NETWORK);
experimental-genesis 195 vRecv.SetVersion(0);
experimental-genesis 196 // Version 0.2 obsoletes 20 Feb 2012
experimental-genesis 197 if (GetTime() > 1329696000)
experimental-genesis 198 {
experimental-genesis 199 vSend.SetVersion(209);
experimental-genesis 200 vRecv.SetVersion(209);
experimental-genesis 201 }
experimental-genesis 202 nLastSend = 0;
experimental-genesis 203 nLastRecv = 0;
experimental-genesis 204 nLastSendEmpty = GetTime();
experimental-genesis 205 nTimeConnected = GetTime();
experimental-genesis 206 nHeaderStart = -1;
experimental-genesis 207 nMessageStart = -1;
experimental-genesis 208 addr = addrIn;
experimental-genesis 209 nVersion = 0;
experimental-genesis 210 strSubVer = "";
experimental-genesis 211 fClient = false; // set by version message
experimental-genesis 212 fInbound = fInboundIn;
experimental-genesis 213 fNetworkNode = false;
experimental-genesis 214 fSuccessfullyConnected = false;
experimental-genesis 215 fDisconnect = false;
experimental-genesis 216 nRefCount = 0;
experimental-genesis 217 nReleaseTime = 0;
experimental-genesis 218 hashContinue = 0;
experimental-genesis 219 pindexLastGetBlocksBegin = 0;
experimental-genesis 220 hashLastGetBlocksEnd = 0;
experimental-genesis 221 nStartingHeight = -1;
experimental-genesis 222 fGetAddr = false;
experimental-genesis 223 vfSubscribe.assign(256, false);
experimental-genesis 224 nMisbehavior = 0;
experimental-genesis 225
experimental-genesis 226 // Be shy and don't send version until we hear
experimental-genesis 227 if (!fInbound)
experimental-genesis 228 PushVersion();
experimental-genesis 229 }
experimental-genesis 230
experimental-genesis 231 ~CNode()
experimental-genesis 232 {
experimental-genesis 233 if (hSocket != INVALID_SOCKET)
experimental-genesis 234 {
experimental-genesis 235 closesocket(hSocket);
experimental-genesis 236 hSocket = INVALID_SOCKET;
experimental-genesis 237 }
experimental-genesis 238 }
experimental-genesis 239
experimental-genesis 240 private:
experimental-genesis 241 CNode(const CNode&);
experimental-genesis 242 void operator=(const CNode&);
experimental-genesis 243 public:
experimental-genesis 244
experimental-genesis 245
experimental-genesis 246 int GetRefCount()
experimental-genesis 247 {
experimental-genesis 248 return std::max(nRefCount, 0) + (GetTime() < nReleaseTime ? 1 : 0);
experimental-genesis 249 }
experimental-genesis 250
experimental-genesis 251 CNode* AddRef(int64 nTimeout=0)
experimental-genesis 252 {
experimental-genesis 253 if (nTimeout != 0)
experimental-genesis 254 nReleaseTime = std::max(nReleaseTime, GetTime() + nTimeout);
experimental-genesis 255 else
experimental-genesis 256 nRefCount++;
experimental-genesis 257 return this;
experimental-genesis 258 }
experimental-genesis 259
experimental-genesis 260 void Release()
experimental-genesis 261 {
experimental-genesis 262 nRefCount--;
experimental-genesis 263 }
experimental-genesis 264
experimental-genesis 265
experimental-genesis 266
experimental-genesis 267 void AddAddressKnown(const CAddress& addr)
experimental-genesis 268 {
experimental-genesis 269 setAddrKnown.insert(addr);
experimental-genesis 270 }
experimental-genesis 271
experimental-genesis 272 void PushAddress(const CAddress& addr)
experimental-genesis 273 {
experimental-genesis 274 // Known checking here is only to save space from duplicates.
experimental-genesis 275 // SendMessages will filter it again for knowns that were added
experimental-genesis 276 // after addresses were pushed.
experimental-genesis 277 if (addr.IsValid() && !setAddrKnown.count(addr))
experimental-genesis 278 vAddrToSend.push_back(addr);
experimental-genesis 279 }
experimental-genesis 280
experimental-genesis 281
experimental-genesis 282 void AddInventoryKnown(const CInv& inv)
experimental-genesis 283 {
experimental-genesis 284 CRITICAL_BLOCK(cs_inventory)
experimental-genesis 285 setInventoryKnown.insert(inv);
experimental-genesis 286 }
experimental-genesis 287
experimental-genesis 288 void PushInventory(const CInv& inv)
experimental-genesis 289 {
experimental-genesis 290 CRITICAL_BLOCK(cs_inventory)
experimental-genesis 291 if (!setInventoryKnown.count(inv))
experimental-genesis 292 vInventoryToSend.push_back(inv);
experimental-genesis 293 }
experimental-genesis 294
experimental-genesis 295 void AskFor(const CInv& inv)
experimental-genesis 296 {
experimental-genesis 297 // We're using mapAskFor as a priority queue,
experimental-genesis 298 // the key is the earliest time the request can be sent
experimental-genesis 299 int64& nRequestTime = mapAlreadyAskedFor[inv];
experimental-genesis 300 printf("askfor %s %"PRI64d"\n", inv.ToString().c_str(), nRequestTime);
experimental-genesis 301
experimental-genesis 302 // Make sure not to reuse time indexes to keep things in the same order
experimental-genesis 303 int64 nNow = (GetTime() - 1) * 1000000;
experimental-genesis 304 static int64 nLastTime;
experimental-genesis 305 ++nLastTime;
experimental-genesis 306 nNow = std::max(nNow, nLastTime);
experimental-genesis 307 nLastTime = nNow;
experimental-genesis 308
experimental-genesis 309 // Each retry is 2 minutes after the last
experimental-genesis 310 nRequestTime = std::max(nRequestTime + 2 * 60 * 1000000, nNow);
experimental-genesis 311 mapAskFor.insert(std::make_pair(nRequestTime, inv));
experimental-genesis 312 }
experimental-genesis 313
experimental-genesis 314
experimental-genesis 315
experimental-genesis 316 void BeginMessage(const char* pszCommand)
experimental-genesis 317 {
experimental-genesis 318 ENTER_CRITICAL_SECTION(cs_vSend);
experimental-genesis 319 if (nHeaderStart != -1)
experimental-genesis 320 AbortMessage();
experimental-genesis 321 nHeaderStart = vSend.size();
experimental-genesis 322 vSend << CMessageHeader(pszCommand, 0);
experimental-genesis 323 nMessageStart = vSend.size();
experimental-genesis 324 if (fDebug) {
experimental-genesis 325 printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
experimental-genesis 326 printf("sending: %s ", pszCommand);
experimental-genesis 327 }
experimental-genesis 328 }
experimental-genesis 329
experimental-genesis 330 void AbortMessage()
experimental-genesis 331 {
experimental-genesis 332 if (nHeaderStart == -1)
experimental-genesis 333 return;
experimental-genesis 334 vSend.resize(nHeaderStart);
experimental-genesis 335 nHeaderStart = -1;
experimental-genesis 336 nMessageStart = -1;
experimental-genesis 337 LEAVE_CRITICAL_SECTION(cs_vSend);
experimental-genesis 338
experimental-genesis 339 if (fDebug)
experimental-genesis 340 printf("(aborted)\n");
experimental-genesis 341 }
experimental-genesis 342
experimental-genesis 343 void EndMessage()
experimental-genesis 344 {
experimental-genesis 345 if (mapArgs.count("-dropmessagestest") && GetRand(atoi(mapArgs["-dropmessagestest"])) == 0)
experimental-genesis 346 {
experimental-genesis 347 printf("dropmessages DROPPING SEND MESSAGE\n");
experimental-genesis 348 AbortMessage();
experimental-genesis 349 return;
experimental-genesis 350 }
experimental-genesis 351
experimental-genesis 352 if (nHeaderStart == -1)
experimental-genesis 353 return;
experimental-genesis 354
experimental-genesis 355 // Set the size
experimental-genesis 356 unsigned int nSize = vSend.size() - nMessageStart;
experimental-genesis 357 memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nMessageSize), &nSize, sizeof(nSize));
experimental-genesis 358
experimental-genesis 359 // Set the checksum
experimental-genesis 360 if (vSend.GetVersion() >= 209)
experimental-genesis 361 {
experimental-genesis 362 uint256 hash = Hash(vSend.begin() + nMessageStart, vSend.end());
experimental-genesis 363 unsigned int nChecksum = 0;
experimental-genesis 364 memcpy(&nChecksum, &hash, sizeof(nChecksum));
experimental-genesis 365 assert(nMessageStart - nHeaderStart >= offsetof(CMessageHeader, nChecksum) + sizeof(nChecksum));
experimental-genesis 366 memcpy((char*)&vSend[nHeaderStart] + offsetof(CMessageHeader, nChecksum), &nChecksum, sizeof(nChecksum));
experimental-genesis 367 }
experimental-genesis 368
experimental-genesis 369 if (fDebug) {
experimental-genesis 370 printf("(%d bytes)\n", nSize);
experimental-genesis 371 }
experimental-genesis 372
experimental-genesis 373 nHeaderStart = -1;
experimental-genesis 374 nMessageStart = -1;
experimental-genesis 375 LEAVE_CRITICAL_SECTION(cs_vSend);
experimental-genesis 376 }
experimental-genesis 377
experimental-genesis 378 void EndMessageAbortIfEmpty()
experimental-genesis 379 {
experimental-genesis 380 if (nHeaderStart == -1)
experimental-genesis 381 return;
experimental-genesis 382 int nSize = vSend.size() - nMessageStart;
experimental-genesis 383 if (nSize > 0)
experimental-genesis 384 EndMessage();
experimental-genesis 385 else
experimental-genesis 386 AbortMessage();
experimental-genesis 387 }
experimental-genesis 388
experimental-genesis 389
experimental-genesis 390
experimental-genesis 391 void PushVersion()
experimental-genesis 392 {
experimental-genesis 393 /// when NTP implemented, change to just nTime = GetAdjustedTime()
experimental-genesis 394 int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
experimental-genesis 395 CAddress addrYou = (fUseProxy ? CAddress("0.0.0.0") : addr);
experimental-genesis 396 CAddress addrMe = (fUseProxy || !addrLocalHost.IsRoutable() ? CAddress("0.0.0.0") : addrLocalHost);
experimental-genesis 397 RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce));
experimental-genesis 398 PushMessage("version", VERSION, nLocalServices, nTime, addrYou, addrMe,
experimental-genesis 399 nLocalHostNonce, std::string(pszSubVer), nBestHeight);
experimental-genesis 400 }
experimental-genesis 401
experimental-genesis 402
experimental-genesis 403
experimental-genesis 404
experimental-genesis 405 void PushMessage(const char* pszCommand)
experimental-genesis 406 {
experimental-genesis 407 try
experimental-genesis 408 {
experimental-genesis 409 BeginMessage(pszCommand);
experimental-genesis 410 EndMessage();
experimental-genesis 411 }
experimental-genesis 412 catch (...)
experimental-genesis 413 {
experimental-genesis 414 AbortMessage();
experimental-genesis 415 throw;
experimental-genesis 416 }
experimental-genesis 417 }
experimental-genesis 418
experimental-genesis 419 template<typename T1>
experimental-genesis 420 void PushMessage(const char* pszCommand, const T1& a1)
experimental-genesis 421 {
experimental-genesis 422 try
experimental-genesis 423 {
experimental-genesis 424 BeginMessage(pszCommand);
experimental-genesis 425 vSend << a1;
experimental-genesis 426 EndMessage();
experimental-genesis 427 }
experimental-genesis 428 catch (...)
experimental-genesis 429 {
experimental-genesis 430 AbortMessage();
experimental-genesis 431 throw;
experimental-genesis 432 }
experimental-genesis 433 }
experimental-genesis 434
experimental-genesis 435 template<typename T1, typename T2>
experimental-genesis 436 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2)
experimental-genesis 437 {
experimental-genesis 438 try
experimental-genesis 439 {
experimental-genesis 440 BeginMessage(pszCommand);
experimental-genesis 441 vSend << a1 << a2;
experimental-genesis 442 EndMessage();
experimental-genesis 443 }
experimental-genesis 444 catch (...)
experimental-genesis 445 {
experimental-genesis 446 AbortMessage();
experimental-genesis 447 throw;
experimental-genesis 448 }
experimental-genesis 449 }
experimental-genesis 450
experimental-genesis 451 template<typename T1, typename T2, typename T3>
experimental-genesis 452 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3)
experimental-genesis 453 {
experimental-genesis 454 try
experimental-genesis 455 {
experimental-genesis 456 BeginMessage(pszCommand);
experimental-genesis 457 vSend << a1 << a2 << a3;
experimental-genesis 458 EndMessage();
experimental-genesis 459 }
experimental-genesis 460 catch (...)
experimental-genesis 461 {
experimental-genesis 462 AbortMessage();
experimental-genesis 463 throw;
experimental-genesis 464 }
experimental-genesis 465 }
experimental-genesis 466
experimental-genesis 467 template<typename T1, typename T2, typename T3, typename T4>
experimental-genesis 468 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4)
experimental-genesis 469 {
experimental-genesis 470 try
experimental-genesis 471 {
experimental-genesis 472 BeginMessage(pszCommand);
experimental-genesis 473 vSend << a1 << a2 << a3 << a4;
experimental-genesis 474 EndMessage();
experimental-genesis 475 }
experimental-genesis 476 catch (...)
experimental-genesis 477 {
experimental-genesis 478 AbortMessage();
experimental-genesis 479 throw;
experimental-genesis 480 }
experimental-genesis 481 }
experimental-genesis 482
experimental-genesis 483 template<typename T1, typename T2, typename T3, typename T4, typename T5>
experimental-genesis 484 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5)
experimental-genesis 485 {
experimental-genesis 486 try
experimental-genesis 487 {
experimental-genesis 488 BeginMessage(pszCommand);
experimental-genesis 489 vSend << a1 << a2 << a3 << a4 << a5;
experimental-genesis 490 EndMessage();
experimental-genesis 491 }
experimental-genesis 492 catch (...)
experimental-genesis 493 {
experimental-genesis 494 AbortMessage();
experimental-genesis 495 throw;
experimental-genesis 496 }
experimental-genesis 497 }
experimental-genesis 498
experimental-genesis 499 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6>
experimental-genesis 500 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6)
experimental-genesis 501 {
experimental-genesis 502 try
experimental-genesis 503 {
experimental-genesis 504 BeginMessage(pszCommand);
experimental-genesis 505 vSend << a1 << a2 << a3 << a4 << a5 << a6;
experimental-genesis 506 EndMessage();
experimental-genesis 507 }
experimental-genesis 508 catch (...)
experimental-genesis 509 {
experimental-genesis 510 AbortMessage();
experimental-genesis 511 throw;
experimental-genesis 512 }
experimental-genesis 513 }
experimental-genesis 514
experimental-genesis 515 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7>
experimental-genesis 516 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7)
experimental-genesis 517 {
experimental-genesis 518 try
experimental-genesis 519 {
experimental-genesis 520 BeginMessage(pszCommand);
experimental-genesis 521 vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7;
experimental-genesis 522 EndMessage();
experimental-genesis 523 }
experimental-genesis 524 catch (...)
experimental-genesis 525 {
experimental-genesis 526 AbortMessage();
experimental-genesis 527 throw;
experimental-genesis 528 }
experimental-genesis 529 }
experimental-genesis 530
experimental-genesis 531 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8>
experimental-genesis 532 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8)
experimental-genesis 533 {
experimental-genesis 534 try
experimental-genesis 535 {
experimental-genesis 536 BeginMessage(pszCommand);
experimental-genesis 537 vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8;
experimental-genesis 538 EndMessage();
experimental-genesis 539 }
experimental-genesis 540 catch (...)
experimental-genesis 541 {
experimental-genesis 542 AbortMessage();
experimental-genesis 543 throw;
experimental-genesis 544 }
experimental-genesis 545 }
experimental-genesis 546
experimental-genesis 547 template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9>
experimental-genesis 548 void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6, const T7& a7, const T8& a8, const T9& a9)
experimental-genesis 549 {
experimental-genesis 550 try
experimental-genesis 551 {
experimental-genesis 552 BeginMessage(pszCommand);
experimental-genesis 553 vSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9;
experimental-genesis 554 EndMessage();
experimental-genesis 555 }
experimental-genesis 556 catch (...)
experimental-genesis 557 {
experimental-genesis 558 AbortMessage();
experimental-genesis 559 throw;
experimental-genesis 560 }
experimental-genesis 561 }
experimental-genesis 562
experimental-genesis 563
experimental-genesis 564 void PushRequest(const char* pszCommand,
experimental-genesis 565 void (*fn)(void*, CDataStream&), void* param1)
experimental-genesis 566 {
experimental-genesis 567 uint256 hashReply;
experimental-genesis 568 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
experimental-genesis 569
experimental-genesis 570 CRITICAL_BLOCK(cs_mapRequests)
experimental-genesis 571 mapRequests[hashReply] = CRequestTracker(fn, param1);
experimental-genesis 572
experimental-genesis 573 PushMessage(pszCommand, hashReply);
experimental-genesis 574 }
experimental-genesis 575
experimental-genesis 576 template<typename T1>
experimental-genesis 577 void PushRequest(const char* pszCommand, const T1& a1,
experimental-genesis 578 void (*fn)(void*, CDataStream&), void* param1)
experimental-genesis 579 {
experimental-genesis 580 uint256 hashReply;
experimental-genesis 581 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
experimental-genesis 582
experimental-genesis 583 CRITICAL_BLOCK(cs_mapRequests)
experimental-genesis 584 mapRequests[hashReply] = CRequestTracker(fn, param1);
experimental-genesis 585
experimental-genesis 586 PushMessage(pszCommand, hashReply, a1);
experimental-genesis 587 }
experimental-genesis 588
experimental-genesis 589 template<typename T1, typename T2>
experimental-genesis 590 void PushRequest(const char* pszCommand, const T1& a1, const T2& a2,
experimental-genesis 591 void (*fn)(void*, CDataStream&), void* param1)
experimental-genesis 592 {
experimental-genesis 593 uint256 hashReply;
experimental-genesis 594 RAND_bytes((unsigned char*)&hashReply, sizeof(hashReply));
experimental-genesis 595
experimental-genesis 596 CRITICAL_BLOCK(cs_mapRequests)
experimental-genesis 597 mapRequests[hashReply] = CRequestTracker(fn, param1);
experimental-genesis 598
experimental-genesis 599 PushMessage(pszCommand, hashReply, a1, a2);
experimental-genesis 600 }
experimental-genesis 601
experimental-genesis 602
experimental-genesis 603
experimental-genesis 604 void PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd);
experimental-genesis 605 bool IsSubscribed(unsigned int nChannel);
experimental-genesis 606 void Subscribe(unsigned int nChannel, unsigned int nHops=0);
experimental-genesis 607 void CancelSubscribe(unsigned int nChannel);
experimental-genesis 608 void CloseSocketDisconnect();
experimental-genesis 609 void Cleanup();
experimental-genesis 610
experimental-genesis 611
experimental-genesis 612 // Denial-of-service detection/prevention
experimental-genesis 613 // The idea is to detect peers that are behaving
experimental-genesis 614 // badly and disconnect/ban them, but do it in a
experimental-genesis 615 // one-coding-mistake-won't-shatter-the-entire-network
experimental-genesis 616 // way.
experimental-genesis 617 // IMPORTANT: There should be nothing I can give a
experimental-genesis 618 // node that it will forward on that will make that
experimental-genesis 619 // node's peers drop it. If there is, an attacker
experimental-genesis 620 // can isolate a node and/or try to split the network.
experimental-genesis 621 // Dropping a node for sending stuff that is invalid
experimental-genesis 622 // now but might be valid in a later version is also
experimental-genesis 623 // dangerous, because it can cause a network split
experimental-genesis 624 // between nodes running old code and nodes running
experimental-genesis 625 // new code.
experimental-genesis 626 static void ClearBanned(); // needed for unit testing
experimental-genesis 627 static bool IsBanned(unsigned int ip);
experimental-genesis 628 bool Misbehaving(int howmuch); // 1 == a little, 100 == a lot
experimental-genesis 629 };
experimental-genesis 630
experimental-genesis 631
experimental-genesis 632
experimental-genesis 633
experimental-genesis 634
experimental-genesis 635
experimental-genesis 636
experimental-genesis 637
experimental-genesis 638
experimental-genesis 639
experimental-genesis 640 inline void RelayInventory(const CInv& inv)
experimental-genesis 641 {
experimental-genesis 642 // Put on lists to offer to the other nodes
experimental-genesis 643 CRITICAL_BLOCK(cs_vNodes)
experimental-genesis 644 BOOST_FOREACH(CNode* pnode, vNodes)
experimental-genesis 645 pnode->PushInventory(inv);
experimental-genesis 646 }
experimental-genesis 647
experimental-genesis 648 template<typename T>
experimental-genesis 649 void RelayMessage(const CInv& inv, const T& a)
experimental-genesis 650 {
experimental-genesis 651 CDataStream ss(SER_NETWORK);
experimental-genesis 652 ss.reserve(10000);
experimental-genesis 653 ss << a;
experimental-genesis 654 RelayMessage(inv, ss);
experimental-genesis 655 }
experimental-genesis 656
experimental-genesis 657 template<>
experimental-genesis 658 inline void RelayMessage<>(const CInv& inv, const CDataStream& ss)
experimental-genesis 659 {
experimental-genesis 660 CRITICAL_BLOCK(cs_mapRelay)
experimental-genesis 661 {
experimental-genesis 662 // Expire old relay messages
experimental-genesis 663 while (!vRelayExpiration.empty() && vRelayExpiration.front().first < GetTime())
experimental-genesis 664 {
experimental-genesis 665 mapRelay.erase(vRelayExpiration.front().second);
experimental-genesis 666 vRelayExpiration.pop_front();
experimental-genesis 667 }
experimental-genesis 668
experimental-genesis 669 // Save original serialized message so newer versions are preserved
experimental-genesis 670 mapRelay[inv] = ss;
experimental-genesis 671 vRelayExpiration.push_back(std::make_pair(GetTime() + 15 * 60, inv));
experimental-genesis 672 }
experimental-genesis 673
experimental-genesis 674 RelayInventory(inv);
experimental-genesis 675 }
experimental-genesis 676
experimental-genesis 677
experimental-genesis 678
experimental-genesis 679
experimental-genesis 680
experimental-genesis 681
experimental-genesis 682
experimental-genesis 683
experimental-genesis 684 //
experimental-genesis 685 // Templates for the publish and subscription system.
experimental-genesis 686 // The object being published as T& obj needs to have:
experimental-genesis 687 // a set<unsigned int> setSources member
experimental-genesis 688 // specializations of AdvertInsert and AdvertErase
experimental-genesis 689 // Currently implemented for CTable and CProduct.
experimental-genesis 690 //
experimental-genesis 691
experimental-genesis 692 template<typename T>
experimental-genesis 693 void AdvertStartPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
experimental-genesis 694 {
experimental-genesis 695 // Add to sources
experimental-genesis 696 obj.setSources.insert(pfrom->addr.ip);
experimental-genesis 697
experimental-genesis 698 if (!AdvertInsert(obj))
experimental-genesis 699 return;
experimental-genesis 700
experimental-genesis 701 // Relay
experimental-genesis 702 CRITICAL_BLOCK(cs_vNodes)
experimental-genesis 703 BOOST_FOREACH(CNode* pnode, vNodes)
experimental-genesis 704 if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
experimental-genesis 705 pnode->PushMessage("publish", nChannel, nHops, obj);
experimental-genesis 706 }
experimental-genesis 707
experimental-genesis 708 template<typename T>
experimental-genesis 709 void AdvertStopPublish(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
experimental-genesis 710 {
experimental-genesis 711 uint256 hash = obj.GetHash();
experimental-genesis 712
experimental-genesis 713 CRITICAL_BLOCK(cs_vNodes)
experimental-genesis 714 BOOST_FOREACH(CNode* pnode, vNodes)
experimental-genesis 715 if (pnode != pfrom && (nHops < PUBLISH_HOPS || pnode->IsSubscribed(nChannel)))
experimental-genesis 716 pnode->PushMessage("pub-cancel", nChannel, nHops, hash);
experimental-genesis 717
experimental-genesis 718 AdvertErase(obj);
experimental-genesis 719 }
experimental-genesis 720
experimental-genesis 721 template<typename T>
experimental-genesis 722 void AdvertRemoveSource(CNode* pfrom, unsigned int nChannel, unsigned int nHops, T& obj)
experimental-genesis 723 {
experimental-genesis 724 // Remove a source
experimental-genesis 725 obj.setSources.erase(pfrom->addr.ip);
experimental-genesis 726
experimental-genesis 727 // If no longer supported by any sources, cancel it
experimental-genesis 728 if (obj.setSources.empty())
experimental-genesis 729 AdvertStopPublish(pfrom, nChannel, nHops, obj);
experimental-genesis 730 }
experimental-genesis 731
experimental-genesis 732 #endif