aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Fabio Bas2010-02-09 16:50:42 +0000
committerGravatar Fabio Bas2010-02-09 16:50:42 +0000
commitbfa2c9ba3f70a893968b5b030208111dc4b60fc3 (patch)
treeca03c844617e453cd7f11b5ce71db60d39c6eb19
parentSet svn:ignore props all around for the people that like to do in-tree builds (diff)
downloadKVIrc-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
-rw-r--r--src/kvirc/CMakeLists.txt2
-rw-r--r--src/kvirc/kernel/kvi_ircconnection.cpp4
-rw-r--r--src/kvirc/kernel/kvi_ircconnection.h9
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionrequestqueue.cpp152
-rw-r--r--src/kvirc/kernel/kvi_ircconnectionrequestqueue.h62
-rw-r--r--src/kvirc/kernel/kvi_irccontext.cpp3
-rw-r--r--src/kvirc/kernel/kvi_options.cpp1
-rw-r--r--src/kvirc/kernel/kvi_options.h3
-rw-r--r--src/kvirc/sparser/kvi_sp_literal.cpp47
-rw-r--r--src/modules/options/optw_channel.cpp6
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)));