linuxdcpp-team team mailing list archive
-
linuxdcpp-team team
-
Mailing list archive
-
Message #01348
[Branch ~dcplusplus-team/dcplusplus/trunk] Rev 2159: c-c error handling: increase reconnect intervals after timeouts; no reconnect after a protocol error
------------------------------------------------------------
revno: 2159
committer: poy <poy@xxxxxxxxxx>
branch nick: repo
timestamp: Sat 2010-06-12 19:59:19 +0200
message:
c-c error handling: increase reconnect intervals after timeouts; no reconnect after a protocol error
modified:
changelog.txt
dcpp/ConnectionManager.cpp
dcpp/ConnectionManager.h
dcpp/DownloadManager.cpp
dcpp/DownloadManager.h
dcpp/UserConnection.cpp
dcpp/UserConnection.h
dcpp/UserConnectionListener.h
--
lp:dcplusplus
https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk
Your team Dcplusplus-team is subscribed to branch lp:dcplusplus.
To unsubscribe from this branch go to https://code.launchpad.net/~dcplusplus-team/dcplusplus/trunk/+edit-subscription
=== modified file 'changelog.txt'
--- changelog.txt 2010-05-25 18:28:09 +0000
+++ changelog.txt 2010-06-12 17:59:19 +0000
@@ -1,5 +1,7 @@
* [L#550300] Catch more potential file corruptions (thanks bigmuscle)
* [ADC] NAT traversal to allow passive-passive connections (thanks cologic)
+* Reduce donwload reconnect attempts after connection failures (poy)
+* [ADC] Handle fatal client-client STA commands (poy)
-- 0.762 2010-05-16 --
* Stability improvement related to menus (poy)
=== modified file 'dcpp/ConnectionManager.cpp'
--- dcpp/ConnectionManager.cpp 2010-02-11 21:44:13 +0000
+++ dcpp/ConnectionManager.cpp 2010-06-12 17:59:19 +0000
@@ -153,7 +153,14 @@
continue;
}
- if(cqi->getLastAttempt() == 0 || (((cqi->getLastAttempt() + 60*1000) < aTick) && !attemptDone)) {
+ if(cqi->getErrors() == -1 && cqi->getLastAttempt() != 0) {
+ // protocol error, don't reconnect except after a forced attempt
+ continue;
+ }
+
+ if(cqi->getLastAttempt() == 0 || (!attemptDone &&
+ cqi->getLastAttempt() + 60 * 1000 * max(1, cqi->getErrors()) < aTick))
+ {
cqi->setLastAttempt(aTick);
QueueItem::Priority prio = QueueManager::getInstance()->hasDownload(cqi->getUser());
@@ -178,7 +185,8 @@
} else if(cqi->getState() == ConnectionQueueItem::NO_DOWNLOAD_SLOTS && startDown) {
cqi->setState(ConnectionQueueItem::WAITING);
}
- } else if(((cqi->getLastAttempt() + 50*1000) < aTick) && (cqi->getState() == ConnectionQueueItem::CONNECTING)) {
+ } else if(cqi->getState() == ConnectionQueueItem::CONNECTING && cqi->getLastAttempt() + 50 * 1000 < aTick) {
+ cqi->setErrors(cqi->getErrors() + 1);
fire(ConnectionManagerListener::Failed(), cqi, _("Connection timeout"));
cqi->setState(ConnectionQueueItem::WAITING);
}
@@ -459,6 +467,7 @@
Lock l(cs);
for(ConnectionQueueItem::Iter i = downloads.begin(); i != downloads.end(); ++i) {
ConnectionQueueItem* cqi = *i;
+ cqi->setErrors(0);
if((cqi->getState() == ConnectionQueueItem::CONNECTING || cqi->getState() == ConnectionQueueItem::WAITING) &&
cqi->getUser().user->getCID() == cid)
{
@@ -664,6 +673,8 @@
ConnectionQueueItem::Iter i = find(downloads.begin(), downloads.end(), aSource->getUser());
if(i != downloads.end()) {
+ (*i)->setErrors(0);
+
const string& to = (*i)->getToken();
// 0.698 would send an empty token in some cases...remove this bugfix at some point
@@ -694,7 +705,7 @@
(*i)->setLastAttempt(0);
}
-void ConnectionManager::on(UserConnectionListener::Failed, UserConnection* aSource, const string& aError) throw() {
+void ConnectionManager::failed(UserConnection* aSource, const string& aError, bool protocolError) {
Lock l(cs);
if(aSource->isSet(UserConnection::FLAG_ASSOCIATED)) {
@@ -704,6 +715,7 @@
ConnectionQueueItem* cqi = *i;
cqi->setState(ConnectionQueueItem::WAITING);
cqi->setLastAttempt(GET_TICK());
+ cqi->setErrors(protocolError ? (cqi->getErrors() + 1) : -1);
fire(ConnectionManagerListener::Failed(), cqi, aError);
} else if(aSource->isSet(UserConnection::FLAG_UPLOAD)) {
ConnectionQueueItem::Iter i = find(uploads.begin(), uploads.end(), aSource->getUser());
@@ -715,6 +727,14 @@
putConnection(aSource);
}
+void ConnectionManager::on(UserConnectionListener::Failed, UserConnection* aSource, const string& aError) throw() {
+ failed(aSource, aError, false);
+}
+
+void ConnectionManager::on(UserConnectionListener::ProtocolError, UserConnection* aSource, const string& aError) throw() {
+ failed(aSource, aError, true);
+}
+
void ConnectionManager::disconnect(const UserPtr& aUser) {
Lock l(cs);
for(UserConnectionList::iterator i = userConnections.begin(); i != userConnections.end(); ++i) {
=== modified file 'dcpp/ConnectionManager.h'
--- dcpp/ConnectionManager.h 2010-02-11 21:44:13 +0000
+++ dcpp/ConnectionManager.h 2010-06-12 17:59:19 +0000
@@ -47,10 +47,11 @@
};
ConnectionQueueItem(const HintedUser& aUser, bool aDownload) : token(Util::toString(Util::rand())),
- lastAttempt(0), state(WAITING), download(aDownload), user(aUser) { }
+ lastAttempt(0), errors(0), state(WAITING), download(aDownload), user(aUser) { }
GETSET(string, token, Token);
GETSET(uint64_t, lastAttempt, LastAttempt);
+ GETSET(int, errors, Errors); // Number of connection errors, or -1 after a protocol error
GETSET(State, state, State);
GETSET(bool, download, Download);
@@ -174,9 +175,12 @@
void accept(const Socket& sock, bool secure) throw();
+ void failed(UserConnection* aSource, const string& aError, bool protocolError);
+
// UserConnectionListener
virtual void on(Connected, UserConnection*) throw();
virtual void on(Failed, UserConnection*, const string&) throw();
+ virtual void on(ProtocolError, UserConnection*, const string&) throw();
virtual void on(CLock, UserConnection*, const string&, const string&) throw();
virtual void on(Key, UserConnection*, const string&) throw();
virtual void on(Direction, UserConnection*, const string&, const string&) throw();
=== modified file 'dcpp/DownloadManager.cpp'
--- dcpp/DownloadManager.cpp 2010-05-25 18:28:09 +0000
+++ dcpp/DownloadManager.cpp 2010-06-12 17:59:19 +0000
@@ -429,7 +429,7 @@
failDownload(aSource, _("No slots available"));
}
-void DownloadManager::on(UserConnectionListener::Failed, UserConnection* aSource, const string& aError) throw() {
+void DownloadManager::onFailed(UserConnection* aSource, const string& aError) {
{
Lock l(cs);
idlers.erase(remove(idlers.begin(), idlers.end(), aSource), idlers.end());
=== modified file 'dcpp/DownloadManager.h'
--- dcpp/DownloadManager.h 2010-02-11 21:44:13 +0000
+++ dcpp/DownloadManager.h 2010-06-12 17:59:19 +0000
@@ -84,9 +84,12 @@
void startData(UserConnection* aSource, int64_t start, int64_t newSize, bool z);
void endData(UserConnection* aSource);
+ void onFailed(UserConnection* aSource, const string& aError);
+
// UserConnectionListener
virtual void on(Data, UserConnection*, const uint8_t*, size_t) throw();
- virtual void on(Failed, UserConnection*, const string&) throw();
+ virtual void on(Failed, UserConnection* aSource, const string& aError) throw() { onFailed(aSource, aError); }
+ virtual void on(ProtocolError, UserConnection* aSource, const string& aError) throw() { onFailed(aSource, aError); }
virtual void on(MaxedOut, UserConnection*) throw();
virtual void on(FileNotAvailable, UserConnection*) throw();
virtual void on(Updated, UserConnection*) throw();
=== modified file 'dcpp/UserConnection.cpp'
--- dcpp/UserConnection.cpp 2010-02-11 21:44:13 +0000
+++ dcpp/UserConnection.cpp 2010-06-12 17:59:19 +0000
@@ -46,12 +46,14 @@
void UserConnection::on(BufferedSocketListener::Line, const string& aLine) throw () {
- if(aLine.length() < 2)
+ if(aLine.length() < 2) {
+ fire(UserConnectionListener::ProtocolError(), this, _("Invalid data"));
return;
+ }
if(aLine[0] == 'C' && !isSet(FLAG_NMDC)) {
if(!Text::validateUtf8(aLine)) {
- // @todo Report to user?
+ fire(UserConnectionListener::ProtocolError(), this, _("Non-UTF-8 data in an ADC connection"));
return;
}
dispatch(aLine);
@@ -59,10 +61,10 @@
} else if(aLine[0] == '$') {
setFlag(FLAG_NMDC);
} else {
- // We shouldn't be here?
- dcdebug("Unknown UserConnection command: %.50s\n", aLine.c_str());
+ fire(UserConnectionListener::ProtocolError(), this, _("Invalid data"));
return;
}
+
string cmd;
string param;
@@ -88,9 +90,7 @@
param.rfind(/*path/file*/" no more exists") != string::npos) {
fire(UserConnectionListener::FileNotAvailable(), this);
} else {
- dcdebug("Unknown $Error %s\n", param.c_str());
- fire(UserConnectionListener::Failed(), this, param);
- disconnect(true);
+ fire(UserConnectionListener::ProtocolError(), this, param);
}
} else if(cmd == "$GetListLen") {
fire(UserConnectionListener::GetListLength(), this);
@@ -129,7 +129,7 @@
} else if(cmd.compare(0, 4, "$ADC") == 0) {
dispatch(aLine, true);
} else {
- dcdebug("Unknown NMDC command: %.50s\n", aLine.c_str());
+ fire(UserConnectionListener::ProtocolError(), this, _("Invalid data"));
}
}
@@ -172,6 +172,18 @@
send("$Supports " + x + '|');
}
+void UserConnection::handle(AdcCommand::STA t, const AdcCommand& c) {
+ if(c.getParameters().size() >= 2) {
+ const string& code = c.getParam(0);
+ if(!code.empty() && code[0] - '0' == AdcCommand::SEV_FATAL) {
+ fire(UserConnectionListener::ProtocolError(), this, c.getParam(1));
+ return;
+ }
+ }
+
+ fire(t, this, c);
+}
+
void UserConnection::on(Connected) throw() {
lastActivity = GET_TICK();
fire(UserConnectionListener::Connected(), this);
=== modified file 'dcpp/UserConnection.h'
--- dcpp/UserConnection.h 2010-02-11 21:44:13 +0000
+++ dcpp/UserConnection.h 2010-06-12 17:59:19 +0000
@@ -155,7 +155,7 @@
void handle(AdcCommand::INF t, const AdcCommand& c) { fire(t, this, c); }
void handle(AdcCommand::GET t, const AdcCommand& c) { fire(t, this, c); }
void handle(AdcCommand::SND t, const AdcCommand& c) { fire(t, this, c); }
- void handle(AdcCommand::STA t, const AdcCommand& c) { fire(t, this, c); }
+ void handle(AdcCommand::STA t, const AdcCommand& c);
void handle(AdcCommand::RES t, const AdcCommand& c) { fire(t, this, c); }
void handle(AdcCommand::GFI t, const AdcCommand& c) { fire(t, this, c); }
=== modified file 'dcpp/UserConnectionListener.h'
--- dcpp/UserConnectionListener.h 2010-02-11 21:44:13 +0000
+++ dcpp/UserConnectionListener.h 2010-06-12 17:59:19 +0000
@@ -46,12 +46,14 @@
typedef X<16> MyNick;
typedef X<17> TransmitDone;
typedef X<18> Supports;
- typedef X<19> FileNotAvailable;
+ typedef X<19> ProtocolError;
+ typedef X<20> FileNotAvailable;
virtual void on(BytesSent, UserConnection*, size_t, size_t) throw() { }
virtual void on(Connected, UserConnection*) throw() { }
virtual void on(Data, UserConnection*, const uint8_t*, size_t) throw() { }
virtual void on(Failed, UserConnection*, const string&) throw() { }
+ virtual void on(ProtocolError, UserConnection*, const string&) throw() { }
virtual void on(CLock, UserConnection*, const string&, const string&) throw() { }
virtual void on(Key, UserConnection*, const string&) throw() { }
virtual void on(Direction, UserConnection*, const string&, const string&) throw() { }