summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2024-01-18 12:27:08 +0100
committerMårten Nordheim <marten.nordheim@qt.io>2024-01-18 21:56:46 +0100
commita3a48815cc9430d6f5c736a312ea4ea5c0895205 (patch)
tree46406bedd5f461dfd097a509f3032d7bd8d44b1b
parent84b792fa98b3a21119f16b0cd9443f90b1ad504d (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.cpp43
-rw-r--r--src/network/access/http2/hpack_p.h3
-rw-r--r--src/network/access/qhttp2connection.cpp45
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp44
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;