QNetworkAccessManager: delay IPv4 connection with Happy Eyeballs
Incase we have both IPv4 and IPv6 available after the host lookup we should delay the connection attempt to IPv4. Task-number: QTBUG-23066 Change-Id: I8c0177cf125c9daae314ada73cacef790a39b856 Reviewed-by: Peter Hartmann <peter.hartmann@nokia.com>
This commit is contained in:
parent
f4ccbc2868
commit
9bc4b56656
@ -116,6 +116,7 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate()
|
|||||||
|
|
||||||
void QHttpNetworkConnectionPrivate::init()
|
void QHttpNetworkConnectionPrivate::init()
|
||||||
{
|
{
|
||||||
|
Q_Q(QHttpNetworkConnection);
|
||||||
for (int i = 0; i < channelCount; i++) {
|
for (int i = 0; i < channelCount; i++) {
|
||||||
channels[i].setConnection(this->q_func());
|
channels[i].setConnection(this->q_func());
|
||||||
channels[i].ssl = encrypt;
|
channels[i].ssl = encrypt;
|
||||||
@ -125,6 +126,8 @@ void QHttpNetworkConnectionPrivate::init()
|
|||||||
#endif
|
#endif
|
||||||
channels[i].init();
|
channels[i].init();
|
||||||
}
|
}
|
||||||
|
ipv4ConnectTimer.setSingleShot(true);
|
||||||
|
QObject::connect(&ipv4ConnectTimer, SIGNAL(timeout()), q, SLOT(_q_connectIPv4Channel()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void QHttpNetworkConnectionPrivate::pauseConnection()
|
void QHttpNetworkConnectionPrivate::pauseConnection()
|
||||||
@ -185,6 +188,12 @@ bool QHttpNetworkConnectionPrivate::shouldEmitChannelError(QAbstractSocket *sock
|
|||||||
int i = indexOf(socket);
|
int i = indexOf(socket);
|
||||||
int otherSocket = (i == 0 ? 1 : 0);
|
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 (channelCount == 1) {
|
if (channelCount == 1) {
|
||||||
if (networkLayerState == QHttpNetworkConnectionPrivate::InProgress)
|
if (networkLayerState == QHttpNetworkConnectionPrivate::InProgress)
|
||||||
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
||||||
@ -1010,7 +1019,18 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
|
|||||||
channels[0].networkLayerPreference = QAbstractSocket::IPv4Protocol;
|
channels[0].networkLayerPreference = QAbstractSocket::IPv4Protocol;
|
||||||
channels[1].networkLayerPreference = QAbstractSocket::IPv6Protocol;
|
channels[1].networkLayerPreference = QAbstractSocket::IPv6Protocol;
|
||||||
|
|
||||||
channels[0].ensureConnection(); // Possibly delay this one..
|
int timeout = 300;
|
||||||
|
#ifndef QT_NO_BEARERMANAGEMENT
|
||||||
|
if (networkSession->configuration().bearerType() == QNetworkConfiguration::Bearer2G)
|
||||||
|
timeout = 800;
|
||||||
|
else if (networkSession->configuration().bearerType() == QNetworkConfiguration::BearerCDMA2000)
|
||||||
|
timeout = 500;
|
||||||
|
else if (networkSession->configuration().bearerType() == QNetworkConfiguration::BearerWCDMA)
|
||||||
|
timeout = 500;
|
||||||
|
else if (networkSession->configuration().bearerType() == QNetworkConfiguration::BearerHSPA)
|
||||||
|
timeout = 400;
|
||||||
|
#endif
|
||||||
|
ipv4ConnectTimer.start(timeout);
|
||||||
channels[1].ensureConnection();
|
channels[1].ensureConnection();
|
||||||
} else {
|
} else {
|
||||||
networkLayerState = InProgress;
|
networkLayerState = InProgress;
|
||||||
@ -1019,6 +1039,10 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QHttpNetworkConnectionPrivate::_q_connectIPv4Channel()
|
||||||
|
{
|
||||||
|
channels[0].ensureConnection();
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_BEARERMANAGEMENT
|
#ifndef QT_NO_BEARERMANAGEMENT
|
||||||
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent, QSharedPointer<QNetworkSession> networkSession)
|
QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent, QSharedPointer<QNetworkSession> networkSession)
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
#include <qauthenticator.h>
|
#include <qauthenticator.h>
|
||||||
#include <qnetworkproxy.h>
|
#include <qnetworkproxy.h>
|
||||||
#include <qbuffer.h>
|
#include <qbuffer.h>
|
||||||
|
#include <qtimer.h>
|
||||||
|
|
||||||
#include <private/qhttpnetworkheader_p.h>
|
#include <private/qhttpnetworkheader_p.h>
|
||||||
#include <private/qhttpnetworkrequest_p.h>
|
#include <private/qhttpnetworkrequest_p.h>
|
||||||
@ -134,6 +135,7 @@ private:
|
|||||||
|
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
|
Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest())
|
||||||
Q_PRIVATE_SLOT(d_func(), void _q_hostLookupFinished(QHostInfo))
|
Q_PRIVATE_SLOT(d_func(), void _q_hostLookupFinished(QHostInfo))
|
||||||
|
Q_PRIVATE_SLOT(d_func(), void _q_connectIPv4Channel())
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -196,6 +198,7 @@ public:
|
|||||||
void _q_startNextRequest(); // send the next request from the queue
|
void _q_startNextRequest(); // send the next request from the queue
|
||||||
|
|
||||||
void _q_hostLookupFinished(QHostInfo info);
|
void _q_hostLookupFinished(QHostInfo info);
|
||||||
|
void _q_connectIPv4Channel();
|
||||||
|
|
||||||
void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
|
void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request);
|
||||||
|
|
||||||
@ -209,6 +212,7 @@ public:
|
|||||||
bool encrypt;
|
bool encrypt;
|
||||||
|
|
||||||
const int channelCount;
|
const int channelCount;
|
||||||
|
QTimer ipv4ConnectTimer;
|
||||||
QHttpNetworkConnectionChannel *channels; // parallel connections to the server
|
QHttpNetworkConnectionChannel *channels; // parallel connections to the server
|
||||||
bool shouldEmitChannelError(QAbstractSocket *socket);
|
bool shouldEmitChannelError(QAbstractSocket *socket);
|
||||||
|
|
||||||
|
@ -951,6 +951,8 @@ void QHttpNetworkConnectionChannel::_q_connected()
|
|||||||
// For the Happy Eyeballs we need to check if this is the first channel to connect.
|
// For the Happy Eyeballs we need to check if this is the first channel to connect.
|
||||||
if (!pendingEncrypt) {
|
if (!pendingEncrypt) {
|
||||||
if (connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::InProgress) {
|
if (connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::InProgress) {
|
||||||
|
if (connection->d_func()->ipv4ConnectTimer.isActive())
|
||||||
|
connection->d_func()->ipv4ConnectTimer.stop();
|
||||||
if (networkLayerPreference == QAbstractSocket::IPv4Protocol)
|
if (networkLayerPreference == QAbstractSocket::IPv4Protocol)
|
||||||
connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv4;
|
connection->d_func()->networkLayerState = QHttpNetworkConnectionPrivate::IPv4;
|
||||||
else if (networkLayerPreference == QAbstractSocket::IPv6Protocol)
|
else if (networkLayerPreference == QAbstractSocket::IPv6Protocol)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user