From df373516909d4dc0dfe8149f4cbff17c9c9bfe54 Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 4 Aug 2009 14:00:05 +0200 Subject: QHttpNetworkConnection: Moved channel slots to channel object Reviewed-by: Peter Hartmann --- src/network/access/qhttpnetworkconnection.cpp | 246 +-------------------- src/network/access/qhttpnetworkconnection_p.h | 30 +-- .../access/qhttpnetworkconnectionchannel.cpp | 214 ++++++++++++++++++ .../access/qhttpnetworkconnectionchannel_p.h | 25 +++ src/network/access/qhttpnetworkreply_p.h | 1 + 5 files changed, 249 insertions(+), 267 deletions(-) diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 75ab837..d73cd67 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -87,58 +87,11 @@ QHttpNetworkConnectionPrivate::~QHttpNetworkConnectionPrivate() delete []channels; } -void QHttpNetworkConnectionPrivate::connectSignals(QAbstractSocket *socket) -{ - Q_Q(QHttpNetworkConnection); - - QObject::connect(socket, SIGNAL(bytesWritten(qint64)), - q, SLOT(_q_bytesWritten(qint64)), - Qt::DirectConnection); - QObject::connect(socket, SIGNAL(connected()), - q, SLOT(_q_connected()), - Qt::DirectConnection); - QObject::connect(socket, SIGNAL(readyRead()), - q, SLOT(_q_readyRead()), - Qt::DirectConnection); - QObject::connect(socket, SIGNAL(disconnected()), - q, SLOT(_q_disconnected()), - Qt::DirectConnection); - QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), - q, SLOT(_q_error(QAbstractSocket::SocketError)), - Qt::DirectConnection); -#ifndef QT_NO_NETWORKPROXY - QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), - q, SLOT(_q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), - Qt::DirectConnection); -#endif - -#ifndef QT_NO_OPENSSL - QSslSocket *sslSocket = qobject_cast(socket); - if (sslSocket) { - // won't be a sslSocket if encrypt is false - QObject::connect(sslSocket, SIGNAL(encrypted()), - q, SLOT(_q_encrypted()), - Qt::DirectConnection); - QObject::connect(sslSocket, SIGNAL(sslErrors(const QList&)), - q, SLOT(_q_sslErrors(const QList&)), - Qt::DirectConnection); - } -#endif -} - void QHttpNetworkConnectionPrivate::init() { - for (int i = 0; i < channelCount; ++i) { -#ifndef QT_NO_OPENSSL - if (encrypt) - channels[i].socket = new QSslSocket; - else - channels[i].socket = new QTcpSocket; -#else - channels[i].socket = new QTcpSocket; -#endif - - connectSignals(channels[i].socket); + for (int i = 0; i < channelCount; i++) { + channels[i].setConnection(this->q_func()); + channels[i].init(); } } @@ -406,7 +359,7 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); if (uploadByteDevice) { // connect the signals so this function gets called again - QObject::connect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead())); + QObject::connect(uploadByteDevice, SIGNAL(readyRead()), &channels[i], SLOT(_q_uploadDataReadyRead())); channels[i].bytesTotal = channels[i].request.contentLength(); } else { @@ -485,7 +438,7 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) { QNonContiguousByteDevice* uploadByteDevice = channels[i].request.uploadByteDevice(); if (uploadByteDevice) { - QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), q, SLOT(_q_uploadDataReadyRead())); + QObject::disconnect(uploadByteDevice, SIGNAL(readyRead()), &channels[i], SLOT(_q_uploadDataReadyRead())); } // ensure we try to receive a reply in all cases, even if _q_readyRead_ hat not been called // this is needed if the sends an reply before we have finished sending the request. In that @@ -1004,11 +957,7 @@ void QHttpNetworkConnectionPrivate::unqueueAndSendRequest(QAbstractSocket *socke void QHttpNetworkConnectionPrivate::closeChannel(int channel) { - QAbstractSocket *socket = channels[channel].socket; - socket->blockSignals(true); - socket->close(); - socket->blockSignals(false); - channels[channel].state = QHttpNetworkConnectionChannel::IdleState; + channels[channel].close(); } void QHttpNetworkConnectionPrivate::resendCurrentRequest(QAbstractSocket *socket) @@ -1102,53 +1051,6 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) } -//private slots -void QHttpNetworkConnectionPrivate::_q_readyRead() -{ - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; // ### error - if (isSocketWaiting(socket) || isSocketReading(socket)) { - int i = indexOf(socket); - channels[i].state = QHttpNetworkConnectionChannel::ReadingState; - if (channels[i].reply) - receiveReply(socket, channels[i].reply); - } - // ### error -} - -void QHttpNetworkConnectionPrivate::_q_bytesWritten(qint64 bytes) -{ - Q_UNUSED(bytes); - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; // ### error - // bytes have been written to the socket. write even more of them :) - if (isSocketWriting(socket)) - sendRequest(socket); - // otherwise we do nothing -} - -void QHttpNetworkConnectionPrivate::_q_disconnected() -{ - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; // ### error - // read the available data before closing - int i = indexOf(socket); - if (isSocketWaiting(socket) || isSocketReading(socket)) { - channels[i].state = QHttpNetworkConnectionChannel::ReadingState; - if (channels[i].reply) - receiveReply(socket, channels[i].reply); - } else if (channels[i].state == QHttpNetworkConnectionChannel::IdleState && channels[i].resendCurrent) { - // re-sending request because the socket was in ClosingState - QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); - } - channels[i].state = QHttpNetworkConnectionChannel::IdleState; -} void QHttpNetworkConnectionPrivate::_q_startNextRequest() { @@ -1188,121 +1090,6 @@ void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests() } } -void QHttpNetworkConnectionPrivate::_q_connected() -{ - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; // ### error - - // improve performance since we get the request sent by the kernel ASAP - socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); - - int i = indexOf(socket); - // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! - //channels[i].reconnectAttempts = 2; - if (!channels[i].pendingEncrypt) { - channels[i].state = QHttpNetworkConnectionChannel::IdleState; - if (channels[i].reply) - sendRequest(socket); - else - closeChannel(i); - } -} - - -void QHttpNetworkConnectionPrivate::_q_error(QAbstractSocket::SocketError socketError) -{ - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; - bool send2Reply = false; - int i = indexOf(socket); - 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 (channels[i].state != QHttpNetworkConnectionChannel::IdleState && channels[i].state != QHttpNetworkConnectionChannel::ReadingState) { - if (channels[i].reconnectAttempts-- > 0) { - resendCurrentRequest(socket); - return; - } else { - send2Reply = true; - errorCode = QNetworkReply::RemoteHostClosedError; - } - } else { - return; - } - break; - case QAbstractSocket::SocketTimeoutError: - // try to reconnect/resend before sending an error. - if (channels[i].state == QHttpNetworkConnectionChannel::WritingState && (channels[i].reconnectAttempts-- > 0)) { - resendCurrentRequest(socket); - return; - } - send2Reply = true; - errorCode = QNetworkReply::TimeoutError; - break; - case QAbstractSocket::ProxyAuthenticationRequiredError: - errorCode = QNetworkReply::ProxyAuthenticationRequiredError; - break; - case QAbstractSocket::SslHandshakeFailedError: - errorCode = QNetworkReply::SslHandshakeFailedError; - break; - default: - // all other errors are treated as NetworkError - errorCode = QNetworkReply::UnknownNetworkError; - break; - } - QPointer that = q; - QString errorString = errorDetail(errorCode, socket); - if (send2Reply) { - if (channels[i].reply) { - channels[i].reply->d_func()->errorString = errorString; - // this error matters only to this reply - emit channels[i].reply->finishedWithError(errorCode, errorString); - } - // send the next request - QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); - } else { - // the failure affects all requests. - emit q->error(errorCode, errorString); - } - if (that) //signals make enter the event loop - closeChannel(i); -} - -#ifndef QT_NO_NETWORKPROXY -void QHttpNetworkConnectionPrivate::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) -{ - Q_Q(QHttpNetworkConnection); - emit q->proxyAuthenticationRequired(proxy, auth, q); -} -#endif - -void QHttpNetworkConnectionPrivate::_q_uploadDataReadyRead() -{ - Q_Q(QHttpNetworkConnection); - // upload data emitted readyRead() - // find out which channel it is for - QObject *sender = q->sender(); - - for (int i = 0; i < channelCount; ++i) { - if (sender == channels[i].request.uploadByteDevice()) { - sendRequest(channels[i].socket); - break; - } - } -} QHttpNetworkConnection::QHttpNetworkConnection(const QString &hostName, quint16 port, bool encrypt, QObject *parent) : QObject(*(new QHttpNetworkConnectionPrivate(hostName, port, encrypt)), parent) @@ -1397,27 +1184,6 @@ QNetworkProxy QHttpNetworkConnection::transparentProxy() const // SSL support below #ifndef QT_NO_OPENSSL -void QHttpNetworkConnectionPrivate::_q_encrypted() -{ - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; // ### error - int i = indexOf(socket); - channels[i].state = QHttpNetworkConnectionChannel::IdleState; - sendRequest(socket); -} - -void QHttpNetworkConnectionPrivate::_q_sslErrors(const QList &errors) -{ - Q_Q(QHttpNetworkConnection); - QAbstractSocket *socket = qobject_cast(q->sender()); - if (!socket) - return; - //QNetworkReply::NetworkError errorCode = QNetworkReply::ProtocolFailure; - emit q->sslErrors(errors); -} - QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNetworkReply &reply) const { if (!encrypt) diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index db6a140..48401d2 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -138,23 +138,10 @@ private: Q_DECLARE_PRIVATE(QHttpNetworkConnection) Q_DISABLE_COPY(QHttpNetworkConnection) friend class QHttpNetworkReply; + friend class QHttpNetworkConnectionChannel; - Q_PRIVATE_SLOT(d_func(), void _q_bytesWritten(qint64)) - Q_PRIVATE_SLOT(d_func(), void _q_readyRead()) - Q_PRIVATE_SLOT(d_func(), void _q_disconnected()) Q_PRIVATE_SLOT(d_func(), void _q_startNextRequest()) Q_PRIVATE_SLOT(d_func(), void _q_restartAuthPendingRequests()) - Q_PRIVATE_SLOT(d_func(), void _q_connected()) - Q_PRIVATE_SLOT(d_func(), void _q_error(QAbstractSocket::SocketError)) -#ifndef QT_NO_NETWORKPROXY - Q_PRIVATE_SLOT(d_func(), void _q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)) -#endif - Q_PRIVATE_SLOT(d_func(), void _q_uploadDataReadyRead()) - -#ifndef QT_NO_OPENSSL - Q_PRIVATE_SLOT(d_func(), void _q_encrypted()) - Q_PRIVATE_SLOT(d_func(), void _q_sslErrors(const QList&)) -#endif }; @@ -169,7 +156,6 @@ public: QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt); ~QHttpNetworkConnectionPrivate(); void init(); - void connectSignals(QAbstractSocket *socket); enum { ChunkSize = 4096 }; @@ -189,18 +175,8 @@ public: void copyCredentials(int fromChannel, QAuthenticator *auth, bool isProxy); // private slots - void _q_bytesWritten(qint64 bytes); // proceed sending - void _q_readyRead(); // pending data to read - void _q_disconnected(); // disconnected from host void _q_startNextRequest(); // send the next request from the queue void _q_restartAuthPendingRequests(); // send the currently blocked request - void _q_connected(); // start sending request - void _q_error(QAbstractSocket::SocketError); // error from socket -#ifndef QT_NO_NETWORKPROXY - void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy -#endif - - void _q_uploadDataReadyRead(); void createAuthorization(QAbstractSocket *socket, QHttpNetworkRequest &request); bool ensureConnection(QAbstractSocket *socket); @@ -237,8 +213,6 @@ public: inline bool expectContent(QHttpNetworkReply *reply); #ifndef QT_NO_OPENSSL - void _q_encrypted(); // start sending request (https) - void _q_sslErrors(const QList &errors); // ssl errors from the socket QSslConfiguration sslConfiguration(const QHttpNetworkReply &reply) const; #endif @@ -249,6 +223,8 @@ public: //The request queues QList highPriorityQueue; QList lowPriorityQueue; + + friend class QHttpNetworkConnectionChannel; }; diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index a04b530..6cd46fd 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -57,6 +57,220 @@ QT_BEGIN_NAMESPACE // TODO: Put channel specific stuff here so it does not polute qhttpnetworkconnection.cpp +void QHttpNetworkConnectionChannel::init() +{ +#ifndef QT_NO_OPENSSL + if (connection->d_func()->encrypt) + socket = new QSslSocket; + else + socket = new QTcpSocket; +#else + socket = new QTcpSocket; +#endif + + QObject::connect(socket, SIGNAL(bytesWritten(qint64)), + this, SLOT(_q_bytesWritten(qint64)), + Qt::DirectConnection); + QObject::connect(socket, SIGNAL(connected()), + this, SLOT(_q_connected()), + Qt::DirectConnection); + QObject::connect(socket, SIGNAL(readyRead()), + this, SLOT(_q_readyRead()), + Qt::DirectConnection); + QObject::connect(socket, SIGNAL(disconnected()), + this, SLOT(_q_disconnected()), + Qt::DirectConnection); + QObject::connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), + this, SLOT(_q_error(QAbstractSocket::SocketError)), + Qt::DirectConnection); +#ifndef QT_NO_NETWORKPROXY + QObject::connect(socket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), + this, SLOT(_q_proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), + Qt::DirectConnection); +#endif + +#ifndef QT_NO_OPENSSL + QSslSocket *sslSocket = qobject_cast(socket); + if (sslSocket) { + // won't be a sslSocket if encrypt is false + QObject::connect(sslSocket, SIGNAL(encrypted()), + this, SLOT(_q_encrypted()), + Qt::DirectConnection); + QObject::connect(sslSocket, SIGNAL(sslErrors(const QList&)), + this, SLOT(_q_sslErrors(const QList&)), + Qt::DirectConnection); + } +#endif +} + + +void QHttpNetworkConnectionChannel::close() +{ + socket->blockSignals(true); + socket->close(); + socket->blockSignals(false); + state = QHttpNetworkConnectionChannel::IdleState; +} + + +//private slots +void QHttpNetworkConnectionChannel::_q_readyRead() +{ + if (!socket) + return; // ### error + if (connection->d_func()->isSocketWaiting(socket) || connection->d_func()->isSocketReading(socket)) { + state = QHttpNetworkConnectionChannel::ReadingState; + if (reply) + connection->d_func()->receiveReply(socket, reply); + } + // ### error +} + +void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes) +{ + Q_UNUSED(bytes); + if (!socket) + return; // ### error + // bytes have been written to the socket. write even more of them :) + if (connection->d_func()->isSocketWriting(socket)) + connection->d_func()->sendRequest(socket); + // otherwise we do nothing +} + +void QHttpNetworkConnectionChannel::_q_disconnected() +{ + if (!socket) + return; // ### error + // read the available data before closing + if (connection->d_func()->isSocketWaiting(socket) || connection->d_func()->isSocketReading(socket)) { + state = QHttpNetworkConnectionChannel::ReadingState; + if (reply) + connection->d_func()->receiveReply(socket, reply); + } else if (state == QHttpNetworkConnectionChannel::IdleState && resendCurrent) { + // re-sending request because the socket was in ClosingState + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + } + state = QHttpNetworkConnectionChannel::IdleState; +} + + +void QHttpNetworkConnectionChannel::_q_connected() +{ + if (!socket) + return; // ### error + + // improve performance since we get the request sent by the kernel ASAP + socket->setSocketOption(QAbstractSocket::LowDelayOption, 1); + + // ### FIXME: if the server closes the connection unexpectedly, we shouldn't send the same broken request again! + //channels[i].reconnectAttempts = 2; + if (!pendingEncrypt) { + state = QHttpNetworkConnectionChannel::IdleState; + if (reply) + connection->d_func()->sendRequest(socket); + else + close(); + } +} + + +void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socketError) +{ + if (!socket) + return; + bool send2Reply = false; + 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) { + connection->d_func()->resendCurrentRequest(socket); + return; + } else { + send2Reply = true; + errorCode = QNetworkReply::RemoteHostClosedError; + } + } else { + return; + } + break; + case QAbstractSocket::SocketTimeoutError: + // try to reconnect/resend before sending an error. + if (state == QHttpNetworkConnectionChannel::WritingState && (reconnectAttempts-- > 0)) { + connection->d_func()->resendCurrentRequest(socket); + return; + } + send2Reply = true; + errorCode = QNetworkReply::TimeoutError; + break; + case QAbstractSocket::ProxyAuthenticationRequiredError: + errorCode = QNetworkReply::ProxyAuthenticationRequiredError; + break; + case QAbstractSocket::SslHandshakeFailedError: + errorCode = QNetworkReply::SslHandshakeFailedError; + break; + default: + // all other errors are treated as NetworkError + errorCode = QNetworkReply::UnknownNetworkError; + break; + } + QPointer that = connection; + QString errorString = connection->d_func()->errorDetail(errorCode, socket); + if (send2Reply) { + if (reply) { + reply->d_func()->errorString = errorString; + // this error matters only to this reply + emit reply->finishedWithError(errorCode, errorString); + } + // send the next request + QMetaObject::invokeMethod(that, "_q_startNextRequest", Qt::QueuedConnection); + } else { + // the failure affects all requests. + emit connection->error(errorCode, errorString); + } + if (that) //signal emission triggered event loop + close(); +} + +#ifndef QT_NO_NETWORKPROXY +void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) +{ + emit connection->proxyAuthenticationRequired(proxy, auth, connection); +} +#endif + +void QHttpNetworkConnectionChannel::_q_uploadDataReadyRead() +{ + connection->d_func()->sendRequest(socket); +} + +#ifndef QT_NO_OPENSSL +void QHttpNetworkConnectionChannel::_q_encrypted() +{ + if (!socket) + return; // ### error + state = QHttpNetworkConnectionChannel::IdleState; + connection->d_func()->sendRequest(socket); +} + +void QHttpNetworkConnectionChannel::_q_sslErrors(const QList &errors) +{ + if (!socket) + return; + //QNetworkReply::NetworkError errorCode = QNetworkReply::ProtocolFailure; + emit connection->sslErrors(errors); +} +#endif + QT_END_NAMESPACE #include "moc_qhttpnetworkconnectionchannel_p.cpp" diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index cbabc67..013e7a5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -80,6 +80,7 @@ QT_BEGIN_NAMESPACE class QHttpNetworkRequest; class QHttpNetworkReply; class QByteArray; +class QHttpNetworkConnection; class QHttpNetworkConnectionChannel : public QObject { Q_OBJECT @@ -117,7 +118,31 @@ public: #ifndef QT_NO_OPENSSL , ignoreAllSslErrors(false) #endif + , connection(0) {} + + void setConnection(QHttpNetworkConnection *c) {connection = c;} + QHttpNetworkConnection *connection; + + void init(); + void close(); + + protected slots: + void _q_bytesWritten(qint64 bytes); // proceed sending + void _q_readyRead(); // pending data to read + void _q_disconnected(); // disconnected from host + void _q_connected(); // start sending request + void _q_error(QAbstractSocket::SocketError); // error from socket +#ifndef QT_NO_NETWORKPROXY + void _q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth); // from transparent proxy +#endif + + void _q_uploadDataReadyRead(); + +#ifndef QT_NO_OPENSSL + void _q_encrypted(); // start sending request (https) + void _q_sslErrors(const QList &errors); // ssl errors from the socket +#endif }; diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index 575e824..a386b10 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -149,6 +149,7 @@ private: Q_DECLARE_PRIVATE(QHttpNetworkReply) friend class QHttpNetworkConnection; friend class QHttpNetworkConnectionPrivate; + friend class QHttpNetworkConnectionChannel; }; -- cgit v0.12