diff options
| author | 2010-02-09 16:50:42 +0000 | |
|---|---|---|
| committer | 2010-02-09 16:50:42 +0000 | |
| commit | bfa2c9ba3f70a893968b5b030208111dc4b60fc3 (patch) | |
| tree | ca03c844617e453cd7f11b5ce71db60d39c6eb19 /src | |
| parent | Set svn:ignore props all around for the people that like to do in-tree builds (diff) | |
| download | KVIrc-bfa2c9ba3f70a893968b5b030208111dc4b60fc3.tar.gz KVIrc-bfa2c9ba3f70a893968b5b030208111dc4b60fc3.tar.bz2 KVIrc-bfa2c9ba3f70a893968b5b030208111dc4b60fc3.zip | |
introduce a queue for channel requests (mode, who, mode E, mode I, mode b) to be able to delay them and avoid excess floods on some servers (yes i'm looking at you irc7/freenode).
git-svn-id: https://svn.kvirc.de/svn/trunk/kvirc@3940 17fca916-40b9-46aa-a4ea-0a15b648b75c
Diffstat (limited to 'src')
| -rw-r--r-- | src/kvirc/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_ircconnection.cpp | 4 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_ircconnection.h | 9 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_ircconnectionrequestqueue.cpp | 152 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_ircconnectionrequestqueue.h | 62 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_irccontext.cpp | 3 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_options.cpp | 1 | ||||
| -rw-r--r-- | src/kvirc/kernel/kvi_options.h | 3 | ||||
| -rw-r--r-- | src/kvirc/sparser/kvi_sp_literal.cpp | 47 | ||||
| -rw-r--r-- | src/modules/options/optw_channel.cpp | 6 |
10 files changed, 243 insertions, 46 deletions
diff --git a/src/kvirc/CMakeLists.txt b/src/kvirc/CMakeLists.txt index 37c8cb2b9..7a697f108 100644 --- a/src/kvirc/CMakeLists.txt +++ b/src/kvirc/CMakeLists.txt @@ -85,6 +85,7 @@ SET(kvirc_MOC_HDRS kernel/kvi_iconmanager.h kernel/kvi_ipc.h kernel/kvi_ircconnection.h + kernel/kvi_ircconnectionrequestqueue.h kernel/kvi_ircconnectiontargetresolver.h kernel/kvi_irccontext.h kernel/kvi_irclink.h @@ -291,6 +292,7 @@ SET(kvirc_SRCS kernel/kvi_ircconnectionantictcpflooddata.cpp kernel/kvi_ircconnectionasyncwhoisdata.cpp kernel/kvi_ircconnectionnetsplitdetectordata.cpp + kernel/kvi_ircconnectionrequestqueue.cpp kernel/kvi_ircconnectionserverinfo.cpp kernel/kvi_ircconnectionstatedata.cpp kernel/kvi_ircconnectionstatistics.cpp diff --git a/src/kvirc/kernel/kvi_ircconnection.cpp b/src/kvirc/kernel/kvi_ircconnection.cpp index 99e5990be..8ca8d138e 100644 --- a/src/kvirc/kernel/kvi_ircconnection.cpp +++ b/src/kvirc/kernel/kvi_ircconnection.cpp @@ -32,6 +32,7 @@ #include "kvi_ircconnectionantictcpflooddata.h" #include "kvi_ircconnectionnetsplitdetectordata.h" #include "kvi_ircconnectionasyncwhoisdata.h" +#include "kvi_ircconnectionrequestqueue.h" #include "kvi_ircconnectionstatistics.h" #include "kvi_irclink.h" #include "kvi_ircsocket.h" @@ -98,6 +99,7 @@ KviIrcConnection::KviIrcConnection(KviIrcContext * pContext,KviIrcConnectionTarg m_pLocalhostDns = 0; m_pLagMeter = 0; m_eState = Idle; + m_pRequestQueue = new KviRequestQueue(); setupSrvCodec(); setupTextCodec(); } @@ -151,6 +153,7 @@ KviIrcConnection::~KviIrcConnection() delete m_pAsyncWhoisData; delete m_pStatistics; delete m_pUserIdentity; + delete m_pRequestQueue; } void KviIrcConnection::setEncoding(const QString & szEncoding) @@ -510,6 +513,7 @@ void KviIrcConnection::registerChannel(KviChannel * c) void KviIrcConnection::unregisterChannel(KviChannel * c) { m_pChannelList->removeRef(c); + requestQueue()->dequeueChannel(c); emit(channelUnregistered(c)); emit(chanListChanged()); } diff --git a/src/kvirc/kernel/kvi_ircconnection.h b/src/kvirc/kernel/kvi_ircconnection.h index 317439a9a..f469bcdb0 100644 --- a/src/kvirc/kernel/kvi_ircconnection.h +++ b/src/kvirc/kernel/kvi_ircconnection.h @@ -62,6 +62,7 @@ class KviIrcConnectionAntiCtcpFloodData; class KviIrcConnectionNetsplitDetectorData; class KviIrcConnectionAsyncWhoisData; class KviIrcConnectionStatistics; +class KviRequestQueue; class KviLagMeter; class KviNotifyListManager; class KviDns; @@ -176,6 +177,8 @@ private: QTextCodec * m_pSrvCodec; // connection codec: never null QTextCodec * m_pTextCodec; // connection codec: never null + KviRequestQueue * m_pRequestQueue; // owned, never null + public: /** * \brief Returns a pointer to the owning console @@ -338,6 +341,12 @@ public: inline KviLagMeter * lagMeter(){ return m_pLagMeter; }; /** + * \brief Returns a pointer to the current KviRequestQueue. + * \return KviRequestQueue * + */ + inline KviRequestQueue * requestQueue(){ return m_pRequestQueue; }; + + /** * \brief Returns the list of the channels bound to the current connection. * * The pointer itself is never null (though the list may be empty). diff --git a/src/kvirc/kernel/kvi_ircconnectionrequestqueue.cpp b/src/kvirc/kernel/kvi_ircconnectionrequestqueue.cpp new file mode 100644 index 000000000..e78f19471 --- /dev/null +++ b/src/kvirc/kernel/kvi_ircconnectionrequestqueue.cpp @@ -0,0 +1,152 @@ +//============================================================================= +// +// File : kvi_ircconnectionrequestqueue.h +// Creation date : Tue 09 Feb 2010 10:24:32 by Fabio Bas +// +// This file is part of the KVIrc IRC client distribution +// Copyright (C) 2010 Fabio Bas <ctrlaltca at gmail dot com> +// +// This program is FREE software. You can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your opinion) any later version. +// +// This program is distributed in the HOPE that it will be USEFUL, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//============================================================================= + +#include "kvi_ircconnectionrequestqueue.h" + +#include "kvi_channel.h" +#include "kvi_options.h" +#include "kvi_lagmeter.h" +#include "kvi_ircconnectionstatedata.h" + +#include <QByteArray> + +KviRequestQueue::KviRequestQueue() +{ + curType=ModeRequest; + connect(&timer, SIGNAL(timeout()), this, SLOT(timerSlot())); +} + +KviRequestQueue::~KviRequestQueue() +{ + disconnect(&timer, SIGNAL(timeout()), this, SLOT(timerSlot())); +} + +void KviRequestQueue::enqueueChannel(KviChannel *pChan) +{ + if(!channels.contains(pChan)) + { + channels.enqueue(pChan); + if(!timer.isActive()) timer.start(KVI_OPTION_UINT(KviOption_uintOnJoinRequestsDelay)*1000); + } +} + +void KviRequestQueue::dequeueChannel(KviChannel *pChan) +{ + if(channels.contains(pChan)) + { + channels.removeOne(pChan); + if(channels.isEmpty()) + timer.stop(); + } +} + +void KviRequestQueue::clearAll() +{ + channels.clear(); + timer.stop(); + curType=ModeRequest; +} + +void KviRequestQueue::timerSlot() +{ + if(channels.isEmpty()) + { + timer.stop(); + } else { + KviChannel* chan = channels.head(); + QByteArray encodedChan = chan->connection()->encodeText(chan->target()).data(); + /* The following switch will let the execution flow pass-trought if any request type + * is currently disabled (or not available on the server). Channel's "MODE" request is + * the only mandatory request. + */ + switch(curType) + { + case BanERequest: + if(chan->connection()->serverInfo()->supportsModesIe() && + !KVI_OPTION_BOOL(KviOption_boolDisableBanExceptionListRequestOnJoin)) + { + if(!chan->connection()->sendFmtData("MODE %s e",encodedChan.data())) + clearAll(); // disconnected + else chan->setSentBanExceptionListRequest(); + curType=InviRequest; + break; + } + case InviRequest: + if(chan->connection()->serverInfo()->supportsModesIe() && + !KVI_OPTION_BOOL(KviOption_boolDisableInviteListRequestOnJoin)) + { + if(!chan->connection()->sendFmtData("MODE %s I",encodedChan.data())) + clearAll(); // disconnected + else chan->setSentInviteListRequest(); + curType=WhoRequest; + break; + } + case WhoRequest: + if(!KVI_OPTION_BOOL(KviOption_boolDisableWhoRequestOnJoin)) + { + chan->connection()->stateData()->setLastSentChannelWhoRequest(kvi_unixTime()); + if(chan->connection()->lagMeter()) + { + KviStr tmp; + tmp.sprintf("WHO %s",encodedChan.data()); + chan->connection()->lagMeter()->lagCheckRegister(tmp.ptr(),60); + } + if(!chan->connection()->sendFmtData("WHO %s",encodedChan.data())) + clearAll(); // disconnected + else chan->setSentWhoRequest(); + curType=BanRequest; + break; + } + case BanRequest: + if(!KVI_OPTION_BOOL(KviOption_boolDisableBanListRequestOnJoin)) + { + if(!chan->connection()->sendFmtData("MODE %s b",encodedChan.data())) + clearAll(); // disconnected + else chan->setSentBanListRequest(); + channels.dequeue(); + curType=ModeRequest; + break; + } + default: + //we're at the end of the list + channels.dequeue(); + if(channels.isEmpty()) + { + timer.stop(); + return; + } + chan = channels.head(); + encodedChan = chan->connection()->encodeText(chan->target()); + curType=ModeRequest; + case ModeRequest: + if(!chan->connection()->sendFmtData("MODE %s",encodedChan.data())) + { + clearAll(); // disconnected + break; + } + curType=BanERequest; + break; + } + } +}
\ No newline at end of file diff --git a/src/kvirc/kernel/kvi_ircconnectionrequestqueue.h b/src/kvirc/kernel/kvi_ircconnectionrequestqueue.h new file mode 100644 index 000000000..539c5d27e --- /dev/null +++ b/src/kvirc/kernel/kvi_ircconnectionrequestqueue.h @@ -0,0 +1,62 @@ +#ifndef _KVI_IRCCONNECTIONREQUESTQUEUE_H_ +#define _KVI_IRCCONNECTIONREQUESTQUEUE_H_ +//============================================================================= +// +// File : kvi_ircconnectionrequestqueue.h +// Creation date : Tue 09 Feb 2010 10:24:32 by Fabio Bas +// +// This file is part of the KVIrc IRC client distribution +// Copyright (C) 2010 Fabio Bas <ctrlaltca at gmail dot com> +// +// This program is FREE software. You can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your opinion) any later version. +// +// This program is distributed in the HOPE that it will be USEFUL, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, write to the Free Software Foundation, +// Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +// +//============================================================================= + +#include "kvi_settings.h" + +#include <QTimer> +#include <QQueue> + +class KviChannel; + +class KVIRC_API KviRequestQueue: public QObject +{ + Q_OBJECT +protected: + QQueue<KviChannel *> channels; + QTimer timer; + // MODE %s b MUST BE THE LAST AUTOMATIC CHANNEL QUERY + // so we get RPL_ENDOFBANLIST as the last reply + // and we know that the channel is in sync + enum requestTypes { + ModeRequest = 0, + BanERequest = 1, + InviRequest = 2, + WhoRequest = 3, + BanRequest = 4 + }; + requestTypes curType; +public: + KviRequestQueue(); + virtual ~KviRequestQueue(); +public: + void enqueueChannel(KviChannel *pChan); + void dequeueChannel(KviChannel *pChan); + void clearAll(); +private slots: + void timerSlot(); +}; + +#endif //!_KVI_IRCCONNECTIONREQUESTQUEUE_H_ diff --git a/src/kvirc/kernel/kvi_irccontext.cpp b/src/kvirc/kernel/kvi_irccontext.cpp index 407a95b09..b5c88c1d3 100644 --- a/src/kvirc/kernel/kvi_irccontext.cpp +++ b/src/kvirc/kernel/kvi_irccontext.cpp @@ -37,6 +37,7 @@ #include "kvi_asynchronousconnectiondata.h" #include "kvi_ircconnectionstatedata.h" #include "kvi_ircconnectionuserinfo.h" +#include "kvi_ircconnectionrequestqueue.h" #include "kvi_irctoolbar.h" #include "kvi_out.h" #include "kvi_ircserverdb.h" @@ -713,6 +714,8 @@ void KviIrcContext::connectionTerminated() pInfo->m_bIsAway = connection()->userInfo()->isAway(); pInfo->m_szAwayReason = connection()->userInfo()->awayReason(); + connection()->requestQueue()->clearAll(); + // we consider it unexpected when we haven't sent a QUIT message and we're connected // or alternatively when a simulation of such a termination is requested (this is used to keep the queries open etc..) bool bUnexpectedDisconnect = (!(connection()->stateData()->sentQuit())) && ((m_eState == KviIrcContext::Connected) || connection()->stateData()->simulateUnexpectedDisconnect()); diff --git a/src/kvirc/kernel/kvi_options.cpp b/src/kvirc/kernel/kvi_options.cpp index 8c55f9281..7b9b45274 100644 --- a/src/kvirc/kernel/kvi_options.cpp +++ b/src/kvirc/kernel/kvi_options.cpp @@ -651,6 +651,7 @@ KviUIntOption g_uintOptionsTable[KVI_NUM_UINT_OPTIONS]= UINT_OPTION("UserIrcViewOwnBackground",8,KviOption_sectFlagIrcView | KviOption_resetUpdateGui | KviOption_groupTheme), UINT_OPTION("NotifierPixmapAlign",0,KviOption_sectFlagNotifier | KviOption_groupTheme), UINT_OPTION("OutputDatetimeFormat",0,KviOption_sectFlagIrcView), + UINT_OPTION("OnJoinRequestsDelay",2,KviOption_sectFlagConnection), }; #define FONT_OPTION(_name,_face,_size,_flags) \ diff --git a/src/kvirc/kernel/kvi_options.h b/src/kvirc/kernel/kvi_options.h index 43bbd422d..8117d5499 100644 --- a/src/kvirc/kernel/kvi_options.h +++ b/src/kvirc/kernel/kvi_options.h @@ -588,7 +588,8 @@ DECLARE_OPTION_STRUCT(KviStringListOption,QStringList) #define KviOption_uintUserIrcViewOwnBackground 75 /* look & feel::ircview */ #define KviOption_uintNotifierPixmapAlign 76 #define KviOption_uintOutputDatetimeFormat 77 /* irc::verbosity */ -#define KVI_NUM_UINT_OPTIONS 78 +#define KviOption_uintOnJoinRequestsDelay 78 +#define KVI_NUM_UINT_OPTIONS 79 namespace KviIdentdOutputMode { enum Mode { diff --git a/src/kvirc/sparser/kvi_sp_literal.cpp b/src/kvirc/sparser/kvi_sp_literal.cpp index cfcd6726b..6f58fbe4b 100644 --- a/src/kvirc/sparser/kvi_sp_literal.cpp +++ b/src/kvirc/sparser/kvi_sp_literal.cpp @@ -51,6 +51,7 @@ #include "kvi_ircconnection.h" #include "kvi_ircconnectionuserinfo.h" #include "kvi_ircconnectiontarget.h" +#include "kvi_ircconnectionrequestqueue.h" #include "kvi_ircconnectionserverinfo.h" #include "kvi_ircconnectionstatedata.h" #include "kvi_ircconnectionnetsplitdetectordata.h" @@ -241,50 +242,8 @@ void KviServerParser::parseLiteralJoin(KviIrcMessage *msg) // message in KviIrcSocket. See the comment in KviIrcSocket::processData() for more info. // FIXME: #warning "IF VERBOSE SAY THAT WE'RE REQUESTING MODES & BAN LIST" (Synching channel) - - if(!msg->connection()->sendFmtData("MODE %s",encodedChan)) - return; // disconnected - - if(msg->connection()->serverInfo()->supportsModesIe()) - { - if(!KVI_OPTION_BOOL(KviOption_boolDisableBanExceptionListRequestOnJoin)) - { - if(!msg->connection()->sendFmtData("MODE %s e",encodedChan)) - return; // disconnected - chan->setSentBanExceptionListRequest(); - } - if(!KVI_OPTION_BOOL(KviOption_boolDisableInviteListRequestOnJoin)) - { - if(!msg->connection()->sendFmtData("MODE %s I",encodedChan)) - return; // disconnected - chan->setSentInviteListRequest(); - } - } - - // MODE %s b MUST BE THE LAST AUTOMATIC CHANNEL QUERY - // so we get RPL_ENDOFBANLIST as the last reply - // and we know that the channel is in sync - - if(!KVI_OPTION_BOOL(KviOption_boolDisableWhoRequestOnJoin)) - { - msg->connection()->stateData()->setLastSentChannelWhoRequest(kvi_unixTime()); - if(msg->connection()->lagMeter()) - { - KviStr tmp(KviStr::Format,"WHO %s",encodedChan); - msg->connection()->lagMeter()->lagCheckRegister(tmp.ptr(),60); - } - if(!msg->connection()->sendFmtData("WHO %s",encodedChan)) - return; // disconnected - chan->setSentWhoRequest(); - } - - if(!KVI_OPTION_BOOL(KviOption_boolDisableBanListRequestOnJoin)) - { - if(!msg->connection()->sendFmtData("MODE %s b",encodedChan)) - return; // disconnected - chan->setSentBanListRequest(); - } - + msg->connection()->requestQueue()->enqueueChannel(chan); + if(KVI_OPTION_BOOL(KviOption_boolPasteLastLogOnChannelJoin)) chan->pasteLastLog(); diff --git a/src/modules/options/optw_channel.cpp b/src/modules/options/optw_channel.cpp index 1c166f99b..cf2159d15 100644 --- a/src/modules/options/optw_channel.cpp +++ b/src/modules/options/optw_channel.cpp @@ -117,6 +117,10 @@ KviChannelAdvancedOptionsWidget::KviChannelAdvancedOptionsWidget(QWidget * pPare m_pBanTypeCombo->setCurrentIndex(KVI_OPTION_UINT(KviOption_uintDefaultBanType)); KviTalGroupBox * g = addGroupBox(0,2,4,2,Qt::Horizontal,__tr2qs_ctx("On Channel Join","options")); + KviUIntSelector *u = addUIntSelector(g,__tr2qs_ctx("Minimum delay between two requests:","options"),KviOption_uintOnJoinRequestsDelay,0,60,2); + u->setSuffix(__tr2qs_ctx(" sec","options")); + mergeTip(u,__tr2qs_ctx("<center>Minimum value: <b>0 secs</b><br>Maximum value: <b>60 secs</b></center>","options")); + addBoolSelector(g,__tr2qs_ctx("Do not send /WHO request","options"),KviOption_boolDisableWhoRequestOnJoin); addBoolSelector(g,__tr2qs_ctx("Do not request ban list","options"),KviOption_boolDisableBanListRequestOnJoin); addBoolSelector(g,__tr2qs_ctx("Do not request ban exception list","options"),KviOption_boolDisableBanExceptionListRequestOnJoin); @@ -127,7 +131,7 @@ KviChannelAdvancedOptionsWidget::KviChannelAdvancedOptionsWidget(QWidget * pPare b = addBoolSelector(g,__tr2qs_ctx("Paste last channel log","options"),KviOption_boolPasteLastLogOnChannelJoin); KviTalHBox * box = new KviTalHBox(g); - KviUIntSelector * u = addUIntSelector(box,__tr2qs_ctx("Paste up to:","options"),KviOption_uintLinesToPasteOnChannelJoin,0,50,10,KVI_OPTION_BOOL(KviOption_boolPasteLastLogOnChannelJoin)); + u = addUIntSelector(box,__tr2qs_ctx("Paste up to:","options"),KviOption_uintLinesToPasteOnChannelJoin,0,50,10,KVI_OPTION_BOOL(KviOption_boolPasteLastLogOnChannelJoin)); u->setSuffix(__tr2qs_ctx(" lines","options")); mergeTip(u,__tr2qs_ctx("<center>Minimum value: <b>0 lines</b><br>Maximum value: <b>50 lines</b></center>","options")); connect(b,SIGNAL(toggled(bool)),u,SLOT(setEnabled(bool))); |
