Add an option to change ping timeout time.

Fix #979
This commit is contained in:
Alexey Sokolov
2016-12-26 15:49:26 +00:00
parent d9c1da8a68
commit b666931883
9 changed files with 67 additions and 26 deletions
+5 -14
View File
@@ -48,18 +48,6 @@ class CIRCNetwork {
CIRCNetwork(const CIRCNetwork&) = delete;
CIRCNetwork& operator=(const CIRCNetwork&) = delete;
enum {
JOIN_FREQUENCY = 30,
/** How long must an IRC connection be idle before ZNC sends a ping */
PING_FREQUENCY = 120,
/** Time between checks if PINGs need to be sent */
PING_SLACK = 30,
/** Timeout after which IRC connections are closed. Must
* obviously be greater than PING_FREQUENCY + PING_SLACK.
*/
NO_TRAFFIC_TIMEOUT = 180
};
void Clone(const CIRCNetwork& Network, bool bCloneName = true);
CString GetNetworkPath() const;
@@ -157,7 +145,8 @@ class CIRCNetwork {
void SetIRCAway(bool b) { m_bIRCAway = b; }
bool Connect();
/** This method will return whether the user is connected and authenticated to an IRC server.
/** This method will return whether the user is connected and authenticated
* to an IRC server.
*/
bool IsIRCConnected() const;
void SetIRCSocket(CIRCSock* pIRCSock);
@@ -266,7 +255,9 @@ class CIRCNetwork {
m_uJoinDelay = uJoinDelay;
}
void SetTrustAllCerts(const bool bTrustAll = false) { m_bTrustAllCerts = bTrustAll; }
void SetTrustAllCerts(const bool bTrustAll = false) {
m_bTrustAllCerts = bTrustAll;
}
bool GetTrustAllCerts() const { return m_bTrustAllCerts; }
void SetTrustPKI(const bool bTrustPKI = true) { m_bTrustPKI = bTrustPKI; }
+10
View File
@@ -155,6 +155,7 @@ class CUser {
void SetSkinName(const CString& s) { m_sSkinName = s; }
void SetMaxNetworks(unsigned int i) { m_uMaxNetworks = i; }
void SetMaxQueryBuffers(unsigned int i) { m_uMaxQueryBuffers = i; }
void SetNoTrafficTimeout(unsigned int i) { m_uNoTrafficTimeout = i; }
// !Setters
// Getters
@@ -185,6 +186,14 @@ class CUser {
bool MultiClients() const;
const CString& GetStatusPrefix() const;
const CString& GetDefaultChanModes() const;
/** How long must an IRC connection be idle before ZNC sends a ping */
unsigned int GetPingFrequency() const { return m_uNoTrafficTimeout / 2; }
/** Time between checks if PINGs need to be sent */
unsigned int GetPingSlack() const { return m_uNoTrafficTimeout / 6; }
/** Timeout after which IRC connections are closed. Must
* obviously be greater than GetPingFrequency() + GetPingSlack().
*/
unsigned int GetNoTrafficTimeout() const { return m_uNoTrafficTimeout; }
CString GetQuitMsg() const;
const MCString& GetCTCPReplies() const;
@@ -254,6 +263,7 @@ class CUser {
unsigned int m_uMaxNetworks;
unsigned int m_uMaxQueryBuffers;
unsigned int m_uMaxJoins;
unsigned int m_uNoTrafficTimeout;
CString m_sSkinName;
CString m_sLanguage;
+12
View File
@@ -249,6 +249,9 @@ class CAdminMod : public CModule {
CString(pUser->AutoClearQueryBuffer()));
else if (sVar == "maxjoins")
PutModule("MaxJoins = " + CString(pUser->MaxJoins()));
else if (sVar == "notraffictimeout")
PutModule("NoTrafficTimeout = " +
CString(pUser->GetNoTrafficTimeout()));
else if (sVar == "maxnetworks")
PutModule("MaxNetworks = " + CString(pUser->MaxNetworks()));
else if (sVar == "maxquerybuffers")
@@ -386,6 +389,15 @@ class CAdminMod : public CModule {
unsigned int i = sValue.ToUInt();
pUser->SetMaxJoins(i);
PutModule("MaxJoins = " + CString(pUser->MaxJoins()));
} else if (sVar == "notraffictimeout") {
unsigned int i = sValue.ToUInt();
if (i < 30) {
PutModule("Timeout can't be less than 30 seconds!");
} else {
pUser->SetNoTrafficTimeout(i);
PutModule("NoTrafficTimeout = " +
CString(pUser->GetNoTrafficTimeout()));
}
} else if (sVar == "maxnetworks") {
if (GetUser()->IsAdmin()) {
unsigned int i = sValue.ToUInt();
@@ -312,6 +312,11 @@
<input id="maxjoins" type="number" name="maxjoins" value="<? VAR MaxJoins ?>" class="third" min="0"
title="<? FORMAT "How many channels are joined in one JOIN command. 0 is unlimited (default). Set to small positive value if you get disconnected with “Max SendQ Exceeded”" ?>"/>
</div>
<div class="subsection">
<div class="inputlabel"><label for="notraffictimeout"><? FORMAT "Timeout before reconnect:" ?></label></div>
<input id="notraffictimeout" type="number" name="notraffictimeout" value="<? VAR NoTrafficTimeout ?>" class="third" min="30"
title="<? FORMAT "How much time ZNC waits (in seconds) until it receives something from network or declares the connection timeout. This happens after attempts to ping the peer." ?>"/>
</div>
<div class="subsection">
<div class="inputlabel"><label for="maxnetworks"><? FORMAT "Max IRC Networks Number:" ?></label></div>
<input type="number" name="maxnetworks" value="<? VAR MaxNetworks ?>" class="third" min="0"
+10
View File
@@ -306,6 +306,14 @@ class CWebAdminMod : public CModule {
WebSock.GetParam("autoclearquerybuffer").ToBool());
pNewUser->SetMaxQueryBuffers(
WebSock.GetParam("maxquerybuffers").ToUInt());
unsigned int uNoTrafficTimeout =
WebSock.GetParam("notraffictimeout").ToUInt();
if (uNoTrafficTimeout < 30) {
uNoTrafficTimeout = 30;
WebSock.GetSession()->AddError(
t_s("Timeout can't be less than 30 seconds!"));
}
pNewUser->SetNoTrafficTimeout(uNoTrafficTimeout);
#ifdef HAVE_I18N
pNewUser->SetLanguage(WebSock.GetParam("language"));
@@ -1319,6 +1327,8 @@ class CWebAdminMod : public CModule {
Tmpl["TimestampFormat"] = pUser->GetTimestampFormat();
Tmpl["Timezone"] = pUser->GetTimezone();
Tmpl["JoinTries"] = CString(pUser->JoinTries());
Tmpl["NoTrafficTimeout"] =
CString(pUser->GetNoTrafficTimeout());
Tmpl["MaxNetworks"] = CString(pUser->MaxNetworks());
Tmpl["MaxJoins"] = CString(pUser->MaxJoins());
Tmpl["MaxQueryBuffers"] = CString(pUser->MaxQueryBuffers());
+1 -1
View File
@@ -388,7 +388,7 @@ void CClient::AcceptLogin(CUser& User) {
// Set our proper timeout and set back our proper timeout mode
// (constructor set a different timeout and mode)
SetTimeout(CIRCNetwork::NO_TRAFFIC_TIMEOUT, TMO_READ);
SetTimeout(User.GetNoTrafficTimeout(), TMO_READ);
SetSockName("USR::" + m_pUser->GetUserName());
SetEncoding(m_pUser->GetClientEncoding());
+12 -7
View File
@@ -36,7 +36,7 @@ class CIRCNetworkPingTimer : public CCron {
SetName("CIRCNetworkPingTimer::" +
m_pNetwork->GetUser()->GetUserName() + "::" +
m_pNetwork->GetName());
Start(CIRCNetwork::PING_SLACK);
Start(m_pNetwork->GetUser()->GetPingSlack());
}
~CIRCNetworkPingTimer() override {}
@@ -47,20 +47,23 @@ class CIRCNetworkPingTimer : public CCron {
protected:
void RunJob() override {
CIRCSock* pIRCSock = m_pNetwork->GetIRCSock();
auto uFrequency = m_pNetwork->GetUser()->GetPingFrequency();
if (pIRCSock &&
pIRCSock->GetTimeSinceLastDataTransaction() >=
CIRCNetwork::PING_FREQUENCY) {
pIRCSock->GetTimeSinceLastDataTransaction() >= uFrequency) {
pIRCSock->PutIRC("PING :ZNC");
}
const vector<CClient*>& vClients = m_pNetwork->GetClients();
for (CClient* pClient : vClients) {
if (pClient->GetTimeSinceLastDataTransaction() >=
CIRCNetwork::PING_FREQUENCY) {
if (pClient->GetTimeSinceLastDataTransaction() >= uFrequency) {
pClient->PutClient("PING :ZNC");
}
}
// Restart timer for the case if the period had changed. Usually this is
// noop
Start(m_pNetwork->GetUser()->GetPingSlack());
}
private:
@@ -68,13 +71,15 @@ class CIRCNetworkPingTimer : public CCron {
};
class CIRCNetworkJoinTimer : public CCron {
constexpr static int JOIN_FREQUENCY = 30 /* seconds */;
public:
CIRCNetworkJoinTimer(CIRCNetwork* pNetwork)
: CCron(), m_bDelayed(false), m_pNetwork(pNetwork) {
SetName("CIRCNetworkJoinTimer::" +
m_pNetwork->GetUser()->GetUserName() + "::" +
m_pNetwork->GetName());
Start(CIRCNetwork::JOIN_FREQUENCY);
Start(JOIN_FREQUENCY);
}
~CIRCNetworkJoinTimer() override {}
@@ -91,7 +96,7 @@ class CIRCNetworkJoinTimer : public CCron {
void RunJob() override {
if (m_bDelayed) {
m_bDelayed = false;
Start(CIRCNetwork::JOIN_FREQUENCY);
Start(JOIN_FREQUENCY);
}
if (m_pNetwork->IsIRCConnected()) {
m_pNetwork->JoinChans();
+1 -1
View File
@@ -686,7 +686,7 @@ bool CIRCSock::OnNumericMessage(CNumericMessage& Message) {
m_pNetwork->SetIRCServer(sServer);
// Now that we are connected, let nature take its course
SetTimeout(CIRCNetwork::NO_TRAFFIC_TIMEOUT, TMO_READ);
SetTimeout(m_pNetwork->GetUser()->GetNoTrafficTimeout(), TMO_READ);
PutIRC("WHO " + sNick);
m_bAuthed = true;
+11 -3
View File
@@ -32,7 +32,7 @@ class CUserTimer : public CCron {
public:
CUserTimer(CUser* pUser) : CCron(), m_pUser(pUser) {
SetName("CUserTimer::" + m_pUser->GetUserName());
Start(CIRCNetwork::PING_SLACK);
Start(m_pUser->GetPingSlack());
}
~CUserTimer() override {}
@@ -46,10 +46,14 @@ class CUserTimer : public CCron {
for (CClient* pUserClient : vUserClients) {
if (pUserClient->GetTimeSinceLastDataTransaction() >=
CIRCNetwork::PING_FREQUENCY) {
m_pUser->GetPingFrequency()) {
pUserClient->PutClient("PING :ZNC");
}
}
// Restart timer for the case if the period had changed. Usually this is
// noop
Start(m_pUser->GetPingSlack());
}
CUser* m_pUser;
@@ -96,6 +100,7 @@ CUser::CUser(const CString& sUserName)
m_uMaxNetworks(1),
m_uMaxQueryBuffers(50),
m_uMaxJoins(0),
m_uNoTrafficTimeout(180),
m_sSkinName(""),
m_pModules(new CModules) {
m_pUserTimer = new CUserTimer(this);
@@ -151,6 +156,7 @@ bool CUser::ParseConfig(CConfig* pConfig, CString& sError) {
{"maxnetworks", &CUser::SetMaxNetworks},
{"maxquerybuffers", &CUser::SetMaxQueryBuffers},
{"maxjoins", &CUser::SetMaxJoins},
{"notraffictimeout", &CUser::SetNoTrafficTimeout},
};
TOption<bool> BoolOptions[] = {
{"keepbuffer",
@@ -752,6 +758,7 @@ bool CUser::Clone(const CUser& User, CString& sErrorRet, bool bCloneNetworks) {
SetMaxNetworks(User.MaxNetworks());
SetMaxQueryBuffers(User.MaxQueryBuffers());
SetMaxJoins(User.MaxJoins());
SetNoTrafficTimeout(User.GetNoTrafficTimeout());
SetClientEncoding(User.GetClientEncoding());
SetLanguage(User.GetLanguage());
@@ -962,7 +969,8 @@ CConfig CUser::ToConfig() const {
config.AddKeyValuePair("MaxQueryBuffers", CString(m_uMaxQueryBuffers));
config.AddKeyValuePair("MaxJoins", CString(m_uMaxJoins));
config.AddKeyValuePair("ClientEncoding", GetClientEncoding());
config.AddKeyValuePair("Language", GetLanguage());
config.AddKeyValuePair("Language", GetLanguage());
config.AddKeyValuePair("NoTrafficTimeout", CString(GetNoTrafficTimeout()));
// Allow Hosts
if (!m_ssAllowedHosts.empty()) {