Commit | Line | Data |
---|---|---|
0a61b0df | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
f914f1a7 | 2 | // Copyright (c) 2009-2014 The Bitcoin Core developers |
78253fcb | 3 | // Distributed under the MIT software license, see the accompanying |
3a25a2b9 | 4 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. |
51ed9ec9 | 5 | |
223b6f1b WL |
6 | #ifndef BITCOIN_NET_H |
7 | #define BITCOIN_NET_H | |
8 | ||
51ed9ec9 BD |
9 | #include "bloom.h" |
10 | #include "compat.h" | |
11 | #include "hash.h" | |
12 | #include "limitedmap.h" | |
13 | #include "mruset.h" | |
14 | #include "netbase.h" | |
15 | #include "protocol.h" | |
6354935c | 16 | #include "random.h" |
fa736190 | 17 | #include "streams.h" |
51ed9ec9 BD |
18 | #include "sync.h" |
19 | #include "uint256.h" | |
ad49c256 | 20 | #include "utilstrencodings.h" |
51ed9ec9 | 21 | |
223b6f1b | 22 | #include <deque> |
51ed9ec9 | 23 | #include <stdint.h> |
223b6f1b | 24 | |
9cb1ec9c | 25 | #ifndef _WIN32 |
223b6f1b WL |
26 | #include <arpa/inet.h> |
27 | #endif | |
0a61b0df | 28 | |
ad49c256 | 29 | #include <boost/filesystem/path.hpp> |
51ed9ec9 BD |
30 | #include <boost/foreach.hpp> |
31 | #include <boost/signals2/signal.hpp> | |
6e68524e | 32 | |
51ed9ec9 | 33 | class CAddrMan; |
0a61b0df | 34 | class CBlockIndex; |
9a1dcea2 | 35 | class CScheduler; |
51ed9ec9 | 36 | class CNode; |
0a61b0df | 37 | |
51ed9ec9 BD |
38 | namespace boost { |
39 | class thread_group; | |
e10dcf27 | 40 | } // namespace boost |
0a61b0df | 41 | |
f1920e86 PW |
42 | /** Time between pings automatically sent out for latency probing and keepalive (in seconds). */ |
43 | static const int PING_INTERVAL = 2 * 60; | |
44 | /** Time after which to disconnect, after waiting for a ping response (or inactivity). */ | |
45 | static const int TIMEOUT_INTERVAL = 20 * 60; | |
51ed9ec9 BD |
46 | /** The maximum number of entries in an 'inv' protocol message */ |
47 | static const unsigned int MAX_INV_SZ = 50000; | |
12a49cac PW |
48 | /** The maximum number of new addresses to accumulate before announcing. */ |
49 | static const unsigned int MAX_ADDR_TO_SEND = 1000; | |
ba04c4a7 PW |
50 | /** Maximum length of incoming protocol messages (no message over 2 MiB is currently acceptable). */ |
51 | static const unsigned int MAX_PROTOCOL_MESSAGE_LENGTH = 2 * 1024 * 1024; | |
56b07d2d PK |
52 | /** -listen default */ |
53 | static const bool DEFAULT_LISTEN = true; | |
d4168c82 WL |
54 | /** The maximum number of entries in mapAskFor */ |
55 | static const size_t MAPASKFOR_MAX_SZ = MAX_INV_SZ; | |
e2190f80 GM |
56 | /** The maximum number of entries in setAskFor (larger due to getdata latency)*/ |
57 | static const size_t SETASKFOR_MAX_SZ = 2 * MAX_INV_SZ; | |
8a5ae3c7 MQ |
58 | /** The maximum number of peer connections to maintain. */ |
59 | static const unsigned int DEFAULT_MAX_PEER_CONNECTIONS = 125; | |
72b21929 S |
60 | /** The period before a network upgrade activates, where connections to upgrading peers are preferred (in blocks). */ |
61 | static const int NETWORK_UPGRADE_PEER_PREFERENCE_BLOCK_PERIOD = 24 * 24 * 3; | |
0a61b0df | 62 | |
651480c8 WL |
63 | unsigned int ReceiveFloodSize(); |
64 | unsigned int SendBufferSize(); | |
0a61b0df | 65 | |
db954a65 | 66 | void AddOneShot(const std::string& strDest); |
67a42f92 PW |
67 | void AddressCurrentlyConnected(const CService& addr); |
68 | CNode* FindNode(const CNetAddr& ip); | |
e5219399 | 69 | CNode* FindNode(const CSubNet& subNet); |
0430c30a | 70 | CNode* FindNode(const std::string& addrName); |
67a42f92 | 71 | CNode* FindNode(const CService& ip); |
5bd6c31b | 72 | CNode* ConnectNode(CAddress addrConnect, const char *pszDest = NULL); |
b641c9cd | 73 | bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); |
5a3cb32e | 74 | unsigned short GetListenPort(); |
dc942e6f | 75 | bool BindListenPort(const CService &bindAddr, std::string& strError, bool fWhitelisted = false); |
9a1dcea2 | 76 | void StartNode(boost::thread_group& threadGroup, CScheduler& scheduler); |
0a61b0df | 77 | bool StopNode(); |
b9ff2970 | 78 | void SocketSendData(CNode *pnode); |
0a61b0df | 79 | |
b2864d2f PW |
80 | typedef int NodeId; |
81 | ||
9519a9a4 PW |
82 | struct CombinerAll |
83 | { | |
84 | typedef bool result_type; | |
85 | ||
86 | template<typename I> | |
87 | bool operator()(I first, I last) const | |
88 | { | |
89 | while (first != last) { | |
90 | if (!(*first)) return false; | |
91 | ++first; | |
92 | } | |
93 | return true; | |
94 | } | |
95 | }; | |
96 | ||
501da250 EL |
97 | // Signals for message handling |
98 | struct CNodeSignals | |
99 | { | |
4c6d41b8 | 100 | boost::signals2::signal<int ()> GetHeight; |
9519a9a4 PW |
101 | boost::signals2::signal<bool (CNode*), CombinerAll> ProcessMessages; |
102 | boost::signals2::signal<bool (CNode*, bool), CombinerAll> SendMessages; | |
b2864d2f PW |
103 | boost::signals2::signal<void (NodeId, const CNode*)> InitializeNode; |
104 | boost::signals2::signal<void (NodeId)> FinalizeNode; | |
501da250 EL |
105 | }; |
106 | ||
b2864d2f | 107 | |
501da250 | 108 | CNodeSignals& GetNodeSignals(); |
663224c2 | 109 | |
663224c2 | 110 | |
39857190 PW |
111 | enum |
112 | { | |
7fa4443f PW |
113 | LOCAL_NONE, // unknown |
114 | LOCAL_IF, // address a local interface listens on | |
8f10a288 | 115 | LOCAL_BIND, // address explicit bound to |
506a2185 | 116 | LOCAL_UPNP, // unused (was: address reported by UPnP) |
7fa4443f | 117 | LOCAL_MANUAL, // address explicitly specified (-externalip=) |
19b6958c PW |
118 | |
119 | LOCAL_MAX | |
39857190 PW |
120 | }; |
121 | ||
845c86d1 GM |
122 | bool IsPeerAddrLocalGood(CNode *pnode); |
123 | void AdvertizeLocal(CNode *pnode); | |
457754d2 | 124 | void SetLimited(enum Network net, bool fLimited = true); |
0f1707de | 125 | bool IsLimited(enum Network net); |
457754d2 | 126 | bool IsLimited(const CNetAddr& addr); |
7fa4443f | 127 | bool AddLocal(const CService& addr, int nScore = LOCAL_NONE); |
5a3cb32e | 128 | bool AddLocal(const CNetAddr& addr, int nScore = LOCAL_NONE); |
975dc649 | 129 | bool RemoveLocal(const CService& addr); |
7fa4443f PW |
130 | bool SeenLocal(const CService& addr); |
131 | bool IsLocal(const CService& addr); | |
132 | bool GetLocal(CService &addr, const CNetAddr *paddrPeer = NULL); | |
c91a9471 | 133 | bool IsReachable(enum Network net); |
090e5b40 | 134 | bool IsReachable(const CNetAddr &addr); |
39857190 PW |
135 | CAddress GetLocalAddress(const CNetAddr *paddrPeer = NULL); |
136 | ||
090e5b40 | 137 | |
587f929c | 138 | extern bool fDiscover; |
53a08815 | 139 | extern bool fListen; |
51ed9ec9 BD |
140 | extern uint64_t nLocalServices; |
141 | extern uint64_t nLocalHostNonce; | |
5fee401f | 142 | extern CAddrMan addrman; |
0560d671 | 143 | /** Maximum number of connections to simultaneously allow (aka connection slots) */ |
ba29a559 | 144 | extern int nMaxConnections; |
0a61b0df | 145 | |
223b6f1b | 146 | extern std::vector<CNode*> vNodes; |
0a61b0df | 147 | extern CCriticalSection cs_vNodes; |
223b6f1b | 148 | extern std::map<CInv, CDataStream> mapRelay; |
51ed9ec9 | 149 | extern std::deque<std::pair<int64_t, CInv> > vRelayExpiration; |
0a61b0df | 150 | extern CCriticalSection cs_mapRelay; |
51ed9ec9 | 151 | extern limitedmap<CInv, int64_t> mapAlreadyAskedFor; |
0a61b0df | 152 | |
74088e86 MC |
153 | extern std::vector<std::string> vAddedNodes; |
154 | extern CCriticalSection cs_vAddedNodes; | |
155 | ||
b2864d2f PW |
156 | extern NodeId nLastNodeId; |
157 | extern CCriticalSection cs_nLastNodeId; | |
0a61b0df | 158 | |
d387b8ec WL |
159 | struct LocalServiceInfo { |
160 | int nScore; | |
161 | int nPort; | |
162 | }; | |
163 | ||
164 | extern CCriticalSection cs_mapLocalHost; | |
2871889e | 165 | extern std::map<CNetAddr, LocalServiceInfo> mapLocalHost; |
0a61b0df | 166 | |
1006f070 JG |
167 | class CNodeStats |
168 | { | |
169 | public: | |
b2864d2f | 170 | NodeId nodeid; |
51ed9ec9 BD |
171 | uint64_t nServices; |
172 | int64_t nLastSend; | |
173 | int64_t nLastRecv; | |
174 | int64_t nTimeConnected; | |
26a6bae7 | 175 | int64_t nTimeOffset; |
1006f070 JG |
176 | std::string addrName; |
177 | int nVersion; | |
a946aa8d | 178 | std::string cleanSubVer; |
1006f070 | 179 | bool fInbound; |
1006f070 | 180 | int nStartingHeight; |
51ed9ec9 BD |
181 | uint64_t nSendBytes; |
182 | uint64_t nRecvBytes; | |
dc942e6f | 183 | bool fWhitelisted; |
971bb3e9 JL |
184 | double dPingTime; |
185 | double dPingWait; | |
547c61f8 | 186 | std::string addrLocal; |
1006f070 JG |
187 | }; |
188 | ||
189 | ||
190 | ||
0a61b0df | 191 | |
607dbfde JG |
192 | class CNetMessage { |
193 | public: | |
194 | bool in_data; // parsing header (false) or data (true) | |
195 | ||
196 | CDataStream hdrbuf; // partially received header | |
197 | CMessageHeader hdr; // complete header | |
198 | unsigned int nHdrPos; | |
199 | ||
200 | CDataStream vRecv; // received message data | |
201 | unsigned int nDataPos; | |
202 | ||
9f4da19b PW |
203 | int64_t nTime; // time (in microseconds) of message receipt. |
204 | ||
eec37136 | 205 | CNetMessage(const CMessageHeader::MessageStartChars& pchMessageStartIn, int nTypeIn, int nVersionIn) : hdrbuf(nTypeIn, nVersionIn), hdr(pchMessageStartIn), vRecv(nTypeIn, nVersionIn) { |
607dbfde JG |
206 | hdrbuf.resize(24); |
207 | in_data = false; | |
208 | nHdrPos = 0; | |
209 | nDataPos = 0; | |
9f4da19b | 210 | nTime = 0; |
607dbfde JG |
211 | } |
212 | ||
213 | bool complete() const | |
214 | { | |
215 | if (!in_data) | |
216 | return false; | |
217 | return (hdr.nMessageSize == nDataPos); | |
218 | } | |
219 | ||
220 | void SetVersion(int nVersionIn) | |
221 | { | |
222 | hdrbuf.SetVersion(nVersionIn); | |
223 | vRecv.SetVersion(nVersionIn); | |
224 | } | |
225 | ||
226 | int readHeader(const char *pch, unsigned int nBytes); | |
227 | int readData(const char *pch, unsigned int nBytes); | |
228 | }; | |
229 | ||
230 | ||
231 | ||
232 | ||
0a61b0df | 233 | |
6b8de05d | 234 | /** Information about a peer */ |
0a61b0df | 235 | class CNode |
236 | { | |
237 | public: | |
238 | // socket | |
51ed9ec9 | 239 | uint64_t nServices; |
0a61b0df | 240 | SOCKET hSocket; |
41b052ad PW |
241 | CDataStream ssSend; |
242 | size_t nSendSize; // total size of all vSendMsg entries | |
243 | size_t nSendOffset; // offset inside the first vSendMsg already sent | |
51ed9ec9 | 244 | uint64_t nSendBytes; |
41b052ad | 245 | std::deque<CSerializeData> vSendMsg; |
0a61b0df | 246 | CCriticalSection cs_vSend; |
607dbfde | 247 | |
c7f039b6 | 248 | std::deque<CInv> vRecvGetData; |
967f2459 | 249 | std::deque<CNetMessage> vRecvMsg; |
607dbfde | 250 | CCriticalSection cs_vRecvMsg; |
51ed9ec9 | 251 | uint64_t nRecvBytes; |
607dbfde JG |
252 | int nRecvVersion; |
253 | ||
51ed9ec9 BD |
254 | int64_t nLastSend; |
255 | int64_t nLastRecv; | |
51ed9ec9 | 256 | int64_t nTimeConnected; |
26a6bae7 | 257 | int64_t nTimeOffset; |
0a61b0df | 258 | CAddress addr; |
9bab521d | 259 | std::string addrName; |
7fa4443f | 260 | CService addrLocal; |
0a61b0df | 261 | int nVersion; |
8ab425f8 | 262 | int lasthdrsreq,sendhdrsreq; |
c037531d | 263 | // strSubVer is whatever byte array we read from the wire. However, this field is intended |
a946aa8d MH |
264 | // to be printed out, displayed to humans in various forms and so on. So we sanitize it and |
265 | // store the sanitized version in cleanSubVer. The original should be used when dealing with | |
266 | // the network or wire types and the cleaned string used when displayed or logged. | |
267 | std::string strSubVer, cleanSubVer; | |
dc942e6f | 268 | bool fWhitelisted; // This peer can bypass DoS banning. |
478b01d9 | 269 | bool fOneShot; |
0a61b0df | 270 | bool fClient; |
271 | bool fInbound; | |
272 | bool fNetworkNode; | |
273 | bool fSuccessfullyConnected; | |
274 | bool fDisconnect; | |
4c8fc1a5 MC |
275 | // We use fRelayTxes for two purposes - |
276 | // a) it allows us to not relay tx invs before receiving the peer's version message | |
7e6d23b1 CD |
277 | // b) the peer may tell us in its version message that we should not relay tx invs |
278 | // until it has initialized its bloom filter. | |
4c8fc1a5 | 279 | bool fRelayTxes; |
a514cb29 | 280 | bool fSentAddr; |
c59abe25 | 281 | CSemaphoreGrant grantOutbound; |
422d1225 MC |
282 | CCriticalSection cs_filter; |
283 | CBloomFilter* pfilter; | |
0a61b0df | 284 | int nRefCount; |
b2864d2f | 285 | NodeId id; |
cedaa714 | 286 | protected: |
15f3ad4d GA |
287 | |
288 | // Denial-of-service detection/prevention | |
814efd6f | 289 | // Key is IP address, value is banned-until-time |
e5219399 | 290 | static std::map<CSubNet, int64_t> setBanned; |
15f3ad4d | 291 | static CCriticalSection cs_setBanned; |
15f3ad4d | 292 | |
dc942e6f PW |
293 | // Whitelisted ranges. Any node connecting from these is automatically |
294 | // whitelisted (as well as those connecting to whitelisted binds). | |
295 | static std::vector<CSubNet> vWhitelistedRange; | |
296 | static CCriticalSection cs_vWhitelistedRange; | |
297 | ||
9038b18f GA |
298 | // Basic fuzz-testing |
299 | void Fuzz(int nChance); // modifies ssSend | |
300 | ||
0a61b0df | 301 | public: |
0a61b0df | 302 | uint256 hashContinue; |
0a61b0df | 303 | int nStartingHeight; |
304 | ||
305 | // flood relay | |
223b6f1b | 306 | std::vector<CAddress> vAddrToSend; |
d81cff32 | 307 | CRollingBloomFilter addrKnown; |
0a61b0df | 308 | bool fGetAddr; |
223b6f1b | 309 | std::set<uint256> setKnown; |
0a61b0df | 310 | |
311 | // inventory based relay | |
c4341fa6 | 312 | mruset<CInv> setInventoryKnown; |
223b6f1b | 313 | std::vector<CInv> vInventoryToSend; |
0a61b0df | 314 | CCriticalSection cs_inventory; |
56f165bd | 315 | std::set<uint256> setAskFor; |
51ed9ec9 | 316 | std::multimap<int64_t, CInv> mapAskFor; |
0a61b0df | 317 | |
f1920e86 PW |
318 | // Ping time measurement: |
319 | // The pong reply we're expecting, or 0 if no pong expected. | |
51ed9ec9 | 320 | uint64_t nPingNonceSent; |
f1920e86 | 321 | // Time (in usec) the last ping was sent, or 0 if no ping was ever sent. |
51ed9ec9 | 322 | int64_t nPingUsecStart; |
f1920e86 | 323 | // Last measured round-trip time. |
51ed9ec9 | 324 | int64_t nPingUsecTime; |
e279e5f9 PS |
325 | // Best measured round-trip time. |
326 | int64_t nMinPingUsecTime; | |
f1920e86 | 327 | // Whether a ping is requested. |
971bb3e9 | 328 | bool fPingQueued; |
c037531d | 329 | |
db954a65 | 330 | CNode(SOCKET hSocketIn, const CAddress &addrIn, const std::string &addrNameIn = "", bool fInboundIn = false); |
651480c8 | 331 | ~CNode(); |
0a61b0df | 332 | |
333 | private: | |
ce14345a SE |
334 | // Network usage totals |
335 | static CCriticalSection cs_totalBytesRecv; | |
336 | static CCriticalSection cs_totalBytesSent; | |
51ed9ec9 BD |
337 | static uint64_t nTotalBytesRecv; |
338 | static uint64_t nTotalBytesSent; | |
ce14345a | 339 | |
0a61b0df | 340 | CNode(const CNode&); |
341 | void operator=(const CNode&); | |
ce14345a | 342 | |
0a61b0df | 343 | public: |
344 | ||
b2864d2f PW |
345 | NodeId GetId() const { |
346 | return id; | |
347 | } | |
0a61b0df | 348 | |
349 | int GetRefCount() | |
350 | { | |
cedaa714 PW |
351 | assert(nRefCount >= 0); |
352 | return nRefCount; | |
0a61b0df | 353 | } |
354 | ||
607dbfde JG |
355 | // requires LOCK(cs_vRecvMsg) |
356 | unsigned int GetTotalRecvSize() | |
357 | { | |
358 | unsigned int total = 0; | |
96b9603c | 359 | BOOST_FOREACH(const CNetMessage &msg, vRecvMsg) |
967f2459 | 360 | total += msg.vRecv.size() + 24; |
607dbfde JG |
361 | return total; |
362 | } | |
363 | ||
364 | // requires LOCK(cs_vRecvMsg) | |
365 | bool ReceiveMsgBytes(const char *pch, unsigned int nBytes); | |
366 | ||
367 | // requires LOCK(cs_vRecvMsg) | |
368 | void SetRecvVersion(int nVersionIn) | |
369 | { | |
370 | nRecvVersion = nVersionIn; | |
967f2459 PW |
371 | BOOST_FOREACH(CNetMessage &msg, vRecvMsg) |
372 | msg.SetVersion(nVersionIn); | |
607dbfde JG |
373 | } |
374 | ||
cedaa714 | 375 | CNode* AddRef() |
0a61b0df | 376 | { |
cedaa714 | 377 | nRefCount++; |
0a61b0df | 378 | return this; |
379 | } | |
380 | ||
381 | void Release() | |
382 | { | |
383 | nRefCount--; | |
384 | } | |
385 | ||
386 | ||
387 | ||
388 | void AddAddressKnown(const CAddress& addr) | |
389 | { | |
d81cff32 | 390 | addrKnown.insert(addr.GetKey()); |
0a61b0df | 391 | } |
392 | ||
393 | void PushAddress(const CAddress& addr) | |
394 | { | |
395 | // Known checking here is only to save space from duplicates. | |
396 | // SendMessages will filter it again for knowns that were added | |
397 | // after addresses were pushed. | |
d81cff32 | 398 | if (addr.IsValid() && !addrKnown.contains(addr.GetKey())) { |
12a49cac PW |
399 | if (vAddrToSend.size() >= MAX_ADDR_TO_SEND) { |
400 | vAddrToSend[insecure_rand() % vAddrToSend.size()] = addr; | |
401 | } else { | |
402 | vAddrToSend.push_back(addr); | |
403 | } | |
404 | } | |
0a61b0df | 405 | } |
406 | ||
407 | ||
408 | void AddInventoryKnown(const CInv& inv) | |
409 | { | |
f8dcd5ca PW |
410 | { |
411 | LOCK(cs_inventory); | |
0a61b0df | 412 | setInventoryKnown.insert(inv); |
f8dcd5ca | 413 | } |
0a61b0df | 414 | } |
415 | ||
416 | void PushInventory(const CInv& inv) | |
417 | { | |
f8dcd5ca PW |
418 | { |
419 | LOCK(cs_inventory); | |
0a61b0df | 420 | if (!setInventoryKnown.count(inv)) |
421 | vInventoryToSend.push_back(inv); | |
f8dcd5ca | 422 | } |
0a61b0df | 423 | } |
424 | ||
651480c8 | 425 | void AskFor(const CInv& inv); |
0a61b0df | 426 | |
25511af4 | 427 | // TODO: Document the postcondition of this function. Is cs_vSend locked? |
651480c8 | 428 | void BeginMessage(const char* pszCommand) EXCLUSIVE_LOCK_FUNCTION(cs_vSend); |
0a61b0df | 429 | |
25511af4 | 430 | // TODO: Document the precondition of this function. Is cs_vSend locked? |
651480c8 | 431 | void AbortMessage() UNLOCK_FUNCTION(cs_vSend); |
0a61b0df | 432 | |
25511af4 | 433 | // TODO: Document the precondition of this function. Is cs_vSend locked? |
651480c8 | 434 | void EndMessage() UNLOCK_FUNCTION(cs_vSend); |
0a61b0df | 435 | |
f8ded588 | 436 | void PushVersion(); |
cbc920d4 | 437 | |
0a61b0df | 438 | |
439 | void PushMessage(const char* pszCommand) | |
440 | { | |
441 | try | |
442 | { | |
443 | BeginMessage(pszCommand); | |
444 | EndMessage(); | |
445 | } | |
446 | catch (...) | |
447 | { | |
448 | AbortMessage(); | |
449 | throw; | |
450 | } | |
451 | } | |
452 | ||
453 | template<typename T1> | |
454 | void PushMessage(const char* pszCommand, const T1& a1) | |
455 | { | |
456 | try | |
457 | { | |
458 | BeginMessage(pszCommand); | |
41b052ad | 459 | ssSend << a1; |
0a61b0df | 460 | EndMessage(); |
461 | } | |
462 | catch (...) | |
463 | { | |
464 | AbortMessage(); | |
465 | throw; | |
466 | } | |
467 | } | |
468 | ||
469 | template<typename T1, typename T2> | |
470 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2) | |
471 | { | |
472 | try | |
473 | { | |
474 | BeginMessage(pszCommand); | |
41b052ad | 475 | ssSend << a1 << a2; |
0a61b0df | 476 | EndMessage(); |
477 | } | |
478 | catch (...) | |
479 | { | |
480 | AbortMessage(); | |
481 | throw; | |
482 | } | |
483 | } | |
484 | ||
485 | template<typename T1, typename T2, typename T3> | |
486 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3) | |
487 | { | |
488 | try | |
489 | { | |
490 | BeginMessage(pszCommand); | |
41b052ad | 491 | ssSend << a1 << a2 << a3; |
0a61b0df | 492 | EndMessage(); |
493 | } | |
494 | catch (...) | |
495 | { | |
496 | AbortMessage(); | |
497 | throw; | |
498 | } | |
499 | } | |
500 | ||
501 | template<typename T1, typename T2, typename T3, typename T4> | |
502 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4) | |
503 | { | |
504 | try | |
505 | { | |
506 | BeginMessage(pszCommand); | |
41b052ad | 507 | ssSend << a1 << a2 << a3 << a4; |
0a61b0df | 508 | EndMessage(); |
509 | } | |
510 | catch (...) | |
511 | { | |
512 | AbortMessage(); | |
513 | throw; | |
514 | } | |
515 | } | |
516 | ||
517 | template<typename T1, typename T2, typename T3, typename T4, typename T5> | |
518 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5) | |
519 | { | |
520 | try | |
521 | { | |
522 | BeginMessage(pszCommand); | |
41b052ad | 523 | ssSend << a1 << a2 << a3 << a4 << a5; |
0a61b0df | 524 | EndMessage(); |
525 | } | |
526 | catch (...) | |
527 | { | |
528 | AbortMessage(); | |
529 | throw; | |
530 | } | |
531 | } | |
532 | ||
533 | template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6> | |
534 | void PushMessage(const char* pszCommand, const T1& a1, const T2& a2, const T3& a3, const T4& a4, const T5& a5, const T6& a6) | |
535 | { | |
536 | try | |
537 | { | |
538 | BeginMessage(pszCommand); | |
41b052ad | 539 | ssSend << a1 << a2 << a3 << a4 << a5 << a6; |
0a61b0df | 540 | EndMessage(); |
541 | } | |
542 | catch (...) | |
543 | { | |
544 | AbortMessage(); | |
545 | throw; | |
546 | } | |
547 | } | |
548 | ||
549 | template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7> | |
550 | 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) | |
551 | { | |
552 | try | |
553 | { | |
554 | BeginMessage(pszCommand); | |
41b052ad | 555 | ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7; |
0a61b0df | 556 | EndMessage(); |
557 | } | |
558 | catch (...) | |
559 | { | |
560 | AbortMessage(); | |
561 | throw; | |
562 | } | |
563 | } | |
564 | ||
565 | template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8> | |
566 | 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) | |
567 | { | |
568 | try | |
569 | { | |
570 | BeginMessage(pszCommand); | |
41b052ad | 571 | ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8; |
0a61b0df | 572 | EndMessage(); |
573 | } | |
574 | catch (...) | |
575 | { | |
576 | AbortMessage(); | |
577 | throw; | |
578 | } | |
579 | } | |
580 | ||
581 | template<typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7, typename T8, typename T9> | |
582 | 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) | |
583 | { | |
584 | try | |
585 | { | |
586 | BeginMessage(pszCommand); | |
41b052ad | 587 | ssSend << a1 << a2 << a3 << a4 << a5 << a6 << a7 << a8 << a9; |
0a61b0df | 588 | EndMessage(); |
589 | } | |
590 | catch (...) | |
591 | { | |
592 | AbortMessage(); | |
593 | throw; | |
594 | } | |
595 | } | |
596 | ||
0a61b0df | 597 | void CloseSocketDisconnect(); |
15f3ad4d GA |
598 | |
599 | // Denial-of-service detection/prevention | |
600 | // The idea is to detect peers that are behaving | |
601 | // badly and disconnect/ban them, but do it in a | |
602 | // one-coding-mistake-won't-shatter-the-entire-network | |
603 | // way. | |
604 | // IMPORTANT: There should be nothing I can give a | |
605 | // node that it will forward on that will make that | |
606 | // node's peers drop it. If there is, an attacker | |
607 | // can isolate a node and/or try to split the network. | |
608 | // Dropping a node for sending stuff that is invalid | |
609 | // now but might be valid in a later version is also | |
610 | // dangerous, because it can cause a network split | |
611 | // between nodes running old code and nodes running | |
612 | // new code. | |
613 | static void ClearBanned(); // needed for unit testing | |
67a42f92 | 614 | static bool IsBanned(CNetAddr ip); |
e5219399 | 615 | static bool IsBanned(CSubNet subnet); |
fcc8920f JS |
616 | static void Ban(const CNetAddr &ip, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); |
617 | static void Ban(const CSubNet &subNet, int64_t bantimeoffset = 0, bool sinceUnixEpoch = false); | |
99782971 | 618 | static bool Unban(const CNetAddr &ip); |
e5219399 JS |
619 | static bool Unban(const CSubNet &ip); |
620 | static void GetBanned(std::map<CSubNet, int64_t> &banmap); | |
99782971 | 621 | |
1006f070 | 622 | void copyStats(CNodeStats &stats); |
ce14345a | 623 | |
dc942e6f PW |
624 | static bool IsWhitelistedRange(const CNetAddr &ip); |
625 | static void AddWhitelistedRange(const CSubNet &subnet); | |
626 | ||
ce14345a | 627 | // Network stats |
51ed9ec9 BD |
628 | static void RecordBytesRecv(uint64_t bytes); |
629 | static void RecordBytesSent(uint64_t bytes); | |
ce14345a | 630 | |
51ed9ec9 BD |
631 | static uint64_t GetTotalBytesRecv(); |
632 | static uint64_t GetTotalBytesSent(); | |
0a61b0df | 633 | }; |
634 | ||
635 | ||
636 | ||
269d9c64 | 637 | class CTransaction; |
d38da59b PW |
638 | void RelayTransaction(const CTransaction& tx); |
639 | void RelayTransaction(const CTransaction& tx, const CDataStream& ss); | |
0a61b0df | 640 | |
d004d727 WL |
641 | /** Access to the (IP) address database (peers.dat) */ |
642 | class CAddrDB | |
643 | { | |
644 | private: | |
645 | boost::filesystem::path pathAddr; | |
646 | public: | |
647 | CAddrDB(); | |
648 | bool Write(const CAddrMan& addr); | |
649 | bool Read(CAddrMan& addr); | |
650 | }; | |
651 | ||
093303a8 | 652 | #endif // BITCOIN_NET_H |