Integrate network sockets into the multichannel infrastructure

Change-Id: I96974a7460c29b46cae8a28aadb3e50cdcdb7beb
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com>
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@theqtcompany.com>
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
bb10
Alex Trotsenko 2015-09-14 15:53:13 +03:00
parent e6b8d742a7
commit 4d0672ed42
17 changed files with 139 additions and 19 deletions

View File

@ -562,7 +562,6 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
socketEngine(0),
cachedSocketDescriptor(-1),
readBufferMaxSize(0),
writeBuffer(QABSTRACTSOCKET_BUFFERSIZE),
isBuffered(false),
connectTimer(0),
disconnectTimer(0),
@ -572,6 +571,7 @@ QAbstractSocketPrivate::QAbstractSocketPrivate()
socketError(QAbstractSocket::UnknownSocketError),
preferredNetworkLayerProtocol(QAbstractSocket::UnknownNetworkLayerProtocol)
{
writeBufferChunkSize = QABSTRACTSOCKET_BUFFERSIZE;
}
/*! \internal
@ -860,15 +860,16 @@ bool QAbstractSocketPrivate::writeToSocket()
written);
#endif
// Remove what we wrote so far.
writeBuffer.free(written);
if (written > 0) {
// Remove what we wrote so far.
writeBuffer.free(written);
// Don't emit bytesWritten() recursively.
if (!emittedBytesWritten) {
QScopedValueRollback<bool> r(emittedBytesWritten);
emittedBytesWritten = true;
emit q->bytesWritten(written);
}
emit q->channelBytesWritten(0, written);
}
if (writeBuffer.isEmpty() && socketEngine && socketEngine->isWriteNotificationEnabled()
@ -1295,6 +1296,7 @@ void QAbstractSocketPrivate::emitReadyRead()
emittedReadyRead = true;
emit q->readyRead();
}
emit q->channelReadyRead(0);
}
/*! \internal
@ -1307,6 +1309,18 @@ void QAbstractSocketPrivate::fetchConnectionParameters()
peerName = hostName;
if (socketEngine) {
if (q->isReadable()) {
const int inboundStreamCount = socketEngine->inboundStreamCount();
setReadChannelCount(qMax(1, inboundStreamCount));
if (inboundStreamCount == 0)
readChannelCount = 0;
}
if (q->isWritable()) {
const int outboundStreamCount = socketEngine->outboundStreamCount();
setWriteChannelCount(qMax(1, outboundStreamCount));
if (outboundStreamCount == 0)
writeChannelCount = 0;
}
socketEngine->setReadNotificationEnabled(true);
socketEngine->setWriteNotificationEnabled(true);
localPort = socketEngine->localPort();
@ -1629,8 +1643,8 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
d->preferredNetworkLayerProtocol = protocol;
d->hostName = hostName;
d->port = port;
d->buffer.clear();
d->writeBuffer.clear();
d->setReadChannelCount(0);
d->setWriteChannelCount(0);
d->abortCalled = false;
d->pendingClose = false;
if (d->state != BoundState) {
@ -1663,6 +1677,8 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port,
openMode |= QAbstractSocket::Unbuffered; // QUdpSocket
QIODevice::open(openMode);
d->readChannelCount = d->writeChannelCount = 0;
d->state = HostLookupState;
emit stateChanged(d->state);
@ -1725,11 +1741,11 @@ void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port,
*/
qint64 QAbstractSocket::bytesToWrite() const
{
Q_D(const QAbstractSocket);
const qint64 pendingBytes = QIODevice::bytesToWrite();
#if defined(QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::bytesToWrite() == %lld", d->writeBuffer.size());
qDebug("QAbstractSocket::bytesToWrite() == %lld", pendingBytes);
#endif
return d->writeBuffer.size();
return pendingBytes;
}
/*!
@ -1868,8 +1884,8 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState
Q_D(QAbstractSocket);
d->resetSocketLayer();
d->writeBuffer.clear();
d->buffer.clear();
d->setReadChannelCount(0);
d->setWriteChannelCount(0);
d->socketEngine = QAbstractSocketEngine::createSocketEngine(socketDescriptor, this);
if (!d->socketEngine) {
d->setError(UnsupportedSocketOperationError, tr("Operation on socket is not supported"));
@ -1890,6 +1906,23 @@ bool QAbstractSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState
QIODevice::open(openMode);
if (socketState == ConnectedState) {
if (isReadable()) {
const int inboundStreamCount = d->socketEngine->inboundStreamCount();
d->setReadChannelCount(qMax(1, inboundStreamCount));
if (inboundStreamCount == 0)
d->readChannelCount = 0;
}
if (isWritable()) {
const int outboundStreamCount = d->socketEngine->outboundStreamCount();
d->setWriteChannelCount(qMax(1, outboundStreamCount));
if (outboundStreamCount == 0)
d->writeChannelCount = 0;
}
} else {
d->readChannelCount = d->writeChannelCount = 0;
}
if (d->state != socketState) {
d->state = socketState;
emit stateChanged(d->state);
@ -2337,7 +2370,7 @@ void QAbstractSocket::abort()
#if defined (QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::abort()");
#endif
d->writeBuffer.clear();
d->setWriteChannelCount(0);
if (d->state == UnconnectedState)
return;
#ifndef QT_NO_SSL
@ -2489,8 +2522,10 @@ qint64 QAbstractSocket::writeData(const char *data, qint64 size)
qt_prettyDebug(data, qMin((int)size, 32), size).data(),
size, written);
#endif
if (written >= 0)
if (written >= 0) {
emit bytesWritten(written);
emit channelBytesWritten(0, written);
}
return written;
}
@ -2741,7 +2776,7 @@ void QAbstractSocket::disconnectFromHost()
d->peerPort = 0;
d->localAddress.clear();
d->peerAddress.clear();
d->writeBuffer.clear();
d->setWriteChannelCount(0);
#if defined(QABSTRACTSOCKET_DEBUG)
qDebug("QAbstractSocket::disconnectFromHost() disconnected!");

View File

@ -55,7 +55,6 @@
#include "QtCore/qbytearray.h"
#include "QtCore/qlist.h"
#include "QtCore/qtimer.h"
#include "private/qringbuffer_p.h"
#include "private/qiodevice_p.h"
#include "private/qabstractsocketengine_p.h"
#include "qnetworkproxy.h"
@ -144,8 +143,6 @@ public:
void setErrorAndEmit(QAbstractSocket::SocketError errorCode, const QString &errorString);
qint64 readBufferMaxSize;
QRingBuffer writeBuffer;
bool isBuffered;
QTimer *connectTimer;

View File

@ -83,6 +83,8 @@ QAbstractSocketEnginePrivate::QAbstractSocketEnginePrivate()
, socketProtocol(QAbstractSocket::UnknownNetworkLayerProtocol)
, localPort(0)
, peerPort(0)
, inboundStreamCount(0)
, outboundStreamCount(0)
, receiver(0)
{
}
@ -261,4 +263,14 @@ void QAbstractSocketEngine::setPeerPort(quint16 port)
d_func()->peerPort = port;
}
int QAbstractSocketEngine::inboundStreamCount() const
{
return d_func()->inboundStreamCount;
}
int QAbstractSocketEngine::outboundStreamCount() const
{
return d_func()->outboundStreamCount;
}
QT_END_NAMESPACE

View File

@ -174,6 +174,8 @@ public:
quint16 localPort() const;
QHostAddress peerAddress() const;
quint16 peerPort() const;
int inboundStreamCount() const;
int outboundStreamCount() const;
virtual bool isReadNotificationEnabled() const = 0;
virtual void setReadNotificationEnabled(bool enable) = 0;
@ -227,6 +229,8 @@ public:
quint16 localPort;
QHostAddress peerAddress;
quint16 peerPort;
int inboundStreamCount;
int outboundStreamCount;
QAbstractSocketEngineReceiver *receiver;
};

View File

@ -576,6 +576,7 @@ void QHttpSocketEngine::slotSocketReadNotification()
d->state = Connected;
setLocalAddress(d->socket->localAddress());
setLocalPort(d->socket->localPort());
d->inboundStreamCount = d->outboundStreamCount = 1;
setState(QAbstractSocket::ConnectedState);
d->authenticator.detach();
priv = QAuthenticatorPrivate::getPrivate(d->authenticator);

View File

@ -922,6 +922,7 @@ void QNativeSocketEngine::close()
d->localAddress.clear();
d->peerPort = 0;
d->peerAddress.clear();
d->inboundStreamCount = d->outboundStreamCount = 0;
if (d->readNotifier) {
qDeleteInEventHandler(d->readNotifier);
d->readNotifier = 0;

View File

@ -1027,6 +1027,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
localAddress.clear();
peerPort = 0;
peerAddress.clear();
inboundStreamCount = outboundStreamCount = 0;
if (socketDescriptor == -1)
return false;
@ -1077,8 +1078,10 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
#endif
// Determine the remote address
if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize))
if (!::getpeername(socketDescriptor, &sa.a, &sockAddrSize)) {
qt_socket_getPortAndAddress(&sa, &peerPort, &peerAddress);
inboundStreamCount = outboundStreamCount = 1;
}
// Determine the socket type (UDP/TCP)
int value = 0;
@ -1101,10 +1104,10 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
else if (socketType == QAbstractSocket::UdpSocket) socketTypeStr = QStringLiteral("UdpSocket");
qDebug("QNativeSocketEnginePrivate::fetchConnectionParameters() local == %s:%i,"
" peer == %s:%i, socket == %s - %s",
" peer == %s:%i, socket == %s - %s, inboundStreamCount == %i, outboundStreamCount == %i",
localAddress.toString().toLatin1().constData(), localPort,
peerAddress.toString().toLatin1().constData(), peerPort,socketTypeStr.toLatin1().constData(),
socketProtocolStr.toLatin1().constData());
socketProtocolStr.toLatin1().constData(), inboundStreamCount, outboundStreamCount);
#endif
return true;
}

View File

@ -528,6 +528,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
localAddress.clear();
peerPort = 0;
peerAddress.clear();
inboundStreamCount = outboundStreamCount = 0;
if (socketDescriptor == -1)
return false;
@ -576,6 +577,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
memset(&sa, 0, sizeof(sa));
if (::getpeername(socketDescriptor, &sa.a, &sockAddrSize) == 0) {
qt_socket_getPortAndAddress(socketDescriptor, &sa, &peerPort, &peerAddress);
inboundStreamCount = outboundStreamCount = 1;
} else {
WS_ERROR_DEBUG(WSAGetLastError());
}

View File

@ -480,6 +480,7 @@ void QNativeSocketEngine::close()
d->localAddress.clear();
d->peerPort = 0;
d->peerAddress.clear();
d->inboundStreamCount = d->outboundStreamCount = 0;
}
bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface)
@ -1082,6 +1083,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
localAddress.clear();
peerPort = 0;
peerAddress.clear();
inboundStreamCount = outboundStreamCount = 0;
HRESULT hr;
if (socketType == QAbstractSocket::TcpSocket) {
@ -1117,6 +1119,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
hr = info->get_RemotePort(tmpHString.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
peerPort = qt_QStringFromHString(tmpHString).toInt();
inboundStreamCount = outboundStreamCount = 1;
}
} else if (socketType == QAbstractSocket::UdpSocket) {
ComPtr<IHostName> hostName;
@ -1144,6 +1147,7 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
hr = info->get_RemotePort(tmpHString.GetAddressOf());
Q_ASSERT_SUCCEEDED(hr);
peerPort = qt_QStringFromHString(tmpHString).toInt();
inboundStreamCount = outboundStreamCount = 1;
}
}
return true;

View File

@ -887,6 +887,7 @@ void QSocks5SocketEnginePrivate::parseRequestMethodReply()
localPort = port;
if (mode == ConnectMode) {
inboundStreamCount = outboundStreamCount = 1;
socks5State = Connected;
// notify the upper layer that we're done
q->setState(QAbstractSocket::ConnectedState);
@ -1047,6 +1048,7 @@ bool QSocks5SocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::
d->localAddress = bindData->localAddress;
d->peerPort = bindData->peerPort;
d->peerAddress = bindData->peerAddress;
d->inboundStreamCount = d->outboundStreamCount = 1;
delete bindData;
QObject::connect(d->data->controlSocket, SIGNAL(connected()), this, SLOT(_q_controlSocketConnected()),
@ -1486,6 +1488,7 @@ void QSocks5SocketEngine::close()
}
d->data->controlSocket->close();
}
d->inboundStreamCount = d->outboundStreamCount = 0;
#ifndef QT_NO_UDPSOCKET
if (d->udpData && d->udpData->udpSocket)
d->udpData->udpSocket->close();

View File

@ -512,6 +512,8 @@ bool QSslSocket::setSocketDescriptor(qintptr socketDescriptor, SocketState state
setPeerPort(d->plainSocket->peerPort());
setPeerAddress(d->plainSocket->peerAddress());
setPeerName(d->plainSocket->peerName());
d->readChannelCount = d->plainSocket->readChannelCount();
d->writeChannelCount = d->plainSocket->writeChannelCount();
return retVal;
}
@ -1925,6 +1927,7 @@ void QSslSocket::connectToHost(const QString &hostName, quint16 port, OpenMode o
d->plainSocket->setProxy(proxy());
#endif
QIODevice::open(openMode);
d->readChannelCount = d->writeChannelCount = 0;
d->plainSocket->connectToHost(hostName, port, openMode, d->preferredNetworkLayerProtocol);
d->cachedSocketDescriptor = d->plainSocket->socketDescriptor();
}
@ -2271,9 +2274,15 @@ void QSslSocketPrivate::createPlainSocket(QIODevice::OpenMode openMode)
q->connect(plainSocket, SIGNAL(readyRead()),
q, SLOT(_q_readyReadSlot()),
Qt::DirectConnection);
q->connect(plainSocket, SIGNAL(channelReadyRead(int)),
q, SLOT(_q_channelReadyReadSlot(int)),
Qt::DirectConnection);
q->connect(plainSocket, SIGNAL(bytesWritten(qint64)),
q, SLOT(_q_bytesWrittenSlot(qint64)),
Qt::DirectConnection);
q->connect(plainSocket, SIGNAL(channelBytesWritten(int, qint64)),
q, SLOT(_q_channelBytesWrittenSlot(int, qint64)),
Qt::DirectConnection);
#ifndef QT_NO_NETWORKPROXY
q->connect(plainSocket, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
q, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
@ -2327,6 +2336,7 @@ bool QSslSocketPrivate::bind(const QHostAddress &address, quint16 port, QAbstrac
localPort = plainSocket->localPort();
localAddress = plainSocket->localAddress();
cachedSocketDescriptor = plainSocket->socketDescriptor();
readChannelCount = writeChannelCount = 0;
return ret;
}
@ -2342,6 +2352,8 @@ void QSslSocketPrivate::_q_connectedSlot()
q->setPeerAddress(plainSocket->peerAddress());
q->setPeerName(plainSocket->peerName());
cachedSocketDescriptor = plainSocket->socketDescriptor();
readChannelCount = plainSocket->readChannelCount();
writeChannelCount = plainSocket->writeChannelCount();
#ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl) << "QSslSocket::_q_connectedSlot()";
@ -2444,6 +2456,16 @@ void QSslSocketPrivate::_q_readyReadSlot()
transmit();
}
/*!
\internal
*/
void QSslSocketPrivate::_q_channelReadyReadSlot(int channel)
{
Q_Q(QSslSocket);
if (mode == QSslSocket::UnencryptedMode)
emit q->channelReadyRead(channel);
}
/*!
\internal
*/
@ -2462,6 +2484,16 @@ void QSslSocketPrivate::_q_bytesWrittenSlot(qint64 written)
q->disconnectFromHost();
}
/*!
\internal
*/
void QSslSocketPrivate::_q_channelBytesWrittenSlot(int channel, qint64 written)
{
Q_Q(QSslSocket);
if (mode == QSslSocket::UnencryptedMode)
emit q->channelBytesWritten(channel, written);
}
/*!
\internal
*/

