Denial-of-service flood control
authorGavin Andresen <gavinandresen@gmail.com>
Wed, 16 Feb 2011 18:18:11 +0000 (13:18 -0500)
committerGavin Andresen <gavinandresen@gmail.com>
Wed, 16 Feb 2011 18:18:11 +0000 (13:18 -0500)
Drop connections that are either sending messages too fast to handle or are processing messages so slowly data starts to back up.
Adds two new options:
  -maxreceivebuffer  Default: 2000 (2000*1000 bytes)
  -maxsendbuffer     Default: 256  (256*1000 bytes)

net.cpp

diff --git a/net.cpp b/net.cpp
index 816c7e3..8480a2f 100644 (file)
--- a/net.cpp
+++ b/net.cpp
@@ -748,32 +748,39 @@ void ThreadSocketHandler2(void* parg)
                     CDataStream& vRecv = pnode->vRecv;
                     unsigned int nPos = vRecv.size();
 
-                    // typical socket buffer is 8K-64K
-                    char pchBuf[0x10000];
-                    int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
-                    if (nBytes > 0)
-                    {
-                        vRecv.resize(nPos + nBytes);
-                        memcpy(&vRecv[nPos], pchBuf, nBytes);
-                        pnode->nLastRecv = GetTime();
-                    }
-                    else if (nBytes == 0)
-                    {
-                        // socket closed gracefully
+                    if (nPos > 1000*GetArg("-maxreceivebuffer", 2*1000)) {
                         if (!pnode->fDisconnect)
-                            printf("socket closed\n");
+                            printf("socket recv flood control disconnect (%d bytes)\n", vRecv.size());
                         pnode->CloseSocketDisconnect();
                     }
-                    else if (nBytes < 0)
-                    {
-                        // error
-                        int nErr = WSAGetLastError();
-                        if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
+                    else {
+                        // typical socket buffer is 8K-64K
+                        char pchBuf[0x10000];
+                        int nBytes = recv(pnode->hSocket, pchBuf, sizeof(pchBuf), MSG_DONTWAIT);
+                        if (nBytes > 0)
                         {
+                            vRecv.resize(nPos + nBytes);
+                            memcpy(&vRecv[nPos], pchBuf, nBytes);
+                            pnode->nLastRecv = GetTime();
+                        }
+                        else if (nBytes == 0)
+                        {
+                            // socket closed gracefully
                             if (!pnode->fDisconnect)
-                                printf("socket recv error %d\n", nErr);
+                                printf("socket closed\n");
                             pnode->CloseSocketDisconnect();
                         }
+                        else if (nBytes < 0)
+                        {
+                            // error
+                            int nErr = WSAGetLastError();
+                            if (nErr != WSAEWOULDBLOCK && nErr != WSAEMSGSIZE && nErr != WSAEINTR && nErr != WSAEINPROGRESS)
+                            {
+                                if (!pnode->fDisconnect)
+                                    printf("socket recv error %d\n", nErr);
+                                pnode->CloseSocketDisconnect();
+                            }
+                        }
                     }
                 }
             }
@@ -806,6 +813,11 @@ void ThreadSocketHandler2(void* parg)
                                 pnode->CloseSocketDisconnect();
                             }
                         }
+                        if (vSend.size() > 1000*GetArg("-maxsendbuffer", 256)) {
+                            if (!pnode->fDisconnect)
+                                printf("socket send flood control disconnect (%d bytes)\n", vSend.size());
+                            pnode->CloseSocketDisconnect();
+                        }
                     }
                 }
             }