]>
Commit | Line | Data |
---|---|---|
0a61b0df | 1 | // Copyright (c) 2009-2010 Satoshi Nakamoto |
88216419 | 2 | // Copyright (c) 2009-2012 The Bitcoin developers |
0a61b0df | 3 | // Distributed under the MIT/X11 software license, see the accompanying |
4 | // file license.txt or http://www.opensource.org/licenses/mit-license.php. | |
5 | ||
f23f9a03 | 6 | #include "irc.h" |
1512d5ce | 7 | #include "db.h" |
40c2614e | 8 | #include "net.h" |
edd309e5 | 9 | #include "init.h" |
fdd7d047 | 10 | #include "strlcpy.h" |
5fee401f | 11 | #include "addrman.h" |
ed6d0b5f | 12 | #include "ui_interface.h" |
0a61b0df | 13 | |
6853e627 | 14 | #ifdef WIN32 |
013df1cc MC |
15 | #include <string.h> |
16 | #endif | |
17 | ||
8bb5edc1 MC |
18 | #ifdef USE_UPNP |
19 | #include <miniupnpc/miniwget.h> | |
20 | #include <miniupnpc/miniupnpc.h> | |
21 | #include <miniupnpc/upnpcommands.h> | |
22 | #include <miniupnpc/upnperrors.h> | |
23 | #endif | |
24 | ||
223b6f1b WL |
25 | using namespace std; |
26 | using namespace boost; | |
27 | ||
0a61b0df | 28 | static const int MAX_OUTBOUND_CONNECTIONS = 8; |
29 | ||
30 | void ThreadMessageHandler2(void* parg); | |
31 | void ThreadSocketHandler2(void* parg); | |
32 | void ThreadOpenConnections2(void* parg); | |
b24e6e4d | 33 | void ThreadOpenAddedConnections2(void* parg); |
8bb5edc1 MC |
34 | #ifdef USE_UPNP |
35 | void ThreadMapPort2(void* parg); | |
36 | #endif | |
2bc6cece | 37 | void ThreadDNSAddressSeed2(void* parg); |
c59abe25 | 38 | bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound = NULL, const char *strDest = NULL, bool fOneShot = false); |
0a61b0df | 39 | |
40 | ||
41 | ||
0a61b0df | 42 | // |
43 | // Global state variables | |
44 | // | |
45 | bool fClient = false; | |
972060ce | 46 | static bool fUseUPnP = false; |
bde280b9 | 47 | uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK); |
090e5b40 | 48 | static CCriticalSection cs_mapLocalHost; |
7fa4443f | 49 | static map<CService, int> mapLocalHost; |
090e5b40 | 50 | static bool vfReachable[NET_MAX] = {}; |
457754d2 | 51 | static bool vfLimited[NET_MAX] = {}; |
99860de3 | 52 | static CNode* pnodeLocalHost = NULL; |
bde280b9 | 53 | uint64 nLocalHostNonce = 0; |
c59881ea | 54 | array<int, THREAD_MAX> vnThreadsRunning; |
8f10a288 | 55 | static std::vector<SOCKET> vhListenSocket; |
5fee401f | 56 | CAddrMan addrman; |
0a61b0df | 57 | |
58 | vector<CNode*> vNodes; | |
59 | CCriticalSection cs_vNodes; | |
0a61b0df | 60 | map<CInv, CDataStream> mapRelay; |
bde280b9 | 61 | deque<pair<int64, CInv> > vRelayExpiration; |
0a61b0df | 62 | CCriticalSection cs_mapRelay; |
bde280b9 | 63 | map<CInv, int64> mapAlreadyAskedFor; |
0a61b0df | 64 | |
478b01d9 PW |
65 | static deque<string> vOneShots; |
66 | CCriticalSection cs_vOneShots; | |
0a61b0df | 67 | |
b24e6e4d MC |
68 | set<CNetAddr> setservAddNodeAddresses; |
69 | CCriticalSection cs_setservAddNodeAddresses; | |
70 | ||
c59abe25 | 71 | static CSemaphore *semOutbound = NULL; |
0a61b0df | 72 | |
478b01d9 PW |
73 | void AddOneShot(string strDest) |
74 | { | |
75 | LOCK(cs_vOneShots); | |
76 | vOneShots.push_back(strDest); | |
77 | } | |
78 | ||
00bcfe0b GA |
79 | unsigned short GetListenPort() |
80 | { | |
81 | return (unsigned short)(GetArg("-port", GetDefaultPort())); | |
82 | } | |
0a61b0df | 83 | |
84 | void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd) | |
85 | { | |
86 | // Filter out duplicate requests | |
87 | if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd) | |
88 | return; | |
89 | pindexLastGetBlocksBegin = pindexBegin; | |
90 | hashLastGetBlocksEnd = hashEnd; | |
91 | ||
92 | PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd); | |
93 | } | |
94 | ||
39857190 | 95 | // find 'best' local address for a particular peer |
7fa4443f | 96 | bool GetLocal(CService& addr, const CNetAddr *paddrPeer) |
39857190 PW |
97 | { |
98 | if (fUseProxy || mapArgs.count("-connect") || fNoListen) | |
99 | return false; | |
0a61b0df | 100 | |
39857190 PW |
101 | int nBestCount = -1; |
102 | int nBestReachability = -1; | |
103 | { | |
104 | LOCK(cs_mapLocalHost); | |
7fa4443f | 105 | for (map<CService, int>::iterator it = mapLocalHost.begin(); it != mapLocalHost.end(); it++) |
39857190 PW |
106 | { |
107 | int nCount = (*it).second; | |
108 | int nReachability = (*it).first.GetReachabilityFrom(paddrPeer); | |
109 | if (nReachability > nBestReachability || (nReachability == nBestReachability && nCount > nBestCount)) | |
110 | { | |
111 | addr = (*it).first; | |
112 | nBestReachability = nReachability; | |
113 | nBestCount = nCount; | |
114 | } | |
115 | } | |
116 | } | |
117 | return nBestCount >= 0; | |
118 | } | |
0a61b0df | 119 | |
39857190 PW |
120 | // get best local address for a particular peer as a CAddress |
121 | CAddress GetLocalAddress(const CNetAddr *paddrPeer) | |
122 | { | |
123 | CAddress ret(CService("0.0.0.0",0),0); | |
7fa4443f | 124 | CService addr; |
39857190 PW |
125 | if (GetLocal(addr, paddrPeer)) |
126 | { | |
7fa4443f | 127 | ret = CAddress(addr); |
39857190 PW |
128 | ret.nServices = nLocalServices; |
129 | ret.nTime = GetAdjustedTime(); | |
130 | } | |
131 | return ret; | |
132 | } | |
0a61b0df | 133 | |
a3342d09 PW |
134 | bool RecvLine(SOCKET hSocket, string& strLine) |
135 | { | |
136 | strLine = ""; | |
137 | loop | |
138 | { | |
139 | char c; | |
140 | int nBytes = recv(hSocket, &c, 1, 0); | |
141 | if (nBytes > 0) | |
142 | { | |
143 | if (c == '\n') | |
144 | continue; | |
145 | if (c == '\r') | |
146 | return true; | |
147 | strLine += c; | |
148 | if (strLine.size() >= 9000) | |
149 | return true; | |
150 | } | |
151 | else if (nBytes <= 0) | |
152 | { | |
153 | if (fShutdown) | |
154 | return false; | |
155 | if (nBytes < 0) | |
156 | { | |
157 | int nErr = WSAGetLastError(); | |
158 | if (nErr == WSAEMSGSIZE) | |
159 | continue; | |
160 | if (nErr == WSAEWOULDBLOCK || nErr == WSAEINTR || nErr == WSAEINPROGRESS) | |
161 | { | |
162 | Sleep(10); | |
163 | continue; | |
164 | } | |
165 | } | |
166 | if (!strLine.empty()) | |
167 | return true; | |
168 | if (nBytes == 0) | |
169 | { | |
170 | // socket closed | |
171 | printf("socket closed\n"); | |
172 | return false; | |
173 | } | |
174 | else | |
175 | { | |
176 | // socket error | |
177 | int nErr = WSAGetLastError(); | |
178 | printf("recv failed: %d\n", nErr); | |
179 | return false; | |
180 | } | |
181 | } | |
182 | } | |
183 | } | |
184 | ||
39857190 PW |
185 | // used when scores of local addresses may have changed |
186 | // pushes better local address to peers | |
187 | void static AdvertizeLocal() | |
188 | { | |
189 | LOCK(cs_vNodes); | |
190 | BOOST_FOREACH(CNode* pnode, vNodes) | |
191 | { | |
192 | if (pnode->fSuccessfullyConnected) | |
193 | { | |
194 | CAddress addrLocal = GetLocalAddress(&pnode->addr); | |
7fa4443f | 195 | if (addrLocal.IsRoutable() && (CService)addrLocal != (CService)pnode->addrLocal) |
39857190 PW |
196 | { |
197 | pnode->PushAddress(addrLocal); | |
198 | pnode->addrLocal = addrLocal; | |
199 | } | |
200 | } | |
201 | } | |
202 | } | |
203 | ||
204 | // learn a new local address | |
7fa4443f | 205 | bool AddLocal(const CService& addr, int nScore) |
39857190 PW |
206 | { |
207 | if (!addr.IsRoutable()) | |
208 | return false; | |
209 | ||
210 | printf("AddLocal(%s,%i)\n", addr.ToString().c_str(), nScore); | |
211 | ||
212 | { | |
213 | LOCK(cs_mapLocalHost); | |
214 | mapLocalHost[addr] = std::max(nScore, mapLocalHost[addr]) + (mapLocalHost.count(addr) ? 1 : 0); | |
090e5b40 PW |
215 | enum Network net = addr.GetNetwork(); |
216 | vfReachable[net] = true; | |
217 | if (net == NET_IPV6) vfReachable[NET_IPV4] = true; | |
39857190 PW |
218 | } |
219 | ||
220 | AdvertizeLocal(); | |
221 | ||
222 | return true; | |
223 | } | |
224 | ||
7fa4443f PW |
225 | bool AddLocal(const CNetAddr& addr, int nScore, int port) |
226 | { | |
227 | if (port == -1) | |
228 | port = GetListenPort(); | |
229 | return AddLocal(CService(addr, port), nScore); | |
230 | } | |
231 | ||
457754d2 PW |
232 | /** Make a particular network entirely off-limits (no automatic connects to it) */ |
233 | void SetLimited(enum Network net, bool fLimited) | |
234 | { | |
235 | LOCK(cs_mapLocalHost); | |
236 | vfLimited[net] = fLimited; | |
237 | } | |
238 | ||
239 | bool IsLimited(const CNetAddr& addr) | |
240 | { | |
241 | LOCK(cs_mapLocalHost); | |
242 | return vfLimited[addr.GetNetwork()]; | |
243 | } | |
244 | ||
245 | /** vote for a local address */ | |
7fa4443f | 246 | bool SeenLocal(const CService& addr) |
39857190 PW |
247 | { |
248 | { | |
249 | LOCK(cs_mapLocalHost); | |
250 | if (mapLocalHost.count(addr) == 0) | |
251 | return false; | |
252 | mapLocalHost[addr]++; | |
253 | } | |
254 | ||
255 | AdvertizeLocal(); | |
256 | ||
257 | return true; | |
258 | } | |
259 | ||
457754d2 | 260 | /** check whether a given address is potentially local */ |
7fa4443f | 261 | bool IsLocal(const CService& addr) |
39857190 PW |
262 | { |
263 | LOCK(cs_mapLocalHost); | |
264 | return mapLocalHost.count(addr) > 0; | |
265 | } | |
0a61b0df | 266 | |
457754d2 | 267 | /** check whether a given address is in a network we can probably connect to */ |
090e5b40 PW |
268 | bool IsReachable(const CNetAddr& addr) |
269 | { | |
270 | LOCK(cs_mapLocalHost); | |
457754d2 PW |
271 | enum Network net = addr.GetNetwork(); |
272 | return vfReachable[net] && !vfLimited[net]; | |
090e5b40 | 273 | } |
0a61b0df | 274 | |
67a42f92 | 275 | bool GetMyExternalIP2(const CService& addrConnect, const char* pszGet, const char* pszKeyword, CNetAddr& ipRet) |
0a61b0df | 276 | { |
277 | SOCKET hSocket; | |
278 | if (!ConnectSocket(addrConnect, hSocket)) | |
279 | return error("GetMyExternalIP() : connection to %s failed", addrConnect.ToString().c_str()); | |
280 | ||
281 | send(hSocket, pszGet, strlen(pszGet), MSG_NOSIGNAL); | |
282 | ||
283 | string strLine; | |
284 | while (RecvLine(hSocket, strLine)) | |
285 | { | |
222e3de4 | 286 | if (strLine.empty()) // HTTP response is separated from headers by blank line |
0a61b0df | 287 | { |
288 | loop | |
289 | { | |
290 | if (!RecvLine(hSocket, strLine)) | |
291 | { | |
292 | closesocket(hSocket); | |
293 | return false; | |
294 | } | |
222e3de4 | 295 | if (pszKeyword == NULL) |
296 | break; | |
ab9dc75a | 297 | if (strLine.find(pszKeyword) != string::npos) |
0a61b0df | 298 | { |
299 | strLine = strLine.substr(strLine.find(pszKeyword) + strlen(pszKeyword)); | |
300 | break; | |
301 | } | |
302 | } | |
303 | closesocket(hSocket); | |
ab9dc75a | 304 | if (strLine.find("<") != string::npos) |
0a61b0df | 305 | strLine = strLine.substr(0, strLine.find("<")); |
306 | strLine = strLine.substr(strspn(strLine.c_str(), " \t\n\r")); | |
307 | while (strLine.size() > 0 && isspace(strLine[strLine.size()-1])) | |
308 | strLine.resize(strLine.size()-1); | |
67a42f92 | 309 | CService addr(strLine,0,true); |
0a61b0df | 310 | printf("GetMyExternalIP() received [%s] %s\n", strLine.c_str(), addr.ToString().c_str()); |
67a42f92 | 311 | if (!addr.IsValid() || !addr.IsRoutable()) |
0a61b0df | 312 | return false; |
67a42f92 | 313 | ipRet.SetIP(addr); |
0a61b0df | 314 | return true; |
315 | } | |
316 | } | |
317 | closesocket(hSocket); | |
318 | return error("GetMyExternalIP() : connection closed"); | |
319 | } | |
320 | ||
629e37dd | 321 | // We now get our external IP from the IRC server first and only use this as a backup |
67a42f92 | 322 | bool GetMyExternalIP(CNetAddr& ipRet) |
0a61b0df | 323 | { |
c981d768 | 324 | CService addrConnect; |
0a61b0df | 325 | const char* pszGet; |
326 | const char* pszKeyword; | |
327 | ||
5d1b8f17 | 328 | if (fNoListen||fUseProxy) |
0a61b0df | 329 | return false; |
330 | ||
331 | for (int nLookup = 0; nLookup <= 1; nLookup++) | |
332 | for (int nHost = 1; nHost <= 2; nHost++) | |
333 | { | |
629e37dd | 334 | // We should be phasing out our use of sites like these. If we need |
335 | // replacements, we should ask for volunteers to put this simple | |
336 | // php file on their webserver that prints the client IP: | |
337 | // <?php echo $_SERVER["REMOTE_ADDR"]; ?> | |
0a61b0df | 338 | if (nHost == 1) |
339 | { | |
c981d768 | 340 | addrConnect = CService("91.198.22.70",80); // checkip.dyndns.org |
0a61b0df | 341 | |
342 | if (nLookup == 1) | |
343 | { | |
67a42f92 | 344 | CService addrIP("checkip.dyndns.org", 80, true); |
a6a5bb7c PW |
345 | if (addrIP.IsValid()) |
346 | addrConnect = addrIP; | |
0a61b0df | 347 | } |
348 | ||
683bcb91 | 349 | pszGet = "GET / HTTP/1.1\r\n" |
350 | "Host: checkip.dyndns.org\r\n" | |
351 | "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n" | |
0a61b0df | 352 | "Connection: close\r\n" |
353 | "\r\n"; | |
354 | ||
683bcb91 | 355 | pszKeyword = "Address:"; |
0a61b0df | 356 | } |
357 | else if (nHost == 2) | |
358 | { | |
c981d768 | 359 | addrConnect = CService("74.208.43.192", 80); // www.showmyip.com |
0a61b0df | 360 | |
361 | if (nLookup == 1) | |
362 | { | |
67a42f92 | 363 | CService addrIP("www.showmyip.com", 80, true); |
a6a5bb7c PW |
364 | if (addrIP.IsValid()) |
365 | addrConnect = addrIP; | |
0a61b0df | 366 | } |
367 | ||
683bcb91 | 368 | pszGet = "GET /simple/ HTTP/1.1\r\n" |
369 | "Host: www.showmyip.com\r\n" | |
0a61b0df | 370 | "User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1)\r\n" |
371 | "Connection: close\r\n" | |
372 | "\r\n"; | |
373 | ||
683bcb91 | 374 | pszKeyword = NULL; // Returns just IP address |
0a61b0df | 375 | } |
376 | ||
377 | if (GetMyExternalIP2(addrConnect, pszGet, pszKeyword, ipRet)) | |
378 | return true; | |
379 | } | |
380 | ||
381 | return false; | |
382 | } | |
383 | ||
629e37dd | 384 | void ThreadGetMyExternalIP(void* parg) |
385 | { | |
39857190 | 386 | CNetAddr addrLocalHost; |
67a42f92 | 387 | if (GetMyExternalIP(addrLocalHost)) |
629e37dd | 388 | { |
389 | printf("GetMyExternalIP() returned %s\n", addrLocalHost.ToStringIP().c_str()); | |
39857190 | 390 | AddLocal(addrLocalHost, LOCAL_HTTP); |
629e37dd | 391 | } |
392 | } | |
393 | ||
0a61b0df | 394 | |
395 | ||
396 | ||
397 | ||
67a42f92 | 398 | void AddressCurrentlyConnected(const CService& addr) |
0a61b0df | 399 | { |
5fee401f | 400 | addrman.Connected(addr); |
0a61b0df | 401 | } |
402 | ||
403 | ||
404 | ||
405 | ||
406 | ||
0a61b0df | 407 | |
408 | ||
67a42f92 | 409 | CNode* FindNode(const CNetAddr& ip) |
0a61b0df | 410 | { |
0a61b0df | 411 | { |
f8dcd5ca | 412 | LOCK(cs_vNodes); |
223b6f1b | 413 | BOOST_FOREACH(CNode* pnode, vNodes) |
67a42f92 | 414 | if ((CNetAddr)pnode->addr == ip) |
0a61b0df | 415 | return (pnode); |
416 | } | |
417 | return NULL; | |
418 | } | |
419 | ||
9bab521d PW |
420 | CNode* FindNode(std::string addrName) |
421 | { | |
422 | LOCK(cs_vNodes); | |
423 | BOOST_FOREACH(CNode* pnode, vNodes) | |
424 | if (pnode->addrName == addrName) | |
425 | return (pnode); | |
426 | return NULL; | |
427 | } | |
428 | ||
67a42f92 | 429 | CNode* FindNode(const CService& addr) |
0a61b0df | 430 | { |
0a61b0df | 431 | { |
f8dcd5ca | 432 | LOCK(cs_vNodes); |
223b6f1b | 433 | BOOST_FOREACH(CNode* pnode, vNodes) |
67a42f92 | 434 | if ((CService)pnode->addr == addr) |
0a61b0df | 435 | return (pnode); |
436 | } | |
437 | return NULL; | |
438 | } | |
439 | ||
9bab521d | 440 | CNode* ConnectNode(CAddress addrConnect, const char *pszDest, int64 nTimeout) |
0a61b0df | 441 | { |
478b01d9 | 442 | if (pszDest == NULL) { |
39857190 | 443 | if (IsLocal(addrConnect)) |
9bab521d | 444 | return NULL; |
0a61b0df | 445 | |
9bab521d PW |
446 | // Look for an existing connection |
447 | CNode* pnode = FindNode((CService)addrConnect); | |
448 | if (pnode) | |
449 | { | |
450 | if (nTimeout != 0) | |
451 | pnode->AddRef(nTimeout); | |
452 | else | |
453 | pnode->AddRef(); | |
454 | return pnode; | |
455 | } | |
0a61b0df | 456 | } |
457 | ||
9bab521d | 458 | |
0a61b0df | 459 | /// debug print |
5fee401f | 460 | printf("trying connection %s lastseen=%.1fhrs\n", |
9bab521d PW |
461 | pszDest ? pszDest : addrConnect.ToString().c_str(), |
462 | pszDest ? 0 : (double)(addrConnect.nTime - GetAdjustedTime())/3600.0); | |
0a61b0df | 463 | |
464 | // Connect | |
465 | SOCKET hSocket; | |
9bab521d | 466 | if (pszDest ? ConnectSocketByName(addrConnect, hSocket, pszDest, GetDefaultPort()) : ConnectSocket(addrConnect, hSocket)) |
0a61b0df | 467 | { |
9bab521d PW |
468 | addrman.Attempt(addrConnect); |
469 | ||
0a61b0df | 470 | /// debug print |
9bab521d | 471 | printf("connected %s\n", pszDest ? pszDest : addrConnect.ToString().c_str()); |
0a61b0df | 472 | |
473 | // Set to nonblocking | |
6853e627 | 474 | #ifdef WIN32 |
0a61b0df | 475 | u_long nOne = 1; |
476 | if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR) | |
477 | printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError()); | |
478 | #else | |
479 | if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) | |
480 | printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno); | |
481 | #endif | |
482 | ||
483 | // Add node | |
9bab521d | 484 | CNode* pnode = new CNode(hSocket, addrConnect, pszDest ? pszDest : "", false); |
0a61b0df | 485 | if (nTimeout != 0) |
486 | pnode->AddRef(nTimeout); | |
487 | else | |
488 | pnode->AddRef(); | |
9bab521d | 489 | |
f8dcd5ca PW |
490 | { |
491 | LOCK(cs_vNodes); | |
0a61b0df | 492 | vNodes.push_back(pnode); |
f8dcd5ca | 493 | } |
0a61b0df | 494 | |
495 | pnode->nTimeConnected = GetTime(); | |
496 | return pnode; | |
497 | } | |
498 | else | |
499 | { | |
500 | return NULL; | |
501 | } | |
502 | } | |
503 | ||
504 | void CNode::CloseSocketDisconnect() | |
505 | { | |
506 | fDisconnect = true; | |
507 | if (hSocket != INVALID_SOCKET) | |
508 | { | |
509 | if (fDebug) | |
510 | printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str()); | |
9bab521d | 511 | printf("disconnecting node %s\n", addrName.c_str()); |
0a61b0df | 512 | closesocket(hSocket); |
513 | hSocket = INVALID_SOCKET; | |
bb13d056 | 514 | vRecv.clear(); |
0a61b0df | 515 | } |
516 | } | |
517 | ||
518 | void CNode::Cleanup() | |
519 | { | |
0a61b0df | 520 | } |
521 | ||
522 | ||
f8ded588 GA |
523 | void CNode::PushVersion() |
524 | { | |
525 | /// when NTP implemented, change to just nTime = GetAdjustedTime() | |
bde280b9 | 526 | int64 nTime = (fInbound ? GetAdjustedTime() : GetTime()); |
c981d768 | 527 | CAddress addrYou = (fUseProxy ? CAddress(CService("0.0.0.0",0)) : addr); |
39857190 | 528 | CAddress addrMe = GetLocalAddress(&addr); |
f8ded588 GA |
529 | RAND_bytes((unsigned char*)&nLocalHostNonce, sizeof(nLocalHostNonce)); |
530 | PushMessage("version", PROTOCOL_VERSION, nLocalServices, nTime, addrYou, addrMe, | |
531 | nLocalHostNonce, FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, std::vector<string>()), nBestHeight); | |
532 | } | |
533 | ||
534 | ||
535 | ||
536 | ||
537 | ||
67a42f92 | 538 | std::map<CNetAddr, int64> CNode::setBanned; |
15f3ad4d GA |
539 | CCriticalSection CNode::cs_setBanned; |
540 | ||
541 | void CNode::ClearBanned() | |
542 | { | |
543 | setBanned.clear(); | |
544 | } | |
545 | ||
67a42f92 | 546 | bool CNode::IsBanned(CNetAddr ip) |
15f3ad4d GA |
547 | { |
548 | bool fResult = false; | |
15f3ad4d | 549 | { |
f8dcd5ca | 550 | LOCK(cs_setBanned); |
67a42f92 | 551 | std::map<CNetAddr, int64>::iterator i = setBanned.find(ip); |
15f3ad4d GA |
552 | if (i != setBanned.end()) |
553 | { | |
bde280b9 | 554 | int64 t = (*i).second; |
15f3ad4d GA |
555 | if (GetTime() < t) |
556 | fResult = true; | |
557 | } | |
558 | } | |
559 | return fResult; | |
560 | } | |
561 | ||
562 | bool CNode::Misbehaving(int howmuch) | |
563 | { | |
564 | if (addr.IsLocal()) | |
565 | { | |
9bab521d | 566 | printf("Warning: local node %s misbehaving\n", addrName.c_str()); |
15f3ad4d GA |
567 | return false; |
568 | } | |
569 | ||
570 | nMisbehavior += howmuch; | |
571 | if (nMisbehavior >= GetArg("-banscore", 100)) | |
572 | { | |
bde280b9 | 573 | int64 banTime = GetTime()+GetArg("-bantime", 60*60*24); // Default 24-hour ban |
f8dcd5ca PW |
574 | { |
575 | LOCK(cs_setBanned); | |
67a42f92 PW |
576 | if (setBanned[addr] < banTime) |
577 | setBanned[addr] = banTime; | |
f8dcd5ca | 578 | } |
15f3ad4d | 579 | CloseSocketDisconnect(); |
9bab521d | 580 | printf("Disconnected %s for misbehavior (score=%d)\n", addrName.c_str(), nMisbehavior); |
15f3ad4d GA |
581 | return true; |
582 | } | |
583 | return false; | |
584 | } | |
585 | ||
0a61b0df | 586 | |
587 | ||
588 | ||
589 | ||
590 | ||
591 | ||
592 | ||
593 | ||
594 | ||
595 | ||
596 | ||
597 | void ThreadSocketHandler(void* parg) | |
598 | { | |
599 | IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg)); | |
600 | try | |
601 | { | |
c59881ea | 602 | vnThreadsRunning[THREAD_SOCKETHANDLER]++; |
0a61b0df | 603 | ThreadSocketHandler2(parg); |
c59881ea | 604 | vnThreadsRunning[THREAD_SOCKETHANDLER]--; |
0a61b0df | 605 | } |
606 | catch (std::exception& e) { | |
c59881ea | 607 | vnThreadsRunning[THREAD_SOCKETHANDLER]--; |
0a61b0df | 608 | PrintException(&e, "ThreadSocketHandler()"); |
609 | } catch (...) { | |
c59881ea | 610 | vnThreadsRunning[THREAD_SOCKETHANDLER]--; |
0a61b0df | 611 | throw; // support pthread_cancel() |
612 | } | |
613 | printf("ThreadSocketHandler exiting\n"); | |
614 | } | |
615 | ||
616 | void ThreadSocketHandler2(void* parg) | |
617 | { | |
618 | printf("ThreadSocketHandler started\n"); | |
619 | list<CNode*> vNodesDisconnected; | |
735a6069 | 620 | unsigned int nPrevNodeCount = 0; |
0a61b0df | 621 | |
622 | loop | |
623 | { | |
624 | // | |
625 | // Disconnect nodes | |
626 | // | |
0a61b0df | 627 | { |
f8dcd5ca | 628 | LOCK(cs_vNodes); |
0a61b0df | 629 | // Disconnect unused nodes |
630 | vector<CNode*> vNodesCopy = vNodes; | |
223b6f1b | 631 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 632 | { |
633 | if (pnode->fDisconnect || | |
634 | (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty())) | |
635 | { | |
636 | // remove from vNodes | |
637 | vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end()); | |
638 | ||
c59abe25 PW |
639 | // release outbound grant (if any) |
640 | pnode->grantOutbound.Release(); | |
092631f0 | 641 | |
0a61b0df | 642 | // close socket and cleanup |
643 | pnode->CloseSocketDisconnect(); | |
644 | pnode->Cleanup(); | |
645 | ||
646 | // hold in disconnected pool until all refs are released | |
647 | pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60); | |
648 | if (pnode->fNetworkNode || pnode->fInbound) | |
649 | pnode->Release(); | |
650 | vNodesDisconnected.push_back(pnode); | |
651 | } | |
652 | } | |
653 | ||
654 | // Delete disconnected nodes | |
655 | list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected; | |
223b6f1b | 656 | BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy) |
0a61b0df | 657 | { |
658 | // wait until threads are done using it | |
659 | if (pnode->GetRefCount() <= 0) | |
660 | { | |
661 | bool fDelete = false; | |
f8dcd5ca PW |
662 | { |
663 | TRY_LOCK(pnode->cs_vSend, lockSend); | |
664 | if (lockSend) | |
665 | { | |
666 | TRY_LOCK(pnode->cs_vRecv, lockRecv); | |
667 | if (lockRecv) | |
668 | { | |
669 | TRY_LOCK(pnode->cs_mapRequests, lockReq); | |
670 | if (lockReq) | |
671 | { | |
672 | TRY_LOCK(pnode->cs_inventory, lockInv); | |
673 | if (lockInv) | |
674 | fDelete = true; | |
675 | } | |
676 | } | |
677 | } | |
678 | } | |
0a61b0df | 679 | if (fDelete) |
680 | { | |
681 | vNodesDisconnected.remove(pnode); | |
682 | delete pnode; | |
683 | } | |
684 | } | |
685 | } | |
686 | } | |
687 | if (vNodes.size() != nPrevNodeCount) | |
688 | { | |
689 | nPrevNodeCount = vNodes.size(); | |
690 | MainFrameRepaint(); | |
691 | } | |
692 | ||
693 | ||
694 | // | |
695 | // Find which sockets have data to receive | |
696 | // | |
697 | struct timeval timeout; | |
698 | timeout.tv_sec = 0; | |
699 | timeout.tv_usec = 50000; // frequency to poll pnode->vSend | |
700 | ||
701 | fd_set fdsetRecv; | |
702 | fd_set fdsetSend; | |
703 | fd_set fdsetError; | |
704 | FD_ZERO(&fdsetRecv); | |
705 | FD_ZERO(&fdsetSend); | |
706 | FD_ZERO(&fdsetError); | |
707 | SOCKET hSocketMax = 0; | |
5f88e888 | 708 | |
8f10a288 | 709 | BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) { |
5f88e888 | 710 | FD_SET(hListenSocket, &fdsetRecv); |
8f10a288 PW |
711 | hSocketMax = max(hSocketMax, hListenSocket); |
712 | } | |
0a61b0df | 713 | { |
f8dcd5ca | 714 | LOCK(cs_vNodes); |
223b6f1b | 715 | BOOST_FOREACH(CNode* pnode, vNodes) |
0a61b0df | 716 | { |
d7f1d200 | 717 | if (pnode->hSocket == INVALID_SOCKET) |
0a61b0df | 718 | continue; |
719 | FD_SET(pnode->hSocket, &fdsetRecv); | |
720 | FD_SET(pnode->hSocket, &fdsetError); | |
721 | hSocketMax = max(hSocketMax, pnode->hSocket); | |
f8dcd5ca PW |
722 | { |
723 | TRY_LOCK(pnode->cs_vSend, lockSend); | |
724 | if (lockSend && !pnode->vSend.empty()) | |
0a61b0df | 725 | FD_SET(pnode->hSocket, &fdsetSend); |
f8dcd5ca | 726 | } |
0a61b0df | 727 | } |
728 | } | |
729 | ||
c59881ea | 730 | vnThreadsRunning[THREAD_SOCKETHANDLER]--; |
0a61b0df | 731 | int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout); |
c59881ea | 732 | vnThreadsRunning[THREAD_SOCKETHANDLER]++; |
0a61b0df | 733 | if (fShutdown) |
734 | return; | |
735 | if (nSelect == SOCKET_ERROR) | |
736 | { | |
737 | int nErr = WSAGetLastError(); | |
3b6ed229 | 738 | if (hSocketMax != INVALID_SOCKET) |
c6710c7a MC |
739 | { |
740 | printf("socket select error %d\n", nErr); | |
c376ac35 | 741 | for (unsigned int i = 0; i <= hSocketMax; i++) |
c6710c7a MC |
742 | FD_SET(i, &fdsetRecv); |
743 | } | |
0a61b0df | 744 | FD_ZERO(&fdsetSend); |
745 | FD_ZERO(&fdsetError); | |
746 | Sleep(timeout.tv_usec/1000); | |
747 | } | |
748 | ||
749 | ||
750 | // | |
751 | // Accept new connections | |
752 | // | |
8f10a288 | 753 | BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) |
5f88e888 | 754 | if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv)) |
0a61b0df | 755 | { |
23aa78c4 | 756 | #ifdef USE_IPV6 |
8f10a288 | 757 | struct sockaddr_storage sockaddr; |
23aa78c4 | 758 | #else |
8f10a288 | 759 | struct sockaddr sockaddr; |
23aa78c4 | 760 | #endif |
0a61b0df | 761 | socklen_t len = sizeof(sockaddr); |
762 | SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len); | |
25ab1758 | 763 | CAddress addr; |
4698dd9a CM |
764 | int nInbound = 0; |
765 | ||
25ab1758 | 766 | if (hSocket != INVALID_SOCKET) |
8f10a288 PW |
767 | if (!addr.SetSockAddr((const struct sockaddr*)&sockaddr)) |
768 | printf("warning: unknown socket family\n"); | |
25ab1758 | 769 | |
f8dcd5ca PW |
770 | { |
771 | LOCK(cs_vNodes); | |
223b6f1b | 772 | BOOST_FOREACH(CNode* pnode, vNodes) |
f8dcd5ca PW |
773 | if (pnode->fInbound) |
774 | nInbound++; | |
775 | } | |
25ab1758 | 776 | |
0a61b0df | 777 | if (hSocket == INVALID_SOCKET) |
778 | { | |
779 | if (WSAGetLastError() != WSAEWOULDBLOCK) | |
780 | printf("socket error accept failed: %d\n", WSAGetLastError()); | |
781 | } | |
5a3e82f9 | 782 | else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS) |
0a61b0df | 783 | { |
f8dcd5ca PW |
784 | { |
785 | LOCK(cs_setservAddNodeAddresses); | |
b24e6e4d MC |
786 | if (!setservAddNodeAddresses.count(addr)) |
787 | closesocket(hSocket); | |
f8dcd5ca | 788 | } |
0a61b0df | 789 | } |
67a42f92 | 790 | else if (CNode::IsBanned(addr)) |
15f3ad4d | 791 | { |
f8c478c4 | 792 | printf("connection from %s dropped (banned)\n", addr.ToString().c_str()); |
15f3ad4d GA |
793 | closesocket(hSocket); |
794 | } | |
0a61b0df | 795 | else |
796 | { | |
a6a5bb7c | 797 | printf("accepted connection %s\n", addr.ToString().c_str()); |
9bab521d | 798 | CNode* pnode = new CNode(hSocket, addr, "", true); |
0a61b0df | 799 | pnode->AddRef(); |
f8dcd5ca PW |
800 | { |
801 | LOCK(cs_vNodes); | |
0a61b0df | 802 | vNodes.push_back(pnode); |
f8dcd5ca | 803 | } |
0a61b0df | 804 | } |
805 | } | |
806 | ||
807 | ||
808 | // | |
809 | // Service each socket | |
810 | // | |
811 | vector<CNode*> vNodesCopy; | |
0a61b0df | 812 | { |
f8dcd5ca | 813 | LOCK(cs_vNodes); |
0a61b0df | 814 | vNodesCopy = vNodes; |
223b6f1b | 815 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 816 | pnode->AddRef(); |
817 | } | |
223b6f1b | 818 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 819 | { |
820 | if (fShutdown) | |
821 | return; | |
822 | ||
823 | // | |
824 | // Receive | |
825 | // | |
826 | if (pnode->hSocket == INVALID_SOCKET) | |
827 | continue; | |
828 | if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError)) | |
829 | { | |
f8dcd5ca PW |
830 | TRY_LOCK(pnode->cs_vRecv, lockRecv); |
831 | if (lockRecv) | |
0a61b0df | 832 | { |
833 | CDataStream& vRecv = pnode->vRecv; | |
834 | unsigned int nPos = vRecv.size(); | |
835 | ||
49731745 | 836 | if (nPos > ReceiveBufferSize()) { |
0a61b0df | 837 | if (!pnode->fDisconnect) |
9cbae55a | 838 | printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size()); |
0a61b0df | 839 | pnode->CloseSocketDisconnect(); |
840 | } | |
9cbae55a GA |
841 | else { |
842 | // typical socket buffer is 8K-64K | |
843 | char pchBuf[0x10000]; | |
844 | int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT); | |
845 | if (nBytes > 0) | |
0a61b0df | 846 | { |
9cbae55a GA |
847 | vRecv.resize(nPos + nBytes); |
848 | memcpy(&vRecv[nPos], pchBuf, nBytes); | |
849 | pnode->nLastRecv = GetTime(); | |
850 | } | |
851 | else if (nBytes == 0) | |
852 | { | |
853 | // socket closed gracefully | |
0a61b0df | 854 | if (!pnode->fDisconnect) |
9cbae55a | 855 | printf("socket closed\n"); |
0a61b0df | 856 | pnode->CloseSocketDisconnect(); |
857 | } | |
9cbae55a GA |
858 | else if (nBytes < 0) |
859 | { | |
860 | // error | |
861 | int nErr = WSAGetLastError(); | |
862 | if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) | |
863 | { | |
864 | if (!pnode->fDisconnect) | |
865 | printf("socket recv error %d\n", nErr); | |
866 | pnode->CloseSocketDisconnect(); | |
867 | } | |
868 | } | |
0a61b0df | 869 | } |
870 | } | |
871 | } | |
872 | ||
873 | // | |
874 | // Send | |
875 | // | |
876 | if (pnode->hSocket == INVALID_SOCKET) | |
877 | continue; | |
878 | if (FD_ISSET(pnode->hSocket, &fdsetSend)) | |
879 | { | |
f8dcd5ca PW |
880 | TRY_LOCK(pnode->cs_vSend, lockSend); |
881 | if (lockSend) | |
0a61b0df | 882 | { |
883 | CDataStream& vSend = pnode->vSend; | |
884 | if (!vSend.empty()) | |
885 | { | |
886 | int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT); | |
887 | if (nBytes > 0) | |
888 | { | |
889 | vSend.erase(vSend.begin(), vSend.begin() + nBytes); | |
890 | pnode->nLastSend = GetTime(); | |
891 | } | |
892 | else if (nBytes < 0) | |
893 | { | |
894 | // error | |
895 | int nErr = WSAGetLastError(); | |
896 | if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS) | |
897 | { | |
898 | printf("socket send error %d\n", nErr); | |
899 | pnode->CloseSocketDisconnect(); | |
900 | } | |
901 | } | |
49731745 | 902 | if (vSend.size() > SendBufferSize()) { |
9cbae55a GA |
903 | if (!pnode->fDisconnect) |
904 | printf("socket send flood control disconnect (%d bytes)\n", vSend.size()); | |
905 | pnode->CloseSocketDisconnect(); | |
906 | } | |
0a61b0df | 907 | } |
908 | } | |
909 | } | |
910 | ||
911 | // | |
912 | // Inactivity checking | |
913 | // | |
914 | if (pnode->vSend.empty()) | |
915 | pnode->nLastSendEmpty = GetTime(); | |
916 | if (GetTime() - pnode->nTimeConnected > 60) | |
917 | { | |
918 | if (pnode->nLastRecv == 0 || pnode->nLastSend == 0) | |
919 | { | |
920 | printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0); | |
921 | pnode->fDisconnect = true; | |
922 | } | |
923 | else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60) | |
924 | { | |
925 | printf("socket not sending\n"); | |
926 | pnode->fDisconnect = true; | |
927 | } | |
928 | else if (GetTime() - pnode->nLastRecv > 90*60) | |
929 | { | |
930 | printf("socket inactivity timeout\n"); | |
931 | pnode->fDisconnect = true; | |
932 | } | |
933 | } | |
934 | } | |
0a61b0df | 935 | { |
f8dcd5ca | 936 | LOCK(cs_vNodes); |
223b6f1b | 937 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 938 | pnode->Release(); |
939 | } | |
940 | ||
0a61b0df | 941 | Sleep(10); |
942 | } | |
943 | } | |
944 | ||
945 | ||
946 | ||
947 | ||
948 | ||
949 | ||
950 | ||
951 | ||
952 | ||
8bb5edc1 MC |
953 | #ifdef USE_UPNP |
954 | void ThreadMapPort(void* parg) | |
955 | { | |
956 | IMPLEMENT_RANDOMIZE_STACK(ThreadMapPort(parg)); | |
957 | try | |
958 | { | |
c59881ea | 959 | vnThreadsRunning[THREAD_UPNP]++; |
8bb5edc1 | 960 | ThreadMapPort2(parg); |
c59881ea | 961 | vnThreadsRunning[THREAD_UPNP]--; |
8bb5edc1 MC |
962 | } |
963 | catch (std::exception& e) { | |
c59881ea | 964 | vnThreadsRunning[THREAD_UPNP]--; |
8bb5edc1 MC |
965 | PrintException(&e, "ThreadMapPort()"); |
966 | } catch (...) { | |
c59881ea | 967 | vnThreadsRunning[THREAD_UPNP]--; |
8bb5edc1 MC |
968 | PrintException(NULL, "ThreadMapPort()"); |
969 | } | |
970 | printf("ThreadMapPort exiting\n"); | |
971 | } | |
972 | ||
973 | void ThreadMapPort2(void* parg) | |
974 | { | |
975 | printf("ThreadMapPort started\n"); | |
976 | ||
977 | char port[6]; | |
00bcfe0b | 978 | sprintf(port, "%d", GetListenPort()); |
8bb5edc1 | 979 | |
8bb5edc1 MC |
980 | const char * multicastif = 0; |
981 | const char * minissdpdpath = 0; | |
982 | struct UPNPDev * devlist = 0; | |
983 | char lanaddr[64]; | |
984 | ||
94b97046 LD |
985 | #ifndef UPNPDISCOVER_SUCCESS |
986 | /* miniupnpc 1.5 */ | |
987 | devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0); | |
988 | #else | |
989 | /* miniupnpc 1.6 */ | |
990 | int error = 0; | |
b4ada906 | 991 | devlist = upnpDiscover(2000, multicastif, minissdpdpath, 0, 0, &error); |
94b97046 | 992 | #endif |
8bb5edc1 MC |
993 | |
994 | struct UPNPUrls urls; | |
995 | struct IGDdatas data; | |
996 | int r; | |
997 | ||
f285d4f4 DH |
998 | r = UPNP_GetValidIGD(devlist, &urls, &data, lanaddr, sizeof(lanaddr)); |
999 | if (r == 1) | |
8bb5edc1 | 1000 | { |
19b6958c | 1001 | if (GetBoolArg("-discover", true)) { |
baba6e7d MC |
1002 | char externalIPAddress[40]; |
1003 | r = UPNP_GetExternalIPAddress(urls.controlURL, data.first.servicetype, externalIPAddress); | |
1004 | if(r != UPNPCOMMAND_SUCCESS) | |
1005 | printf("UPnP: GetExternalIPAddress() returned %d\n", r); | |
1006 | else | |
1007 | { | |
1008 | if(externalIPAddress[0]) | |
1009 | { | |
1010 | printf("UPnP: ExternalIPAddress = %s\n", externalIPAddress); | |
19b6958c | 1011 | AddLocal(CNetAddr(externalIPAddress), LOCAL_UPNP); |
baba6e7d MC |
1012 | } |
1013 | else | |
1014 | printf("UPnP: GetExternalIPAddress failed.\n"); | |
1015 | } | |
1016 | } | |
1017 | ||
15656981 | 1018 | string strDesc = "Bitcoin " + FormatFullVersion(); |
94b97046 | 1019 | #ifndef UPNPDISCOVER_SUCCESS |
177dbcaa | 1020 | /* miniupnpc 1.5 */ |
94b97046 | 1021 | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, |
b985efaa | 1022 | port, port, lanaddr, strDesc.c_str(), "TCP", 0); |
94b97046 | 1023 | #else |
177dbcaa | 1024 | /* miniupnpc 1.6 */ |
8bb5edc1 | 1025 | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, |
b985efaa | 1026 | port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0"); |
94b97046 | 1027 | #endif |
b4ada906 | 1028 | |
8bb5edc1 MC |
1029 | if(r!=UPNPCOMMAND_SUCCESS) |
1030 | printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", | |
1031 | port, port, lanaddr, r, strupnperror(r)); | |
1032 | else | |
1033 | printf("UPnP Port Mapping successful.\n"); | |
177dbcaa | 1034 | int i = 1; |
8bb5edc1 MC |
1035 | loop { |
1036 | if (fShutdown || !fUseUPnP) | |
1037 | { | |
1038 | r = UPNP_DeletePortMapping(urls.controlURL, data.first.servicetype, port, "TCP", 0); | |
1039 | printf("UPNP_DeletePortMapping() returned : %d\n", r); | |
1040 | freeUPNPDevlist(devlist); devlist = 0; | |
1041 | FreeUPNPUrls(&urls); | |
1042 | return; | |
1043 | } | |
177dbcaa MC |
1044 | if (i % 600 == 0) // Refresh every 20 minutes |
1045 | { | |
1046 | #ifndef UPNPDISCOVER_SUCCESS | |
1047 | /* miniupnpc 1.5 */ | |
1048 | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | |
1049 | port, port, lanaddr, strDesc.c_str(), "TCP", 0); | |
1050 | #else | |
1051 | /* miniupnpc 1.6 */ | |
1052 | r = UPNP_AddPortMapping(urls.controlURL, data.first.servicetype, | |
1053 | port, port, lanaddr, strDesc.c_str(), "TCP", 0, "0"); | |
1054 | #endif | |
1055 | ||
1056 | if(r!=UPNPCOMMAND_SUCCESS) | |
1057 | printf("AddPortMapping(%s, %s, %s) failed with code %d (%s)\n", | |
1058 | port, port, lanaddr, r, strupnperror(r)); | |
1059 | else | |
1060 | printf("UPnP Port Mapping successful.\n");; | |
1061 | } | |
8bb5edc1 | 1062 | Sleep(2000); |
177dbcaa | 1063 | i++; |
8bb5edc1 MC |
1064 | } |
1065 | } else { | |
1066 | printf("No valid UPnP IGDs found\n"); | |
1067 | freeUPNPDevlist(devlist); devlist = 0; | |
f285d4f4 DH |
1068 | if (r != 0) |
1069 | FreeUPNPUrls(&urls); | |
8bb5edc1 | 1070 | loop { |
973800b5 | 1071 | if (fShutdown || !fUseUPnP) |
8bb5edc1 MC |
1072 | return; |
1073 | Sleep(2000); | |
1074 | } | |
1075 | } | |
1076 | } | |
1077 | ||
1078 | void MapPort(bool fMapPort) | |
1079 | { | |
1080 | if (fUseUPnP != fMapPort) | |
1081 | { | |
1082 | fUseUPnP = fMapPort; | |
8bb5edc1 | 1083 | } |
c59881ea | 1084 | if (fUseUPnP && vnThreadsRunning[THREAD_UPNP] < 1) |
8bb5edc1 MC |
1085 | { |
1086 | if (!CreateThread(ThreadMapPort, NULL)) | |
1087 | printf("Error: ThreadMapPort(ThreadMapPort) failed\n"); | |
1088 | } | |
1089 | } | |
9f0ac169 GA |
1090 | #else |
1091 | void MapPort(bool /* unused fMapPort */) | |
1092 | { | |
1093 | // Intentionally left blank. | |
1094 | } | |
8bb5edc1 MC |
1095 | #endif |
1096 | ||
1097 | ||
1098 | ||
1099 | ||
1100 | ||
1101 | ||
1102 | ||
1103 | ||
1104 | ||
5fee401f PW |
1105 | // DNS seeds |
1106 | // Each pair gives a source name and a seed name. | |
1107 | // The first name is used as information source for addrman. | |
1108 | // The second name should resolve to a list of seed addresses. | |
1109 | static const char *strDNSSeed[][2] = { | |
1110 | {"xf2.org", "bitseed.xf2.org"}, | |
1111 | {"bluematt.me", "dnsseed.bluematt.me"}, | |
1112 | {"bitcoin.sipa.be", "seed.bitcoin.sipa.be"}, | |
1113 | {"dashjr.org", "dnsseed.bitcoin.dashjr.org"}, | |
f684aec4 | 1114 | }; |
0a61b0df | 1115 | |
2bc6cece | 1116 | void ThreadDNSAddressSeed(void* parg) |
f684aec4 | 1117 | { |
2bc6cece MC |
1118 | IMPLEMENT_RANDOMIZE_STACK(ThreadDNSAddressSeed(parg)); |
1119 | try | |
1120 | { | |
c59881ea | 1121 | vnThreadsRunning[THREAD_DNSSEED]++; |
2bc6cece | 1122 | ThreadDNSAddressSeed2(parg); |
c59881ea | 1123 | vnThreadsRunning[THREAD_DNSSEED]--; |
2bc6cece MC |
1124 | } |
1125 | catch (std::exception& e) { | |
c59881ea | 1126 | vnThreadsRunning[THREAD_DNSSEED]--; |
2bc6cece MC |
1127 | PrintException(&e, "ThreadDNSAddressSeed()"); |
1128 | } catch (...) { | |
c59881ea | 1129 | vnThreadsRunning[THREAD_DNSSEED]--; |
2bc6cece MC |
1130 | throw; // support pthread_cancel() |
1131 | } | |
1132 | printf("ThreadDNSAddressSeed exiting\n"); | |
1133 | } | |
1134 | ||
1135 | void ThreadDNSAddressSeed2(void* parg) | |
1136 | { | |
1137 | printf("ThreadDNSAddressSeed started\n"); | |
f684aec4 JG |
1138 | int found = 0; |
1139 | ||
ce8f78a7 MC |
1140 | if (!fTestNet) |
1141 | { | |
1142 | printf("Loading addresses from DNS seeds (could take a while)\n"); | |
f684aec4 | 1143 | |
c376ac35 | 1144 | for (unsigned int seed_idx = 0; seed_idx < ARRAYLEN(strDNSSeed); seed_idx++) { |
9bab521d | 1145 | if (fProxyNameLookup) { |
478b01d9 | 1146 | AddOneShot(strDNSSeed[seed_idx][1]); |
9bab521d PW |
1147 | } else { |
1148 | vector<CNetAddr> vaddr; | |
1149 | vector<CAddress> vAdd; | |
1150 | if (LookupHost(strDNSSeed[seed_idx][1], vaddr)) | |
a6a5bb7c | 1151 | { |
9bab521d PW |
1152 | BOOST_FOREACH(CNetAddr& ip, vaddr) |
1153 | { | |
1154 | int nOneDay = 24*3600; | |
1155 | CAddress addr = CAddress(CService(ip, GetDefaultPort())); | |
1156 | addr.nTime = GetTime() - 3*nOneDay - GetRand(4*nOneDay); // use a random age between 3 and 7 days old | |
1157 | vAdd.push_back(addr); | |
1158 | found++; | |
1159 | } | |
a6a5bb7c | 1160 | } |
9bab521d | 1161 | addrman.Add(vAdd, CNetAddr(strDNSSeed[seed_idx][0], true)); |
f684aec4 JG |
1162 | } |
1163 | } | |
1164 | } | |
1165 | ||
448b4516 | 1166 | printf("%d addresses found from DNS seeds\n", found); |
f684aec4 | 1167 | } |
0a61b0df | 1168 | |
1169 | ||
1170 | ||
2bc6cece MC |
1171 | |
1172 | ||
1173 | ||
1174 | ||
1175 | ||
1176 | ||
1177 | ||
1178 | ||
1179 | ||
0a61b0df | 1180 | unsigned int pnSeed[] = |
1181 | { | |
b2f76e9d DF |
1182 | 0x959bd347, 0xf8de42b2, 0x73bc0518, 0xea6edc50, 0x21b00a4d, 0xc725b43d, 0xd665464d, 0x1a2a770e, |
1183 | 0x27c93946, 0x65b2fa46, 0xb80ae255, 0x66b3b446, 0xb1877a3e, 0x6ee89e3e, 0xc3175b40, 0x2a01a83c, | |
1184 | 0x95b1363a, 0xa079ad3d, 0xe6ca801f, 0x027f4f4a, 0x34f7f03a, 0xf790f04a, 0x16ca801f, 0x2f4d5e40, | |
1185 | 0x3a4d5e40, 0xc43a322e, 0xc8159753, 0x14d4724c, 0x7919a118, 0xe0bdb34e, 0x68a16b2e, 0xff64b44d, | |
1186 | 0x6099115b, 0x9b57b05b, 0x7bd1b4ad, 0xdf95944f, 0x29d2b73d, 0xafa8db79, 0xe247ba41, 0x24078348, | |
1187 | 0xf722f03c, 0x33567ebc, 0xace64ed4, 0x984d3932, 0xb5f34e55, 0x27b7024d, 0x94579247, 0x8894042e, | |
1188 | 0x9357d34c, 0x1063c24b, 0xcaa228b1, 0xa3c5a8b2, 0x5dc64857, 0xa2c23643, 0xa8369a54, 0x31203077, | |
1189 | 0x00707c5c, 0x09fc0b3a, 0x272e9e2e, 0xf80f043e, 0x9449ca3e, 0x5512c33e, 0xd106b555, 0xe8024157, | |
1190 | 0xe288ec29, 0xc79c5461, 0xafb63932, 0xdb02ab4b, 0x0e512777, 0x8a145a4c, 0xb201ff4f, 0x5e09314b, | |
1191 | 0xcd9bfbcd, 0x1c023765, 0x4394e75c, 0xa728bd4d, 0x65331552, 0xa98420b1, 0x89ecf559, 0x6e80801f, | |
1192 | 0xf404f118, 0xefd62b51, 0x05918346, 0x9b186d5f, 0xacabab46, 0xf912e255, 0xc188ea62, 0xcc55734e, | |
1193 | 0xc668064d, 0xd77a4558, 0x46201c55, 0xf17dfc80, 0xf7142f2e, 0x87bfb718, 0x8aa54fb2, 0xc451d518, | |
1194 | 0xc4ae8831, 0x8dd44d55, 0x5bbd206c, 0x64536b5d, 0x5c667e60, 0x3b064242, 0xfe963a42, 0xa28e6dc8, | |
1195 | 0xe8a9604a, 0xc989464e, 0xd124a659, 0x50065140, 0xa44dfe5e, 0x1079e655, 0x3fb986d5, 0x47895b18, | |
1196 | 0x7d3ce4ad, 0x4561ba50, 0x296eec62, 0x255b41ad, 0xaed35ec9, 0x55556f12, 0xc7d3154d, 0x3297b65d, | |
1197 | 0x8930121f, 0xabf42e4e, 0x4a29e044, 0x1212685d, 0x676c1e40, 0xce009744, 0x383a8948, 0xa2dbd0ad, | |
1198 | 0xecc2564d, 0x07dbc252, 0x887ee24b, 0x5171644c, 0x6bb798c1, 0x847f495d, 0x4cbb7145, 0x3bb81c32, | |
1199 | 0x45eb262e, 0xc8015a4e, 0x250a361b, 0xf694f946, 0xd64a183e, 0xd4f1dd59, 0x8f20ffd4, 0x51d9e55c, | |
1200 | 0x09521763, 0x5e02002e, 0x32c8074d, 0xe685762e, 0x8290b0bc, 0x762a922e, 0xfc5ee754, 0x83a24829, | |
1201 | 0x775b224d, 0x6295bb4d, 0x38ec0555, 0xbffbba50, 0xe5560260, 0x86b16a7c, 0xd372234e, 0x49a3c24b, | |
1202 | 0x2f6a171f, 0x4d75ed60, 0xae94115b, 0xcb543744, 0x63080c59, 0x3f9c724c, 0xc977ce18, 0x532efb18, | |
1203 | 0x69dc3b2e, 0x5f94d929, 0x1732bb4d, 0x9c814b4d, 0xe6b3762e, 0xc024f662, 0x8face35b, 0x6b5b044d, | |
1204 | 0x798c7b57, 0x79a6b44c, 0x067d3057, 0xf9e94e5f, 0x91cbe15b, 0x71405eb2, 0x2662234e, 0xcbcc4a6d, | |
1205 | 0xbf69d54b, 0xa79b4e55, 0xec6d3e51, 0x7c0b3c02, 0x60f83653, 0x24c1e15c, 0x1110b62e, 0x10350f59, | |
1206 | 0xa56f1d55, 0x3509e7a9, 0xeb128354, 0x14268e2e, 0x934e28bc, 0x8e32692e, 0x8331a21f, 0x3e633932, | |
1207 | 0xc812b12e, 0xc684bf2e, 0x80112d2e, 0xe0ddc96c, 0xc630ca4a, 0x5c09b3b2, 0x0b580518, 0xc8e9d54b, | |
1208 | 0xd169aa43, 0x17d0d655, 0x1d029963, 0x7ff87559, 0xcb701f1f, 0x6fa3e85d, 0xe45e9a54, 0xf05d1802, | |
1209 | 0x44d03b2e, 0x837b692e, 0xccd4354e, 0x3d6da13c, 0x3423084d, 0xf707c34a, 0x55f6db3a, 0xad26e442, | |
1210 | 0x6233a21f, 0x09e80e59, 0x8caeb54d, 0xbe870941, 0xb407d20e, 0x20b51018, 0x56fb152e, 0x460d2a4e, | |
1211 | 0xbb9a2946, 0x560eb12e, 0xed83dd29, 0xd6724f53, 0xa50aafb8, 0x451346d9, 0x88348e2e, 0x7312fead, | |
1212 | 0x8ecaf96f, 0x1bda4e5f, 0xf1671e40, 0x3c8c3e3b, 0x4716324d, 0xdde24ede, 0xf98cd17d, 0xa91d4644, | |
1213 | 0x28124eb2, 0x147d5129, 0xd022042e, 0x61733d3b, 0xad0d5e02, 0x8ce2932e, 0xe5c18502, 0x549c1e32, | |
1214 | 0x9685801f, 0x86e217ad, 0xd948214b, 0x4110f462, 0x3a2e894e, 0xbd35492e, 0x87e0d558, 0x64b8ef7d, | |
1215 | 0x7c3eb962, 0x72a84b3e, 0x7cd667c9, 0x28370a2e, 0x4bc60e7b, 0x6fc1ec60, 0x14a6983f, 0x86739a4b, | |
1216 | 0x46954e5f, 0x32e2e15c, 0x2e9326cf, 0xe5801c5e, 0x379607b2, 0x32151145, 0xf0e39744, 0xacb54c55, | |
1217 | 0xa37dfb60, 0x83b55cc9, 0x388f7ca5, 0x15034f5f, 0x3e94965b, 0x68e0ffad, 0x35280f59, 0x8fe190cf, | |
1218 | 0x7c6ba5b2, 0xa5e9db43, 0x4ee1fc60, 0xd9d94e5f, 0x04040677, 0x0ea9b35e, 0x5961f14f, 0x67fda063, | |
1219 | 0xa48a5a31, 0xc6524e55, 0x283d325e, 0x3f37515f, 0x96b94b3e, 0xacce620e, 0x6481cc5b, 0xa4a06d4b, | |
1220 | 0x9e95d2d9, 0xe40c03d5, 0xc2f4514b, 0xb79aad44, 0xf64be843, 0xb2064070, 0xfca00455, 0x429dfa4e, | |
1221 | 0x2323f173, 0xeda4185e, 0xabd5227d, 0x9efd4d58, 0xb1104758, 0x4811e955, 0xbd9ab355, 0xe921f44b, | |
1222 | 0x9f166dce, 0x09e279b2, 0xe0c9ac7b, 0x7901a5ad, 0xa145d4b0, 0x79104671, 0xec31e35a, 0x4fe0b555, | |
1223 | 0xc7d9cbad, 0xad057f55, 0xe94cc759, 0x7fe0b043, 0xe4529f2e, 0x0d4dd4b2, 0x9f11a54d, 0x031e2e4e, | |
1224 | 0xe6014f5f, 0x11d1ca6c, 0x26bd7f61, 0xeb86854f, 0x4d347b57, 0x116bbe2e, 0xdba7234e, 0x7bcbfd2e, | |
1225 | 0x174dd4b2, 0x6686762e, 0xb089ba50, 0xc6258246, 0x087e767b, 0xc4a8cb4a, 0x595dba50, 0x7f0ae502, | |
1226 | 0x7b1dbd5a, 0xa0603492, 0x57d1af4b, 0x9e21ffd4, 0x6393064d, 0x7407376e, 0xe484762e, 0x122a4e53, | |
1227 | 0x4a37aa43, 0x3888a6be, 0xee77864e, 0x039c8dd5, 0x688d89af, 0x0e988f62, 0x08218246, 0xfc2f8246, | |
1228 | 0xd1d97040, 0xd64cd4b2, 0x5ae4a6b8, 0x7d0de9bc, 0x8d304d61, 0x06c5c672, 0xa4c8bd4d, 0xe0fd373b, | |
1229 | 0x575ebe4d, 0x72d26277, 0x55570f55, 0x77b154d9, 0xe214293a, 0xfc740f4b, 0xfe3f6a57, 0xa9c55f02, | |
1230 | 0xae4054db, 0x2394d918, 0xb511b24a, 0xb8741ab2, 0x0758e65e, 0xc7b5795b, 0xb0a30a4c, 0xaf7f170c, | |
1231 | 0xf3b4762e, 0x8179576d, 0x738a1581, 0x4b95b64c, 0x9829b618, 0x1bea932e, 0x7bdeaa4b, 0xcb5e0281, | |
1232 | 0x65618f54, 0x0658474b, 0x27066acf, 0x40556d65, 0x7d204d53, 0xf28bc244, 0xdce23455, 0xadc0ff54, | |
1233 | 0x3863c948, 0xcee34e5f, 0xdeb85e02, 0x2ed17a61, 0x6a7b094d, 0x7f0cfc40, 0x59603f54, 0x3220afbc, | |
1234 | 0xb5dfd962, 0x125d21c0, 0x13f8d243, 0xacfefb4e, 0x86c2c147, 0x3d8bbd59, 0xbd02a21f, 0x2593042e, | |
1235 | 0xc6a17a7c, 0x28925861, 0xb487ed44, 0xb5f4fd6d, 0x90c28a45, 0x5a14f74d, 0x43d71b4c, 0x728ebb5d, | |
1236 | 0x885bf950, 0x08134dd0, 0x38ec046e, 0xc575684b, 0x50082d2e, 0xa2f47757, 0x270f86ae, 0xf3ff6462, | |
1237 | 0x10ed3f4e, 0x4b58d462, 0xe01ce23e, 0x8c5b092e, 0x63e52f4e, 0x22c1e85d, 0xa908f54e, 0x8591624f, | |
1238 | 0x2c0fb94e, 0xa280ba3c, 0xb6f41b4c, 0x24f9aa47, 0x27201647, 0x3a3ea6dc, 0xa14fc3be, 0x3c34bdd5, | |
1239 | 0x5b8d4f5b, 0xaadeaf4b, 0xc71cab50, 0x15697a4c, 0x9a1a734c, 0x2a037d81, 0x2590bd59, 0x48ec2741, | |
1240 | 0x53489c5b, 0x7f00314b, 0x2170d362, 0xf2e92542, 0x42c10b44, 0x98f0f118, 0x883a3456, 0x099a932e, | |
1241 | 0xea38f7bc, 0x644e9247, 0xbb61b62e, 0x30e0863d, 0x5f51be54, 0x207215c7, 0x5f306c45, 0xaa7f3932, | |
1242 | 0x98da7d45, 0x4e339b59, 0x2e411581, 0xa808f618, 0xad2c0c59, 0x54476741, 0x09e99fd1, 0x5db8f752, | |
1243 | 0xc16df8bd, 0x1dd4b44f, 0x106edf2e, 0x9e15c180, 0x2ad6b56f, 0x633a5332, 0xff33787c, 0x077cb545, | |
1244 | 0x6610be6d, 0x75aad2c4, 0x72fb4d5b, 0xe81e0f59, 0x576f6332, 0x47333373, 0x351ed783, 0x2d90fb50, | |
1245 | 0x8d5e0f6c, 0x5b27a552, 0xdb293ebb, 0xe55ef950, 0x4b133ad8, 0x75df975a, 0x7b6a8740, 0xa899464b, | |
1246 | 0xfab15161, 0x10f8b64d, 0xd055ea4d, 0xee8e146b, 0x4b14afb8, 0x4bc1c44a, 0x9b961dcc, 0xd111ff43, | |
1247 | 0xfca0b745, 0xc800e412, 0x0afad9d1, 0xf751c350, 0xf9f0cccf, 0xa290a545, 0x8ef13763, 0x7ec70d59, | |
1248 | 0x2b066acf, 0x65496c45, 0xade02c1b, 0xae6eb077, 0x92c1e65b, 0xc064e6a9, 0xc649e56d, 0x5287a243, | |
1249 | 0x36de4f5b, 0x5b1df6ad, 0x65c39a59, 0xdba805b2, 0x20067aa8, 0x6457e56d, 0x3cee26cf, 0xfd3ff26d, | |
1250 | 0x04f86d4a, 0x06b8e048, 0xa93bcd5c, 0x91135852, 0xbe90a643, 0x8fa0094d, 0x06d8215f, 0x2677094d, | |
1251 | 0xd735685c, 0x164a00c9, 0x5209ac5f, 0xa9564c5c, 0x3b504f5f, 0xcc826bd0, 0x4615042e, 0x5fe13b4a, | |
1252 | 0x8c81b86d, 0x879ab68c, 0x1de564b8, 0x434487d8, 0x2dcb1b63, 0x82ab524a, 0xb0676abb, 0xa13d9c62, | |
1253 | 0xdbb5b86d, 0x5b7f4b59, 0xaddfb44d, 0xad773532, 0x3997054c, 0x72cebd89, 0xb194544c, 0xc5b8046e, | |
1254 | 0x6e1adeb2, 0xaa5abb51, 0xefb54b44, 0x15efc54f, 0xe9f1bc4d, 0x5f401b6c, 0x97f018ad, 0xc82f9252, | |
1255 | 0x2cdc762e, 0x8e52e56d, 0x1827175e, 0x9b7d7d80, 0xb2ad6845, 0x51065140, 0x71180a18, 0x5b27006c, | |
1256 | 0x0621e255, 0x721cbe58, 0x670c0cb8, 0xf8bd715d, 0xe0bdc5d9, 0xed843501, 0x4b84554d, 0x7f1a18bc, | |
1257 | 0x53bcaf47, 0x5729d35f, 0xf0dda246, 0x22382bd0, 0x4d641fb0, 0x316afcde, 0x50a22f1f, 0x73608046, | |
1258 | 0xc461d84a, 0xb2dbe247, | |
0a61b0df | 1259 | }; |
1260 | ||
5fee401f PW |
1261 | void DumpAddresses() |
1262 | { | |
1263 | CAddrDB adb; | |
1264 | adb.WriteAddrman(addrman); | |
1265 | } | |
0a61b0df | 1266 | |
5fee401f PW |
1267 | void ThreadDumpAddress2(void* parg) |
1268 | { | |
1269 | vnThreadsRunning[THREAD_DUMPADDRESS]++; | |
1270 | while (!fShutdown) | |
1271 | { | |
1272 | DumpAddresses(); | |
1273 | vnThreadsRunning[THREAD_DUMPADDRESS]--; | |
1274 | Sleep(100000); | |
1275 | vnThreadsRunning[THREAD_DUMPADDRESS]++; | |
1276 | } | |
1277 | vnThreadsRunning[THREAD_DUMPADDRESS]--; | |
1278 | } | |
1279 | ||
1280 | void ThreadDumpAddress(void* parg) | |
1281 | { | |
1282 | IMPLEMENT_RANDOMIZE_STACK(ThreadDumpAddress(parg)); | |
1283 | try | |
1284 | { | |
1285 | ThreadDumpAddress2(parg); | |
1286 | } | |
1287 | catch (std::exception& e) { | |
1288 | PrintException(&e, "ThreadDumpAddress()"); | |
1289 | } | |
1290 | printf("ThreadDumpAddress exiting\n"); | |
1291 | } | |
0a61b0df | 1292 | |
1293 | void ThreadOpenConnections(void* parg) | |
1294 | { | |
1295 | IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg)); | |
1296 | try | |
1297 | { | |
c59881ea | 1298 | vnThreadsRunning[THREAD_OPENCONNECTIONS]++; |
0a61b0df | 1299 | ThreadOpenConnections2(parg); |
c59881ea | 1300 | vnThreadsRunning[THREAD_OPENCONNECTIONS]--; |
0a61b0df | 1301 | } |
1302 | catch (std::exception& e) { | |
c59881ea | 1303 | vnThreadsRunning[THREAD_OPENCONNECTIONS]--; |
0a61b0df | 1304 | PrintException(&e, "ThreadOpenConnections()"); |
1305 | } catch (...) { | |
c59881ea | 1306 | vnThreadsRunning[THREAD_OPENCONNECTIONS]--; |
0a61b0df | 1307 | PrintException(NULL, "ThreadOpenConnections()"); |
1308 | } | |
1309 | printf("ThreadOpenConnections exiting\n"); | |
1310 | } | |
1311 | ||
478b01d9 PW |
1312 | void static ProcessOneShot() |
1313 | { | |
1314 | string strDest; | |
1315 | { | |
1316 | LOCK(cs_vOneShots); | |
1317 | if (vOneShots.empty()) | |
1318 | return; | |
1319 | strDest = vOneShots.front(); | |
1320 | vOneShots.pop_front(); | |
1321 | } | |
1322 | CAddress addr; | |
c59abe25 PW |
1323 | CSemaphoreGrant grant(*semOutbound, true); |
1324 | if (grant) { | |
1325 | if (!OpenNetworkConnection(addr, &grant, strDest.c_str(), true)) | |
1326 | AddOneShot(strDest); | |
1327 | } | |
478b01d9 PW |
1328 | } |
1329 | ||
0a61b0df | 1330 | void ThreadOpenConnections2(void* parg) |
1331 | { | |
1332 | printf("ThreadOpenConnections started\n"); | |
1333 | ||
1334 | // Connect to specific addresses | |
1335 | if (mapArgs.count("-connect")) | |
1336 | { | |
bde280b9 | 1337 | for (int64 nLoop = 0;; nLoop++) |
0a61b0df | 1338 | { |
478b01d9 | 1339 | ProcessOneShot(); |
223b6f1b | 1340 | BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"]) |
0a61b0df | 1341 | { |
478b01d9 | 1342 | CAddress addr; |
c59abe25 | 1343 | OpenNetworkConnection(addr, NULL, strAddr.c_str()); |
0a61b0df | 1344 | for (int i = 0; i < 10 && i < nLoop; i++) |
1345 | { | |
1346 | Sleep(500); | |
1347 | if (fShutdown) | |
1348 | return; | |
1349 | } | |
1350 | } | |
1351 | } | |
1352 | } | |
1353 | ||
0a61b0df | 1354 | // Initiate network connections |
bde280b9 | 1355 | int64 nStart = GetTime(); |
0a61b0df | 1356 | loop |
1357 | { | |
478b01d9 PW |
1358 | ProcessOneShot(); |
1359 | ||
c59881ea | 1360 | vnThreadsRunning[THREAD_OPENCONNECTIONS]--; |
0a61b0df | 1361 | Sleep(500); |
c59881ea | 1362 | vnThreadsRunning[THREAD_OPENCONNECTIONS]++; |
cc201e01 PW |
1363 | if (fShutdown) |
1364 | return; | |
1365 | ||
c59abe25 | 1366 | |
092631f0 | 1367 | vnThreadsRunning[THREAD_OPENCONNECTIONS]--; |
c59abe25 | 1368 | CSemaphoreGrant grant(*semOutbound); |
092631f0 PW |
1369 | vnThreadsRunning[THREAD_OPENCONNECTIONS]++; |
1370 | if (fShutdown) | |
1371 | return; | |
0a61b0df | 1372 | |
5fee401f PW |
1373 | // Add seed nodes if IRC isn't working |
1374 | bool fTOR = (fUseProxy && addrProxy.GetPort() == 9050); | |
1375 | if (addrman.size()==0 && (GetTime() - nStart > 60 || fTOR) && !fTestNet) | |
a75d7066 | 1376 | { |
5fee401f | 1377 | std::vector<CAddress> vAdd; |
c376ac35 | 1378 | for (unsigned int i = 0; i < ARRAYLEN(pnSeed); i++) |
0a61b0df | 1379 | { |
a75d7066 PW |
1380 | // It'll only connect to one or two seed nodes because once it connects, |
1381 | // it'll get a pile of addresses with newer timestamps. | |
1382 | // Seed nodes are given a random 'last seen time' of between one and two | |
1383 | // weeks ago. | |
1384 | const int64 nOneWeek = 7*24*60*60; | |
67a42f92 PW |
1385 | struct in_addr ip; |
1386 | memcpy(&ip, &pnSeed[i], sizeof(ip)); | |
1387 | CAddress addr(CService(ip, GetDefaultPort())); | |
a75d7066 | 1388 | addr.nTime = GetTime()-GetRand(nOneWeek)-nOneWeek; |
5fee401f | 1389 | vAdd.push_back(addr); |
0a61b0df | 1390 | } |
5fee401f | 1391 | addrman.Add(vAdd, CNetAddr("127.0.0.1")); |
0a61b0df | 1392 | } |
1393 | ||
0a61b0df | 1394 | // |
1395 | // Choose an address to connect to based on most recently seen | |
1396 | // | |
1397 | CAddress addrConnect; | |
0a61b0df | 1398 | |
1399 | // Only connect to one address per a.b.?.? range. | |
1400 | // Do this here so we don't have to critsect vNodes inside mapAddresses critsect. | |
c59abe25 | 1401 | int nOutbound = 0; |
67a42f92 | 1402 | set<vector<unsigned char> > setConnected; |
f8dcd5ca PW |
1403 | { |
1404 | LOCK(cs_vNodes); | |
c59abe25 | 1405 | BOOST_FOREACH(CNode* pnode, vNodes) { |
67a42f92 | 1406 | setConnected.insert(pnode->addr.GetGroup()); |
c59abe25 PW |
1407 | if (!pnode->fInbound) |
1408 | nOutbound++; | |
1409 | } | |
f8dcd5ca | 1410 | } |
0a61b0df | 1411 | |
bde280b9 | 1412 | int64 nANow = GetAdjustedTime(); |
a4e6ae10 | 1413 | |
5fee401f PW |
1414 | int nTries = 0; |
1415 | loop | |
0a61b0df | 1416 | { |
5fee401f PW |
1417 | // use an nUnkBias between 10 (no outgoing connections) and 90 (8 outgoing connections) |
1418 | CAddress addr = addrman.Select(10 + min(nOutbound,8)*10); | |
0a61b0df | 1419 | |
5fee401f | 1420 | // if we selected an invalid address, restart |
23aa78c4 | 1421 | if (!addr.IsValid() || setConnected.count(addr.GetGroup()) || IsLocal(addr)) |
5fee401f | 1422 | break; |
0a61b0df | 1423 | |
5fee401f | 1424 | nTries++; |
0a61b0df | 1425 | |
457754d2 PW |
1426 | if (IsLimited(addr)) |
1427 | continue; | |
1428 | ||
5fee401f PW |
1429 | // only consider very recently tried nodes after 30 failed attempts |
1430 | if (nANow - addr.nLastTry < 600 && nTries < 30) | |
1431 | continue; | |
1432 | ||
1433 | // do not allow non-default ports, unless after 50 invalid addresses selected already | |
1434 | if (addr.GetPort() != GetDefaultPort() && nTries < 50) | |
1435 | continue; | |
1436 | ||
1437 | addrConnect = addr; | |
1438 | break; | |
0a61b0df | 1439 | } |
1440 | ||
1441 | if (addrConnect.IsValid()) | |
c59abe25 | 1442 | OpenNetworkConnection(addrConnect, &grant); |
0a61b0df | 1443 | } |
1444 | } | |
1445 | ||
b24e6e4d MC |
1446 | void ThreadOpenAddedConnections(void* parg) |
1447 | { | |
1448 | IMPLEMENT_RANDOMIZE_STACK(ThreadOpenAddedConnections(parg)); | |
1449 | try | |
1450 | { | |
c59881ea | 1451 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; |
b24e6e4d | 1452 | ThreadOpenAddedConnections2(parg); |
c59881ea | 1453 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; |
b24e6e4d MC |
1454 | } |
1455 | catch (std::exception& e) { | |
c59881ea | 1456 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; |
b24e6e4d MC |
1457 | PrintException(&e, "ThreadOpenAddedConnections()"); |
1458 | } catch (...) { | |
c59881ea | 1459 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; |
b24e6e4d MC |
1460 | PrintException(NULL, "ThreadOpenAddedConnections()"); |
1461 | } | |
1462 | printf("ThreadOpenAddedConnections exiting\n"); | |
1463 | } | |
1464 | ||
1465 | void ThreadOpenAddedConnections2(void* parg) | |
1466 | { | |
1467 | printf("ThreadOpenAddedConnections started\n"); | |
1468 | ||
1469 | if (mapArgs.count("-addnode") == 0) | |
1470 | return; | |
1471 | ||
9bab521d PW |
1472 | if (fProxyNameLookup) { |
1473 | while(!fShutdown) { | |
1474 | BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) { | |
1475 | CAddress addr; | |
c59abe25 PW |
1476 | CSemaphoreGrant grant(*semOutbound); |
1477 | OpenNetworkConnection(addr, &grant, strAddNode.c_str()); | |
9bab521d PW |
1478 | Sleep(500); |
1479 | } | |
1480 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; | |
1481 | Sleep(120000); // Retry every 2 minutes | |
1482 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; | |
1483 | } | |
1484 | return; | |
1485 | } | |
1486 | ||
b24e6e4d MC |
1487 | vector<vector<CService> > vservAddressesToAdd(0); |
1488 | BOOST_FOREACH(string& strAddNode, mapMultiArgs["-addnode"]) | |
1489 | { | |
1490 | vector<CService> vservNode(0); | |
9bab521d | 1491 | if(Lookup(strAddNode.c_str(), vservNode, GetDefaultPort(), fNameLookup, 0)) |
b24e6e4d MC |
1492 | { |
1493 | vservAddressesToAdd.push_back(vservNode); | |
f8dcd5ca PW |
1494 | { |
1495 | LOCK(cs_setservAddNodeAddresses); | |
b24e6e4d MC |
1496 | BOOST_FOREACH(CService& serv, vservNode) |
1497 | setservAddNodeAddresses.insert(serv); | |
f8dcd5ca | 1498 | } |
b24e6e4d MC |
1499 | } |
1500 | } | |
1501 | loop | |
1502 | { | |
1503 | vector<vector<CService> > vservConnectAddresses = vservAddressesToAdd; | |
1504 | // Attempt to connect to each IP for each addnode entry until at least one is successful per addnode entry | |
9bab521d | 1505 | // (keeping in mind that addnode entries can have many IPs if fNameLookup) |
f8dcd5ca PW |
1506 | { |
1507 | LOCK(cs_vNodes); | |
b24e6e4d MC |
1508 | BOOST_FOREACH(CNode* pnode, vNodes) |
1509 | for (vector<vector<CService> >::iterator it = vservConnectAddresses.begin(); it != vservConnectAddresses.end(); it++) | |
1510 | BOOST_FOREACH(CService& addrNode, *(it)) | |
1511 | if (pnode->addr == addrNode) | |
1512 | { | |
1513 | it = vservConnectAddresses.erase(it); | |
1514 | it--; | |
1515 | break; | |
1516 | } | |
f8dcd5ca | 1517 | } |
b24e6e4d MC |
1518 | BOOST_FOREACH(vector<CService>& vserv, vservConnectAddresses) |
1519 | { | |
c59abe25 PW |
1520 | CSemaphoreGrant grant(*semOutbound); |
1521 | OpenNetworkConnection(CAddress(*(vserv.begin())), &grant); | |
b24e6e4d MC |
1522 | Sleep(500); |
1523 | if (fShutdown) | |
1524 | return; | |
1525 | } | |
1526 | if (fShutdown) | |
1527 | return; | |
c59881ea | 1528 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]--; |
b24e6e4d | 1529 | Sleep(120000); // Retry every 2 minutes |
c59881ea | 1530 | vnThreadsRunning[THREAD_ADDEDCONNECTIONS]++; |
b24e6e4d MC |
1531 | if (fShutdown) |
1532 | return; | |
1533 | } | |
1534 | } | |
1535 | ||
c59abe25 PW |
1536 | // if succesful, this moves the passed grant to the constructed node |
1537 | bool OpenNetworkConnection(const CAddress& addrConnect, CSemaphoreGrant *grantOutbound, const char *strDest, bool fOneShot) | |
0a61b0df | 1538 | { |
1539 | // | |
1540 | // Initiate outbound network connection | |
1541 | // | |
1542 | if (fShutdown) | |
1543 | return false; | |
9bab521d | 1544 | if (!strDest) |
39857190 PW |
1545 | if (IsLocal(addrConnect) || |
1546 | FindNode((CNetAddr)addrConnect) || CNode::IsBanned(addrConnect) || | |
9bab521d PW |
1547 | FindNode(addrConnect.ToStringIPPort().c_str())) |
1548 | return false; | |
1549 | if (strDest && FindNode(strDest)) | |
0a61b0df | 1550 | return false; |
1551 | ||
c59881ea | 1552 | vnThreadsRunning[THREAD_OPENCONNECTIONS]--; |
9bab521d | 1553 | CNode* pnode = ConnectNode(addrConnect, strDest); |
c59881ea | 1554 | vnThreadsRunning[THREAD_OPENCONNECTIONS]++; |
0a61b0df | 1555 | if (fShutdown) |
1556 | return false; | |
1557 | if (!pnode) | |
1558 | return false; | |
c59abe25 PW |
1559 | if (grantOutbound) |
1560 | grantOutbound->MoveTo(pnode->grantOutbound); | |
0a61b0df | 1561 | pnode->fNetworkNode = true; |
478b01d9 PW |
1562 | if (fOneShot) |
1563 | pnode->fOneShot = true; | |
0a61b0df | 1564 | |
0a61b0df | 1565 | return true; |
1566 | } | |
1567 | ||
1568 | ||
1569 | ||
1570 | ||
1571 | ||
1572 | ||
1573 | ||
1574 | ||
1575 | void ThreadMessageHandler(void* parg) | |
1576 | { | |
1577 | IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg)); | |
1578 | try | |
1579 | { | |
c59881ea | 1580 | vnThreadsRunning[THREAD_MESSAGEHANDLER]++; |
0a61b0df | 1581 | ThreadMessageHandler2(parg); |
c59881ea | 1582 | vnThreadsRunning[THREAD_MESSAGEHANDLER]--; |
0a61b0df | 1583 | } |
1584 | catch (std::exception& e) { | |
c59881ea | 1585 | vnThreadsRunning[THREAD_MESSAGEHANDLER]--; |
0a61b0df | 1586 | PrintException(&e, "ThreadMessageHandler()"); |
1587 | } catch (...) { | |
c59881ea | 1588 | vnThreadsRunning[THREAD_MESSAGEHANDLER]--; |
0a61b0df | 1589 | PrintException(NULL, "ThreadMessageHandler()"); |
1590 | } | |
1591 | printf("ThreadMessageHandler exiting\n"); | |
1592 | } | |
1593 | ||
1594 | void ThreadMessageHandler2(void* parg) | |
1595 | { | |
1596 | printf("ThreadMessageHandler started\n"); | |
1597 | SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL); | |
1598 | while (!fShutdown) | |
1599 | { | |
1600 | vector<CNode*> vNodesCopy; | |
0a61b0df | 1601 | { |
f8dcd5ca | 1602 | LOCK(cs_vNodes); |
0a61b0df | 1603 | vNodesCopy = vNodes; |
223b6f1b | 1604 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 1605 | pnode->AddRef(); |
1606 | } | |
1607 | ||
1608 | // Poll the connected nodes for messages | |
1609 | CNode* pnodeTrickle = NULL; | |
1610 | if (!vNodesCopy.empty()) | |
1611 | pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())]; | |
223b6f1b | 1612 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 1613 | { |
1614 | // Receive messages | |
f8dcd5ca PW |
1615 | { |
1616 | TRY_LOCK(pnode->cs_vRecv, lockRecv); | |
1617 | if (lockRecv) | |
1618 | ProcessMessages(pnode); | |
1619 | } | |
0a61b0df | 1620 | if (fShutdown) |
1621 | return; | |
1622 | ||
1623 | // Send messages | |
f8dcd5ca PW |
1624 | { |
1625 | TRY_LOCK(pnode->cs_vSend, lockSend); | |
1626 | if (lockSend) | |
1627 | SendMessages(pnode, pnode == pnodeTrickle); | |
1628 | } | |
0a61b0df | 1629 | if (fShutdown) |
1630 | return; | |
1631 | } | |
1632 | ||
0a61b0df | 1633 | { |
f8dcd5ca | 1634 | LOCK(cs_vNodes); |
223b6f1b | 1635 | BOOST_FOREACH(CNode* pnode, vNodesCopy) |
0a61b0df | 1636 | pnode->Release(); |
1637 | } | |
1638 | ||
7629d36a | 1639 | // Wait and allow messages to bunch up. |
1640 | // Reduce vnThreadsRunning so StopNode has permission to exit while | |
1641 | // we're sleeping, but we must always check fShutdown after doing this. | |
c59881ea | 1642 | vnThreadsRunning[THREAD_MESSAGEHANDLER]--; |
0a61b0df | 1643 | Sleep(100); |
3f647537 | 1644 | if (fRequestShutdown) |
1645 | Shutdown(NULL); | |
c59881ea | 1646 | vnThreadsRunning[THREAD_MESSAGEHANDLER]++; |
0a61b0df | 1647 | if (fShutdown) |
1648 | return; | |
1649 | } | |
1650 | } | |
1651 | ||
1652 | ||
1653 | ||
1654 | ||
1655 | ||
1656 | ||
8f10a288 | 1657 | bool BindListenPort(const CService &addrBind, string& strError) |
0a61b0df | 1658 | { |
1659 | strError = ""; | |
1660 | int nOne = 1; | |
1661 | ||
6853e627 | 1662 | #ifdef WIN32 |
0a61b0df | 1663 | // Initialize Windows Sockets |
1664 | WSADATA wsadata; | |
1665 | int ret = WSAStartup(MAKEWORD(2,2), &wsadata); | |
1666 | if (ret != NO_ERROR) | |
1667 | { | |
1668 | strError = strprintf("Error: TCP/IP socket library failed to start (WSAStartup returned error %d)", ret); | |
1669 | printf("%s\n", strError.c_str()); | |
1670 | return false; | |
1671 | } | |
1672 | #endif | |
1673 | ||
1674 | // Create socket for listening for incoming connections | |
23aa78c4 | 1675 | #ifdef USE_IPV6 |
8f10a288 | 1676 | struct sockaddr_storage sockaddr; |
23aa78c4 | 1677 | #else |
8f10a288 | 1678 | struct sockaddr sockaddr; |
23aa78c4 | 1679 | #endif |
8f10a288 PW |
1680 | socklen_t len = sizeof(sockaddr); |
1681 | if (!addrBind.GetSockAddr((struct sockaddr*)&sockaddr, &len)) | |
1682 | { | |
1683 | strError = strprintf("Error: bind address family for %s not supported", addrBind.ToString().c_str()); | |
1684 | printf("%s\n", strError.c_str()); | |
1685 | return false; | |
1686 | } | |
1687 | ||
1688 | SOCKET hListenSocket = socket(((struct sockaddr*)&sockaddr)->sa_family, SOCK_STREAM, IPPROTO_TCP); | |
0a61b0df | 1689 | if (hListenSocket == INVALID_SOCKET) |
1690 | { | |
1691 | strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError()); | |
1692 | printf("%s\n", strError.c_str()); | |
1693 | return false; | |
1694 | } | |
1695 | ||
ec93a0e2 | 1696 | #ifdef SO_NOSIGPIPE |
0a61b0df | 1697 | // Different way of disabling SIGPIPE on BSD |
1698 | setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int)); | |
1699 | #endif | |
1700 | ||
6853e627 | 1701 | #ifndef WIN32 |
0a61b0df | 1702 | // Allow binding if the port is still in TIME_WAIT state after |
1703 | // the program was closed and restarted. Not an issue on windows. | |
1704 | setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int)); | |
1705 | #endif | |
1706 | ||
8f10a288 | 1707 | |
6853e627 | 1708 | #ifdef WIN32 |
0a61b0df | 1709 | // Set to nonblocking, incoming connections will also inherit this |
1710 | if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR) | |
1711 | #else | |
1712 | if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR) | |
1713 | #endif | |
1714 | { | |
1715 | strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError()); | |
1716 | printf("%s\n", strError.c_str()); | |
1717 | return false; | |
1718 | } | |
1719 | ||
23aa78c4 | 1720 | #ifdef USE_IPV6 |
8f10a288 PW |
1721 | // some systems don't have IPV6_V6ONLY but are always v6only; others do have the option |
1722 | // and enable it by default or not. Try to enable it, if possible. | |
1723 | if (addrBind.IsIPv6()) { | |
1724 | #ifdef IPV6_V6ONLY | |
1725 | setsockopt(hListenSocket, IPPROTO_IPV6, IPV6_V6ONLY, (void*)&nOne, sizeof(int)); | |
23aa78c4 | 1726 | #endif |
8f10a288 PW |
1727 | #ifdef WIN32 |
1728 | int nProtLevel = 10 /* PROTECTION_LEVEL_UNRESTRICTED */; | |
1729 | int nParameterId = 23 /* IPV6_PROTECTION_LEVEl */; | |
1730 | // this call is allowed to fail | |
1731 | setsockopt(hListenSocket, IPPROTO_IPV6, nParameterId, (const char*)&nProtLevel, sizeof(int)); | |
1732 | #endif | |
1733 | } | |
1734 | #endif | |
1735 | ||
1736 | if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, len) == SOCKET_ERROR) | |
0a61b0df | 1737 | { |
1738 | int nErr = WSAGetLastError(); | |
1739 | if (nErr == WSAEADDRINUSE) | |
8f10a288 | 1740 | strError = strprintf(_("Unable to bind to %s on this computer. Bitcoin is probably already running."), addrBind.ToString().c_str()); |
0a61b0df | 1741 | else |
8f10a288 | 1742 | strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %d, %s)"), addrBind.ToString().c_str(), nErr, strerror(nErr)); |
0a61b0df | 1743 | printf("%s\n", strError.c_str()); |
1744 | return false; | |
1745 | } | |
8f10a288 | 1746 | printf("Bound to %s\n", addrBind.ToString().c_str()); |
0a61b0df | 1747 | |
1748 | // Listen for incoming connections | |
1749 | if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR) | |
1750 | { | |
1751 | strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError()); | |
1752 | printf("%s\n", strError.c_str()); | |
1753 | return false; | |
1754 | } | |
1755 | ||
8f10a288 PW |
1756 | vhListenSocket.push_back(hListenSocket); |
1757 | ||
1758 | if (addrBind.IsRoutable() && GetBoolArg("-discover", true)) | |
1759 | AddLocal(addrBind, LOCAL_BIND); | |
1760 | ||
0a61b0df | 1761 | return true; |
1762 | } | |
1763 | ||
19b6958c | 1764 | void static Discover() |
0a61b0df | 1765 | { |
19b6958c PW |
1766 | if (!GetBoolArg("-discover", true)) |
1767 | return; | |
0a61b0df | 1768 | |
6853e627 | 1769 | #ifdef WIN32 |
0a61b0df | 1770 | // Get local host ip |
1771 | char pszHostName[1000] = ""; | |
1772 | if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR) | |
1773 | { | |
67a42f92 PW |
1774 | vector<CNetAddr> vaddr; |
1775 | if (LookupHost(pszHostName, vaddr)) | |
f8e4d43b | 1776 | { |
67a42f92 | 1777 | BOOST_FOREACH (const CNetAddr &addr, vaddr) |
f8e4d43b | 1778 | { |
39857190 | 1779 | AddLocal(addr, LOCAL_IF); |
f8e4d43b PK |
1780 | } |
1781 | } | |
0a61b0df | 1782 | } |
1783 | #else | |
1784 | // Get local host ip | |
1785 | struct ifaddrs* myaddrs; | |
1786 | if (getifaddrs(&myaddrs) == 0) | |
1787 | { | |
1788 | for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) | |
1789 | { | |
1790 | if (ifa->ifa_addr == NULL) continue; | |
1791 | if ((ifa->ifa_flags & IFF_UP) == 0) continue; | |
1792 | if (strcmp(ifa->ifa_name, "lo") == 0) continue; | |
1793 | if (strcmp(ifa->ifa_name, "lo0") == 0) continue; | |
0a61b0df | 1794 | if (ifa->ifa_addr->sa_family == AF_INET) |
1795 | { | |
1796 | struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr); | |
39857190 | 1797 | CNetAddr addr(s4->sin_addr); |
23aa78c4 PW |
1798 | if (AddLocal(addr, LOCAL_IF)) |
1799 | printf("ipv4 %s: %s\n", ifa->ifa_name, addr.ToString().c_str()); | |
0a61b0df | 1800 | } |
23aa78c4 | 1801 | #ifdef USE_IPV6 |
0a61b0df | 1802 | else if (ifa->ifa_addr->sa_family == AF_INET6) |
1803 | { | |
1804 | struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr); | |
39857190 | 1805 | CNetAddr addr(s6->sin6_addr); |
23aa78c4 PW |
1806 | if (AddLocal(addr, LOCAL_IF)) |
1807 | printf("ipv6 %s: %s\n", ifa->ifa_name, addr.ToString().c_str()); | |
0a61b0df | 1808 | } |
23aa78c4 | 1809 | #endif |
0a61b0df | 1810 | } |
1811 | freeifaddrs(myaddrs); | |
1812 | } | |
1813 | #endif | |
0a61b0df | 1814 | |
39857190 | 1815 | if (!fUseProxy && !mapArgs.count("-connect") && !fNoListen) |
0a61b0df | 1816 | { |
629e37dd | 1817 | CreateThread(ThreadGetMyExternalIP, NULL); |
0a61b0df | 1818 | } |
19b6958c PW |
1819 | } |
1820 | ||
1821 | void StartNode(void* parg) | |
1822 | { | |
1823 | #ifdef USE_UPNP | |
1824 | #if USE_UPNP | |
1825 | fUseUPnP = GetBoolArg("-upnp", true); | |
1826 | #else | |
1827 | fUseUPnP = GetBoolArg("-upnp", false); | |
1828 | #endif | |
1829 | #endif | |
1830 | ||
c59abe25 PW |
1831 | if (semOutbound == NULL) { |
1832 | // initialize semaphore | |
1833 | int nMaxOutbound = min(MAX_OUTBOUND_CONNECTIONS, (int)GetArg("-maxconnections", 125)); | |
1834 | semOutbound = new CSemaphore(nMaxOutbound); | |
1835 | } | |
1836 | ||
19b6958c PW |
1837 | if (pnodeLocalHost == NULL) |
1838 | pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress(CService("127.0.0.1", 0), nLocalServices)); | |
1839 | ||
1840 | Discover(); | |
0a61b0df | 1841 | |
1842 | // | |
1843 | // Start threads | |
1844 | // | |
1845 | ||
9d952d17 | 1846 | if (!GetBoolArg("-dnsseed", true)) |
2bc6cece MC |
1847 | printf("DNS seeding disabled\n"); |
1848 | else | |
1849 | if (!CreateThread(ThreadDNSAddressSeed, NULL)) | |
1850 | printf("Error: CreateThread(ThreadDNSAddressSeed) failed\n"); | |
1851 | ||
8bb5edc1 MC |
1852 | // Map ports with UPnP |
1853 | if (fHaveUPnP) | |
1854 | MapPort(fUseUPnP); | |
1855 | ||
0a61b0df | 1856 | // Get addresses from IRC and advertise ours |
1857 | if (!CreateThread(ThreadIRCSeed, NULL)) | |
1858 | printf("Error: CreateThread(ThreadIRCSeed) failed\n"); | |
1859 | ||
1860 | // Send and receive from sockets, accept connections | |
65ba3e2f LD |
1861 | if (!CreateThread(ThreadSocketHandler, NULL)) |
1862 | printf("Error: CreateThread(ThreadSocketHandler) failed\n"); | |
0a61b0df | 1863 | |
b24e6e4d MC |
1864 | // Initiate outbound connections from -addnode |
1865 | if (!CreateThread(ThreadOpenAddedConnections, NULL)) | |
1866 | printf("Error: CreateThread(ThreadOpenAddedConnections) failed\n"); | |
1867 | ||
0a61b0df | 1868 | // Initiate outbound connections |
1869 | if (!CreateThread(ThreadOpenConnections, NULL)) | |
1870 | printf("Error: CreateThread(ThreadOpenConnections) failed\n"); | |
1871 | ||
1872 | // Process messages | |
1873 | if (!CreateThread(ThreadMessageHandler, NULL)) | |
1874 | printf("Error: CreateThread(ThreadMessageHandler) failed\n"); | |
1875 | ||
5fee401f PW |
1876 | // Dump network addresses |
1877 | if (!CreateThread(ThreadDumpAddress, NULL)) | |
1878 | printf("Error; CreateThread(ThreadDumpAddress) failed\n"); | |
1879 | ||
0a61b0df | 1880 | // Generate coins in the background |
972060ce | 1881 | GenerateBitcoins(GetBoolArg("-gen", false), pwalletMain); |
0a61b0df | 1882 | } |
1883 | ||
1884 | bool StopNode() | |
1885 | { | |
1886 | printf("StopNode()\n"); | |
1887 | fShutdown = true; | |
1888 | nTransactionsUpdated++; | |
bde280b9 | 1889 | int64 nStart = GetTime(); |
89b5616d PW |
1890 | if (semOutbound) |
1891 | for (int i=0; i<MAX_OUTBOUND_CONNECTIONS; i++) | |
1892 | semOutbound->post(); | |
c59881ea | 1893 | do |
0a61b0df | 1894 | { |
c59881ea PW |
1895 | int nThreadsRunning = 0; |
1896 | for (int n = 0; n < THREAD_MAX; n++) | |
1897 | nThreadsRunning += vnThreadsRunning[n]; | |
1898 | if (nThreadsRunning == 0) | |
1899 | break; | |
0a61b0df | 1900 | if (GetTime() - nStart > 20) |
1901 | break; | |
1902 | Sleep(20); | |
c59881ea PW |
1903 | } while(true); |
1904 | if (vnThreadsRunning[THREAD_SOCKETHANDLER] > 0) printf("ThreadSocketHandler still running\n"); | |
1905 | if (vnThreadsRunning[THREAD_OPENCONNECTIONS] > 0) printf("ThreadOpenConnections still running\n"); | |
1906 | if (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0) printf("ThreadMessageHandler still running\n"); | |
1907 | if (vnThreadsRunning[THREAD_MINER] > 0) printf("ThreadBitcoinMiner still running\n"); | |
e9205293 DJS |
1908 | if (vnThreadsRunning[THREAD_RPCLISTENER] > 0) printf("ThreadRPCListener still running\n"); |
1909 | if (vnThreadsRunning[THREAD_RPCHANDLER] > 0) printf("ThreadsRPCServer still running\n"); | |
c59881ea PW |
1910 | if (fHaveUPnP && vnThreadsRunning[THREAD_UPNP] > 0) printf("ThreadMapPort still running\n"); |
1911 | if (vnThreadsRunning[THREAD_DNSSEED] > 0) printf("ThreadDNSAddressSeed still running\n"); | |
1912 | if (vnThreadsRunning[THREAD_ADDEDCONNECTIONS] > 0) printf("ThreadOpenAddedConnections still running\n"); | |
5fee401f | 1913 | if (vnThreadsRunning[THREAD_DUMPADDRESS] > 0) printf("ThreadDumpAddresses still running\n"); |
e9205293 | 1914 | while (vnThreadsRunning[THREAD_MESSAGEHANDLER] > 0 || vnThreadsRunning[THREAD_RPCHANDLER] > 0) |
0a61b0df | 1915 | Sleep(20); |
1916 | Sleep(50); | |
5fee401f | 1917 | DumpAddresses(); |
0a61b0df | 1918 | return true; |
1919 | } | |
1920 | ||
1921 | class CNetCleanup | |
1922 | { | |
1923 | public: | |
1924 | CNetCleanup() | |
1925 | { | |
1926 | } | |
1927 | ~CNetCleanup() | |
1928 | { | |
1929 | // Close sockets | |
223b6f1b | 1930 | BOOST_FOREACH(CNode* pnode, vNodes) |
0a61b0df | 1931 | if (pnode->hSocket != INVALID_SOCKET) |
1932 | closesocket(pnode->hSocket); | |
8f10a288 PW |
1933 | BOOST_FOREACH(SOCKET hListenSocket, vhListenSocket) |
1934 | if (hListenSocket != INVALID_SOCKET) | |
1935 | if (closesocket(hListenSocket) == SOCKET_ERROR) | |
1936 | printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError()); | |
0a61b0df | 1937 | |
6853e627 | 1938 | #ifdef WIN32 |
0a61b0df | 1939 | // Shutdown Windows Sockets |
1940 | WSACleanup(); | |
1941 | #endif | |
1942 | } | |
1943 | } | |
1944 | instance_of_cnetcleanup; |