Welcome to mirror list, hosted at ThFree Co, Russian Federation.

abstractnetworkjob.h « libsync « src - github.com/owncloud/client.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: af5f2b28d272f733ad43ff0f896b930674e4272e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
/*
 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
 * Copyright (C) by Daniel Molkentin <danimo@owncloud.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 option) 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.
 */

#pragma once

#include "accountfwd.h"
#include "jobqueue.h"

#include "common/asserts.h"

#include "owncloudlib.h"

#include <QObject>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QPointer>
#include <QElapsedTimer>
#include <QDateTime>
#include <QTimer>

class QUrl;


OWNCLOUDSYNC_EXPORT QDebug operator<<(QDebug debug, const OCC::AbstractNetworkJob *job);

namespace OCC {

class AbstractSslErrorHandler;

/**
 * @brief The AbstractNetworkJob class
 * @ingroup libsync
 */
class OWNCLOUDSYNC_EXPORT AbstractNetworkJob : public QObject
{
    Q_OBJECT
public:
    explicit AbstractNetworkJob(AccountPtr account, const QString &path, QObject *parent = nullptr);
    ~AbstractNetworkJob() override;

    virtual void start();

    AccountPtr account() const { return _account; }

    void setPath(const QString &path);
    QString path() const { return _path; }

    QUrl url() const { return _request.url(); }

    QNetworkReply *reply() const;

    void setIgnoreCredentialFailure(bool ignore);
    bool ignoreCredentialFailure() const { return _ignoreCredentialFailure; }

    QByteArray responseTimestamp();
    /* Content of the X-Request-ID header. (Only set after the request is sent) */
    QByteArray requestId();

    qint64 timeoutMsec() const { return _timer.interval(); }
    bool timedOut() const { return _timedout; }

    /** Returns an error message, if any. */
    QString errorString() const;

    /** Like errorString, but also checking the reply body for information.
     *
     * Specifically, sometimes xml bodies have extra error information.
     * This function reads the body of the reply and parses out the
     * error information, if possible.
     *
     * \a body is optinally filled with the reply body.
     *
     * Warning: Needs to call reply()->readAll().
     */
    QString errorStringParsingBody(QByteArray *body = nullptr);

    /** Make a new request */
    void retry();

    /** Abort the job due to an error */
    void abort();

    /** static variable the HTTP timeout (in seconds). If set to 0, the default will be used
     */
    static int httpTimeout;

    /** whether or noth this job should be restarted after authentication */
    bool  isAuthenticationJob() const;
    void  setAuthenticationJob(bool b);

    /** How many times was that job retried */
    int retryCount() const { return _retryCount; }


    virtual bool needsRetry() const;

public slots:
    void setTimeout(qint64 msec);
    void resetTimeout();
signals:
    /** Emitted on network error.
     *
     * \a reply is never null
     */
    void networkError(QNetworkReply *reply);
    void networkActivity();

protected:
    /** Initiate a network request, returning a QNetworkReply.
     *
     * Calls setReply() and setupConnections() on it.
     *
     * Takes ownership of the requestBody (to allow redirects).
     */
    void sendRequest(const QByteArray &verb, const QUrl &url,
        const QNetworkRequest &req = QNetworkRequest(),
        QIODevice *requestBody = nullptr);

    void setReply(QNetworkReply *reply);

    /** Makes this job drive a pre-made QNetworkReply
     *
     * This reply cannot have a QIODevice request body because we can't get
     * at it and thus not resend it in case of redirects.
     */
    void adoptRequest(QNetworkReply *reply);

    void setupConnections(QNetworkReply *reply);

    /** Can be used by derived classes to set up the network reply.
     *
     * Particularly useful when the request is redirected and reply()
     * changes. For things like setting up additional signal connections
     * on the new reply.
     */
    virtual void newReplyHook(QNetworkReply *) {}

    /// Creates a url for the account from a relative path
    QUrl makeAccountUrl(const QString &relativePath) const;

    /// Like makeAccountUrl() but uses the account's dav base path
    QUrl makeDavUrl(const QString &relativePath) const;

    /** Called at the end of QNetworkReply::finished processing.
     *
     * Returning true triggers a deleteLater() of this job.
     */
    virtual bool finished() = 0;

    /** Called on timeout.
     *
     * The default implementation aborts the reply.
     */
    virtual void onTimedOut();

    QByteArray _responseTimestamp;
    bool _timedout; // set to true when the timeout slot is received

    QString replyStatusString();

private slots:
    void slotFinished();
    void slotTimeout();

protected:
    AccountPtr _account;

private:
    QNetworkReply *addTimer(QNetworkReply *reply);
    bool _ignoreCredentialFailure;
    QNetworkRequest _request;
    QByteArray _verb;
    QPointer<QNetworkReply> _reply; // (QPointer because the NetworkManager may be destroyed before the jobs at exit)
    QString _path;
    QTimer _timer;
    int _http2ResendCount = 0;

    // Set by the xyzRequest() functions and needed to be able to redirect
    // requests, should it be required.
    //
    // Reparented to the currently running QNetworkReply.
    QPointer<QIODevice> _requestBody;

    bool _isAuthenticationJob = false;
    int _retryCount = 0;

    friend QDebug(::operator<<)(QDebug debug, const AbstractNetworkJob *job);
};

/**
 * @brief Internal Helper class
 */
class NetworkJobTimeoutPauser
{
public:
    NetworkJobTimeoutPauser(QNetworkReply *reply);
    ~NetworkJobTimeoutPauser();

private:
    QPointer<QTimer> _timer;
};


/** Gets the SabreDAV-style error message from an error response.
 *
 * This assumes the response is XML with a 'error' tag that has a
 * 'message' tag that contains the data to extract.
 *
 * Returns a null string if no message was found.
 */
QString OWNCLOUDSYNC_EXPORT extractErrorMessage(const QByteArray &errorResponse);

/** Builds a error message based on the error and the reply body. */
QString OWNCLOUDSYNC_EXPORT errorMessage(const QString &baseError, const QByteArray &body);

/** Nicer errorString() for QNetworkReply
 *
 * By default QNetworkReply::errorString() often produces messages like
 *   "Error downloading <url> - server replied: <reason>"
 * but the "downloading" part invariably confuses people since the
 * error might very well have been produced by a PUT request.
 *
 * This function produces clearer error messages for HTTP errors.
 */
QString OWNCLOUDSYNC_EXPORT networkReplyErrorString(const QNetworkReply &reply);

} // namespace OCC