Skip to content

Commit b15f65f

Browse files
committed
fix(network): enable again timeout for network requests
Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
1 parent 6b50a18 commit b15f65f

3 files changed

Lines changed: 22 additions & 68 deletions

File tree

src/libsync/abstractnetworkjob.cpp

Lines changed: 20 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -48,19 +48,6 @@ AbstractNetworkJob::AbstractNetworkJob(const AccountPtr &account, const QString
4848
{
4949
// Since we hold a QSharedPointer to the account, this makes no sense. (issue #6893)
5050
ASSERT(account != parent);
51-
52-
_timer.setSingleShot(true);
53-
_timer.setInterval((httpTimeout ? httpTimeout : 300) * 1000); // default to 5 minutes.
54-
connect(&_timer, &QTimer::timeout, this, &AbstractNetworkJob::slotTimeout);
55-
56-
connect(this, &AbstractNetworkJob::networkActivity, this, &AbstractNetworkJob::resetTimeout);
57-
58-
// Network activity on the propagator jobs (GET/PUT) keeps all requests alive.
59-
// This is a workaround for OC instances which only support one
60-
// parallel up and download
61-
if (_account) {
62-
connect(_account.data(), &Account::propagatorNetworkActivity, this, &AbstractNetworkJob::resetTimeout);
63-
}
6451
}
6552

6653
void AbstractNetworkJob::setReply(QNetworkReply *reply)
@@ -75,14 +62,7 @@ void AbstractNetworkJob::setReply(QNetworkReply *reply)
7562

7663
void AbstractNetworkJob::setTimeout(qint64 msec)
7764
{
78-
_timer.start(msec);
79-
}
80-
81-
void AbstractNetworkJob::resetTimeout()
82-
{
83-
qint64 interval = _timer.interval();
84-
_timer.stop();
85-
_timer.start(interval);
65+
_timeoutDuration = msec;
8666
}
8767

8868
void AbstractNetworkJob::setIgnoreCredentialFailure(bool ignore)
@@ -112,17 +92,13 @@ void AbstractNetworkJob::setupConnections(QNetworkReply *reply)
11292
connect(reply, &QNetworkReply::redirected, this, [reply, this] (const QUrl &url) { emit redirected(reply, url, 0);});
11393
}
11494

