Merge branch '0.4.x' into 0.5.x
[novacoin.git] / src / net.cpp
index 92ccb1e..5b3faea 100644 (file)
@@ -10,7 +10,7 @@
 #include "init.h"
 #include "strlcpy.h"
 
-#ifdef __WXMSW__
+#ifdef WIN32
 #include <string.h>
 #endif
 
@@ -103,7 +103,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout
     bool fProxy = (fUseProxy && addrConnect.IsRoutable());
     struct sockaddr_in sockaddr = (fProxy ? addrProxy.GetSockAddr() : addrConnect.GetSockAddr());
 
-#ifdef __WXMSW__
+#ifdef WIN32
     u_long fNonblock = 1;
     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
 #else
@@ -142,7 +142,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout
                 return false;
             }
             socklen_t nRetSize = sizeof(nRet);
-#ifdef __WXMSW__
+#ifdef WIN32
             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, (char*)(&nRet), &nRetSize) == SOCKET_ERROR)
 #else
             if (getsockopt(hSocket, SOL_SOCKET, SO_ERROR, &nRet, &nRetSize) == SOCKET_ERROR)
@@ -159,7 +159,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout
                 return false;
             }
         }
-#ifdef __WXMSW__
+#ifdef WIN32
         else if (WSAGetLastError() != WSAEISCONN)
 #else
         else
@@ -176,7 +176,7 @@ bool ConnectSocket(const CAddress& addrConnect, SOCKET& hSocketRet, int nTimeout
     CNode::ConnectNode immediately turns the socket back to non-blocking
     but we'll turn it back to blocking just in case
     */
-#ifdef __WXMSW__
+#ifdef WIN32
     fNonblock = 0;
     if (ioctlsocket(hSocket, FIONBIO, &fNonblock) == SOCKET_ERROR)
 #else
@@ -679,7 +679,7 @@ CNode* ConnectNode(CAddress addrConnect, int64 nTimeout)
         printf("connected %s\n", addrConnect.ToString().c_str());
 
         // Set to nonblocking
-#ifdef __WXMSW__
+#ifdef WIN32
         u_long nOne = 1;
         if (ioctlsocket(hSocket, FIONBIO, &nOne) == SOCKET_ERROR)
             printf("ConnectSocket() : ioctlsocket nonblocking setting failed, error %d\n", WSAGetLastError());
@@ -732,6 +732,52 @@ void CNode::Cleanup()
 }
 
 
+std::map<unsigned int, int64> CNode::setBanned;
+CCriticalSection CNode::cs_setBanned;
+
+void CNode::ClearBanned()
+{
+    setBanned.clear();
+}
+
+bool CNode::IsBanned(unsigned int ip)
+{
+    bool fResult = false;
+    CRITICAL_BLOCK(cs_setBanned)
+    {
+        std::map<unsigned int, int64>::iterator i = setBanned.find(ip);
+        if (i != setBanned.end())
+        {
+            int64 t = (*i).second;
+            if (GetTime() < t)
+                fResult = true;
+        }
+    }
+    return fResult;
+}
+
+bool CNode::Misbehaving(int howmuch)
+{
+    if (addr.IsLocal())
+    {
+        printf("Warning: local node %s misbehaving\n", addr.ToString().c_str());
+        return false;
+    }
+
+    nMisbehavior += howmuch;
+    if (nMisbehavior >= GetArg("-banscore", 100))
+    {
+        int64 banTime = GetTime()+GetArg("-bantime", 60*60*24);  // Default 24-hour ban
+        CRITICAL_BLOCK(cs_setBanned)
+            if (setBanned[addr.ip] < banTime)
+                setBanned[addr.ip] = banTime;
+        CloseSocketDisconnect();
+        printf("Disconnected %s for misbehavior (score=%d)\n", addr.ToString().c_str(), nMisbehavior);
+        return true;
+    }
+    return false;
+}
+
 
 
 
@@ -906,6 +952,11 @@ void ThreadSocketHandler2(void* parg)
             {
                 closesocket(hSocket);
             }
