Fix Q_ASSERT(!channels[0].isSocketBusy());
Since commit f30641a7 is has been possible to issue more than one host lookup request per HttpNetworkConnection. If the result was both an IPv4 and IPv6 address, and we get a second similar DNS reply, we end up triggering the assert in startNetworkLayerStateLookup(). This patch splits the InProgress state to HostLookupPending and the state of trying both IPv4 and IPv6. This makes it possible to ignore any new DNS replies received after the first succesfull one. Change-Id: I0b8d6b1582fdaed69dde5926019b60bb0cbd580d Reviewed-by: Peter Hartmann <phartmann@blackberry.com>
This commit is contained in:
parent
13035f7fd6
commit
690cf426f3
@ -181,7 +181,7 @@ int QHttpNetworkConnectionPrivate::indexOf(QAbstractSocket *socket) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the connection is in the InProgress state channel errors should not always be
|
// If the connection is in the HostLookupPendening state channel errors should not always be
|
||||||
// emitted. This function will check the status of the connection channels if we
|
// emitted. This function will check the status of the connection channels if we
|
||||||
// have not decided the networkLayerState and will return true if the channel error
|
// have not decided the networkLayerState and will return true if the channel error
|
||||||
// should be emitted by the channel.
|
// should be emitted by the channel.
|
||||||
@ -200,12 +200,12 @@ bool QHttpNetworkConnectionPrivate::shouldEmitChannelError(QAbstractSocket *sock
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (channelCount == 1) {
|
if (channelCount == 1) {
|
||||||
if (networkLayerState == QHttpNetworkConnectionPrivate::InProgress)
|
if (networkLayerState == HostLookupPending || networkLayerState == IPv4or6)
|
||||||
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
networkLayerState = QHttpNetworkConnectionPrivate::Unknown;
|
||||||
channels[0].close();
|
channels[0].close();
|
||||||
emitError = true;
|
emitError = true;
|
||||||
} else {
|
} else {
|
||||||
if (networkLayerState == QHttpNetworkConnectionPrivate::InProgress) {
|
if (networkLayerState == HostLookupPending || networkLayerState == IPv4or6) {
|
||||||
if (channels[otherSocket].isSocketBusy() && (channels[otherSocket].state != QHttpNetworkConnectionChannel::ClosingState)) {
|
if (channels[otherSocket].isSocketBusy() && (channels[otherSocket].state != QHttpNetworkConnectionChannel::ClosingState)) {
|
||||||
// this was the first socket to fail.
|
// this was the first socket to fail.
|
||||||
channels[i].close();
|
channels[i].close();
|
||||||
@ -560,7 +560,7 @@ QHttpNetworkReply* QHttpNetworkConnectionPrivate::queueRequest(const QHttpNetwor
|
|||||||
// untill we have started the first connection attempt. So no
|
// untill we have started the first connection attempt. So no
|
||||||
// request will be started untill we know if IPv4 or IPv6
|
// request will be started untill we know if IPv4 or IPv6
|
||||||
// should be used.
|
// should be used.
|
||||||
if (networkLayerState == Unknown || networkLayerState == InProgress) {
|
if (networkLayerState == Unknown || networkLayerState == HostLookupPending) {
|
||||||
startHostInfoLookup();
|
startHostInfoLookup();
|
||||||
} else if ( networkLayerState == IPv4 || networkLayerState == IPv6 ) {
|
} else if ( networkLayerState == IPv4 || networkLayerState == IPv6 ) {
|
||||||
// this used to be called via invokeMethod and a QueuedConnection
|
// this used to be called via invokeMethod and a QueuedConnection
|
||||||
@ -878,7 +878,7 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
|
|||||||
void QHttpNetworkConnectionPrivate::_q_startNextRequest()
|
void QHttpNetworkConnectionPrivate::_q_startNextRequest()
|
||||||
{
|
{
|
||||||
// If there is no network layer state decided we should not start any new requests.
|
// If there is no network layer state decided we should not start any new requests.
|
||||||
if (networkLayerState == Unknown || networkLayerState == InProgress)
|
if (networkLayerState == Unknown || networkLayerState == HostLookupPending || networkLayerState == IPv4or6)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// If the QHttpNetworkConnection is currently paused then bail out immediately
|
// If the QHttpNetworkConnection is currently paused then bail out immediately
|
||||||
@ -986,7 +986,7 @@ void QHttpNetworkConnectionPrivate::readMoreLater(QHttpNetworkReply *reply)
|
|||||||
// lookup as then the hostinfo will already be in the cache.
|
// lookup as then the hostinfo will already be in the cache.
|
||||||
void QHttpNetworkConnectionPrivate::startHostInfoLookup()
|
void QHttpNetworkConnectionPrivate::startHostInfoLookup()
|
||||||
{
|
{
|
||||||
networkLayerState = InProgress;
|
networkLayerState = HostLookupPending;
|
||||||
|
|
||||||
// check if we already now can decide if this is IPv4 or IPv6
|
// check if we already now can decide if this is IPv4 or IPv6
|
||||||
QString lookupHost = hostName;
|
QString lookupHost = hostName;
|
||||||
@ -1028,6 +1028,8 @@ void QHttpNetworkConnectionPrivate::_q_hostLookupFinished(QHostInfo info)
|
|||||||
bool bIpv4 = false;
|
bool bIpv4 = false;
|
||||||
bool bIpv6 = false;
|
bool bIpv6 = false;
|
||||||
bool foundAddress = false;
|
bool foundAddress = false;
|
||||||
|
if (networkLayerState == IPv4 || networkLayerState == IPv6 || networkLayerState == IPv4or6)
|
||||||
|
return;
|
||||||
|
|
||||||
foreach (const QHostAddress &address, info.addresses()) {
|
foreach (const QHostAddress &address, info.addresses()) {
|
||||||
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
|
if (address.protocol() == QAbstractSocket::IPv4Protocol) {
|
||||||
@ -1077,7 +1079,7 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
|
|||||||
Q_ASSERT(!channels[0].isSocketBusy());
|
Q_ASSERT(!channels[0].isSocketBusy());
|
||||||
Q_ASSERT(!channels[1].isSocketBusy());
|
Q_ASSERT(!channels[1].isSocketBusy());
|
||||||
|
|
||||||
networkLayerState = InProgress;
|
networkLayerState = IPv4or6;
|
||||||
|
|
||||||
channels[0].networkLayerPreference = QAbstractSocket::IPv4Protocol;
|
channels[0].networkLayerPreference = QAbstractSocket::IPv4Protocol;
|
||||||
channels[1].networkLayerPreference = QAbstractSocket::IPv6Protocol;
|
channels[1].networkLayerPreference = QAbstractSocket::IPv6Protocol;
|
||||||
@ -1101,7 +1103,7 @@ void QHttpNetworkConnectionPrivate::startNetworkLayerStateLookup()
|
|||||||
else
|
else
|
||||||
channels[0].ensureConnection();
|
channels[0].ensureConnection();
|
||||||
} else {
|
} else {
|
||||||
networkLayerState = InProgress;
|
networkLayerState = IPv4or6;
|
||||||
channels[0].networkLayerPreference = QAbstractSocket::AnyIPProtocol;
|
channels[0].networkLayerPreference = QAbstractSocket::AnyIPProtocol;
|
||||||
channels[0].ensureConnection();
|
channels[0].ensureConnection();
|
||||||
}
|
}
|
||||||
|
@ -165,9 +165,10 @@ public:
|
|||||||
|
|
||||||
enum NetworkLayerPreferenceState {
|
enum NetworkLayerPreferenceState {
|
||||||
Unknown,
|
Unknown,
|
||||||
InProgress,
|
HostLookupPending,
|
||||||
IPv4,
|
IPv4,
|
||||||
IPv6
|
IPv6,
|
||||||
|
IPv4or6
|
||||||
};
|
};
|
||||||
|
|
||||||
QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt);
|
QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt);
|
||||||
|
@ -1045,7 +1045,7 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
|
|||||||
void QHttpNetworkConnectionChannel::_q_connected()
|
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 (connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::InProgress) {
|
if (connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::HostLookupPending || connection->d_func()->networkLayerState == QHttpNetworkConnectionPrivate::IPv4or6) {
|
||||||
if (connection->d_func()->delayedConnectionTimer.isActive())
|
if (connection->d_func()->delayedConnectionTimer.isActive())
|
||||||
connection->d_func()->delayedConnectionTimer.stop();
|
connection->d_func()->delayedConnectionTimer.stop();
|
||||||
if (networkLayerPreference == QAbstractSocket::IPv4Protocol)
|
if (networkLayerPreference == QAbstractSocket::IPv4Protocol)
|
||||||
@ -1212,7 +1212,7 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket
|
|||||||
QPointer<QHttpNetworkConnection> that = connection;
|
QPointer<QHttpNetworkConnection> that = connection;
|
||||||
QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString());
|
QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString());
|
||||||
|
|
||||||
// In the InProgress state the channel should not emit the error.
|
// In the HostLookupPending state the channel should not emit the error.
|
||||||
// This will instead be handled by the connection.
|
// This will instead be handled by the connection.
|
||||||
if (!connection->d_func()->shouldEmitChannelError(socket))
|
if (!connection->d_func()->shouldEmitChannelError(socket))
|
||||||
return;
|
return;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user