diff options
-rw-r--r-- | CMakeLists.txt | 11 | ||||
-rw-r--r-- | gtad/gtad.yaml (renamed from lib/csapi/gtad.yaml) | 8 | ||||
-rw-r--r-- | gtad/preamble.mustache (renamed from lib/csapi/preamble.mustache) | 0 | ||||
-rw-r--r-- | gtad/template.cpp.mustache (renamed from lib/csapi/{{base}}.cpp.mustache) | 0 | ||||
-rw-r--r-- | gtad/template.h.mustache (renamed from lib/csapi/{{base}}.h.mustache) | 0 | ||||
-rw-r--r-- | lib/connection.cpp | 4 | ||||
-rw-r--r-- | lib/jobs/basejob.cpp | 96 | ||||
-rw-r--r-- | lib/jobs/basejob.h | 30 | ||||
-rw-r--r-- | lib/syncdata.h | 2 |
9 files changed, 86 insertions, 65 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 68e49a67..1e336673 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -200,7 +200,6 @@ endforeach() # new files you have to re-run cmake. # TODO: check `file(GLOB_RECURSE ... CONFIGURE_DEPENDS)` (from CMake 3.14) if (MATRIX_DOC_PATH AND GTAD_PATH) - set(FULL_CSAPI_DIR lib/${CSAPI_DIR}) set(FULL_CSAPI_SRC_DIR ${ABS_API_DEF_PATH}/client-server) file(GLOB_RECURSE API_DEFS RELATIVE ${PROJECT_SOURCE_DIR} ${FULL_CSAPI_SRC_DIR}/*.yaml @@ -208,15 +207,15 @@ if (MATRIX_DOC_PATH AND GTAD_PATH) ${ABS_API_DEF_PATH}/${ISAPI_DEF_DIR}/*.yaml ) add_custom_target(update-api - ${ABS_GTAD_PATH} --config ${CSAPI_DIR}/gtad.yaml --out ${CSAPI_DIR} + ${ABS_GTAD_PATH} --config ../gtad/gtad.yaml --out ${CSAPI_DIR} ${FULL_CSAPI_SRC_DIR} old_sync.yaml- room_initial_sync.yaml- # deprecated search.yaml- # current GTAD is limited in handling move-only data sync.yaml- # we have a better handcrafted implementation WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/lib - SOURCES ${FULL_CSAPI_DIR}/gtad.yaml - ${FULL_CSAPI_DIR}/{{base}}.h.mustache - ${FULL_CSAPI_DIR}/{{base}}.cpp.mustache + SOURCES gtad/gtad.yaml + gtad/template.h.mustache + gtad/template.cpp.mustache ${API_DEFS} VERBATIM ) @@ -232,7 +231,7 @@ if (MATRIX_DOC_PATH AND GTAD_PATH) COMMAND ${ABS_CLANG_FORMAT} ${CLANG_FORMAT_ARGS} ${api_HDRS} WORKING_DIRECTORY ${PROJECT_SOURCE_DIR} VERBATIM - COMMENT Formatting files + COMMENT "Formatting files" ) endif() endif() diff --git a/lib/csapi/gtad.yaml b/gtad/gtad.yaml index 086bd4f7..51f9e26b 100644 --- a/lib/csapi/gtad.yaml +++ b/gtad/gtad.yaml @@ -158,8 +158,12 @@ mustache: *{{/summary}} templates: - - "{{base}}.h.mustache" - - "{{base}}.cpp.mustache" + data: + .h: "{{>template.h.mustache}}" + .cpp: "{{>template.cpp.mustache}}" + api: + .h: "{{>template.h.mustache}}" + .cpp: "{{>template.cpp.mustache}}" #outFilesList: apifiles.txt diff --git a/lib/csapi/preamble.mustache b/gtad/preamble.mustache index 3ba87d61..3ba87d61 100644 --- a/lib/csapi/preamble.mustache +++ b/gtad/preamble.mustache diff --git a/lib/csapi/{{base}}.cpp.mustache b/gtad/template.cpp.mustache index b3bd4de9..b3bd4de9 100644 --- a/lib/csapi/{{base}}.cpp.mustache +++ b/gtad/template.cpp.mustache diff --git a/lib/csapi/{{base}}.h.mustache b/gtad/template.h.mustache index 404aafe8..404aafe8 100644 --- a/lib/csapi/{{base}}.h.mustache +++ b/gtad/template.h.mustache diff --git a/lib/connection.cpp b/lib/connection.cpp index 9f4f7082..efc7163e 100644 --- a/lib/connection.cpp +++ b/lib/connection.cpp @@ -20,7 +20,7 @@ #include "connectiondata.h" #ifdef Quotient_E2EE_ENABLED -#include "encryptionmanager.h" +# include "encryptionmanager.h" #endif // Quotient_E2EE_ENABLED #include "room.h" #include "settings.h" @@ -45,7 +45,7 @@ #include "jobs/syncjob.h" #ifdef Quotient_E2EE_ENABLED -#include "account.h" // QtOlm +# include "account.h" // QtOlm #endif // Quotient_E2EE_ENABLED #include <QtCore/QCoreApplication> diff --git a/lib/jobs/basejob.cpp b/lib/jobs/basejob.cpp index 470250bf..2519713e 100644 --- a/lib/jobs/basejob.cpp +++ b/lib/jobs/basejob.cpp @@ -35,6 +35,47 @@ using namespace Quotient; using std::chrono::seconds, std::chrono::milliseconds; using namespace std::chrono_literals; +BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) +{ + if (httpCode / 10 == 41) // 41x errors + return httpCode == 410 ? IncorrectRequestError : NotFoundError; + switch (httpCode) { + case 401: + return Unauthorised; + // clang-format off + case 403: case 407: // clang-format on + return ContentAccessError; + case 404: + return NotFoundError; + // clang-format off + case 400: case 405: case 406: case 426: case 428: case 505: // clang-format on + case 494: // Unofficial nginx "Request header too large" + case 497: // Unofficial nginx "HTTP request sent to HTTPS port" + return IncorrectRequestError; + case 429: + return TooManyRequestsError; + case 501: + case 510: + return RequestNotImplementedError; + case 511: + return NetworkAuthRequiredError; + default: + return NetworkError; + } +} + +QDebug BaseJob::Status::dumpToLog(QDebug dbg) const +{ + QDebugStateSaver _s(dbg); + dbg.noquote().nospace(); + if (auto* const k = QMetaEnum::fromType<StatusCode>().valueToKey(code)) { + const QByteArray b = k; + dbg << b.mid(b.lastIndexOf(':')); + } else + dbg << code; + return dbg << ": " << message; +} + struct NetworkReplyDeleter : public QScopedPointerDeleteLater { static inline void cleanup(QNetworkReply* reply) { @@ -232,7 +273,13 @@ void BaseJob::Private::sendRequest() // Pipelining doesn't fly quite well with SSL, occasionally crashing at // what seems like an attempt to write to a closed channel. // req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true); - req.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true); + req.setAttribute( +#if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) + QNetworkRequest::Http2AllowedAttribute +#else + QNetworkRequest::HTTP2AllowedAttribute +#endif + , true); Q_ASSERT(req.url().isValid()); for (auto it = requestHeaders.cbegin(); it != requestHeaders.cend(); ++it) req.setRawHeader(it.key(), it.value()); @@ -316,8 +363,6 @@ void BaseJob::sendRequest() << "Request could not start:" << d->dumpRequest(); } -void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } - void BaseJob::gotReply() { checkReply(); @@ -363,47 +408,6 @@ bool checkContentType(const QByteArray& type, const QByteArrayList& patterns) return false; } -BaseJob::StatusCode BaseJob::Status::fromHttpCode(int httpCode) -{ - if (httpCode / 10 == 41) // 41x errors - return httpCode == 410 ? IncorrectRequestError : NotFoundError; - switch (httpCode) { - case 401: - return Unauthorised; - // clang-format off - case 403: case 407: // clang-format on - return ContentAccessError; - case 404: - return NotFoundError; - // clang-format off - case 400: case 405: case 406: case 426: case 428: case 505: // clang-format on - case 494: // Unofficial nginx "Request header too large" - case 497: // Unofficial nginx "HTTP request sent to HTTPS port" - return IncorrectRequestError; - case 429: - return TooManyRequestsError; - case 501: case 510: - return RequestNotImplementedError; - case 511: - return NetworkAuthRequiredError; - default: - return NetworkError; - } -} - -QDebug BaseJob::Status::dumpToLog(QDebug dbg) const -{ - QDebugStateSaver _s(dbg); - dbg.noquote().nospace(); - if (auto* const k = QMetaEnum::fromType<StatusCode>().valueToKey(code)) { - const QByteArray b = k; - dbg << b.mid(b.lastIndexOf(':')); - } else - dbg << code; - return dbg << ": " << message; - -} - BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const { // QNetworkReply error codes seem to be flawed when it comes to HTTP; @@ -440,6 +444,8 @@ BaseJob::Status BaseJob::doCheckReply(QNetworkReply* reply) const return Status::fromHttpCode(httpCode, message); } +void BaseJob::checkReply() { setStatus(doCheckReply(d->reply.data())); } + BaseJob::Status BaseJob::parseReply(QNetworkReply* reply) { d->rawResponse = reply->readAll(); @@ -602,6 +608,8 @@ QByteArray BaseJob::rawData(int bytesAtMost) const : d->rawResponse; } +const QByteArray& BaseJob::rawData() const { return d->rawResponse; } + QString BaseJob::rawDataSample(int bytesAtMost) const { auto data = rawData(bytesAtMost); diff --git a/lib/jobs/basejob.h b/lib/jobs/basejob.h index 2049f59c..010aca78 100644 --- a/lib/jobs/basejob.h +++ b/lib/jobs/basejob.h @@ -157,11 +157,16 @@ public: /** Short human-friendly message on the job status */ QString statusCaption() const; - /** Get raw response body as received from the server - * \param bytesAtMost return this number of leftmost bytes, or -1 - * to return the entire response + /*! Get first bytes of the raw response body as received from the server + * + * \param bytesAtMost the number of leftmost bytes to return + * + * \sa rawDataSample */ - QByteArray rawData(int bytesAtMost = -1) const; + QByteArray rawData(int bytesAtMost) const; + + /*! Access the whole response body as received from the server */ + const QByteArray& rawData() const; /** Get UI-friendly sample of raw data * @@ -170,6 +175,8 @@ public: * recommended to present a sample of raw data as "details" next to * error messages. Note that the default \p bytesAtMost value is * also tailored to UI cases. + * + * \sa rawData */ QString rawDataSample(int bytesAtMost = 65535) const; @@ -322,6 +329,7 @@ protected: * on retries. */ virtual void doPrepare(); + /*! Postprocessing after the network request has been sent * * This method is called every time the job receives a running @@ -331,13 +339,15 @@ protected: virtual void onSentRequest(QNetworkReply*); virtual void beforeAbandon(QNetworkReply*); - /** - * Used by gotReply() to check the received reply for general - * issues such as network errors or access denial. - * Returning anything except NoError/Success prevents - * further parseReply()/parseJson() invocation. + /*! \brief Check the pending or received reply for upfront issues + * + * This is invoked when headers are first received and also once + * the complete reply is obtained; the base implementation checks the HTTP + * headers to detect general issues such as network errors or access denial. + * It cannot read the response body (use parseReply/parseError to check + * for problems in the body). Returning anything except NoError/Success + * prevents further processing of the reply. * - * @param reply the reply received from the server * @return the result of checking the reply * * @see gotReply diff --git a/lib/syncdata.h b/lib/syncdata.h index 6e7183ee..41b8186e 100644 --- a/lib/syncdata.h +++ b/lib/syncdata.h @@ -75,7 +75,7 @@ public: static const QString UnreadCountKey; }; -// QVector cannot work with non-copiable objects, std::vector can. +// QVector cannot work with non-copyable objects, std::vector can. using SyncDataList = std::vector<SyncRoomData>; class SyncData { |