diff --git a/src/network/access/qhttp2connection.cpp b/src/network/access/qhttp2connection.cpp index 64e10724fa7..32190d2dee7 100644 --- a/src/network/access/qhttp2connection.cpp +++ b/src/network/access/qhttp2connection.cpp @@ -552,7 +552,7 @@ QHttp2Connection::createStreamInternal() if (m_goingAway) return { QHttp2Connection::CreateStreamError::ReceivedGOAWAY }; const quint32 streamID = m_nextStreamID; - if (size_t(m_maxConcurrentStreams) <= size_t(numActiveStreams())) + if (size_t(m_maxConcurrentStreams) <= size_t(numActiveLocalStreams())) return { QHttp2Connection::CreateStreamError::MaxConcurrentStreamsReached }; m_nextStreamID += 2; return { createStreamInternal_impl(streamID) }; @@ -570,12 +570,32 @@ QHttp2Stream *QHttp2Connection::createStreamInternal_impl(quint32 streamID) return stream; } -qsizetype QHttp2Connection::numActiveStreams() const noexcept +qsizetype QHttp2Connection::numActiveStreamsImpl(quint32 mask) const noexcept { - return std::count_if(m_streams.cbegin(), m_streams.cend(), - [](const QPointer &stream) { - return stream && stream->state() == QHttp2Stream::State::Open; - }); + const auto shouldCount = [mask](const QPointer &stream) -> bool { + return stream && (stream->streamID() & 1) == mask; + }; + return std::count_if(m_streams.cbegin(), m_streams.cend(), shouldCount); +} + +/*! + \internal + The number of streams the remote peer has started that are still active. +*/ +qsizetype QHttp2Connection::numActiveRemoteStreams() const noexcept +{ + const quint32 RemoteMask = m_connectionType == Type::Client ? 0 : 1; + return numActiveStreamsImpl(RemoteMask); +} + +/*! + \internal + The number of streams we have started that are still active. +*/ +qsizetype QHttp2Connection::numActiveLocalStreams() const noexcept +{ + const quint32 LocalMask = m_connectionType == Type::Client ? 1 : 0; + return numActiveStreamsImpl(LocalMask); } QHttp2Stream *QHttp2Connection::getStream(quint32 streamID) const diff --git a/src/network/access/qhttp2connection_p.h b/src/network/access/qhttp2connection_p.h index 5d525537e58..4d70ae36771 100644 --- a/src/network/access/qhttp2connection_p.h +++ b/src/network/access/qhttp2connection_p.h @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -253,7 +254,9 @@ private: const char *message); // Connection failed to be established? void setH2Configuration(QHttp2Configuration config); void closeSession(); - qsizetype numActiveStreams() const noexcept; + qsizetype numActiveStreamsImpl(quint32 mask) const noexcept; + qsizetype numActiveRemoteStreams() const noexcept; + qsizetype numActiveLocalStreams() const noexcept; bool sendClientPreface(); bool sendSETTINGS(); diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp index d17b62565ee..f2508383d8b 100644 --- a/src/network/access/qhttp2protocolhandler.cpp +++ b/src/network/access/qhttp2protocolhandler.cpp @@ -325,7 +325,10 @@ bool QHttp2ProtocolHandler::sendRequest() initReplyFromPushPromise(message, key); } - const qint64 streamsToUse = qBound(0, qint64(maxConcurrentStreams) - activeStreams.size(), + const auto isClientSide = [](const auto &pair) -> bool { return (pair.first & 1) == 1; }; + const auto activeClientSideStreams = std::count_if( + activeStreams.constKeyValueBegin(), activeStreams.constKeyValueEnd(), isClientSide); + const qint64 streamsToUse = qBound(0, qint64(maxConcurrentStreams) - activeClientSideStreams, requests.size()); auto it = requests.begin(); for (qint64 i = 0; i < streamsToUse; ++i) {