diff options
author | Lars Schmertmann <Lars.Schmertmann@governikus.de> | 2017-09-14 12:47:11 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-05-11 21:31:46 +0000 |
commit | 516d8d22ff45da01ae9de367a39c129dd408246a (patch) | |
tree | daa459cbd225decbbbcb9d753ba4f0b239e5cc71 /src/network | |
parent | e5946f7b18f52d184b44ff62f3117ef760506122 (diff) |
Prefer previously used channels in QHttpNetworkConnection
When IPv4 and IPv6 are supported by a server, QHttpNetworkConnection
will start up two connections and pick the network layer of the one
that finish first. In this case the channel with index 1 is used for
IPv6. When IPv6 wins, there is no channel at index 0. This situation
needs to be respected and we should try to use existing channels first
when there is a next request.
This is especially important when TLS session resumption is used.
Creating a new channel will cause to lose the ephemeralServerKey
used in the first connection.
Fixes: QTBUG-93295
Change-Id: Ic9dc6a24ef793a29c2652ad37bc11120e2e6ceef
Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
(cherry picked from commit a120d11cb5506ef0a5535e790f23d49595fb8857)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 57 |
1 files changed, 38 insertions, 19 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 13c86c6a9b..18b9e38b9a 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1117,31 +1117,50 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() int normalRequests = queuedRequests - preConnectRequests; neededOpenChannels = qMax(normalRequests, preConnectRequests); } + + if (neededOpenChannels <= 0) + return; + + QQueue<int> channelsToConnect; + + // use previously used channels first for (int i = 0; i < activeChannelCount && neededOpenChannels > 0; ++i) { - bool connectChannel = false; - if (channels[i].socket) { - if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) - || (channels[i].socket->state() == QAbstractSocket::HostLookupState) - || channels[i].pendingEncrypt) // pendingEncrypt == "EncryptingState" - neededOpenChannels--; - - if (neededOpenChannels <= 0) - break; - if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) - connectChannel = true; - } else { // not previously used channel - connectChannel = true; + if (!channels[i].socket) + continue; + + if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) + || (channels[i].socket->state() == QAbstractSocket::HostLookupState) + || channels[i].pendingEncrypt) { // pendingEncrypt == "EncryptingState" + neededOpenChannels--; + continue; } - if (connectChannel) { - if (networkLayerState == IPv4) - channels[i].networkLayerPreference = QAbstractSocket::IPv4Protocol; - else if (networkLayerState == IPv6) - channels[i].networkLayerPreference = QAbstractSocket::IPv6Protocol; - channels[i].ensureConnection(); + if (!channels[i].reply && !channels[i].isSocketBusy() + && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) { + channelsToConnect.enqueue(i); neededOpenChannels--; } } + + // use other channels + for (int i = 0; i < activeChannelCount && neededOpenChannels > 0; ++i) { + if (channels[i].socket) + continue; + + channelsToConnect.enqueue(i); + neededOpenChannels--; + } + + while (!channelsToConnect.isEmpty()) { + const int channel = channelsToConnect.dequeue(); + + if (networkLayerState == IPv4) + channels[channel].networkLayerPreference = QAbstractSocket::IPv4Protocol; + else if (networkLayerState == IPv6) + channels[channel].networkLayerPreference = QAbstractSocket::IPv6Protocol; + + channels[channel].ensureConnection(); + } } |