summaryrefslogtreecommitdiffstats
path: root/src/network/access/http2/http2protocol.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access/http2/http2protocol.cpp')
-rw-r--r--src/network/access/http2/http2protocol.cpp141
1 files changed, 68 insertions, 73 deletions
diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp
index 31da6fd616..8e7e176c41 100644
--- a/src/network/access/http2/http2protocol.cpp
+++ b/src/network/access/http2/http2protocol.cpp
@@ -1,41 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2016 The Qt Company Ltd.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "http2protocol_p.h"
#include "http2frames_p.h"
@@ -50,6 +14,10 @@
QT_BEGIN_NAMESPACE
+using namespace Qt::StringLiterals;
+
+QT_IMPL_METATYPE_EXTERN_TAGGED(Http2::Settings, Http2__Settings)
+
Q_LOGGING_CATEGORY(QT_HTTP2, "qt.network.http2")
namespace Http2
@@ -71,9 +39,12 @@ Frame configurationToSettingsFrame(const QHttp2Configuration &config)
// Server push:
builder.append(Settings::ENABLE_PUSH_ID);
builder.append(int(config.serverPushEnabled()));
- // Stream receive window size:
- builder.append(Settings::INITIAL_WINDOW_SIZE_ID);
- builder.append(config.streamReceiveWindowSize());
+
+ // Stream receive window size (if it's a default value, don't include):
+ if (config.streamReceiveWindowSize() != defaultSessionWindowSize) {
+ builder.append(Settings::INITIAL_WINDOW_SIZE_ID);
+ builder.append(config.streamReceiveWindowSize());
+ }
if (config.maxFrameSize() != minPayloadLimit) {
builder.append(Settings::MAX_FRAME_SIZE_ID);
@@ -105,12 +76,10 @@ void appendProtocolUpgradeHeaders(const QHttp2Configuration &config, QHttpNetwor
Q_ASSERT(request);
// RFC 2616, 14.10
// RFC 7540, 3.2
- QByteArray value(request->headerField("Connection"));
+ const QByteArray connectionHeader = request->headerField("Connection");
+ const auto separator = connectionHeader.isEmpty() ? QByteArrayView() : QByteArrayView(", ");
// We _append_ 'Upgrade':
- if (value.size())
- value += ", ";
-
- value += "Upgrade, HTTP2-Settings";
+ QByteArray value = connectionHeader + separator + "Upgrade, HTTP2-Settings";
request->setHeaderField("Connection", value);
// This we just (re)write.
request->setHeaderField("Upgrade", "h2c");
@@ -125,7 +94,7 @@ void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error,
{
if (errorCode > quint32(HTTP_1_1_REQUIRED)) {
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("RST_STREAM with unknown error code (%1)");
+ errorMessage = "RST_STREAM with unknown error code (%1)"_L1;
errorMessage = errorMessage.arg(errorCode);
return;
}
@@ -139,61 +108,61 @@ void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error,
break;
case PROTOCOL_ERROR:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("HTTP/2 protocol error");
+ errorMessage = "HTTP/2 protocol error"_L1;
break;
case INTERNAL_ERROR:
error = QNetworkReply::InternalServerError;
- errorMessage = QLatin1String("Internal server error");
+ errorMessage = "Internal server error"_L1;
break;
case FLOW_CONTROL_ERROR:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Flow control error");
+ errorMessage = "Flow control error"_L1;
break;
case SETTINGS_TIMEOUT:
error = QNetworkReply::TimeoutError;
- errorMessage = QLatin1String("SETTINGS ACK timeout error");
+ errorMessage = "SETTINGS ACK timeout error"_L1;
break;
case STREAM_CLOSED:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Server received frame(s) on a half-closed stream");
+ errorMessage = "Server received frame(s) on a half-closed stream"_L1;
break;
case FRAME_SIZE_ERROR:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Server received a frame with an invalid size");
+ errorMessage = "Server received a frame with an invalid size"_L1;
break;
case REFUSE_STREAM:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Server refused a stream");
+ errorMessage = "Server refused a stream"_L1;
break;
case CANCEL:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Stream is no longer needed");
+ errorMessage = "Stream is no longer needed"_L1;
break;
case COMPRESSION_ERROR:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Server is unable to maintain the "
- "header compression context for the connection");
+ errorMessage = "Server is unable to maintain the "
+ "header compression context for the connection"_L1;
break;
case CONNECT_ERROR:
// TODO: in Qt6 we'll have to add more error codes in QNetworkReply.
error = QNetworkReply::UnknownNetworkError;
- errorMessage = QLatin1String("The connection established in response "
- "to a CONNECT request was reset or abnormally closed");
+ errorMessage = "The connection established in response "
+ "to a CONNECT request was reset or abnormally closed"_L1;
break;
case ENHANCE_YOUR_CALM:
error = QNetworkReply::UnknownServerError;
- errorMessage = QLatin1String("Server dislikes our behavior, excessive load detected.");
+ errorMessage = "Server dislikes our behavior, excessive load detected."_L1;
break;
case INADEQUATE_SECURITY:
error = QNetworkReply::ContentAccessDenied;
- errorMessage = QLatin1String("The underlying transport has properties "
- "that do not meet minimum security "
- "requirements");
+ errorMessage = "The underlying transport has properties "
+ "that do not meet minimum security "
+ "requirements"_L1;
break;
case HTTP_1_1_REQUIRED:
error = QNetworkReply::ProtocolFailure;
- errorMessage = QLatin1String("Server requires that HTTP/1.1 "
- "be used instead of HTTP/2.");
+ errorMessage = "Server requires that HTTP/1.1 "
+ "be used instead of HTTP/2."_L1;
}
}
@@ -215,19 +184,45 @@ QNetworkReply::NetworkError qt_error(quint32 errorCode)
bool is_protocol_upgraded(const QHttpNetworkReply &reply)
{
- if (reply.statusCode() == 101) {
- // Do some minimal checks here - we expect 'Upgrade: h2c' to be found.
- const auto &header = reply.header();
- for (const QPair<QByteArray, QByteArray> &field : header) {
- if (field.first.compare("upgrade", Qt::CaseInsensitive) == 0 &&
- field.second.compare("h2c", Qt::CaseInsensitive) == 0)
- return true;
- }
+ if (reply.statusCode() != 101)
+ return false;
+
+ // Do some minimal checks here - we expect 'Upgrade: h2c' to be found.
+ for (const auto &v : reply.header().values(QHttpHeaders::WellKnownHeader::Upgrade)) {
+ if (v.compare("h2c", Qt::CaseInsensitive) == 0)
+ return true;
}
return false;
}
+std::vector<uchar> assemble_hpack_block(const std::vector<Frame> &frames)
+{
+ std::vector<uchar> hpackBlock;
+
+ size_t total = 0;
+ for (const auto &frame : frames) {
+ if (qAddOverflow(total, size_t{frame.hpackBlockSize()}, &total))
+ return hpackBlock;
+ }
+
+ if (!total)
+ return hpackBlock;
+
+ hpackBlock.resize(total);
+ auto dst = hpackBlock.begin();
+ for (const auto &frame : frames) {
+ if (const auto hpackBlockSize = frame.hpackBlockSize()) {
+ const uchar *src = frame.hpackBlockBegin();
+ std::copy(src, src + hpackBlockSize, dst);
+ dst += hpackBlockSize;
+ }
+ }
+
+ return hpackBlock;
+}
+
+
} // namespace Http2
QT_END_NAMESPACE