From 4fd07208ab7ae0f8b30c1d0d143548b6467464bb Mon Sep 17 00:00:00 2001 From: psychon Date: Sat, 24 May 2008 17:16:29 +0000 Subject: [PATCH] DCC bouncing: Throttle the receiving side if we can't bounce the data fast enough It could happen that ZNC was killed by the OOM killer. This was caused by DCC bouncing receiving as fast as possible and caching everything in memory. This throttles the receiving side via PauseRead() and UnPauseRead(). git-svn-id: https://znc.svn.sourceforge.net/svnroot/znc/trunk@1069 726aef4b-f618-498e-8847-2d620e286838 --- DCCBounce.cpp | 20 ++++++++++++++++++++ DCCBounce.h | 6 +++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/DCCBounce.cpp b/DCCBounce.cpp index 644211c9..e6a54ac8 100644 --- a/DCCBounce.cpp +++ b/DCCBounce.cpp @@ -9,6 +9,11 @@ #include "DCCBounce.h" #include "User.h" +// If we buffer more than this in memory, we will throttle the receiving side +const unsigned int CDCCBounce::m_uiMaxDCCBuffer = 10 * 1024; +// If less than this is in the buffer, the receiving side continues +const unsigned int CDCCBounce::m_uiMinDCCBuffer = 2 * 1024; + void CDCCBounce::ReadLine(const CString& sData) { CString sLine = sData; @@ -22,11 +27,26 @@ void CDCCBounce::ReadLine(const CString& sData) { } void CDCCBounce::ReadData(const char* data, int len) { + size_t BufLen; + if (m_pPeer) { m_pPeer->Write(data, len); + + BufLen = m_pPeer->GetInternalWriteBuffer().length(); + + if (BufLen >= m_uiMaxDCCBuffer) { + DEBUG_ONLY(cout << GetSockName() << " The send buffer is over the " + "limit (" << BufLen <<"), throttling" << endl); + PauseRead(); + } } } +void CDCCBounce::ReadPaused() { + if (!m_pPeer || m_pPeer->GetInternalWriteBuffer().length() <= m_uiMinDCCBuffer) + UnPauseRead(); +} + void CDCCBounce::Timeout() { DEBUG_ONLY(cout << GetSockName() << " == Timeout()" << endl); CString sType = (m_bIsChat) ? "Chat" : "Xfer"; diff --git a/DCCBounce.h b/DCCBounce.h index b949c315..d9237b9a 100644 --- a/DCCBounce.h +++ b/DCCBounce.h @@ -55,6 +55,7 @@ public: void ReadLine(const CString& sData); virtual void ReadData(const char* data, int len); + virtual void ReadPaused(); virtual void Timeout(); virtual void ConnectionRefused(); virtual void SockError(int iErrno); @@ -90,9 +91,12 @@ protected: CString m_sFileName; CUser* m_pUser; CDCCBounce* m_pPeer; - unsigned short m_uRemotePort; + unsigned short m_uRemotePort; bool m_bIsChat; bool m_bIsRemote; + + static const unsigned int m_uiMaxDCCBuffer; + static const unsigned int m_uiMinDCCBuffer; }; #endif // !_DCCBOUNCE_H