View File

@ -220,7 +220,9 @@ private:
Q_PRIVATE_SLOT(d_func(), void _q_stateChangedSlot(QAbstractSocket::SocketState))
Q_PRIVATE_SLOT(d_func(), void _q_errorSlot(QAbstractSocket::SocketError))
Q_PRIVATE_SLOT(d_func(), void _q_readyReadSlot())
Q_PRIVATE_SLOT(d_func(), void _q_channelReadyReadSlot(int))
Q_PRIVATE_SLOT(d_func(), void _q_bytesWrittenSlot(qint64))
Q_PRIVATE_SLOT(d_func(), void _q_channelBytesWrittenSlot(int, qint64))
Q_PRIVATE_SLOT(d_func(), void _q_flushWriteBuffer())
Q_PRIVATE_SLOT(d_func(), void _q_flushReadBuffer())
Q_PRIVATE_SLOT(d_func(), void _q_resumeImplementation())

View File

@ -646,6 +646,7 @@ void QSslSocketBackendPrivate::transmit()
emit q->bytesWritten(totalBytesWritten);
emittedBytesWritten = false;
}
emit q->channelBytesWritten(0, totalBytesWritten);
}
}
@ -674,6 +675,7 @@ void QSslSocketBackendPrivate::transmit()
if (readyReadEmittedPointer)
*readyReadEmittedPointer = true;
emit q->readyRead();
emit q->channelReadyRead(0);
}
if (err == errSSLWouldBlock)

