void QHttpNetworkConnectionChannel::emitFinishedWithError(QNetworkReply::NetworkError error, const char *message) { if (reply) emit reply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message)); QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values(); for (int a = 0; a < spdyPairs.count(); ++a) { QHttpNetworkReply *currentReply = spdyPairs.at(a).second; Q_ASSERT(currentReply); emit currentReply->finishedWithError(error, QHttpNetworkConnectionChannel::tr(message)); } }
void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socketError) { if (!socket) return; QNetworkReply::NetworkError errorCode = QNetworkReply::UnknownNetworkError; switch (socketError) { case QAbstractSocket::HostNotFoundError: errorCode = QNetworkReply::HostNotFoundError; break; case QAbstractSocket::ConnectionRefusedError: errorCode = QNetworkReply::ConnectionRefusedError; break; case QAbstractSocket::RemoteHostClosedError: // try to reconnect/resend before sending an error. // while "Reading" the _q_disconnected() will handle this. if (state != QHttpNetworkConnectionChannel::IdleState && state != QHttpNetworkConnectionChannel::ReadingState) { if (reconnectAttempts-- > 0) { closeAndResendCurrentRequest(); return; } else { errorCode = QNetworkReply::RemoteHostClosedError; } } else if (state == QHttpNetworkConnectionChannel::ReadingState) { if (!reply) break; if (!reply->d_func()->expectContent()) { // No content expected, this is a valid way to have the connection closed by the server return; } if (reply->contentLength() == -1 && !reply->d_func()->isChunked()) { // There was no content-length header and it's not chunked encoding, // so this is a valid way to have the connection closed by the server return; } // ok, we got a disconnect even though we did not expect it // Try to read everything from the socket before we emit the error. if (socket->bytesAvailable()) { // Read everything from the socket into the reply buffer. // we can ignore the readbuffersize as the data is already // in memory and we will not receive more data on the socket. reply->setReadBufferSize(0); _q_receiveReply(); #ifndef QT_NO_SSL if (ssl) { // QT_NO_OPENSSL. The QSslSocket can still have encrypted bytes in the plainsocket. // So we need to check this if the socket is a QSslSocket. When the socket is flushed // it will force a decrypt of the encrypted data in the plainsocket. QSslSocket *sslSocket = static_cast<QSslSocket*>(socket); qint64 beforeFlush = sslSocket->encryptedBytesAvailable(); while (sslSocket->encryptedBytesAvailable()) { sslSocket->flush(); _q_receiveReply(); qint64 afterFlush = sslSocket->encryptedBytesAvailable(); if (afterFlush == beforeFlush) break; beforeFlush = afterFlush; } } #endif } errorCode = QNetworkReply::RemoteHostClosedError; } else { errorCode = QNetworkReply::RemoteHostClosedError; } break; case QAbstractSocket::SocketTimeoutError: // try to reconnect/resend before sending an error. if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) { closeAndResendCurrentRequest(); return; } errorCode = QNetworkReply::TimeoutError; break; case QAbstractSocket::ProxyAuthenticationRequiredError: errorCode = QNetworkReply::ProxyAuthenticationRequiredError; break; case QAbstractSocket::SslHandshakeFailedError: errorCode = QNetworkReply::SslHandshakeFailedError; break; case QAbstractSocket::ProxyConnectionClosedError: // try to reconnect/resend before sending an error. if (reconnectAttempts-- > 0) { closeAndResendCurrentRequest(); return; } errorCode = QNetworkReply::ProxyConnectionClosedError; break; case QAbstractSocket::ProxyConnectionTimeoutError: // try to reconnect/resend before sending an error. if (reconnectAttempts-- > 0) { closeAndResendCurrentRequest(); return; } errorCode = QNetworkReply::ProxyTimeoutError; break; default: // all other errors are treated as NetworkError errorCode = QNetworkReply::UnknownNetworkError; break; } QPointer<QHttpNetworkConnection> that = connection; QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString()); // In the HostLookupPending state the channel should not emit the error. // This will instead be handled by the connection. if (!connection->d_func()->shouldEmitChannelError(socket)) return; // emit error for all waiting replies do { // Need to dequeu the request so that we can emit the error. if (!reply) connection->d_func()->dequeueRequest(socket); if (reply) { reply->d_func()->errorString = errorString; emit reply->finishedWithError(errorCode, errorString); reply = 0; if (protocolHandler) protocolHandler->setReply(0); } } while (!connection->d_func()->highPriorityQueue.isEmpty() || !connection->d_func()->lowPriorityQueue.isEmpty()); #ifndef QT_NO_SSL if (connection->connectionType() == QHttpNetworkConnection::ConnectionTypeSPDY) { QList<HttpMessagePair> spdyPairs = spdyRequestsToSend.values(); for (int a = 0; a < spdyPairs.count(); ++a) { // emit error for all replies QHttpNetworkReply *currentReply = spdyPairs.at(a).second; Q_ASSERT(currentReply); emit currentReply->finishedWithError(errorCode, errorString); } } #endif // QT_NO_SSL // send the next request QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); if (that) //signal emission triggered event loop close(); }