diff --git a/Client.cpp b/Client.cpp index 1c5badc1..2954de9d 100644 --- a/Client.cpp +++ b/Client.cpp @@ -67,25 +67,6 @@ void CClient::ReadLine(const CString& sData) { if (IsAttached()) { MODULECALL(OnUserRaw(sLine), m_pUser, this, return); } else { - // If it's an HTTP Request - Check the webmods - if (sLine.WildCmp("GET * HTTP/1.?") || sLine.WildCmp("POST * HTTP/1.?")) { - CModule* pMod = new CModule(NULL, "", ""); - pMod->SetFake(true); - - CWebSock* pSock = new CWebSock(pMod); - CZNC::Get().GetManager().SwapSockByAddr(pSock, this); - - // And don't forget to give it some sane name / timeout - pSock->SetSockName("WebMod::Client"); - pSock->SetTimeout(120); - - // TODO can we somehow get rid of this? - pSock->ReadLine(sLine); - pSock->PushBuff("", 0, true); - - return; - } - if (CZNC::Get().GetModules().OnUnknownUserRaw(this, sLine)) { return; } diff --git a/Client.h b/Client.h index 4f80d207..d6902cc1 100644 --- a/Client.h +++ b/Client.h @@ -73,7 +73,7 @@ protected: class CClient : public CZNCSock { public: - CClient(const CString& sHostname, unsigned short uPort) : CZNCSock(sHostname, uPort) { + CClient() : CZNCSock() { m_pUser = NULL; m_bGotPass = false; m_bGotNick = false; @@ -85,10 +85,6 @@ public: // a little more gentle ;) SetMaxBufferThreshold(1024); - // Disable all timeout types. The socket will now time out in 60 - // seconds, no matter what. AcceptLogin() fixes this up. - SetTimeout(60, 0); - SetNick("unknown-nick"); } diff --git a/Listener.cpp b/Listener.cpp index 4b36d3d8..d98818db 100644 --- a/Listener.cpp +++ b/Listener.cpp @@ -38,11 +38,12 @@ bool CRealListener::ConnectionFrom(const CString& sHost, unsigned short uPort) { } Csock* CRealListener::GetSockObj(const CString& sHost, unsigned short uPort) { - CClient *pClient = new CClient(sHost, uPort); + CIncomingConnection *pClient = new CIncomingConnection(sHost, uPort); if (CZNC::Get().AllowConnectionFrom(sHost)) { CZNC::Get().GetModules().OnClientConnect(pClient, sHost, uPort); } else { - pClient->RefuseLogin("Too many anonymous connections from your IP"); + pClient->Write(":irc.znc.in 464 unknown-nick :Too many anonymous connections from your IP\r\n"); + pClient->Close(Csock::CLT_AFTERWRITE); CZNC::Get().GetModules().OnFailedLogin("", sHost); } return pClient; @@ -56,3 +57,43 @@ void CRealListener::SockError(int iErrno) { Close(); } } + +CIncomingConnection::CIncomingConnection(const CString& sHostname, unsigned short uPort) : CZNCSock(sHostname, uPort) { + // The socket will time out in 120 secs, no matter what. + // This has to be fixed up later, if desired. + SetTimeout(120, 0); + + EnableReadLine(); +} + +void CIncomingConnection::ReadLine(const CString& sLine) { + bool bIsHTTP = (sLine.WildCmp("GET * HTTP/1.?\r\n") || sLine.WildCmp("POST * HTTP/1.?\r\n")); + Csock *pSock = NULL; + + if (!bIsHTTP) { + // Let's assume it's an IRC connection + + pSock = new CClient(); + CZNC::Get().GetManager().SwapSockByAddr(pSock, this); + + // And don't forget to give it some sane name / timeout + pSock->SetSockName("USR::???"); + } else { + // This is a HTTP request, let the webmods handle it + + CModule* pMod = new CModule(NULL, "", ""); + pMod->SetFake(true); + + pSock = new CWebSock(pMod); + CZNC::Get().GetManager().SwapSockByAddr(pSock, this); + + // And don't forget to give it some sane name / timeout + pSock->SetSockName("WebMod::Client"); + } + + if (pSock) { + // TODO can we somehow get rid of this? + pSock->ReadLine(sLine); + pSock->PushBuff("", 0, true); + } +} diff --git a/Listener.h b/Listener.h index 0ead18d2..5c220d5f 100644 --- a/Listener.h +++ b/Listener.h @@ -66,4 +66,11 @@ protected: CRealListener* m_pListener; }; +class CIncomingConnection : public CZNCSock { +public: + CIncomingConnection(const CString& sHostname, unsigned short uPort); + virtual ~CIncomingConnection() {} + virtual void ReadLine(const CString& sData); +}; + #endif // !_LISTENER_H diff --git a/Modules.cpp b/Modules.cpp index ad23c732..0aeb9bc7 100644 --- a/Modules.cpp +++ b/Modules.cpp @@ -501,7 +501,7 @@ bool CModule::PutModNotice(const CString& sLine, const CString& sIdent, const CS CModule::EModRet CGlobalModule::OnWriteConfig(CFile& Config) { return CONTINUE; } CModule::EModRet CGlobalModule::OnAddUser(CUser& User, CString& sErrorRet) { return CONTINUE; } CModule::EModRet CGlobalModule::OnDeleteUser(CUser& User) { return CONTINUE; } -void CGlobalModule::OnClientConnect(CClient* pClient, const CString& sHost, unsigned short uPort) {} +void CGlobalModule::OnClientConnect(CZNCSock* pClient, const CString& sHost, unsigned short uPort) {} CModule::EModRet CGlobalModule::OnLoginAttempt(CSmartPtr Auth) { return CONTINUE; } void CGlobalModule::OnFailedLogin(const CString& sUsername, const CString& sRemoteIP) {} CModule::EModRet CGlobalModule::OnUnknownUserRaw(CClient* pClient, CString& sLine) { return CONTINUE; } @@ -613,7 +613,7 @@ bool CGlobalModules::OnDeleteUser(CUser& User) { GLOBALMODHALTCHK(OnDeleteUser(User)); } -void CGlobalModules::OnClientConnect(CClient* pClient, const CString& sHost, unsigned short uPort) { +void CGlobalModules::OnClientConnect(CZNCSock* pClient, const CString& sHost, unsigned short uPort) { GLOBALMODCALL(OnClientConnect(pClient, sHost, uPort)); } diff --git a/Modules.h b/Modules.h index 30480efd..e06f128a 100644 --- a/Modules.h +++ b/Modules.h @@ -940,11 +940,11 @@ public: virtual EModRet OnDeleteUser(CUser& User); /** This module hook is called when there is an incoming connection on * any of ZNC's listening sockets. - * @param pClient The incoming client socket. + * @param pSock The incoming client socket. * @param sHost The IP the client is connecting from. * @param uPort The port the client is connecting from. */ - virtual void OnClientConnect(CClient* pClient, const CString& sHost, unsigned short uPort); + virtual void OnClientConnect(CZNCSock* pSock, const CString& sHost, unsigned short uPort); /** This module hook is called when a client tries to login. If your * module wants to handle the login attempt, it must return * CModule::EModRet::HALT; @@ -977,7 +977,7 @@ public: bool OnWriteConfig(CFile& Config); bool OnAddUser(CUser& User, CString& sErrorRet); bool OnDeleteUser(CUser& User); - void OnClientConnect(CClient* pClient, const CString& sHost, unsigned short uPort); + void OnClientConnect(CZNCSock* pSock, const CString& sHost, unsigned short uPort); bool OnLoginAttempt(CSmartPtr Auth); void OnFailedLogin(const CString& sUsername, const CString& sRemoteIP); bool OnUnknownUserRaw(CClient* pClient, CString& sLine); diff --git a/modules/fail2ban.cpp b/modules/fail2ban.cpp index c5be7316..6ee9b7f9 100644 --- a/modules/fail2ban.cpp +++ b/modules/fail2ban.cpp @@ -52,7 +52,7 @@ public: PutModule("is blocked after a failed login."); } - virtual void OnClientConnect(CClient* pClient, const CString& sHost, unsigned short uPort) { + virtual void OnClientConnect(CZNCSock* pClient, const CString& sHost, unsigned short uPort) { unsigned int *pCount = m_Cache.GetItem(sHost); if (sHost.empty() || pCount == NULL || *pCount < m_uiAllowedFailed) { return; @@ -61,7 +61,7 @@ public: // refresh their ban Add(sHost, *pCount); - pClient->PutClient("ERROR :Closing link [Please try again later - reconnecting too fast]"); + pClient->Write("ERROR :Closing link [Please try again later - reconnecting too fast]\r\n"); pClient->Close(Csock::CLT_AFTERWRITE); }