QNetworkAccessManager: delay IPv4 or IPv6 based on getaddrinfo order
Instead of always delaying IPv4 when we have both Ipv4 and IPv6 we should use the order we get from getaddrinfo to descide which one that should be delayed. Task-number: QTBUG-23066 Change-Id: Ibe8c4d7000abd6e57fe8c6afac8a4a843e17ff27 Reviewed-by: Peter Hartmann <peter.hartmann@nokia.com> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
This commit is contained in:
parent
bc8f25c7e6
commit
54c487cdd2
@ -81,7 +81,7 @@ const int QHttpNetworkConnectionPrivate::defaultRePipelineLength = 2;
|
||||
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt)
|
||||
: state(RunningState),
|
||||
networkLayerState(Unknown),
|
||||
hostName(hostName), port(port), encrypt(encrypt),
|
||||
hostName(hostName), port(port), encrypt(encrypt), delayIpv4(true),
|
||||
channelCount(defaultChannelCount)
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
, networkProxy(QNetworkProxy::NoProxy)
|
||||
@ -92,7 +92,7 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host
|
||||
|
||||
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt)
|
||||
: state(RunningState), networkLayerState(Unknown),
|
||||
hostName(hostName), port(port), encrypt(encrypt),
|
||||
hostName(hostName), port(port), encrypt(encrypt), delayIpv4(true),
|
||||
channelCount(channelCount)
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
, networkProxy(QNetworkProxy::NoProxy)
|
||||
@ -126,8 +126,8 @@ void QHttpNetworkConnectionPrivate::init()
|
||||
#endif
|
||||
channels[i].init();
|
||||
}
|
||||
ipv4ConnectTimer.setSingleShot(true);
|
||||
QObject::connect(&ipv4ConnectTimer, SIGNAL(timeout()), q, SLOT(_q_connectIPv4Channel()));
|
||||
delayedConnectionTimer.setSingleShot(true);
|
||||
QObject::connect(&delayedConnectionTimer, SIGNAL(timeout()), q, SLOT(_q_connectDelayedChannel()));
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionPrivate::pauseConnection()
|
||||
@ -189,9 +189,9 @@ bool QHttpNetworkConnectionPrivate::shouldEmitChannelError(QAbstractSocket *sock
|
||||
int otherSocket = (i == 0 ? 1 : 0);
|
||||
|
||||
// If the IPv4 connection still isn't started we need to start it now.
|
||||
if (ipv4ConnectTimer.isActive()) {
|
||||
ipv4ConnectTimer.stop();
|
||||
channels[0].ensureConnection();
|
||||
if (delayedConnectionTimer.isActive()) {
|
||||
delayedConnectionTimer.stop();
|
||||
channels[otherSocket].ensureConnection();
|
||||
}
|
||||
|
||||
if (channelCount == 1) {
|
||||
@ -974,12 +974,22 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(QHostInfo info)
|
||||
{
|
||||
bool bIpv4 = false;
|
||||
bool bIpv6 = false;
|
||||
bool foundAddress = false;
|
||||
|
||||
foreach (QHostAddress address, info.addresses()) {
|
||||
if (address.protocol() == QAbstractSocket::IPv4Protocol)
|
||||
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||
if (!foundAddress) {
|
||||
foundAddress = true;
|
||||
delayIpv4 = false;
|
||||
}
|
||||
bIpv4 = true;
|
||||
else if (address.protocol() == QAbstractSocket::IPv6Protocol)
|
||||
} else if (address.protocol() == QAbstractSocket::IPv6Protocol) {
|
||||
if (!foundAddress) {
|
||||
foundAddress = true;
|
||||
delayIpv4 = true;
|
||||
}
|
||||
bIpv6 = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (bIpv4 && bIpv6)
|
||||
@ -1030,8 +1040,11 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
|
||||
else if (networkSession->configuration().bearerType() == QNetworkConfiguration::BearerHSPA)
|
||||
timeout = 400;
|
||||
#endif
|
||||
ipv4ConnectTimer.start(timeout);
|
||||
channels[1].ensureConnection();
|
||||
delayedConnectionTimer.start(timeout);
|
||||
if (delayIpv4)
|
||||
channels[1].ensureConnection();
|
||||
else
|
||||
channels[0].ensureConnection();
|
||||
} else {
|
||||
networkLayerState = InProgress;
|
||||
channels[0].networkLayerPreference = QAbstractSocket::AnyIPProtocol;
|
||||
@ -1039,9 +1052,12 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
|
||||
}
|
||||
}
|
||||
|
||||
void QHttpNetworkConnectionPrivate::_q_connectIPv4Channel()
|
||||
void QHttpNetworkConnectionPrivate::_q_connectDelayedChannel()
|
||||
{
|
||||
channels[0].ensureConnection();
|
||||
if (delayIpv4)
|
||||
channels[0].ensureConnection();
|
||||
else
|
||||
channels[1].ensureConnection();
|
||||
}
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
|
@ -135,7 +135,7 @@ private:
|
||||
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_hostLookupFinished(QHostInfo))
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_connectIPv4Channel())
|
||||
Q_PRIVATE_SLOT(d_func(), void _q_connectDelayedChannel())
|
||||
};
|
||||
|
||||
|
||||
@ -198,7 +198,7 @@ public:
|
||||
void _q_startNextRequest(); // send the next request from the queue
|
||||
|
||||
void _q_hostLookupFinished(QHostInfo info);
|
||||
void _q_connectIPv4Channel();
|
||||
void _q_connectDelayedChannel();
|
||||
|
||||
void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
|
||||
|
||||
@ -210,9 +210,10 @@ public:
|
||||
QString hostName;
|
||||
quint16 port;
|
||||
bool encrypt;
|
||||
bool delayIpv4;
|
||||
|
||||
const int channelCount;
|
||||
QTimer ipv4ConnectTimer;
|
||||
QTimer delayedConnectionTimer;
|
||||
QHttpNetworkConnectionChannel *channels; // parallel connections to the server
|
||||
bool shouldEmitChannelError(QAbstractSocket *socket);
|
||||
|
||||
|
@ -954,8 +954,8 @@ void QHttpNetworkConnectionChannel::_q_connected()
|
||||
// For the Happy Eyeballs we need to check if this is the first channel to connect.
|
||||
if (!pendingEncrypt) {
|
||||
if (connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::InProgress) {
|
||||
if (connection->d_func()->ipv4ConnectTimer.isActive())
|
||||
connection->d_func()->ipv4ConnectTimer.stop();
|
||||
if (connection->d_func()->delayedConnectionTimer.isActive())
|
||||
connection->d_func()->delayedConnectionTimer.stop();
|
||||
if (networkLayerPreference == QAbstractSocket::IPv4Protocol)
|
||||
connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv4;
|
||||
else if (networkLayerPreference == QAbstractSocket::IPv6Protocol)
|
||||
|
Loading…
Reference in New Issue
Block a user