summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp61
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel_p.h1
-rw-r--r--src/network/socket/qlocalsocket_p.h6
-rw-r--r--src/network/socket/qlocalsocket_win.cpp22
4 files changed, 59 insertions, 31 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index b0e632a..2a3036b 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -283,20 +283,17 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
// connection might be closed to signal the end of data
if (socketState == QAbstractSocket::UnconnectedState) {
- if (!socket->bytesAvailable()) {
+ if (socket->bytesAvailable() <= 0) {
if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
+ // finish this reply. this case happens when the server did not send a content length
reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
allDone();
} else {
- // try to reconnect/resend before sending an error.
- if (reconnectAttempts-- > 0) {
- closeAndResendCurrentRequest();
- } else if (reply) {
- reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket);
- emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString);
- QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
- }
+ handleUnexpectedEOF();
+ return;
}
+ } else {
+ // socket not connected but still bytes for reading.. just continue in this function
}
}
@@ -311,18 +308,10 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
}
case QHttpNetworkReplyPrivate::ReadingStatusState: {
qint64 statusBytes = reply->d_func()->readStatus(socket);
- if (statusBytes == -1 && reconnectAttempts <= 0) {
- // too many errors reading/receiving/parsing the status, close the socket and emit error
- close();
- reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::ProtocolFailure, socket);
- emit reply->finishedWithError(QNetworkReply::ProtocolFailure, reply->d_func()->errorString);
- QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
- break;
- } else if (statusBytes == -1) {
- reconnectAttempts--;
- reply->d_func()->clear();
- closeAndResendCurrentRequest();
- break;
+ if (statusBytes == -1) {
+ // connection broke while reading status. also handled if later _q_disconnected is called
+ handleUnexpectedEOF();
+ return;
}
bytes += statusBytes;
lastStatus = reply->d_func()->statusCode;
@@ -330,7 +319,13 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
}
case QHttpNetworkReplyPrivate::ReadingHeaderState: {
QHttpNetworkReplyPrivate *replyPrivate = reply->d_func();
- bytes += replyPrivate->readHeader(socket);
+ qint64 headerBytes = replyPrivate->readHeader(socket);
+ if (headerBytes == -1) {
+ // connection broke while reading headers. also handled if later _q_disconnected is called
+ handleUnexpectedEOF();
+ return;
+ }
+ bytes += headerBytes;
if (replyPrivate->state == QHttpNetworkReplyPrivate::ReadingDataState) {
if (replyPrivate->isGzipped() && replyPrivate->autoDecompress) {
// remove the Content-Length from header
@@ -430,6 +425,23 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
}
}
+// called when unexpectedly reading a -1 or when data is expected but socket is closed
+void QHttpNetworkConnectionChannel::handleUnexpectedEOF()
+{
+ if (reconnectAttempts <= 0) {
+ // too many errors reading/receiving/parsing the status, close the socket and emit error
+ requeueCurrentlyPipelinedRequests();
+ close();
+ reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket);
+ emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString);
+ QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
+ } else {
+ reconnectAttempts--;
+ reply->d_func()->clear();
+ closeAndResendCurrentRequest();
+ }
+}
+
bool QHttpNetworkConnectionChannel::ensureConnection()
{
QAbstractSocket::SocketState socketState = socket->state();
@@ -799,9 +811,10 @@ void QHttpNetworkConnectionChannel::_q_disconnected()
{
// read the available data before closing
if (isSocketWaiting() || isSocketReading()) {
- state = QHttpNetworkConnectionChannel::ReadingState;
- if (reply)
+ if (reply) {
+ state = QHttpNetworkConnectionChannel::ReadingState;
_q_receiveReply();
+ }
} else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) {
// re-sending request because the socket was in ClosingState
QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection);
diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h
index 75ab50d..5032d2b 100644
--- a/src/network/access/qhttpnetworkconnectionchannel_p.h
+++ b/src/network/access/qhttpnetworkconnectionchannel_p.h
@@ -157,6 +157,7 @@ public:
void requeueCurrentlyPipelinedRequests();
void detectPipeliningSupport();
+ void handleUnexpectedEOF();
void closeAndResendCurrentRequest();
void eatWhitespace();
diff --git a/src/network/socket/qlocalsocket_p.h b/src/network/socket/qlocalsocket_p.h
index 081697b..0f1c23c 100644
--- a/src/network/socket/qlocalsocket_p.h
+++ b/src/network/socket/qlocalsocket_p.h
@@ -128,10 +128,8 @@ public:
void _q_stateChanged(QAbstractSocket::SocketState newState);
void _q_error(QAbstractSocket::SocketError newError);
#elif defined(Q_OS_WIN)
- ~QLocalSocketPrivate() {
- CloseHandle(overlapped.hEvent);
- }
-
+ ~QLocalSocketPrivate();
+ void destroyPipeHandles();
void setErrorString(const QString &function);
void _q_notified();
void _q_canWrite();
diff --git a/src/network/socket/qlocalsocket_win.cpp b/src/network/socket/qlocalsocket_win.cpp
index 1f94df6..3283bf2 100644
--- a/src/network/socket/qlocalsocket_win.cpp
+++ b/src/network/socket/qlocalsocket_win.cpp
@@ -110,6 +110,20 @@ QLocalSocketPrivate::QLocalSocketPrivate() : QIODevicePrivate(),
{
}
+QLocalSocketPrivate::~QLocalSocketPrivate()
+{
+ destroyPipeHandles();
+ CloseHandle(overlapped.hEvent);
+}
+
+void QLocalSocketPrivate::destroyPipeHandles()
+{
+ if (handle != INVALID_HANDLE_VALUE) {
+ DisconnectNamedPipe(handle);
+ CloseHandle(handle);
+ }
+}
+
void QLocalSocket::connectToServer(const QString &name, OpenMode openMode)
{
Q_D(QLocalSocket);
@@ -388,8 +402,7 @@ void QLocalSocket::close()
d->readSequenceStarted = false;
d->pendingReadyRead = false;
d->pipeClosed = false;
- DisconnectNamedPipe(d->handle);
- CloseHandle(d->handle);
+ d->destroyPipeHandles();
d->handle = INVALID_HANDLE_VALUE;
ResetEvent(d->overlapped.hEvent);
d->state = UnconnectedState;
@@ -524,7 +537,10 @@ bool QLocalSocket::waitForDisconnected(int msecs)
bool QLocalSocket::isValid() const
{
Q_D(const QLocalSocket);
- return (d->handle != INVALID_HANDLE_VALUE);
+ if (d->handle == INVALID_HANDLE_VALUE)
+ return false;
+
+ return PeekNamedPipe(d->handle, NULL, 0, NULL, NULL, NULL);
}
bool QLocalSocket::waitForReadyRead(int msecs)