115-
QNetworkReply *AbstractNetworkJob::addTimer(QNetworkReply *reply)
116-
{
117-
reply->setProperty("timer", QVariant::fromValue(&_timer));
118-
return reply;
119-
}
120-
12195
QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb,
12296
const QUrl &url,
12397
QNetworkRequest req,
12498
QIODevice *requestBody)
12599
{
100+
req.setTransferTimeout(_timeoutDuration);
101+
126102
auto reply = _account->sendRawRequest(verb, url, req, requestBody);
127103
_requestBody = requestBody;
128104
if (_requestBody) {
@@ -137,6 +113,8 @@ QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb,
137113
QNetworkRequest req,
138114
const QByteArray &requestBody)
139115
{
116+
req.setTransferTimeout(_timeoutDuration);
117+
140118
auto reply = _account->sendRawRequest(verb, url, req, requestBody);
141119
_requestBody = nullptr;
142120
adoptRequest(reply);
@@ -148,6 +126,8 @@ QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb,
148126
QNetworkRequest req,
149127
QHttpMultiPart *requestBody)
150128
{
129+
req.setTransferTimeout(_timeoutDuration);
130+
151131
auto reply = _account->sendRawRequest(verb, url, req, requestBody);
152132
_requestBody = nullptr;
153133
adoptRequest(reply);
@@ -156,8 +136,6 @@ QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb,
156136

157137
void AbstractNetworkJob::adoptRequest(QNetworkReply *reply)
158138
{
159-
addTimer(reply);
160-
setReply(reply);
161139
setupConnections(reply);
162140
newReplyHook(reply);
163141
}
@@ -172,9 +150,21 @@ QUrl AbstractNetworkJob::makeDavUrl(const QString &relativePath) const
172150
return Utility::concatUrlPath(_account->davUrl(), relativePath);
173151
}
174152

153+
void AbstractNetworkJob::onTimedOut()
154+
{
155+
if (reply()) {
156+
reply()->abort();
157+
} else {
158+
deleteLater();
159+
}
160+
}
161+
175162
void AbstractNetworkJob::slotFinished()
176163
{
177-
_timer.stop();
164+
if (_reply->error() == QNetworkReply::TimeoutError) {
165+
qCWarning(lcNetworkJob) << "TimeoutError" << errorString();
166+
onTimedOut();
167+
}
178168

179169
if (_reply->error() == QNetworkReply::SslHandshakeFailedError) {
180170
qCWarning(lcNetworkJob) << "SslHandshakeFailedError: " << errorString() << " : can be caused by a webserver wanting SSL client certificates";
@@ -195,7 +185,6 @@ void AbstractNetworkJob::slotFinished()
195185
qCInfo(lcNetworkJob) << "HTTP2 resending" << _reply->request().url();
196186
_http2ResendCount++;
197187

198-
resetTimeout();
199188
if (_requestBody) {
200189
if(!_requestBody->isOpen())
201190
_requestBody->open(QIODevice::ReadOnly);
@@ -265,7 +254,6 @@ void AbstractNetworkJob::slotFinished()
265254

266255
// Create the redirected request and send it
267256
qCInfo(lcNetworkJob) << "Redirecting" << verb << requestedUrl << redirectUrl;
268-
resetTimeout();
269257
if (_requestBody) {
270258
if(!_requestBody->isOpen()) {
271259
// Avoid the QIODevice::seek (QBuffer): The device is not open warning message
@@ -321,10 +309,6 @@ QByteArray AbstractNetworkJob::requestId()
321309

322310
QString AbstractNetworkJob::errorString() const
323311
{
324-
if (_timedout) {
325-
return tr("The server took too long to respond. Check your connection and try syncing again. If it still doesn’t work, reach out to your server administrator.");
326-
}
327-
328312
if (!reply()) {
329313
return tr("An unexpected error occurred. Please try syncing again or contact your server administrator if the issue continues.");
330314
}
@@ -373,36 +357,13 @@ AbstractNetworkJob::~AbstractNetworkJob()
373357

374358
void AbstractNetworkJob::start()
375359
{
376-
_timer.start();
377-
378360
const QUrl url = account()->url();
379361
const QString displayUrl = QStringLiteral("%1://%2%3").arg(url.scheme()).arg(url.host()).arg(url.path());
380362

381363
QString parentMetaObjectName = parent() ? parent()->metaObject()->className() : "";
382364
qCInfo(lcNetworkJob) << metaObject()->className() << "created for" << displayUrl << "+" << path() << parentMetaObjectName;
383365
}
384366

385-
void AbstractNetworkJob::slotTimeout()
386-
{
387-
// TODO: workaround, find cause of https://github.com/nextcloud/desktop/issues/7184
388-
if (!AbstractNetworkJob::enableTimeout) {
389-
return;
390-
}
391-
392-
_timedout = true;
393-
qCWarning(lcNetworkJob) << "Network job timeout" << (reply() ? reply()->request().url() : path());
394-
onTimedOut();
395-
}
396-
397-
void AbstractNetworkJob::onTimedOut()
398-
{
399-
if (reply()) {
400-
reply()->abort();
401-
} else {
402-
deleteLater();
403-
}
404-
}
405-
406367
QString AbstractNetworkJob::replyStatusString() {
407368
Q_ASSERT(reply());
408369
if (reply()->error() == QNetworkReply::NoError) {
@@ -579,7 +540,6 @@ void AbstractNetworkJob::retry()
579540
QUrl requestedUrl = req.url();
580541
QByteArray verb = HttpLogger::requestVerb(*_reply);
581542
qCInfo(lcNetworkJob) << "Restarting" << verb << requestedUrl;
582-
resetTimeout();
583543
if (_requestBody) {
584544
_requestBody->seek(0);
585545
}

src/libsync/abstractnetworkjob.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,7 @@ class OWNCLOUDSYNC_EXPORT AbstractNetworkJob : public QObject
7070
/* Content of the X-Request-ID header. (Only set after the request is sent) */
7171
QByteArray requestId();
7272

73-
[[nodiscard]] qint64 timeoutMsec() const { return _timer.interval(); }
74-
[[nodiscard]] bool timedOut() const { return _timedout; }
73+
[[nodiscard]] qint64 timeoutMsec() const { return _timeoutDuration; }
7574

7675
/** Returns an error message, if any. */
7776
[[nodiscard]] virtual QString errorString() const;
@@ -112,7 +111,6 @@ class OWNCLOUDSYNC_EXPORT AbstractNetworkJob : public QObject
112111

113112
public slots:
114113
void setTimeout(qint64 msec);
115-
void resetTimeout();
116114
signals:
117115
/** Emitted on network error.
118116
*
@@ -191,7 +189,6 @@ public slots:
191189
virtual void onTimedOut();
192190

193191
QByteArray _responseTimestamp;
194-
bool _timedout = false; // set to true when the timeout slot is received
195192

196193
// Automatically follows redirects. Note that this only works for
197194
// GET requests that don't set up any HTTP body or other flags.
@@ -201,19 +198,17 @@ public slots:
201198

202199
private slots:
203200
void slotFinished();
204-
void slotTimeout();
205201

206202
protected:
207203
AccountPtr _account;
208204

209205
private:
210-
QNetworkReply *addTimer(QNetworkReply *reply);
211206
bool _ignoreCredentialFailure = false;
212207
QPointer<QNetworkReply> _reply; // (QPointer because the NetworkManager may be destroyed before the jobs at exit)
213208
QString _path;
214-
QTimer _timer;
215209
int _redirectCount = 0;
216210
int _http2ResendCount = 0;
211+
qint64 _timeoutDuration = 300000;
217212

218213
// Set by the xyzRequest() functions and needed to be able to redirect
219214
// requests, should it be required.

src/libsync/propagateupload.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,6 @@ void PollJob::start()
102102
QUrl finalUrl = QUrl::fromUserInput(accountUrl.scheme() + QLatin1String("://") + accountUrl.authority()
103103
+ (path().startsWith('/') ? QLatin1String("") : QLatin1String("/")) + path());
104104
sendRequest("GET", finalUrl);
105-
connect(reply(), &QNetworkReply::downloadProgress, this, &AbstractNetworkJob::resetTimeout, Qt::UniqueConnection);
106105
AbstractNetworkJob::start();
107106
}
108107

0 commit comments

Comments
 (0)