From 2d1f1371733c85b23eb91d27999c5a0ec9373a54 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 4 Aug 2016 09:34:50 +0200 Subject: Revert "Implement protocol upgrade for HTTP/2 enabled requests" This reverts commit 12d71f4ea20415ff2274e1e90f9e4d5a8b935d7f. This change is breaking a build + incomplete as my test revealed. Will have to re-try later. Change-Id: I7ea089093a832aa5822caaaac56e62f5fda4df17 Reviewed-by: Liang Qi --- src/network/access/http2/http2protocol.cpp | 47 -------------------- src/network/access/http2/http2protocol_p.h | 5 --- src/network/access/qhttp2protocolhandler.cpp | 51 +++++++--------------- src/network/access/qhttp2protocolhandler_p.h | 14 ++---- .../access/qhttpnetworkconnectionchannel.cpp | 40 ++++------------- .../access/qhttpnetworkconnectionchannel_p.h | 6 +-- src/network/access/qhttpprotocolhandler.cpp | 9 ---- src/network/access/qhttpthreaddelegate.cpp | 5 +-- 8 files changed, 28 insertions(+), 149 deletions(-) (limited to 'src/network/access') diff --git a/src/network/access/http2/http2protocol.cpp b/src/network/access/http2/http2protocol.cpp index 9f05e926c9..7f788a6f42 100644 --- a/src/network/access/http2/http2protocol.cpp +++ b/src/network/access/http2/http2protocol.cpp @@ -37,12 +37,9 @@ ** ****************************************************************************/ -#include #include -#include "private/qhttpnetworkrequest_p.h" #include "http2protocol_p.h" -#include "http2frames_p.h" QT_BEGIN_NAMESPACE @@ -60,37 +57,6 @@ const char Http2clientPreface[clientPrefaceLength] = 0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a, 0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a}; -QByteArray qt_default_SETTINGS_to_Base64() -{ - FrameWriter frame(qt_default_SETTINGS_frame()); - // SETTINGS frame's payload consists of pairs: - // 2-byte-identifier | 4-byte-value - multiple of 6. - // Also it's allowed to be empty. - Q_ASSERT(!(frame.payloadSize() % 6)); - const char *src = reinterpret_cast(&frame.rawFrameBuffer()[frameHeaderSize]); - const QByteArray wrapper(QByteArray::fromRawData(src, int(frame.payloadSize()))); - // 3.2.1 - // The content of the HTTP2-Settings header field is the payload - // of a SETTINGS frame (Section 6.5), encoded as a base64url string - // (that is, the URL- and filename-safe Base64 encoding described in - // Section 5 of [RFC4648], with any trailing '=' characters omitted). - return wrapper.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals); -} - -void qt_add_ProtocolUpgradeRequest(QHttpNetworkRequest &request) -{ - // RFC 2616, 14.10 - QByteArray value(request.headerField("Connection")); - if (value.size()) - value += ", "; - - value += "Upgrade, HTTP2-Settings"; - request.setHeaderField("Connection", value); - // This we just (re)write. - request.setHeaderField("Upgrade", "h2c"); - // This we just (re)write. - request.setHeaderField("HTTP2-Settings", qt_default_SETTINGS_to_Base64()); -} void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error, QString &errorMessage) @@ -185,19 +151,6 @@ QNetworkReply::NetworkError qt_error(quint32 errorCode) return error; } -FrameWriter qt_default_SETTINGS_frame() -{ - // 6.5 SETTINGS - FrameWriter frame(FrameType::SETTINGS, FrameFlag::EMPTY, connectionStreamID); - // MAX frame size (16 kb), disable PUSH - frame.append(Settings::MAX_FRAME_SIZE_ID); - frame.append(quint32(maxFrameSize)); - frame.append(Settings::ENABLE_PUSH_ID); - frame.append(quint32(0)); - - return frame; -} - } QT_END_NAMESPACE diff --git a/src/network/access/http2/http2protocol_p.h b/src/network/access/http2/http2protocol_p.h index e49e9f1218..5c46949e23 100644 --- a/src/network/access/http2/http2protocol_p.h +++ b/src/network/access/http2/http2protocol_p.h @@ -59,8 +59,6 @@ QT_BEGIN_NAMESPACE -class QHttpNetworkRequest; -class QByteArray; class QString; namespace Http2 @@ -130,7 +128,6 @@ enum Http2PredefinedParameters }; extern const Q_AUTOTEST_EXPORT char Http2clientPreface[clientPrefaceLength]; -void qt_add_ProtocolUpgradeRequest(QHttpNetworkRequest &request); enum class FrameStatus { @@ -169,8 +166,6 @@ void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error, QString &er QString qt_error_string(quint32 errorCode); QNetworkReply::NetworkError qt_error(quint32 errorCode); -class FrameWriter qt_default_SETTINGS_frame(); - } Q_DECLARE_LOGGING_CATEGORY(QT_HTTP2) diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 2cf44521eb..937686920c 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -40,7 +40,7 @@ #include "qhttpnetworkconnection_p.h" #include "qhttp2protocolhandler_p.h" -#if !defined(QT_NO_HTTP) +#if !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) #include "http2/bitstreams_p.h" @@ -54,7 +54,6 @@ #include #include -#include #include QT_BEGIN_NAMESPACE @@ -134,28 +133,6 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan continuedFrames.reserve(20); } -QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *channel, - const HttpMessagePair &message) - : QAbstractProtocolHandler(channel), - prefaceSent(false), - waitingForSettingsACK(false), - decoder(HPack::FieldLookupTable::DefaultSize), - encoder(HPack::FieldLookupTable::DefaultSize, true) -{ - // That's a protocol upgrade scenario - 3.2. - // - // We still have to send settings and the preface - // (though SETTINGS was a part of the first HTTP/1.1 - // request "HTTP2-Settings" field). - // - // We pass 'false' for upload data, this was done by HTTP/1.1 protocol - // handler for us while sending the first request. - const quint32 initialStreamID = createNewStream(message, false); - Q_ASSERT(initialStreamID == 1); - Stream &stream = activeStreams[initialStreamID]; - stream.state = Stream::halfClosedLocal; -} - void QHttp2ProtocolHandler::_q_uploadDataReadyRead() { auto data = qobject_cast(sender()); @@ -270,7 +247,7 @@ bool QHttp2ProtocolHandler::sendRequest() auto it = requests.begin(); m_channel->state = QHttpNetworkConnectionChannel::WritingState; for (quint32 i = 0; i < streamsToUse; ++i) { - const qint32 newStreamID = createNewStream(*it, true /* upload data */); + const qint32 newStreamID = createNewStream(*it); if (!newStreamID) { // TODO: actually we have to open a new connection. qCCritical(QT_HTTP2, "sendRequest: out of stream IDs"); @@ -301,6 +278,7 @@ bool QHttp2ProtocolHandler::sendRequest() return true; } + bool QHttp2ProtocolHandler::sendClientPreface() { // 3.5 HTTP/2 Connection Preface @@ -315,8 +293,12 @@ bool QHttp2ProtocolHandler::sendClientPreface() return false; // 6.5 SETTINGS - outboundFrame = Http2::qt_default_SETTINGS_frame(); - Q_ASSERT(outboundFrame.payloadSize()); + outboundFrame.start(FrameType::SETTINGS, FrameFlag::EMPTY, Http2::connectionStreamID); + // MAX frame size (16 kb), disable PUSH + outboundFrame.append(Settings::MAX_FRAME_SIZE_ID); + outboundFrame.append(quint32(Http2::maxFrameSize)); + outboundFrame.append(Settings::ENABLE_PUSH_ID); + outboundFrame.append(quint32(0)); if (!outboundFrame.write(*m_socket)) return false; @@ -1040,8 +1022,7 @@ void QHttp2ProtocolHandler::finishStreamWithError(Stream &stream, QNetworkReply: emit httpReply->finishedWithError(error, message); } -quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message, - bool uploadData) +quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message) { const qint32 newStreamID = allocateStreamID(); if (!newStreamID) @@ -1062,12 +1043,10 @@ quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message, streamInitialSendWindowSize, streamInitialRecvWindowSize); - if (uploadData) { - if (auto src = newStream.data()) { - connect(src, SIGNAL(readyRead()), this, - SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection); - src->setProperty("HTTP2StreamID", newStreamID); - } + if (auto src = newStream.data()) { + connect(src, SIGNAL(readyRead()), this, + SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection); + src->setProperty("HTTP2StreamID", newStreamID); } activeStreams.insert(newStreamID, newStream); @@ -1235,4 +1214,4 @@ void QHttp2ProtocolHandler::closeSession() QT_END_NAMESPACE -#endif // !defined(QT_NO_HTTP) +#endif // !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) diff --git a/src/network/access/qhttp2protocolhandler_p.h b/src/network/access/qhttp2protocolhandler_p.h index e41b1360bf..b146e37dd3 100644 --- a/src/network/access/qhttp2protocolhandler_p.h +++ b/src/network/access/qhttp2protocolhandler_p.h @@ -55,7 +55,7 @@ #include #include -#if !defined(QT_NO_HTTP) +#if !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) #include "http2/http2protocol_p.h" #include "http2/http2streams_p.h" @@ -81,15 +81,7 @@ class QHttp2ProtocolHandler : public QObject, public QAbstractProtocolHandler Q_OBJECT public: - // "TLS + ALPN/NPN" case: QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *channel); - // HTTP2 without TLS - the first request was sent as an HTTP/1.1 request - // with Upgrade:h2c header. That serves as an implicit HTTP/2 request - // on a stream with ID 1 (it will be created in this ctor in a - // 'half-closed-local' state); reply, if server supports HTTP/2, - // will be HTTP/2 frame(s): - QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *channel, - const HttpMessagePair &message); QHttp2ProtocolHandler(const QHttp2ProtocolHandler &rhs) = delete; QHttp2ProtocolHandler(QHttp2ProtocolHandler &&rhs) = delete; @@ -141,7 +133,7 @@ private: const QString &message); // Stream's lifecycle management: - quint32 createNewStream(const HttpMessagePair &message, bool uploadData); + quint32 createNewStream(const HttpMessagePair &message); void addToSuspended(Stream &stream); void markAsReset(quint32 streamID); quint32 popStreamToResume(); @@ -210,6 +202,6 @@ private: QT_END_NAMESPACE -#endif // !defined(QT_NO_HTTP) +#endif // !defined(QT_NO_HTTP) && !defined(QT_NO_SSL) #endif diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 3d35fe5f04..3a780f636b 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -50,7 +50,6 @@ #include #include #include -#include #ifndef QT_NO_SSL # include @@ -181,9 +180,6 @@ void QHttpNetworkConnectionChannel::init() sslSocket->setSslConfiguration(sslConfiguration); } else { #endif // QT_NO_SSL - // Even if connection->connectionType is ConnectionTypeHTTP2, - // we first start as HTTP/1.1, asking for a protocol upgrade - // in the first response. protocolHandler.reset(new QHttpProtocolHandler(this)); #ifndef QT_NO_SSL } @@ -839,16 +835,6 @@ void QHttpNetworkConnectionChannel::_q_connected() #endif } else { state = QHttpNetworkConnectionChannel::IdleState; - if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) { - Q_ASSERT(spdyRequestsToSend.size()); - auto it = spdyRequestsToSend.begin(); - // Let's inject some magic fields, requesting a protocol upgrade: - Http2::qt_add_ProtocolUpgradeRequest(it->first); - connection->d_func()->requeueRequest(*it); - // Remove it, we never send it again as HTTP/2. - spdyRequestsToSend.erase(it); - } - if (!reply) connection->d_func()->dequeueRequest(socket); if (reply) @@ -986,12 +972,9 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket } } while (!connection->d_func()->highPriorityQueue.isEmpty() || !connection->d_func()->lowPriorityQueue.isEmpty()); - - if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 #ifndef QT_NO_SSL - || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY -#endif - ) { + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY || + connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) { QList spdyPairs = spdyRequestsToSend.values(); for (int a = 0; a < spdyPairs.count(); ++a) { // emit error for all replies @@ -1000,6 +983,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket emit currentReply->finishedWithError(errorCode, errorString); } } +#endif // QT_NO_SSL // send the next request QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); @@ -1018,31 +1002,23 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket } } -void QHttpNetworkConnectionChannel::_q_protocolSwitch() -{ - Q_ASSERT(connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2); - Q_ASSERT(reply); - Q_ASSERT(reply->statusCode() == 101); - protocolHandler.reset(new QHttp2ProtocolHandler(this, HttpMessagePair(request, reply))); - protocolHandler->_q_receiveReply(); -} - #ifndef QT_NO_NETWORKPROXY void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) { - if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2 #ifndef QT_NO_SSL - || connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY -#endif - ) { + if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY || + connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) { connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); } else { // HTTP +#endif // QT_NO_SSL // Need to dequeue the request before we can emit the error. if (!reply) connection->d_func()->dequeueRequest(socket); if (reply) connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); +#ifndef QT_NO_SSL } +#endif // QT_NO_SSL } #endif diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index a20cc1beb8..d7d5d86a7a 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -121,14 +121,11 @@ public: bool authenticationCredentialsSent; bool proxyCredentialsSent; QScopedPointer protocolHandler; - // SPDY or HTTP/2 requests; SPDY is TLS-only, but - // HTTP/2 can be cleartext also, that's why it's - // outside of QT_NO_SSL section. Sorted by priority: - QMultiMap spdyRequestsToSend; #ifndef QT_NO_SSL bool ignoreAllSslErrors; QList ignoreSslErrorsList; QSslConfiguration sslConfiguration; + QMultiMap spdyRequestsToSend; // sorted by priority void ignoreSslErrors(); void ignoreSslErrors(const QList &errors); void setSslConfiguration(const QSslConfiguration &config); @@ -195,7 +192,6 @@ public: void _q_disconnected(); // disconnected from host void _q_connected(); // start sending request void _q_error(QAbstractSocket::SocketError); // error from socket - void _q_protocolSwitch(); // HTTP/2 was negotiated to replace HTTP/1.1 #ifndef QT_NO_NETWORKPROXY void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy #endif diff --git a/src/network/access/qhttpprotocolhandler.cpp b/src/network/access/qhttpprotocolhandler.cpp index ab136af083..b486b75449 100644 --- a/src/network/access/qhttpprotocolhandler.cpp +++ b/src/network/access/qhttpprotocolhandler.cpp @@ -129,15 +129,6 @@ void QHttpProtocolHandler::_q_receiveReply() } else { replyPrivate->autoDecompress = false; } - if (m_connection->connectionType() == QHttpNetworkConnection::ConnectionTypeHTTP2) { - if (replyPrivate->statusCode == 101) { - QMetaObject::invokeMethod(m_channel, "_q_protocolSwitch", Qt::QueuedConnection); - return; - } - - // HTTP/2 is not supported? TODO - but can it be something else? - m_channel->requeueSpdyRequests(); - } if (replyPrivate->statusCode == 100) { replyPrivate->clearHttpLayerInformation(); replyPrivate->state = QHttpNetworkReplyPrivate::ReadingStatusState; diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 8b200ebc04..e16519c2f2 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -286,12 +286,9 @@ void QHttpThreadDelegate::startRequest() QHttpNetworkConnection::ConnectionType connectionType = QHttpNetworkConnection::ConnectionTypeHTTP; - - if (httpRequest.isHTTP2Allowed()) - connectionType = QHttpNetworkConnection::ConnectionTypeHTTP2; - #ifndef QT_NO_SSL if (httpRequest.isHTTP2Allowed() && ssl) { + connectionType = QHttpNetworkConnection::ConnectionTypeHTTP2; QList protocols; protocols << QSslConfiguration::ALPNProtocolHTTP2 << QSslConfiguration::NextProtocolHttp1_1; -- cgit v1.2.3