diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2024-01-18 12:27:08 +0100 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2024-01-18 21:56:46 +0100 |
commit | a3a48815cc9430d6f5c736a312ea4ea5c0895205 (patch) | |
tree | 46406bedd5f461dfd097a509f3032d7bd8d44b1b | |
parent | 84b792fa98b3a21119f16b0cd9443f90b1ad504d (diff) |
QH2Connection: Fix issue with unity-build/odr
The static function appeared in two places, and in a unity-build
this fails quite visibly.
Pick-to: 6.7
Change-Id: I60000d01194a2c79ca9c101f2a6d3f77f469f1a7
Reviewed-by: Alexey Edelev <alexey.edelev@qt.io>
Reviewed-by: Nodir Temirkhodjaev <nodir.temir@gmail.com>
-rw-r--r-- | src/network/access/http2/hpack.cpp | 43 | ||||
-rw-r--r-- | src/network/access/http2/hpack_p.h | 3 | ||||
-rw-r--r-- | src/network/access/qhttp2connection.cpp | 45 | ||||
-rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 44 |
4 files changed, 48 insertions, 87 deletions
diff --git a/src/network/access/http2/hpack.cpp b/src/network/access/http2/hpack.cpp index a2a06e8cd5..9e970dda53 100644 --- a/src/network/access/http2/hpack.cpp +++ b/src/network/access/http2/hpack.cpp @@ -504,6 +504,49 @@ void Decoder::handleStreamError(BitIStream &inputStream) // HTTP2 layer will end with session error/COMPRESSION_ERROR. } +std::optional<QUrl> makePromiseKeyUrl(const HttpHeader &requestHeader) +{ + constexpr QByteArrayView names[] = { ":authority", ":method", ":path", ":scheme" }; + enum PseudoHeaderEnum + { + Authority, + Method, + Path, + Scheme + }; + std::array<std::optional<QByteArrayView>, std::size(names)> pseudoHeaders{}; + for (const auto &field : requestHeader) { + const auto *it = std::find(std::begin(names), std::end(names), QByteArrayView(field.name)); + if (it != std::end(names)) { + const auto index = std::distance(std::begin(names), it); + if (field.value.isEmpty() || pseudoHeaders.at(index).has_value()) + return {}; + pseudoHeaders[index] = field.value; + } + } + + auto optionalIsSet = [](const auto &x) { return x.has_value(); }; + if (!std::all_of(pseudoHeaders.begin(), pseudoHeaders.end(), optionalIsSet)) { + // All four required, HTTP/2 8.1.2.3. + return {}; + } + + const QByteArrayView method = pseudoHeaders[Method].value(); + if (method.compare("get", Qt::CaseInsensitive) != 0 && + method.compare("head", Qt::CaseInsensitive) != 0) { + return {}; + } + + QUrl url; + url.setScheme(QLatin1StringView(pseudoHeaders[Scheme].value())); + url.setAuthority(QLatin1StringView(pseudoHeaders[Authority].value())); + url.setPath(QLatin1StringView(pseudoHeaders[Path].value())); + + if (!url.isValid()) + return {}; + return url; +} + } QT_END_NAMESPACE diff --git a/src/network/access/http2/hpack_p.h b/src/network/access/http2/hpack_p.h index 75693da73c..b407b81941 100644 --- a/src/network/access/http2/hpack_p.h +++ b/src/network/access/http2/hpack_p.h @@ -18,8 +18,10 @@ #include "hpacktable_p.h" #include <QtCore/qglobal.h> +#include <QtCore/qurl.h> #include <vector> +#include <optional> QT_BEGIN_NAMESPACE @@ -112,6 +114,7 @@ private: FieldLookupTable lookupTable; }; +std::optional<QUrl> makePromiseKeyUrl(const HttpHeader &requestHeader); } QT_END_NAMESPACE diff --git a/src/network/access/qhttp2connection.cpp b/src/network/access/qhttp2connection.cpp index 1d092f6eb7..d2ac5f0290 100644 --- a/src/network/access/qhttp2connection.cpp +++ b/src/network/access/qhttp2connection.cpp @@ -21,49 +21,6 @@ Q_LOGGING_CATEGORY(qHttp2ConnectionLog, "qt.network.http2.connection", QtCritica using namespace Qt::StringLiterals; using namespace Http2; -static std::optional<QUrl> makeUrl(const HPack::HttpHeader &requestHeader) -{ - constexpr QByteArrayView names[] = { ":authority", ":method", ":path", ":scheme" }; - enum PseudoHeaderEnum - { - Authority, - Method, - Path, - Scheme - }; - std::array<std::optional<QByteArrayView>, std::size(names)> pseudoHeaders{}; - for (const auto &field : requestHeader) { - const auto *it = std::find(std::begin(names), std::end(names), QByteArrayView(field.name)); - if (it != std::end(names)) { - const auto index = std::distance(std::begin(names), it); - if (field.value.isEmpty() || pseudoHeaders.at(index).has_value()) - return {}; - pseudoHeaders[index] = field.value; - } - } - - auto optionalIsSet = [](const auto &x) { return x.has_value(); }; - if (!std::all_of(pseudoHeaders.begin(), pseudoHeaders.end(), optionalIsSet)) { - // All four required, HTTP/2 8.1.2.3. - return {}; - } - - const QByteArrayView method = pseudoHeaders[Method].value(); - if (method.compare("get", Qt::CaseInsensitive) != 0 && - method.compare("head", Qt::CaseInsensitive) != 0) { - return {}; - } - - QUrl url; - url.setScheme(QLatin1StringView(pseudoHeaders[Scheme].value())); - url.setAuthority(QLatin1StringView(pseudoHeaders[Authority].value())); - url.setPath(QLatin1StringView(pseudoHeaders[Path].value())); - - if (!url.isValid()) - return {}; - return url; -} - QHttp2Stream::QHttp2Stream(QHttp2Connection *connection, quint32 streamID) noexcept : QObject(connection), m_streamID(streamID) { @@ -1297,7 +1254,7 @@ void QHttp2Connection::handleContinuedHEADERS() streamIt.value()->handleHEADERS(continuedFrames[0].flags(), decoder.decodedHeader()); break; case FrameType::PUSH_PROMISE: { - std::optional<QUrl> promiseKey = makeUrl(decoder.decodedHeader()); + std::optional<QUrl> promiseKey = HPack::makePromiseKeyUrl(decoder.decodedHeader()); if (!promiseKey) return; // invalid URL/key ! if (m_promisedStreams.contains(*promiseKey)) diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 4e7c1e1d61..60f7ea12a6 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -1468,54 +1468,12 @@ quint32 QHttp2ProtocolHandler::allocateStreamID() return streamID; } -static std::optional<QUrl> makeUrl(const HPack::HttpHeader &requestHeader) -{ - constexpr QByteArrayView names[] = { ":authority", ":method", ":path", ":scheme" }; - enum PseudoHeaderEnum - { - Authority, - Method, - Path, - Scheme - }; - std::array<std::optional<QByteArrayView>, std::size(names)> pseudoHeaders{}; - for (const auto &field : requestHeader) { - const auto it = std::find(std::begin(names), std::end(names), QByteArrayView(field.name)); - if (it != std::end(names)) { - const auto index = std::distance(std::begin(names), it); - if (field.value.isEmpty() || pseudoHeaders.at(index).has_value()) - return {}; - pseudoHeaders[index] = field.value; - } - } - - if (!std::all_of(pseudoHeaders.begin(), pseudoHeaders.end(), [](const auto &x) { return x.has_value();})) { - // All four required, HTTP/2 8.1.2.3. - return {}; - } - - const QByteArrayView method = pseudoHeaders[Method].value(); - if (method.compare("get", Qt::CaseInsensitive) != 0 && - method.compare("head", Qt::CaseInsensitive) != 0) { - return {}; - } - - QUrl url; - url.setScheme(QLatin1StringView(pseudoHeaders[Scheme].value())); - url.setAuthority(QLatin1StringView(pseudoHeaders[Authority].value())); - url.setPath(QLatin1StringView(pseudoHeaders[Path].value())); - - if (!url.isValid()) - return {}; - return url; -} - bool QHttp2ProtocolHandler::tryReserveStream(const Http2::Frame &pushPromiseFrame, const HPack::HttpHeader &requestHeader) { Q_ASSERT(pushPromiseFrame.type() == FrameType::PUSH_PROMISE); - const auto url = makeUrl(requestHeader); + const auto url = HPack::makePromiseKeyUrl(requestHeader); if (!url.has_value()) return false; |