diff options
Diffstat (limited to 'src/network/access/qhttp2protocolhandler.cpp')
-rw-r--r-- | src/network/access/qhttp2protocolhandler.cpp | 69 |
1 files changed, 38 insertions, 31 deletions
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index 114feb91b7..461f2429b3 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -161,8 +161,6 @@ bool sum_will_overflow(qint32 windowSize, qint32 delta) using namespace Http2; const std::deque<quint32>::size_type QHttp2ProtocolHandler::maxRecycledStreams = 10000; -const qint32 QHttp2ProtocolHandler::sessionMaxRecvWindowSize; -const qint32 QHttp2ProtocolHandler::streamInitialRecvWindowSize; const quint32 QHttp2ProtocolHandler::maxAcceptableTableSize; QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *channel) @@ -170,10 +168,22 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan decoder(HPack::FieldLookupTable::DefaultSize), encoder(HPack::FieldLookupTable::DefaultSize, true) { + Q_ASSERT(channel); continuedFrames.reserve(20); - bool ok = false; - const int env = qEnvironmentVariableIntValue("QT_HTTP2_ENABLE_PUSH_PROMISE", &ok); - pushPromiseEnabled = ok && env; + pushPromiseEnabled = is_PUSH_PROMISE_enabled(); + + if (!channel->ssl) { + // We upgraded from HTTP/1.1 to HTTP/2. channel->request was already sent + // as HTTP/1.1 request. The response with status code 101 triggered + // protocol switch and now we are waiting for the real response, sent + // as HTTP/2 frames. + Q_ASSERT(channel->reply); + const quint32 initialStreamID = createNewStream(HttpMessagePair(channel->request, channel->reply), + true /* uploaded by HTTP/1.1 */); + Q_ASSERT(initialStreamID == 1); + Stream &stream = activeStreams[initialStreamID]; + stream.state = Stream::halfClosedLocal; + } } void QHttp2ProtocolHandler::_q_uploadDataReadyRead() @@ -356,22 +366,16 @@ bool QHttp2ProtocolHandler::sendClientPreface() return false; // 6.5 SETTINGS - frameWriter.start(FrameType::SETTINGS, FrameFlag::EMPTY, Http2::connectionStreamID); - // MAX frame size (16 kb), enable/disable PUSH - frameWriter.append(Settings::MAX_FRAME_SIZE_ID); - frameWriter.append(quint32(Http2::maxFrameSize)); - frameWriter.append(Settings::ENABLE_PUSH_ID); - frameWriter.append(quint32(pushPromiseEnabled)); + frameWriter.setOutboundFrame(default_SETTINGS_frame()); + Q_ASSERT(frameWriter.outboundFrame().payloadSize()); if (!frameWriter.write(*m_socket)) return false; - sessionRecvWindowSize = sessionMaxRecvWindowSize; - if (defaultSessionWindowSize < sessionMaxRecvWindowSize) { - const auto delta = sessionMaxRecvWindowSize - defaultSessionWindowSize; - if (!sendWINDOW_UPDATE(connectionStreamID, delta)) - return false; - } + sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize; + const auto delta = Http2::initialSessionReceiveWindowSize - Http2::defaultSessionWindowSize; + if (!sendWINDOW_UPDATE(Http2::connectionStreamID, delta)) + return false; prefaceSent = true; waitingForSettingsACK = true; @@ -541,20 +545,20 @@ void QHttp2ProtocolHandler::handleDATA() if (inboundFrame.flags().testFlag(FrameFlag::END_STREAM)) { finishStream(stream); deleteActiveStream(stream.streamID); - } else if (stream.recvWindow < streamInitialRecvWindowSize / 2) { + } else if (stream.recvWindow < Http2::initialStreamReceiveWindowSize / 2) { QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection, Q_ARG(quint32, stream.streamID), - Q_ARG(quint32, streamInitialRecvWindowSize - stream.recvWindow)); - stream.recvWindow = streamInitialRecvWindowSize; + Q_ARG(quint32, Http2::initialStreamReceiveWindowSize - stream.recvWindow)); + stream.recvWindow = Http2::initialStreamReceiveWindowSize; } } } - if (sessionRecvWindowSize < sessionMaxRecvWindowSize / 2) { + if (sessionRecvWindowSize < Http2::initialSessionReceiveWindowSize / 2) { QMetaObject::invokeMethod(this, "sendWINDOW_UPDATE", Qt::QueuedConnection, Q_ARG(quint32, connectionStreamID), - Q_ARG(quint32, sessionMaxRecvWindowSize - sessionRecvWindowSize)); - sessionRecvWindowSize = sessionMaxRecvWindowSize; + Q_ARG(quint32, Http2::initialSessionReceiveWindowSize - sessionRecvWindowSize)); + sessionRecvWindowSize = Http2::initialSessionReceiveWindowSize; } } @@ -1176,7 +1180,7 @@ void QHttp2ProtocolHandler::finishStreamWithError(Stream &stream, QNetworkReply: << "finished with error:" << message; } -quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message) +quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message, bool uploadDone) { const qint32 newStreamID = allocateStreamID(); if (!newStreamID) @@ -1195,12 +1199,14 @@ quint32 QHttp2ProtocolHandler::createNewStream(const HttpMessagePair &message) const Stream newStream(message, newStreamID, streamInitialSendWindowSize, - streamInitialRecvWindowSize); + Http2::initialStreamReceiveWindowSize); - if (auto src = newStream.data()) { - connect(src, SIGNAL(readyRead()), this, - SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection); - src->setProperty("HTTP2StreamID", newStreamID); + if (!uploadDone) { + if (auto src = newStream.data()) { + connect(src, SIGNAL(readyRead()), this, + SLOT(_q_uploadDataReadyRead()), Qt::QueuedConnection); + src->setProperty("HTTP2StreamID", newStreamID); + } } activeStreams.insert(newStreamID, newStream); @@ -1388,7 +1394,8 @@ bool QHttp2ProtocolHandler::tryReserveStream(const Http2::Frame &pushPromiseFram promise.reservedID = reservedID; promise.pushHeader = requestHeader; - activeStreams.insert(reservedID, Stream(urlKey, reservedID, streamInitialRecvWindowSize)); + activeStreams.insert(reservedID, Stream(urlKey, reservedID, + Http2::initialStreamReceiveWindowSize)); return true; } @@ -1422,7 +1429,7 @@ void QHttp2ProtocolHandler::initReplyFromPushPromise(const HttpMessagePair &mess // Let's pretent we're sending a request now: Stream closedStream(message, promise.reservedID, streamInitialSendWindowSize, - streamInitialRecvWindowSize); + Http2::initialStreamReceiveWindowSize); closedStream.state = Stream::halfClosedLocal; activeStreams.insert(promise.reservedID, closedStream); promisedStream = &activeStreams[promise.reservedID]; |