genesis                 1 
genesis                 2 
genesis                 3 
genesis                 4 
genesis                 5 
genesis                 6 #include "headers.h"
genesis                 7 #include "db.h"
genesis                 8 #include "net.h"
genesis                 9 #include "init.h"
genesis                10 #include "strlcpy.h"
genesis                11 
genesis                12 
genesis                13 using namespace std;
genesis                14 using namespace boost;
genesis                15 
genesis                16 static const int MAX_OUTBOUND_CONNECTIONS = 8;
genesis                17 
genesis                18 void ThreadMessageHandler2(void* parg);
genesis                19 void ThreadSocketHandler2(void* parg);
genesis                20 void ThreadOpenConnections2(void* parg);
asciilifeform_wir...   21 void ThreadOpenWires2(void* parg);
asciilifeform_wir...   22 bool OpenNetworkConnection(const CAddress& addrConnect, bool fWireConnection=false);
genesis                23 
genesis                24 
genesis                25 
genesis                26 
genesis                27 
genesis                28 
genesis                29 
genesis                30 bool fClient = false;
genesis                31 uint64 nLocalServices = (fClient ? 0 : NODE_NETWORK);
asciilifeform_dns...   32 CAddress addrLocalHost("0.0.0.0", 0, nLocalServices);
genesis                33 static CNode* pnodeLocalHost = NULL;
genesis                34 uint64 nLocalHostNonce = 0;
genesis                35 array<int, 10> vnThreadsRunning;
genesis                36 static SOCKET hListenSocket = INVALID_SOCKET;
genesis                37 
genesis                38 vector<CNode*> vNodes;
genesis                39 CCriticalSection cs_vNodes;
asciilifeform_wir...   40 map<vector<unsigned char>, CAddress> mapWires;
genesis                41 map<vector<unsigned char>, CAddress> mapAddresses;
genesis                42 CCriticalSection cs_mapAddresses;
genesis                43 map<CInv, CDataStream> mapRelay;
genesis                44 deque<pair<int64, CInv> > vRelayExpiration;
genesis                45 CCriticalSection cs_mapRelay;
genesis                46 map<CInv, int64> mapAlreadyAskedFor;
genesis                47 
genesis                48 
genesis                49 int fUseProxy = false;
genesis                50 int nConnectTimeout = 5000;
genesis                51 CAddress addrProxy("127.0.0.1",9050);
genesis                52 
genesis                53 
genesis                54 
genesis                55 
genesis                56 unsigned short GetListenPort()
genesis                57 {
genesis                58     return (unsigned short)(GetArg("-port", GetDefaultPort()));
genesis                59 }
genesis                60 
genesis                61 void CNode::PushGetBlocks(CBlockIndex* pindexBegin, uint256 hashEnd)
genesis                62 {
genesis                63     
genesis                64     if (pindexBegin == pindexLastGetBlocksBegin && hashEnd == hashLastGetBlocksEnd)
genesis                65         return;
genesis                66     pindexLastGetBlocksBegin = pindexBegin;
genesis                67     hashLastGetBlocksEnd = hashEnd;
genesis                68 
genesis                69     PushMessage("getblocks", CBlockLocator(pindexBegin), hashEnd);
genesis                70 }
genesis                71 
genesis                72 
genesis                73 
genesis                74 
genesis                75 
genesis                76 bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout)
genesis                77 {
genesis                78     hSocketRet = INVALID_SOCKET;
genesis                79 
genesis                80     SOCKET hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis                81     if (hSocket == INVALID_SOCKET)
genesis                82         return false;
genesis                83 #ifdef SO_NOSIGPIPE
genesis                84     int set = 1;
genesis                85     setsockopt(hSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&set, sizeof(int));
genesis                86 #endif
genesis                87 
genesis                88     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
genesis                89     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
genesis                90 
genesis                91     int fFlags = fcntl(hSocket, F_GETFL, 0);
genesis                92     if (fcntl(hSocket, F_SETFL, fFlags | O_NONBLOCK) == -1)
bitcoin-asciilife...   93 
genesis                94     {
genesis                95         closesocket(hSocket);
genesis                96         return false;
genesis                97     }
genesis                98 
genesis                99 
genesis               100     if (connect(hSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis               101     {
genesis               102         
genesis               103         if (WSAGetLastError() == WSAEINPROGRESS || WSAGetLastError() == WSAEWOULDBLOCK || WSAGetLastError() == WSAEINVAL)
genesis               104         {
genesis               105             struct timeval timeout;
genesis               106             timeout.tv_sec  = nTimeout / 1000;
genesis               107             timeout.tv_usec = (nTimeout % 1000) * 1000;
genesis               108 
genesis               109             fd_set fdset;
genesis               110             FD_ZERO(&fdset);
genesis               111             FD_SET(hSocket, &fdset);
genesis               112             int nRet = select(hSocket + 1, NULL, &fdset, NULL, &timeout);
genesis               113             if (nRet == 0)
genesis               114             {
genesis               115                 printf("connection timeout\n");
genesis               116                 closesocket(hSocket);
genesis               117                 return false;
genesis               118             }
genesis               119             if (nRet == SOCKET_ERROR)
genesis               120             {
genesis               121                 printf("select() for connection failed: %i\n",WSAGetLastError());
genesis               122                 closesocket(hSocket);
genesis               123                 return false;
genesis               124             }
genesis               125             socklen_t nRetSize = sizeof(nRet);
genesis               126             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
genesis               127             {
genesis               128                 printf("getsockopt() for connection failed: %i\n",WSAGetLastError());
genesis               129                 closesocket(hSocket);
genesis               130                 return false;
genesis               131             }
genesis               132             if (nRet != 0)
genesis               133             {
genesis               134                 printf("connect() failed after select(): %s\n",strerror(nRet));
genesis               135                 closesocket(hSocket);
genesis               136                 return false;
genesis               137             }
genesis               138         }
genesis               139         else
genesis               140         {
genesis               141             printf("connect() failed: %i\n",WSAGetLastError());
genesis               142             closesocket(hSocket);
genesis               143             return false;
genesis               144         }
genesis               145     }
genesis               146 
genesis               147     
genesis               148     this isn't even strictly necessary
genesis               149     CNode::ConnectNode immediately turns the socket back to non-blocking
genesis               150     but we'll turn it back to blocking just in case
genesis               151     */
genesis               152     fFlags = fcntl(hSocket, F_GETFL, 0);
genesis               153     if (fcntl(hSocket, F_SETFL, fFlags & !O_NONBLOCK) == SOCKET_ERROR)
genesis               154     {
genesis               155         closesocket(hSocket);
genesis               156         return false;
genesis               157     }
genesis               158 
genesis               159     if (fProxy)
genesis               160     {
genesis               161         printf("proxy connecting %s\n", addrConnect.ToString().c_str());
genesis               162         char pszSocks4IP[] = "\4\1\0\0\0\0\0\0user";
genesis               163         memcpy(pszSocks4IP + 2, &addrConnect.port, 2);
genesis               164         memcpy(pszSocks4IP + 4, &addrConnect.ip, 4);
genesis               165         char* pszSocks4 = pszSocks4IP;
genesis               166         int nSize = sizeof(pszSocks4IP);
genesis               167 
genesis               168         int ret = send(hSocket, pszSocks4, nSize, MSG_NOSIGNAL);
genesis               169         if (ret != nSize)
genesis               170         {
genesis               171             closesocket(hSocket);
genesis               172             return error("Error sending to proxy");
genesis               173         }
genesis               174         char pchRet[8];
genesis               175         if (recv(hSocket, pchRet, 8, 0) != 8)
genesis               176         {
genesis               177             closesocket(hSocket);
genesis               178             return error("Error reading proxy response");
genesis               179         }
genesis               180         if (pchRet[1] != 0x5a)
genesis               181         {
genesis               182             closesocket(hSocket);
genesis               183             if (pchRet[1] != 0x5b)
genesis               184                 printf("ERROR: Proxy returned error %d\n", pchRet[1]);
genesis               185             return false;
genesis               186         }
genesis               187         printf("proxy connected %s\n", addrConnect.ToString().c_str());
genesis               188     }
genesis               189 
genesis               190     hSocketRet = hSocket;
genesis               191     return true;
genesis               192 }
genesis               193 
genesis               194 
asciilifeform_dns...  195 bool Lookup(const char *pszName, vector<CAddress>& vaddr, int nServices, int nMaxSolutions, int portDefault, bool fAllowPort)
genesis               196 {
genesis               197     vaddr.clear();
genesis               198     if (pszName[0] == 0)
genesis               199         return false;
genesis               200     int port = portDefault;
genesis               201     char psz[256];
genesis               202     char *pszHost = psz;
genesis               203     strlcpy(psz, pszName, sizeof(psz));
genesis               204     if (fAllowPort)
genesis               205     {
genesis               206         char* pszColon = strrchr(psz+1,':');
genesis               207         char *pszPortEnd = NULL;
genesis               208         int portParsed = pszColon ? strtoul(pszColon+1, &pszPortEnd, 10) : 0;
genesis               209         if (pszColon && pszPortEnd && pszPortEnd[0] == 0)
genesis               210         {
genesis               211             if (psz[0] == '[' && pszColon[-1] == ']')
genesis               212             {
genesis               213                 
genesis               214                 pszHost = psz+1;
genesis               215                 pszColon[-1] = 0;
genesis               216             }
genesis               217             else
genesis               218                 pszColon[0] = 0;
genesis               219             port = portParsed;
genesis               220             if (port < 0 || port > USHRT_MAX)
genesis               221                 port = USHRT_MAX;
genesis               222         }
genesis               223     }
genesis               224 
genesis               225     unsigned int addrIP = inet_addr(pszHost);
genesis               226     if (addrIP != INADDR_NONE)
genesis               227     {
genesis               228         
genesis               229         vaddr.push_back(CAddress(addrIP, port, nServices));
genesis               230         return true;
genesis               231     }
genesis               232 
asciilifeform_dns...  233     return false;
genesis               234 }
genesis               235 
genesis               236 
asciilifeform_dns...  237 bool Lookup(const char *pszName, CAddress& addr, int nServices, int portDefault, bool fAllowPort)
genesis               238 {
genesis               239     vector<CAddress> vaddr;
asciilifeform_dns...  240     bool fRet = Lookup(pszName, vaddr, nServices, 1, portDefault, fAllowPort);
genesis               241     if (fRet)
genesis               242         addr = vaddr[0];
genesis               243     return fRet;
genesis               244 }
genesis               245 
genesis               246 
asciilifeform_wir...  247 
asciilifeform_wir...  248 
asciilifeform_wir...  249 
asciilifeform_wir...  250 
asciilifeform_wir...  251 
asciilifeform_wir...  252 
asciilifeform_wir...  253 bool AddWire(CAddress addr)
asciilifeform_wir...  254 {
asciilifeform_wir...  255   printf("AddWire(%s)\n", addr.ToString().c_str());
asciilifeform_wir...  256   mapWires.insert(make_pair(addr.GetKey(), addr)); 
asciilifeform_wir...  257   return true;
asciilifeform_wir...  258 }
asciilifeform_wir...  259 
asciilifeform_wir...  260 
genesis               261 bool AddAddress(CAddress addr, int64 nTimePenalty, CAddrDB *pAddrDB)
genesis               262 {
genesis               263     if (!addr.IsRoutable())
genesis               264         return false;
genesis               265     if (addr.ip == addrLocalHost.ip)
genesis               266         return false;
genesis               267     addr.nTime = max((int64)0, (int64)addr.nTime - nTimePenalty);
genesis               268     bool fUpdated = false;
genesis               269     bool fNew = false;
genesis               270     CAddress addrFound = addr;
genesis               271 
genesis               272     CRITICAL_BLOCK(cs_mapAddresses)
genesis               273     {
genesis               274         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis               275         if (it == mapAddresses.end())
genesis               276         {
genesis               277             
genesis               278             printf("AddAddress(%s)\n", addr.ToString().c_str());
genesis               279             mapAddresses.insert(make_pair(addr.GetKey(), addr));
genesis               280             fUpdated = true;
genesis               281             fNew = true;
genesis               282         }
genesis               283         else
genesis               284         {
genesis               285             addrFound = (*it).second;
genesis               286             if ((addrFound.nServices | addr.nServices) != addrFound.nServices)
genesis               287             {
genesis               288                 
genesis               289                 addrFound.nServices |= addr.nServices;
genesis               290                 fUpdated = true;
genesis               291             }
genesis               292             bool fCurrentlyOnline = (GetAdjustedTime() - addr.nTime < 24 * 60 * 60);
genesis               293             int64 nUpdateInterval = (fCurrentlyOnline ? 60 * 60 : 24 * 60 * 60);
genesis               294             if (addrFound.nTime < addr.nTime - nUpdateInterval)
genesis               295             {
genesis               296                 
genesis               297                 addrFound.nTime = addr.nTime;
genesis               298                 fUpdated = true;
genesis               299             }
genesis               300         }
genesis               301     }
genesis               302     
genesis               303     
genesis               304     
genesis               305     
genesis               306     
genesis               307     
genesis               308     if (fUpdated)
genesis               309     {
genesis               310         if (pAddrDB)
genesis               311             pAddrDB->WriteAddress(addrFound);
genesis               312         else
genesis               313             CAddrDB().WriteAddress(addrFound);
genesis               314     }
genesis               315     return fNew;
genesis               316 }
genesis               317 
genesis               318 void AddressCurrentlyConnected(const CAddress& addr)
genesis               319 {
genesis               320     CAddress *paddrFound = NULL;
genesis               321 
genesis               322     CRITICAL_BLOCK(cs_mapAddresses)
genesis               323     {
genesis               324         
genesis               325         map<vector<unsigned char>, CAddress>::iterator it = mapAddresses.find(addr.GetKey());
genesis               326         if (it != mapAddresses.end())
genesis               327             paddrFound = &(*it).second;
genesis               328     }
genesis               329 
genesis               330     if (paddrFound)
genesis               331     {
genesis               332         int64 nUpdateInterval = 20 * 60;
genesis               333         if (paddrFound->nTime < GetAdjustedTime() - nUpdateInterval)
genesis               334         {
genesis               335             
genesis               336             paddrFound->nTime = GetAdjustedTime();
genesis               337             CAddrDB addrdb;
genesis               338             addrdb.WriteAddress(*paddrFound);
genesis               339         }
genesis               340     }
genesis               341 }
genesis               342 
genesis               343 
genesis               344 
genesis               345 
genesis               346 
genesis               347 void AbandonRequests(void (*fn)(void*, CDataStream&), void* param1)
genesis               348 {
genesis               349     
genesis               350     
genesis               351     CRITICAL_BLOCK(cs_vNodes)
genesis               352     {
genesis               353         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               354         {
genesis               355             CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis               356             {
genesis               357                 for (map<uint256, CRequestTracker>::iterator mi = pnode->mapRequests.begin(); mi != pnode->mapRequests.end();)
genesis               358                 {
genesis               359                     CRequestTracker& tracker = (*mi).second;
genesis               360                     if (tracker.fn == fn && tracker.param1 == param1)
genesis               361                         pnode->mapRequests.erase(mi++);
genesis               362                     else
genesis               363                         mi++;
genesis               364                 }
genesis               365             }
genesis               366         }
genesis               367     }
genesis               368 }
genesis               369 
genesis               370 
genesis               371 
genesis               372 
genesis               373 
genesis               374 
genesis               375 
genesis               376 
genesis               377 
genesis               378 
genesis               379 
genesis               380 
genesis               381 
genesis               382 
genesis               383 
genesis               384 
genesis               385 bool AnySubscribed(unsigned int nChannel)
genesis               386 {
genesis               387     if (pnodeLocalHost->IsSubscribed(nChannel))
genesis               388         return true;
genesis               389     CRITICAL_BLOCK(cs_vNodes)
genesis               390         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               391             if (pnode->IsSubscribed(nChannel))
genesis               392                 return true;
genesis               393     return false;
genesis               394 }
genesis               395 
genesis               396 bool CNode::IsSubscribed(unsigned int nChannel)
genesis               397 {
genesis               398     if (nChannel >= vfSubscribe.size())
genesis               399         return false;
genesis               400     return vfSubscribe[nChannel];
genesis               401 }
genesis               402 
genesis               403 void CNode::Subscribe(unsigned int nChannel, unsigned int nHops)
genesis               404 {
genesis               405     if (nChannel >= vfSubscribe.size())
genesis               406         return;
genesis               407 
genesis               408     if (!AnySubscribed(nChannel))
genesis               409     {
genesis               410         
genesis               411         CRITICAL_BLOCK(cs_vNodes)
genesis               412             BOOST_FOREACH(CNode* pnode, vNodes)
genesis               413                 if (pnode != this)
genesis               414                     pnode->PushMessage("subscribe", nChannel, nHops);
genesis               415     }
genesis               416 
genesis               417     vfSubscribe[nChannel] = true;
genesis               418 }
genesis               419 
genesis               420 void CNode::CancelSubscribe(unsigned int nChannel)
genesis               421 {
genesis               422     if (nChannel >= vfSubscribe.size())
genesis               423         return;
genesis               424 
genesis               425     
genesis               426     if (!vfSubscribe[nChannel])
genesis               427         return;
genesis               428     vfSubscribe[nChannel] = false;
genesis               429 
genesis               430     if (!AnySubscribed(nChannel))
genesis               431     {
genesis               432         
genesis               433         CRITICAL_BLOCK(cs_vNodes)
genesis               434             BOOST_FOREACH(CNode* pnode, vNodes)
genesis               435                 if (pnode != this)
genesis               436                     pnode->PushMessage("sub-cancel", nChannel);
genesis               437     }
genesis               438 }
genesis               439 
genesis               440 
genesis               441 
genesis               442 
genesis               443 
genesis               444 
genesis               445 
genesis               446 
genesis               447 
genesis               448 CNode* FindNode(unsigned int ip)
genesis               449 {
genesis               450     CRITICAL_BLOCK(cs_vNodes)
genesis               451     {
genesis               452         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               453             if (pnode->addr.ip == ip)
genesis               454                 return (pnode);
genesis               455     }
genesis               456     return NULL;
genesis               457 }
genesis               458 
genesis               459 CNode* FindNode(CAddress addr)
genesis               460 {
genesis               461     CRITICAL_BLOCK(cs_vNodes)
genesis               462     {
genesis               463         BOOST_FOREACH(CNode* pnode, vNodes)
genesis               464             if (pnode->addr == addr)
genesis               465                 return (pnode);
genesis               466     }
genesis               467     return NULL;
genesis               468 }
genesis               469 
asciilifeform_wir...  470 CNode* ConnectNode(CAddress addrConnect, int64 nTimeout, bool fWireNode)
genesis               471 {
asciilifeform_wir...  472     if (!fWireNode && (addrConnect.ip == addrLocalHost.ip))
genesis               473         return NULL;
asciilifeform_wir...  474     
asciilifeform_wir...  475     if (fWireNode) {
asciilifeform_wir...  476       nTimeout = 0;
asciilifeform_wir...  477       printf("Connecting to wire node... %s\n",
asciilifeform_wir...  478              addrConnect.ToString().c_str());
genesis               479     }
asciilifeform_wir...  480     
genesis               481     
genesis               482     printf("trying connection %s lastseen=%.1fhrs lasttry=%.1fhrs\n",
genesis               483         addrConnect.ToString().c_str(),
genesis               484         (double)(addrConnect.nTime - GetAdjustedTime())/3600.0,
genesis               485         (double)(addrConnect.nLastTry - GetAdjustedTime())/3600.0);
genesis               486 
asciilifeform_wir...  487     if (!fWireNode)
asciilifeform_wir...  488       {
asciilifeform_wir...  489         CRITICAL_BLOCK(cs_mapAddresses)
asciilifeform_wir...  490           mapAddresses[addrConnect.GetKey()].nLastTry = GetAdjustedTime();
asciilifeform_wir...  491       }
asciilifeform_wir...  492     
genesis               493     
genesis               494     SOCKET hSocket;
genesis               495     if (ConnectSocket(addrConnect, hSocket))
genesis               496     {
genesis               497         
genesis               498         printf("connected %s\n", addrConnect.ToString().c_str());
genesis               499 
genesis               500         
genesis               501         if (fcntl(hSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis               502             printf("ConnectSocket() : fcntl nonblocking setting failed, error %d\n", errno);
genesis               503 
genesis               504         
genesis               505         CNode* pnode = new CNode(hSocket, addrConnect, false);
asciilifeform_wir...  506         pnode->fWireNode = fWireNode;
asciilifeform_wir...  507 
asciilifeform_wir...  508         if (fWireNode) printf("Added wire node !\n");
asciilifeform_wir...  509 
genesis               510         if (nTimeout != 0)
genesis               511             pnode->AddRef(nTimeout);
genesis               512         else
genesis               513             pnode->AddRef();
genesis               514         CRITICAL_BLOCK(cs_vNodes)
genesis               515             vNodes.push_back(pnode);
genesis               516 
genesis               517         pnode->nTimeConnected = GetTime();
genesis               518         return pnode;
genesis               519     }
genesis               520     else
genesis               521     {
genesis               522         return NULL;
genesis               523     }
genesis               524 }
genesis               525 
genesis               526 void CNode::CloseSocketDisconnect()
genesis               527 {
asciilifeform_wir...  528     if (fWireNode) {
asciilifeform_wir...  529       printf("WARNING: disconnecting wire %s ! (will retry...)\n",
asciilifeform_wir...  530              addr.ToString().c_str());
asciilifeform_wir...  531     }
genesis               532     fDisconnect = true;
genesis               533     if (hSocket != INVALID_SOCKET)
genesis               534     {
genesis               535         if (fDebug)
genesis               536             printf("%s ", DateTimeStrFormat("%x %H:%M:%S", GetTime()).c_str());
genesis               537         printf("disconnecting node %s\n", addr.ToString().c_str());
genesis               538         closesocket(hSocket);
genesis               539         hSocket = INVALID_SOCKET;
genesis               540     }
genesis               541 }
genesis               542 
genesis               543 void CNode::Cleanup()
genesis               544 {
genesis               545     
genesis               546     
genesis               547 
genesis               548     
genesis               549     for (unsigned int nChannel = 0; nChannel < vfSubscribe.size(); nChannel++)
genesis               550         if (vfSubscribe[nChannel])
genesis               551             CancelSubscribe(nChannel);
genesis               552 }
genesis               553 
genesis               554 
genesis               555 std::map<unsigned int, int64> CNode::setBanned;
genesis               556 CCriticalSection CNode::cs_setBanned;
genesis               557 
genesis               558 void CNode::ClearBanned()
genesis               559 {
genesis               560     setBanned.clear();
genesis               561 }
genesis               562 
genesis               563 bool CNode::IsBanned(unsigned int ip)
genesis               564 {
genesis               565     bool fResult = false;
genesis               566     CRITICAL_BLOCK(cs_setBanned)
genesis               567     {
genesis               568         std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
genesis               569         if (i != setBanned.end())
genesis               570         {
genesis               571             int64 t = (*i).second;
genesis               572             if (GetTime() < t)
genesis               573                 fResult = true;
genesis               574         }
genesis               575     }
genesis               576     return fResult;
genesis               577 }
genesis               578 
genesis               579 bool CNode::Misbehaving(int howmuch)
genesis               580 {
asciilifeform_wir...  581     if (fWireNode)
asciilifeform_wir...  582     {
asciilifeform_wir...  583         printf("Warning: wire node %s misbehaving (no disconnect)\n", addr.ToString().c_str());
asciilifeform_wir...  584         return false;
asciilifeform_wir...  585     }
asciilifeform_wir...  586 
genesis               587     if (addr.IsLocal())
genesis               588     {
genesis               589         printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
genesis               590         return false;
genesis               591     }
genesis               592 
genesis               593     nMisbehavior += howmuch;
genesis               594     if (nMisbehavior >= GetArg("-banscore", 100))
genesis               595     {
genesis               596         int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  
genesis               597         CRITICAL_BLOCK(cs_setBanned)
genesis               598             if (setBanned[addr.ip] < banTime)
genesis               599                 setBanned[addr.ip] = banTime;
genesis               600         CloseSocketDisconnect();
genesis               601         printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
genesis               602         return true;
genesis               603     }
genesis               604     return false;
genesis               605 }
genesis               606 
genesis               607 
genesis               608 
genesis               609 
genesis               610 
genesis               611 
genesis               612 
genesis               613 
genesis               614 
genesis               615 
genesis               616 
genesis               617 
genesis               618 void ThreadSocketHandler(void* parg)
genesis               619 {
genesis               620     IMPLEMENT_RANDOMIZE_STACK(ThreadSocketHandler(parg));
genesis               621     try
genesis               622     {
genesis               623         vnThreadsRunning[0]++;
genesis               624         ThreadSocketHandler2(parg);
genesis               625         vnThreadsRunning[0]--;
genesis               626     }
genesis               627     catch (std::exception& e) {
genesis               628         vnThreadsRunning[0]--;
genesis               629         PrintException(&e, "ThreadSocketHandler()");
genesis               630     } catch (...) {
genesis               631         vnThreadsRunning[0]--;
genesis               632         throw; 
genesis               633     }
genesis               634     printf("ThreadSocketHandler exiting\n");
genesis               635 }
genesis               636 
genesis               637 void ThreadSocketHandler2(void* parg)
genesis               638 {
genesis               639     printf("ThreadSocketHandler started\n");
genesis               640     list<CNode*> vNodesDisconnected;
genesis               641     int nPrevNodeCount = 0;
genesis               642 
genesis               643     loop
genesis               644     {
genesis               645         
genesis               646         
genesis               647         
genesis               648         CRITICAL_BLOCK(cs_vNodes)
genesis               649         {
genesis               650             
genesis               651             vector<CNode*> vNodesCopy = vNodes;
genesis               652             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               653             {
genesis               654                 if (pnode->fDisconnect ||
genesis               655                     (pnode->GetRefCount() <= 0 && pnode->vRecv.empty() && pnode->vSend.empty()))
genesis               656                 {
genesis               657                     
genesis               658                     vNodes.erase(remove(vNodes.begin(), vNodes.end(), pnode), vNodes.end());
genesis               659 
genesis               660                     
genesis               661                     pnode->CloseSocketDisconnect();
genesis               662                     pnode->Cleanup();
genesis               663 
genesis               664                     
genesis               665                     pnode->nReleaseTime = max(pnode->nReleaseTime, GetTime() + 15 * 60);
genesis               666                     if (pnode->fNetworkNode || pnode->fInbound)
genesis               667                         pnode->Release();
genesis               668                     vNodesDisconnected.push_back(pnode);
genesis               669                 }
genesis               670             }
genesis               671 
genesis               672             
genesis               673             list<CNode*> vNodesDisconnectedCopy = vNodesDisconnected;
genesis               674             BOOST_FOREACH(CNode* pnode, vNodesDisconnectedCopy)
genesis               675             {
genesis               676                 
genesis               677                 if (pnode->GetRefCount() <= 0)
genesis               678                 {
genesis               679                     bool fDelete = false;
genesis               680                     TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis               681                      TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis               682                       TRY_CRITICAL_BLOCK(pnode->cs_mapRequests)
genesis               683                        TRY_CRITICAL_BLOCK(pnode->cs_inventory)
genesis               684                         fDelete = true;
genesis               685                     if (fDelete)
genesis               686                     {
genesis               687                         vNodesDisconnected.remove(pnode);
genesis               688                         delete pnode;
genesis               689                     }
genesis               690                 }
genesis               691             }
genesis               692         }
genesis               693         if (vNodes.size() != nPrevNodeCount)
genesis               694         {
genesis               695             nPrevNodeCount = vNodes.size();
genesis               696             MainFrameRepaint();
genesis               697         }
genesis               698 
genesis               699 
genesis               700         
genesis               701         
genesis               702         
genesis               703         struct timeval timeout;
genesis               704         timeout.tv_sec  = 0;
genesis               705         timeout.tv_usec = 50000; 
genesis               706 
genesis               707         fd_set fdsetRecv;
genesis               708         fd_set fdsetSend;
genesis               709         fd_set fdsetError;
genesis               710         FD_ZERO(&fdsetRecv);
genesis               711         FD_ZERO(&fdsetSend);
genesis               712         FD_ZERO(&fdsetError);
genesis               713         SOCKET hSocketMax = 0;
genesis               714 
genesis               715         if(hListenSocket != INVALID_SOCKET)
genesis               716             FD_SET(hListenSocket, &fdsetRecv);
genesis               717         hSocketMax = max(hSocketMax, hListenSocket);
genesis               718         CRITICAL_BLOCK(cs_vNodes)
genesis               719         {
genesis               720             BOOST_FOREACH(CNode* pnode, vNodes)
genesis               721             {
genesis               722                 if (pnode->hSocket == INVALID_SOCKET)
genesis               723                     continue;
genesis               724                 FD_SET(pnode->hSocket, &fdsetRecv);
genesis               725                 FD_SET(pnode->hSocket, &fdsetError);
genesis               726                 hSocketMax = max(hSocketMax, pnode->hSocket);
genesis               727                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis               728                     if (!pnode->vSend.empty())
genesis               729                         FD_SET(pnode->hSocket, &fdsetSend);
genesis               730             }
genesis               731         }
genesis               732 
genesis               733         vnThreadsRunning[0]--;
genesis               734         int nSelect = select(hSocketMax + 1, &fdsetRecv, &fdsetSend, &fdsetError, &timeout);
genesis               735         vnThreadsRunning[0]++;
genesis               736         if (fShutdown)
genesis               737             return;
genesis               738         if (nSelect == SOCKET_ERROR)
genesis               739         {
genesis               740             int nErr = WSAGetLastError();
genesis               741             if (hSocketMax > -1)
genesis               742             {
genesis               743                 printf("socket select error %d\n", nErr);
genesis               744                 for (int i = 0; i <= hSocketMax; i++)
genesis               745                     FD_SET(i, &fdsetRecv);
genesis               746             }
genesis               747             FD_ZERO(&fdsetSend);
genesis               748             FD_ZERO(&fdsetError);
genesis               749             Sleep(timeout.tv_usec/1000);
genesis               750         }
genesis               751 
genesis               752 
genesis               753         
genesis               754         
genesis               755         
genesis               756         if (hListenSocket != INVALID_SOCKET && FD_ISSET(hListenSocket, &fdsetRecv))
genesis               757         {
genesis               758             struct sockaddr_in sockaddr;
genesis               759             socklen_t len = sizeof(sockaddr);
genesis               760             SOCKET hSocket = accept(hListenSocket, (struct sockaddr*)&sockaddr, &len);
genesis               761             CAddress addr;
genesis               762             int nInbound = 0;
genesis               763 
genesis               764             if (hSocket != INVALID_SOCKET)
genesis               765                 addr = CAddress(sockaddr);
genesis               766 
genesis               767             CRITICAL_BLOCK(cs_vNodes)
genesis               768                 BOOST_FOREACH(CNode* pnode, vNodes)
genesis               769                 if (pnode->fInbound)
genesis               770                     nInbound++;
genesis               771 
genesis               772             if (hSocket == INVALID_SOCKET)
genesis               773             {
genesis               774                 if (WSAGetLastError() != WSAEWOULDBLOCK)
genesis               775                     printf("socket error accept failed: %d\n", WSAGetLastError());
genesis               776             }
genesis               777             else if (nInbound >= GetArg("-maxconnections", 125) - MAX_OUTBOUND_CONNECTIONS)
genesis               778             {
genesis               779                 closesocket(hSocket);
genesis               780             }
genesis               781             else if (CNode::IsBanned(addr.ip))
genesis               782             {
genesis               783                 printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
genesis               784                 closesocket(hSocket);
genesis               785             }
genesis               786             else
genesis               787             {
genesis               788                 printf("accepted connection %s\n", addr.ToString().c_str());
genesis               789                 CNode* pnode = new CNode(hSocket, addr, true);
genesis               790                 pnode->AddRef();
genesis               791                 CRITICAL_BLOCK(cs_vNodes)
genesis               792                     vNodes.push_back(pnode);
genesis               793             }
genesis               794         }
genesis               795 
genesis               796 
genesis               797         
genesis               798         
genesis               799         
genesis               800         vector<CNode*> vNodesCopy;
genesis               801         CRITICAL_BLOCK(cs_vNodes)
genesis               802         {
genesis               803             vNodesCopy = vNodes;
genesis               804             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               805                 pnode->AddRef();
genesis               806         }
genesis               807         BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               808         {
genesis               809             if (fShutdown)
genesis               810                 return;
genesis               811 
genesis               812             
genesis               813             
genesis               814             
genesis               815             if (pnode->hSocket == INVALID_SOCKET)
genesis               816                 continue;
genesis               817             if (FD_ISSET(pnode->hSocket, &fdsetRecv) || FD_ISSET(pnode->hSocket, &fdsetError))
genesis               818             {
genesis               819                 TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis               820                 {
genesis               821                     CDataStream& vRecv = pnode->vRecv;
genesis               822                     unsigned int nPos = vRecv.size();
genesis               823 
genesis               824                     if (nPos > ReceiveBufferSize()) {
genesis               825                         if (!pnode->fDisconnect)
genesis               826                             printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
genesis               827                         pnode->CloseSocketDisconnect();
genesis               828                     }
genesis               829                     else {
genesis               830                         
genesis               831                         char pchBuf[0x10000];
genesis               832                         int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
genesis               833                         if (nBytes > 0)
genesis               834                         {
genesis               835                             vRecv.resize(nPos + nBytes);
genesis               836                             memcpy(&vRecv[nPos], pchBuf, nBytes);
genesis               837                             pnode->nLastRecv = GetTime();
genesis               838                         }
genesis               839                         else if (nBytes == 0)
genesis               840                         {
genesis               841                             
genesis               842                             if (!pnode->fDisconnect)
genesis               843                                 printf("socket closed\n");
genesis               844                             pnode->CloseSocketDisconnect();
genesis               845                         }
genesis               846                         else if (nBytes < 0)
genesis               847                         {
genesis               848                             
genesis               849                             int nErr = WSAGetLastError();
genesis               850                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis               851                             {
genesis               852                                 if (!pnode->fDisconnect)
genesis               853                                     printf("socket recv error %d\n", nErr);
genesis               854                                 pnode->CloseSocketDisconnect();
genesis               855                             }
genesis               856                         }
genesis               857                     }
genesis               858                 }
genesis               859             }
genesis               860 
genesis               861             
genesis               862             
genesis               863             
genesis               864             if (pnode->hSocket == INVALID_SOCKET)
genesis               865                 continue;
genesis               866             if (FD_ISSET(pnode->hSocket, &fdsetSend))
genesis               867             {
genesis               868                 TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis               869                 {
genesis               870                     CDataStream& vSend = pnode->vSend;
genesis               871                     if (!vSend.empty())
genesis               872                     {
genesis               873                         int nBytes = send(pnode->hSocket, &vSend[0], vSend.size(), MSG_NOSIGNAL | MSG_DONTWAIT);
genesis               874                         if (nBytes > 0)
genesis               875                         {
genesis               876                             vSend.erase(vSend.begin(), vSend.begin() + nBytes);
genesis               877                             pnode->nLastSend = GetTime();
genesis               878                         }
genesis               879                         else if (nBytes < 0)
genesis               880                         {
genesis               881                             
genesis               882                             int nErr = WSAGetLastError();
genesis               883                             if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
genesis               884                             {
genesis               885                                 printf("socket send error %d\n", nErr);
genesis               886                                 pnode->CloseSocketDisconnect();
genesis               887                             }
genesis               888                         }
genesis               889                         if (vSend.size() > SendBufferSize()) {
genesis               890                             if (!pnode->fDisconnect)
genesis               891                                 printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
genesis               892                             pnode->CloseSocketDisconnect();
genesis               893                         }
genesis               894                     }
genesis               895                 }
genesis               896             }
genesis               897 
genesis               898             
genesis               899             
genesis               900             
genesis               901             if (pnode->vSend.empty())
genesis               902                 pnode->nLastSendEmpty = GetTime();
asciilifeform_wir...  903             if ((!pnode->fWireNode) && (GetTime() - pnode->nTimeConnected > 60))
asciilifeform_wir...  904             { 
genesis               905                 if (pnode->nLastRecv == 0 || pnode->nLastSend == 0)
genesis               906                 {
genesis               907                     printf("socket no message in first 60 seconds, %d %d\n", pnode->nLastRecv != 0, pnode->nLastSend != 0);
genesis               908                     pnode->fDisconnect = true;
genesis               909                 }
genesis               910                 else if (GetTime() - pnode->nLastSend > 90*60 && GetTime() - pnode->nLastSendEmpty > 90*60)
genesis               911                 {
genesis               912                     printf("socket not sending\n");
genesis               913                     pnode->fDisconnect = true;
genesis               914                 }
genesis               915                 else if (GetTime() - pnode->nLastRecv > 90*60)
genesis               916                 {
genesis               917                     printf("socket inactivity timeout\n");
genesis               918                     pnode->fDisconnect = true;
genesis               919                 }
genesis               920             }
genesis               921         }
genesis               922         CRITICAL_BLOCK(cs_vNodes)
genesis               923         {
genesis               924             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis               925                 pnode->Release();
genesis               926         }
genesis               927 
genesis               928         Sleep(10);
genesis               929     }
genesis               930 }
genesis               931 
genesis               932 
genesis               933 void ThreadOpenConnections(void* parg)
genesis               934 {
genesis               935     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenConnections(parg));
genesis               936     try
genesis               937     {
genesis               938         vnThreadsRunning[1]++;
genesis               939         ThreadOpenConnections2(parg);
genesis               940         vnThreadsRunning[1]--;
genesis               941     }
genesis               942     catch (std::exception& e) {
genesis               943         vnThreadsRunning[1]--;
genesis               944         PrintException(&e, "ThreadOpenConnections()");
genesis               945     } catch (...) {
genesis               946         vnThreadsRunning[1]--;
genesis               947         PrintException(NULL, "ThreadOpenConnections()");
genesis               948     }
genesis               949     printf("ThreadOpenConnections exiting\n");
genesis               950 }
genesis               951 
genesis               952 void ThreadOpenConnections2(void* parg)
genesis               953 {
genesis               954     printf("ThreadOpenConnections started\n");
genesis               955 
genesis               956     
genesis               957     if (mapArgs.count("-connect"))
genesis               958     {
genesis               959         for (int64 nLoop = 0;; nLoop++)
genesis               960         {
genesis               961             BOOST_FOREACH(string strAddr, mapMultiArgs["-connect"])
genesis               962             {
asciilifeform_dns...  963                 CAddress addr(strAddr);
genesis               964                 if (addr.IsValid())
genesis               965                     OpenNetworkConnection(addr);
genesis               966                 for (int i = 0; i < 10 && i < nLoop; i++)
genesis               967                 {
genesis               968                     Sleep(500);
genesis               969                     if (fShutdown)
genesis               970                         return;
genesis               971                 }
genesis               972             }
genesis               973         }
genesis               974     }
genesis               975 
genesis               976     
genesis               977     if (mapArgs.count("-addnode"))
genesis               978     {
genesis               979         BOOST_FOREACH(string strAddr, mapMultiArgs["-addnode"])
genesis               980         {
asciilifeform_dns...  981             CAddress addr(strAddr);
genesis               982             if (addr.IsValid())
genesis               983             {
genesis               984                 OpenNetworkConnection(addr);
genesis               985                 Sleep(500);
genesis               986                 if (fShutdown)
genesis               987                     return;
genesis               988             }
genesis               989         }
genesis               990     }
genesis               991 
genesis               992     
genesis               993     int64 nStart = GetTime();
genesis               994     loop
genesis               995     {
genesis               996         vnThreadsRunning[1]--;
genesis               997         Sleep(500);
genesis               998         vnThreadsRunning[1]++;
genesis               999         if (fShutdown)
genesis              1000             return;
genesis              1001 
genesis              1002         
genesis              1003         loop
genesis              1004         {
genesis              1005             int nOutbound = 0;
genesis              1006             CRITICAL_BLOCK(cs_vNodes)
genesis              1007                 BOOST_FOREACH(CNode* pnode, vNodes)
genesis              1008                     if (!pnode->fInbound)
genesis              1009                         nOutbound++;
genesis              1010             int nMaxOutboundConnections = MAX_OUTBOUND_CONNECTIONS;
genesis              1011             nMaxOutboundConnections = min(nMaxOutboundConnections, (int)GetArg("-maxconnections", 125));
genesis              1012             if (nOutbound < nMaxOutboundConnections)
genesis              1013                 break;
genesis              1014             vnThreadsRunning[1]--;
genesis              1015             Sleep(2000);
genesis              1016             vnThreadsRunning[1]++;
genesis              1017             if (fShutdown)
genesis              1018                 return;
genesis              1019         }
genesis              1020 
genesis              1021         
genesis              1022         
genesis              1023         
genesis              1024         CAddress addrConnect;
genesis              1025         int64 nBest = INT64_MIN;
genesis              1026 
genesis              1027         
genesis              1028         
genesis              1029         set<unsigned int> setConnected;
genesis              1030         CRITICAL_BLOCK(cs_vNodes)
genesis              1031             BOOST_FOREACH(CNode* pnode, vNodes)
genesis              1032                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
genesis              1033 
genesis              1034         int64 nANow = GetAdjustedTime();
genesis              1035 
genesis              1036         CRITICAL_BLOCK(cs_mapAddresses)
genesis              1037         {
genesis              1038             BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
genesis              1039             {
genesis              1040                 const CAddress& addr = item.second;
genesis              1041                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
genesis              1042                     continue;
genesis              1043                 int64 nSinceLastSeen = nANow - addr.nTime;
genesis              1044                 int64 nSinceLastTry = nANow - addr.nLastTry;
genesis              1045 
genesis              1046                 
genesis              1047                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
genesis              1048                 if (addr.port != htons(GetDefaultPort()))
genesis              1049                     nRandomizer += 2 * 60 * 60;
genesis              1050 
genesis              1051                 
genesis              1052                 
genesis              1053                 
genesis              1054                 
genesis              1055                 
genesis              1056                 
genesis              1057                 
genesis              1058                 
genesis              1059                 
genesis              1060                 
genesis              1061                 int64 nDelay = (int64)(3600.0 * sqrt(fabs((double)nSinceLastSeen) / 3600.0) + nRandomizer);
genesis              1062 
genesis              1063                 
genesis              1064                 if (nSinceLastSeen < 60 * 60)
genesis              1065                     nDelay = 10 * 60;
genesis              1066 
genesis              1067                 
genesis              1068                 if (nSinceLastTry < nDelay)
genesis              1069                     continue;
genesis              1070 
genesis              1071                 
genesis              1072                 if (vNodes.size() >= 8 && nSinceLastSeen > 24 * 60 * 60)
genesis              1073                     continue;
genesis              1074 
genesis              1075                 
genesis              1076                 
genesis              1077                 int64 nScore = min(nSinceLastTry, (int64)24 * 60 * 60) - nSinceLastSeen - nRandomizer;
genesis              1078                 if (nScore > nBest)
genesis              1079                 {
genesis              1080                     nBest = nScore;
genesis              1081                     addrConnect = addr;
genesis              1082                 }
genesis              1083             }
genesis              1084         }
genesis              1085 
genesis              1086         if (addrConnect.IsValid())
genesis              1087             OpenNetworkConnection(addrConnect);
genesis              1088     }
genesis              1089 }
genesis              1090 
asciilifeform_wir... 1091 bool OpenNetworkConnection(const CAddress& addrConnect, bool fWireConnection)
genesis              1092 {
genesis              1093     
genesis              1094     
genesis              1095     
genesis              1096     if (fShutdown)
genesis              1097         return false;
asciilifeform_wir... 1098 
asciilifeform_wir... 1099     if (!fWireConnection && 
asciilifeform_wir... 1100         (addrConnect.ip == addrLocalHost.ip || CNode::IsBanned(addrConnect.ip)))
asciilifeform_wir... 1101         return false;
asciilifeform_wir... 1102 
asciilifeform_wir... 1103     if (!addrConnect.IsIPv4() || FindNode(addrConnect.ip))
genesis              1104         return false;
genesis              1105 
genesis              1106     vnThreadsRunning[1]--;
asciilifeform_wir... 1107     CNode* pnode = ConnectNode(addrConnect, 0, fWireConnection);
genesis              1108     vnThreadsRunning[1]++;
genesis              1109     if (fShutdown)
genesis              1110         return false;
genesis              1111     if (!pnode)
genesis              1112         return false;
genesis              1113     pnode->fNetworkNode = true;
genesis              1114 
genesis              1115     return true;
genesis              1116 }
genesis              1117 
genesis              1118 
asciilifeform_wir... 1119 void ThreadOpenWires(void* parg)
asciilifeform_wir... 1120 {
asciilifeform_wir... 1121     IMPLEMENT_RANDOMIZE_STACK(ThreadOpenWires(parg));
asciilifeform_wir... 1122     try
asciilifeform_wir... 1123     {
asciilifeform_wir... 1124         vnThreadsRunning[5]++;
asciilifeform_wir... 1125         ThreadOpenWires2(parg);
asciilifeform_wir... 1126         vnThreadsRunning[5]--;
asciilifeform_wir... 1127     }
asciilifeform_wir... 1128     catch (std::exception& e) {
asciilifeform_wir... 1129         vnThreadsRunning[5]--;
asciilifeform_wir... 1130         PrintException(&e, "ThreadOpenWires()");
asciilifeform_wir... 1131     } catch (...) {
asciilifeform_wir... 1132         vnThreadsRunning[5]--;
asciilifeform_wir... 1133         PrintException(NULL, "ThreadOpenWires()");
asciilifeform_wir... 1134     }
asciilifeform_wir... 1135     printf("ThreadOpenWires exiting\n");
asciilifeform_wir... 1136 }
genesis              1137 
genesis              1138 
asciilifeform_wir... 1139 void ThreadOpenWires2(void* parg)
asciilifeform_wir... 1140 {
asciilifeform_wir... 1141     printf("ThreadOpenWires started\n");
genesis              1142 
asciilifeform_wir... 1143     while (1)
asciilifeform_wir... 1144       {
asciilifeform_wir... 1145         BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapWires)
asciilifeform_wir... 1146           {
asciilifeform_wir... 1147             const CAddress& addr = item.second;
asciilifeform_wir... 1148             OpenNetworkConnection(addr, true);
asciilifeform_wir... 1149             if (fShutdown)
asciilifeform_wir... 1150               return;
asciilifeform_wir... 1151           }
asciilifeform_wir... 1152         Sleep(wireRefresh);
asciilifeform_wir... 1153       }
asciilifeform_wir... 1154 }
genesis              1155 
genesis              1156 
genesis              1157 void ThreadMessageHandler(void* parg)
genesis              1158 {
genesis              1159     IMPLEMENT_RANDOMIZE_STACK(ThreadMessageHandler(parg));
genesis              1160     try
genesis              1161     {
genesis              1162         vnThreadsRunning[2]++;
genesis              1163         ThreadMessageHandler2(parg);
genesis              1164         vnThreadsRunning[2]--;
genesis              1165     }
genesis              1166     catch (std::exception& e) {
genesis              1167         vnThreadsRunning[2]--;
genesis              1168         PrintException(&e, "ThreadMessageHandler()");
genesis              1169     } catch (...) {
genesis              1170         vnThreadsRunning[2]--;
genesis              1171         PrintException(NULL, "ThreadMessageHandler()");
genesis              1172     }
genesis              1173     printf("ThreadMessageHandler exiting\n");
genesis              1174 }
genesis              1175 
genesis              1176 void ThreadMessageHandler2(void* parg)
genesis              1177 {
genesis              1178     printf("ThreadMessageHandler started\n");
genesis              1179     SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
genesis              1180     while (!fShutdown)
genesis              1181     {
genesis              1182         vector<CNode*> vNodesCopy;
genesis              1183         CRITICAL_BLOCK(cs_vNodes)
genesis              1184         {
genesis              1185             vNodesCopy = vNodes;
genesis              1186             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1187                 pnode->AddRef();
genesis              1188         }
genesis              1189 
genesis              1190         
genesis              1191         CNode* pnodeTrickle = NULL;
genesis              1192         if (!vNodesCopy.empty())
genesis              1193             pnodeTrickle = vNodesCopy[GetRand(vNodesCopy.size())];
genesis              1194         BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1195         {
genesis              1196             
genesis              1197             TRY_CRITICAL_BLOCK(pnode->cs_vRecv)
genesis              1198                 ProcessMessages(pnode);
genesis              1199             if (fShutdown)
genesis              1200                 return;
genesis              1201 
genesis              1202             
genesis              1203             TRY_CRITICAL_BLOCK(pnode->cs_vSend)
genesis              1204                 SendMessages(pnode, pnode == pnodeTrickle);
genesis              1205             if (fShutdown)
genesis              1206                 return;
genesis              1207         }
genesis              1208 
genesis              1209         CRITICAL_BLOCK(cs_vNodes)
genesis              1210         {
genesis              1211             BOOST_FOREACH(CNode* pnode, vNodesCopy)
genesis              1212                 pnode->Release();
genesis              1213         }
genesis              1214 
genesis              1215         
genesis              1216         
genesis              1217         
genesis              1218         vnThreadsRunning[2]--;
genesis              1219         Sleep(100);
genesis              1220         if (fRequestShutdown)
genesis              1221             Shutdown(NULL);
genesis              1222         vnThreadsRunning[2]++;
genesis              1223         if (fShutdown)
genesis              1224             return;
genesis              1225     }
genesis              1226 }
genesis              1227 
genesis              1228 
genesis              1229 
genesis              1230 
genesis              1231 
genesis              1232 
genesis              1233 bool BindListenPort(string& strError)
genesis              1234 {
genesis              1235     strError = "";
genesis              1236     int nOne = 1;
genesis              1237     addrLocalHost.port = htons(GetListenPort());
genesis              1238 
genesis              1239     
genesis              1240     hListenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
genesis              1241     if (hListenSocket == INVALID_SOCKET)
genesis              1242     {
genesis              1243         strError = strprintf("Error: Couldn't open socket for incoming connections (socket returned error %d)", WSAGetLastError());
genesis              1244         printf("%s\n", strError.c_str());
genesis              1245         return false;
genesis              1246     }
genesis              1247 
genesis              1248 #ifdef SO_NOSIGPIPE
genesis              1249     
genesis              1250     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
genesis              1251 #endif
genesis              1252 
genesis              1253     
genesis              1254     
genesis              1255     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
genesis              1256 
genesis              1257     if (fcntl(hListenSocket, F_SETFL, O_NONBLOCK) == SOCKET_ERROR)
genesis              1258     {
genesis              1259         strError = strprintf("Error: Couldn't set properties on socket for incoming connections (error %d)", WSAGetLastError());
genesis              1260         printf("%s\n", strError.c_str());
genesis              1261         return false;
genesis              1262     }
genesis              1263 
genesis              1264     
genesis              1265     
genesis              1266     struct sockaddr_in sockaddr;
genesis              1267     memset(&sockaddr, 0, sizeof(sockaddr));
genesis              1268     sockaddr.sin_family = AF_INET;
genesis              1269     sockaddr.sin_addr.s_addr = INADDR_ANY; 
genesis              1270     sockaddr.sin_port = htons(GetListenPort());
genesis              1271     if (::bind(hListenSocket, (struct sockaddr*)&sockaddr, sizeof(sockaddr)) == SOCKET_ERROR)
genesis              1272     {
genesis              1273         int nErr = WSAGetLastError();
genesis              1274         if (nErr == WSAEADDRINUSE)
genesis              1275             strError = strprintf(_("Unable to bind to port %d on this computer.  Bitcoin is probably already running."), ntohs(sockaddr.sin_port));
genesis              1276         else
genesis              1277             strError = strprintf("Error: Unable to bind to port %d on this computer (bind returned error %d)", ntohs(sockaddr.sin_port), nErr);
genesis              1278         printf("%s\n", strError.c_str());
genesis              1279         return false;
genesis              1280     }
genesis              1281     printf("Bound to port %d\n", ntohs(sockaddr.sin_port));
genesis              1282 
genesis              1283     
genesis              1284     if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
genesis              1285     {
genesis              1286         strError = strprintf("Error: Listening for incoming connections failed (listen returned error %d)", WSAGetLastError());
genesis              1287         printf("%s\n", strError.c_str());
genesis              1288         return false;
genesis              1289     }
genesis              1290 
genesis              1291     return true;
genesis              1292 }
genesis              1293 
genesis              1294 void StartNode(void* parg)
genesis              1295 {
genesis              1296     if (pnodeLocalHost == NULL)
asciilifeform_dns... 1297         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, nLocalServices));
genesis              1298 
genesis              1299     
genesis              1300     struct ifaddrs* myaddrs;
genesis              1301     if (getifaddrs(&myaddrs) == 0)
genesis              1302     {
genesis              1303         for (struct ifaddrs* ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
genesis              1304         {
genesis              1305             if (ifa->ifa_addr == NULL) continue;
genesis              1306             if ((ifa->ifa_flags & IFF_UP) == 0) continue;
genesis              1307             if (strcmp(ifa->ifa_name, "lo") == 0) continue;
genesis              1308             if (strcmp(ifa->ifa_name, "lo0") == 0) continue;
genesis              1309             char pszIP[100];
genesis              1310             if (ifa->ifa_addr->sa_family == AF_INET)
genesis              1311             {
genesis              1312                 struct sockaddr_in* s4 = (struct sockaddr_in*)(ifa->ifa_addr);
genesis              1313                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s4->sin_addr), pszIP, sizeof(pszIP)) != NULL)
genesis              1314                     printf("ipv4 %s: %s\n", ifa->ifa_name, pszIP);
genesis              1315 
genesis              1316                 
genesis              1317                 CAddress addr(*(unsigned int*)&s4->sin_addr, GetListenPort(), nLocalServices);
genesis              1318                 if (addr.IsValid() && addr.GetByte(3) != 127)
genesis              1319                 {
genesis              1320                     addrLocalHost = addr;
genesis              1321                     break;
genesis              1322                 }
genesis              1323             }
genesis              1324             else if (ifa->ifa_addr->sa_family == AF_INET6)
genesis              1325             {
genesis              1326                 struct sockaddr_in6* s6 = (struct sockaddr_in6*)(ifa->ifa_addr);
genesis              1327                 if (inet_ntop(ifa->ifa_addr->sa_family, (void*)&(s6->sin6_addr), pszIP, sizeof(pszIP)) != NULL)
genesis              1328                     printf("ipv6 %s: %s\n", ifa->ifa_name, pszIP);
genesis              1329             }
genesis              1330         }
genesis              1331         freeifaddrs(myaddrs);
genesis              1332     }
bitcoin-asciilife... 1333 
genesis              1334     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
genesis              1335 
genesis              1336     if (fUseProxy || mapArgs.count("-connect") || fNoListen)
genesis              1337     {
genesis              1338         
genesis              1339         addrLocalHost.ip = CAddress("0.0.0.0").ip;
genesis              1340     }
genesis              1341     else
genesis              1342     {
asciilifeform_ver... 1343         addrLocalHost.ip = CAddress(mapArgs["-myip"]).ip;
asciilifeform_ver... 1344         if (!addrLocalHost.IsValid())
asciilifeform_ver... 1345 	  throw runtime_error(strprintf(_("You must set myip=<ipaddress> on the command line or in the configuration file:\n%s\n"
asciilifeform_ver... 1346 					  "If the file does not exist, create it with owner-readable-only file permissions."),
asciilifeform_ver... 1347 					GetConfigFile().c_str()));
genesis              1348     }
genesis              1349 
asciilifeform_ver... 1350     printf("addrLocalHost = %s\n", addrLocalHost.ToString().c_str());
asciilifeform_ver... 1351 
genesis              1352     
genesis              1353     
genesis              1354     
genesis              1355 
genesis              1356     
genesis              1357     if (!CreateThread(ThreadSocketHandler, NULL))
genesis              1358         printf("Error: CreateThread(ThreadSocketHandler) failed\n");
genesis              1359 
genesis              1360     
genesis              1361     if (!CreateThread(ThreadOpenConnections, NULL))
genesis              1362         printf("Error: CreateThread(ThreadOpenConnections) failed\n");
genesis              1363 
asciilifeform_wir... 1364     
asciilifeform_wir... 1365     if (fWires && !CreateThread(ThreadOpenWires, NULL))
asciilifeform_wir... 1366         printf("Error: CreateThread(ThreadOpenWires) failed\n");
asciilifeform_wir... 1367 
genesis              1368     
genesis              1369     if (!CreateThread(ThreadMessageHandler, NULL))
genesis              1370         printf("Error: CreateThread(ThreadMessageHandler) failed\n");
genesis              1371 
genesis              1372     
genesis              1373     GenerateBitcoins(fGenerateBitcoins, pwalletMain);
genesis              1374 }
genesis              1375 
genesis              1376 bool StopNode()
genesis              1377 {
genesis              1378     printf("StopNode()\n");
genesis              1379     fShutdown = true;
genesis              1380     nTransactionsUpdated++;
genesis              1381     int64 nStart = GetTime();
asciilifeform_wir... 1382     while (vnThreadsRunning[0] > 0 || vnThreadsRunning[1] > 0 || vnThreadsRunning[2] > 0 || vnThreadsRunning[3] > 0 || vnThreadsRunning[4] > 0 || vnThreadsRunning[5] > 0
genesis              1383     )
genesis              1384     {
genesis              1385         if (GetTime() - nStart > 20)
genesis              1386             break;
genesis              1387         Sleep(20);
genesis              1388     }
genesis              1389     if (vnThreadsRunning[0] > 0) printf("ThreadSocketHandler still running\n");
genesis              1390     if (vnThreadsRunning[1] > 0) printf("ThreadOpenConnections still running\n");
genesis              1391     if (vnThreadsRunning[2] > 0) printf("ThreadMessageHandler still running\n");
genesis              1392     if (vnThreadsRunning[3] > 0) printf("ThreadBitcoinMiner still running\n");
genesis              1393     if (vnThreadsRunning[4] > 0) printf("ThreadRPCServer still running\n");
asciilifeform_wir... 1394     if (vnThreadsRunning[5] > 0) printf("ThreadOpenWires still running\n");
genesis              1395     while (vnThreadsRunning[2] > 0 || vnThreadsRunning[4] > 0)
genesis              1396         Sleep(20);
genesis              1397     Sleep(50);
genesis              1398 
genesis              1399     return true;
genesis              1400 }
genesis              1401 
genesis              1402 class CNetCleanup
genesis              1403 {
genesis              1404 public:
genesis              1405     CNetCleanup()
genesis              1406     {
genesis              1407     }
genesis              1408     ~CNetCleanup()
genesis              1409     {
genesis              1410         
genesis              1411         BOOST_FOREACH(CNode* pnode, vNodes)
genesis              1412             if (pnode->hSocket != INVALID_SOCKET)
genesis              1413                 closesocket(pnode->hSocket);
genesis              1414         if (hListenSocket != INVALID_SOCKET)
genesis              1415             if (closesocket(hListenSocket) == SOCKET_ERROR)
genesis              1416                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
genesis              1417 
genesis              1418     }
genesis              1419 }
genesis              1420 instance_of_cnetcleanup;