+            else if (CNode::IsBanned(addr.ip))
+            {
+                printf("connection from %s dropped (banned)\n", addr.ToString().c_str());
+                closesocket(hSocket);
+            }
             else
             {
                 printf("accepted connection %s\n", addr.ToString().c_str());
@@ -1496,6 +1547,8 @@ void ThreadOpenConnections2(void* parg)
             BOOST_FOREACH(CNode* pnode, vNodes)
                 setConnected.insert(pnode->addr.ip & 0x0000ffff);
 
+        int64 nANow = GetAdjustedTime();
+
         CRITICAL_BLOCK(cs_mapAddresses)
         {
             BOOST_FOREACH(const PAIRTYPE(vector<unsigned char>, CAddress)& item, mapAddresses)
@@ -1503,8 +1556,8 @@ void ThreadOpenConnections2(void* parg)
                 const CAddress& addr = item.second;
                 if (!addr.IsIPv4() || !addr.IsValid() || setConnected.count(addr.ip & 0x0000ffff))
                     continue;
-                int64 nSinceLastSeen = GetAdjustedTime() - addr.nTime;
-                int64 nSinceLastTry = GetAdjustedTime() - addr.nLastTry;
+                int64 nSinceLastSeen = nANow - addr.nTime;
+                int64 nSinceLastTry = nANow - addr.nLastTry;
 
                 // Randomize the order in a deterministic way, putting the standard port first
                 int64 nRandomizer = (uint64)(nStart * 4951 + addr.nLastTry * 9567851 + addr.ip * 7789) % (2 * 60 * 60);
@@ -1563,7 +1616,8 @@ bool OpenNetworkConnection(const CAddress& addrConnect)
     //
     if (fShutdown)
         return false;
-    if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() || FindNode(addrConnect.ip))
+    if (addrConnect.ip == addrLocalHost.ip || !addrConnect.IsIPv4() ||
+        FindNode(addrConnect.ip) || CNode::IsBanned(addrConnect.ip))
         return false;
 
     vnThreadsRunning[1]--;
@@ -1667,7 +1721,7 @@ bool BindListenPort(string& strError)
     int nOne = 1;
     addrLocalHost.port = htons(GetListenPort());
 
-#ifdef __WXMSW__
+#ifdef WIN32
     // Initialize Windows Sockets
     WSADATA wsadata;
     int ret = WSAStartup(MAKEWORD(2,2), &wsadata);
@@ -1693,13 +1747,13 @@ bool BindListenPort(string& strError)
     setsockopt(hListenSocket, SOL_SOCKET, SO_NOSIGPIPE, (void*)&nOne, sizeof(int));
 #endif
 
-#ifndef __WXMSW__
+#ifndef WIN32
     // Allow binding if the port is still in TIME_WAIT state after
     // the program was closed and restarted.  Not an issue on windows.
     setsockopt(hListenSocket, SOL_SOCKET, SO_REUSEADDR, (void*)&nOne, sizeof(int));
 #endif
 
-#ifdef __WXMSW__
+#ifdef WIN32
     // Set to nonblocking, incoming connections will also inherit this
     if (ioctlsocket(hListenSocket, FIONBIO, (u_long*)&nOne) == SOCKET_ERROR)
 #else
@@ -1746,7 +1800,7 @@ void StartNode(void* parg)
     if (pnodeLocalHost == NULL)
         pnodeLocalHost = new CNode(INVALID_SOCKET, CAddress("127.0.0.1", 0, false, nLocalServices));
 
-#ifdef __WXMSW__
+#ifdef WIN32
     // Get local host ip
     char pszHostName[1000] = "";
     if (gethostname(pszHostName, sizeof(pszHostName)) != SOCKET_ERROR)
@@ -1889,7 +1943,7 @@ public:
             if (closesocket(hListenSocket) == SOCKET_ERROR)
                 printf("closesocket(hListenSocket) failed with error %d\n", WSAGetLastError());
 
-#ifdef __WXMSW__
+#ifdef WIN32
         // Shutdown Windows Sockets
         WSACleanup();
 #endif