View File

@ -851,6 +851,7 @@ void QSslSocketBackendPrivate::transmit()
emit q->bytesWritten(totalBytesWritten);
emittedBytesWritten = false;
}
emit q->channelBytesWritten(0, totalBytesWritten);
}
}
@ -954,6 +955,7 @@ void QSslSocketBackendPrivate::transmit()
if (readyReadEmittedPointer)
*readyReadEmittedPointer = true;
emit q->readyRead();
emit q->channelReadyRead(0);
transmitting = true;
continue;
}

View File

@ -179,7 +179,9 @@ public:
void _q_stateChangedSlot(QAbstractSocket::SocketState);
void _q_errorSlot(QAbstractSocket::SocketError);
void _q_readyReadSlot();
void _q_channelReadyReadSlot(int);
void _q_bytesWrittenSlot(qint64);
void _q_channelBytesWrittenSlot(int, qint64);
void _q_flushWriteBuffer();
void _q_flushReadBuffer();
void _q_resumeImplementation();

View File

@ -306,6 +306,7 @@ void QSslSocketBackendPrivate::transmit()
emit q->bytesWritten(totalBytesWritten);
emittedBytesWritten = false;
}
emit q->channelBytesWritten(0, totalBytesWritten);
}
}
@ -323,6 +324,7 @@ void QSslSocketBackendPrivate::transmit()
if (readyReadEmittedPointer)
*readyReadEmittedPointer = true;
emit q->readyRead();
emit q->channelReadyRead(0);
}
if (pendingClose) {

View File

@ -478,6 +478,8 @@ void tst_QTcpSocket::constructing()
QCOMPARE(socket->localAddress(), QHostAddress());
QCOMPARE((int) socket->peerPort(), 0);
QCOMPARE(socket->peerAddress(), QHostAddress());
QCOMPARE(socket->readChannelCount(), 0);
QCOMPARE(socket->writeChannelCount(), 0);
QCOMPARE(socket->error(), QTcpSocket::UnknownSocketError);
QCOMPARE(socket->errorString(), QString("Unknown error"));
@ -594,6 +596,8 @@ void tst_QTcpSocket::bind()
} while (randomPort && attemptsLeft);
QCOMPARE(socket->state(), QAbstractSocket::BoundState);
QCOMPARE(socket->readChannelCount(), 0);
QCOMPARE(socket->writeChannelCount(), 0);
boundPort = socket->localPort();
if (port)
QCOMPARE(int(boundPort), port);
@ -729,6 +733,8 @@ void tst_QTcpSocket::setSocketDescriptor()
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->socketDescriptor(), (qintptr)sock);
QCOMPARE(socket->readChannelCount(), 1);
QCOMPARE(socket->writeChannelCount(), 1);
delete socket;
#ifdef Q_OS_WIN
delete dummy;
@ -764,6 +770,8 @@ void tst_QTcpSocket::blockingIMAP()
QVERIFY(socket->waitForConnected(10000));
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
QVERIFY(socket->isValid());
QCOMPARE(socket->readChannelCount(), 1);
QCOMPARE(socket->writeChannelCount(), 1);
// Read greeting
QVERIFY(socket->waitForReadyRead(5000));
@ -820,6 +828,8 @@ void tst_QTcpSocket::blockingIMAP()
// Check that it's closed
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
QCOMPARE(socket->readChannelCount(), 0);
QCOMPARE(socket->writeChannelCount(), 0);
delete socket;
}
@ -860,6 +870,8 @@ void tst_QTcpSocket::timeoutConnect()
QVERIFY(!socket->waitForConnected(1000)); //200ms is too short when using SOCKS proxy authentication
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
QCOMPARE(int(socket->error()), int(QTcpSocket::SocketTimeoutError));
QCOMPARE(socket->readChannelCount(), 0);
QCOMPARE(socket->writeChannelCount(), 0);
timer.start();
socket->connectToHost(address, 1357);
@ -906,6 +918,8 @@ void tst_QTcpSocket::nonBlockingIMAP()
}
QCOMPARE(socket->state(), QTcpSocket::ConnectedState);
QCOMPARE(socket->readChannelCount(), 1);
QCOMPARE(socket->writeChannelCount(), 1);
enterLoop(30);
if (timeout()) {
@ -971,6 +985,8 @@ void tst_QTcpSocket::nonBlockingIMAP()
// Check that it's closed
QCOMPARE(socket->state(), QTcpSocket::UnconnectedState);
QCOMPARE(socket->readChannelCount(), 0);
QCOMPARE(socket->writeChannelCount(), 0);
delete socket;
}