Abort underlying socket when aborting QNetworkReply

If we abort a connection in QNetworkReply::encrypted the underlying
socket gets flushed. This patch fixes that no data will be transmitted
after someone called abort().

Change-Id: I59306e69cb9f2e1421b324e11947375130e52135
Task-number: QTBUG-47471
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
bb10
Sebastian Lösch 2015-08-10 12:47:04 +02:00 committed by André Klitzing
parent f0f9f309e0
commit f98c2ef27a
6 changed files with 45 additions and 3 deletions

View File

@ -835,8 +835,13 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
// if HTTP mandates we should close
// or the reply is not finished yet, e.g. it was aborted
// we have to close that connection
if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished())
channels[i].close();
if (reply->d_func()->isConnectionCloseEnabled() || !reply->isFinished()) {
if (reply->isAborted()) {
channels[i].abort();
} else {
channels[i].close();
}
}
QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
return;

View File

@ -205,6 +205,26 @@ void QHttpNetworkConnectionChannel::close()
}
void QHttpNetworkConnectionChannel::abort()
{
if (!socket)
state = QHttpNetworkConnectionChannel::IdleState;
else if (socket->state() == QAbstractSocket::UnconnectedState)
state = QHttpNetworkConnectionChannel::IdleState;
else
state = QHttpNetworkConnectionChannel::ClosingState;
// pendingEncrypt must only be true in between connected and encrypted states
pendingEncrypt = false;
if (socket) {
// socket can be 0 since the host lookup is done from qhttpnetworkconnection.cpp while
// there is no socket yet.
socket->abort();
}
}
bool QHttpNetworkConnectionChannel::sendRequest()
{
Q_ASSERT(!protocolHandler.isNull());

View File

@ -157,6 +157,7 @@ public:
void init();
void close();
void abort();
bool sendRequest();

View File

@ -247,6 +247,17 @@ char* QHttpNetworkReply::userProvidedDownloadBuffer()
return d->userProvidedDownloadBuffer;
}
void QHttpNetworkReply::abort()
{
Q_D(QHttpNetworkReply);
d->state = QHttpNetworkReplyPrivate::Aborted;
}
bool QHttpNetworkReply::isAborted() const
{
return d_func()->state == QHttpNetworkReplyPrivate::Aborted;
}
bool QHttpNetworkReply::isFinished() const
{
return d_func()->state == QHttpNetworkReplyPrivate::AllDoneState;

View File

@ -121,6 +121,9 @@ public:
void setUserProvidedDownloadBuffer(char*);
char* userProvidedDownloadBuffer();
void abort();
bool isAborted() const;
bool isFinished() const;
bool isPipeliningUsed() const;
@ -205,7 +208,8 @@ public:
SPDYSYNSent,
SPDYUploading,
SPDYHalfClosed,
SPDYClosed
SPDYClosed,
Aborted
} state;
QHttpNetworkRequest request;

View File

@ -396,6 +396,7 @@ void QHttpThreadDelegate::abortRequest()
qDebug() << "QHttpThreadDelegate::abortRequest() thread=" << QThread::currentThreadId() << "sync=" << synchronous;
#endif
if (httpReply) {
httpReply->abort();
delete httpReply;
httpReply = 0;
}