diff options
author | Kurt Pattyn <pattyn.kurt@gmail.com> | 2013-12-07 12:54:09 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-12-10 11:46:11 +0100 |
commit | 7d35f5c6b7b8b187388523674b4a95585f369d78 (patch) | |
tree | 9c56fc7bc7eddc0da37e0d144e054eef288eb1e2 /src/websockets | |
parent | 7c8d645c4759f7290fd31fe439abf0a99aac9161 (diff) | |
download | qtwebsockets-7d35f5c6b7b8b187388523674b4a95585f369d78.tar.gz |
Cleanup code to comply with Qt style
- Correct placement of curly braces
- Remove commented-out code
- Remove superfluous qDebug statements
- Add missing QT_BEGIN_NAMESPACE declarations
- Add move semantics
- Add cleanup handling to QWebSocketServerPrivate
- Add error handling to handshake response, QWebSocketServerPrivate,
QWebSocketServer, dataprocessor
Change-Id: I0690dc2c444fd6fc0db974d1459bf41bd8c31d40
Reviewed-by: Kurt Pattyn <pattyn.kurt@gmail.com>
Diffstat (limited to 'src/websockets')
-rw-r--r-- | src/websockets/qsslserver_p.cpp | 11 | ||||
-rw-r--r-- | src/websockets/qwebsocket.cpp | 4 | ||||
-rw-r--r-- | src/websockets/qwebsocket_p.cpp | 570 | ||||
-rw-r--r-- | src/websockets/qwebsocket_p.h | 7 | ||||
-rw-r--r-- | src/websockets/qwebsocketcorsauthenticator.cpp | 24 | ||||
-rw-r--r-- | src/websockets/qwebsocketcorsauthenticator.h | 10 | ||||
-rw-r--r-- | src/websockets/qwebsocketdataprocessor_p.cpp | 93 | ||||
-rw-r--r-- | src/websockets/qwebsocketframe_p.cpp | 213 | ||||
-rw-r--r-- | src/websockets/qwebsocketframe_p.h | 7 | ||||
-rw-r--r-- | src/websockets/qwebsockethandshakerequest_p.cpp | 195 | ||||
-rw-r--r-- | src/websockets/qwebsockethandshakeresponse_p.cpp | 80 | ||||
-rw-r--r-- | src/websockets/qwebsockethandshakeresponse_p.h | 5 | ||||
-rw-r--r-- | src/websockets/qwebsocketprotocol_p.cpp | 19 | ||||
-rw-r--r-- | src/websockets/qwebsocketserver.cpp | 21 | ||||
-rw-r--r-- | src/websockets/qwebsocketserver.h | 8 | ||||
-rw-r--r-- | src/websockets/qwebsocketserver_p.cpp | 124 | ||||
-rw-r--r-- | src/websockets/qwebsocketserver_p.h | 10 |
17 files changed, 659 insertions, 742 deletions
diff --git a/src/websockets/qsslserver_p.cpp b/src/websockets/qsslserver_p.cpp index 658243a..550c511 100644 --- a/src/websockets/qsslserver_p.cpp +++ b/src/websockets/qsslserver_p.cpp @@ -44,6 +44,8 @@ #include <QtNetwork/QSslSocket> #include <QtNetwork/QSslCipher> +QT_BEGIN_NAMESPACE + QSslServer::QSslServer(QObject *parent) : QTcpServer(parent), m_sslConfiguration(QSslConfiguration::defaultConfiguration()) @@ -70,8 +72,7 @@ void QSslServer::incomingConnection(qintptr socket) pSslSocket->setSslConfiguration(m_sslConfiguration); - if (pSslSocket->setSocketDescriptor(socket)) - { + if (pSslSocket->setSocketDescriptor(socket)) { connect(pSslSocket, SIGNAL(peerVerifyError(QSslError)), this, SIGNAL(peerVerifyError(QSslError))); connect(pSslSocket, SIGNAL(sslErrors(QList<QSslError>)), this, SIGNAL(sslErrors(QList<QSslError>))); connect(pSslSocket, SIGNAL(encrypted()), this, SIGNAL(newEncryptedConnection())); @@ -79,9 +80,9 @@ void QSslServer::incomingConnection(qintptr socket) addPendingConnection(pSslSocket); pSslSocket->startServerEncryption(); - } - else - { + } else { delete pSslSocket; } } + +QT_END_NAMESPACE diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp index 0d3b23d..d8378b4 100644 --- a/src/websockets/qwebsocket.cpp +++ b/src/websockets/qwebsocket.cpp @@ -368,10 +368,6 @@ void QWebSocket::open(const QUrl &url, bool mask) void QWebSocket::ping(const QByteArray &payload) { Q_D(QWebSocket); - if (payload.length() > 125) - { - payload.left(125); - } d->ping(payload); } diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index 9537f2a..d605617 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -145,16 +145,13 @@ QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol: */ QWebSocketPrivate::~QWebSocketPrivate() { - if (m_pSocket) - { - if (state() == QAbstractSocket::ConnectedState) - { - close(QWebSocketProtocol::CC_GOING_AWAY, tr("Connection closed")); - } - releaseConnections(m_pSocket.data()); -// m_pSocket->deleteLater(); -// m_pSocket = Q_NULLPTR; + if (!m_pSocket) { + return; + } + if (state() == QAbstractSocket::ConnectedState) { + close(QWebSocketProtocol::CC_GOING_AWAY, tr("Connection closed")); } + releaseConnections(m_pSocket.data()); } /*! @@ -162,8 +159,7 @@ QWebSocketPrivate::~QWebSocketPrivate() */ void QWebSocketPrivate::abort() { - if (m_pSocket) - { + if (m_pSocket) { m_pSocket->abort(); } } @@ -174,8 +170,7 @@ void QWebSocketPrivate::abort() QAbstractSocket::SocketError QWebSocketPrivate::error() const { QAbstractSocket::SocketError err = QAbstractSocket::OperationError; - if (m_pSocket) - { + if (m_pSocket) { err = m_pSocket->error(); } return err; @@ -187,12 +182,9 @@ QAbstractSocket::SocketError QWebSocketPrivate::error() const QString QWebSocketPrivate::errorString() const { QString errMsg; - if (!m_errorString.isEmpty()) - { + if (!m_errorString.isEmpty()) { errMsg = m_errorString; - } - else if (m_pSocket) - { + } else if (m_pSocket) { errMsg = m_pSocket->errorString(); } return errMsg; @@ -204,8 +196,7 @@ QString QWebSocketPrivate::errorString() const bool QWebSocketPrivate::flush() { bool result = true; - if (m_pSocket) - { + if (m_pSocket) { result = m_pSocket->flush(); } return result; @@ -216,7 +207,7 @@ bool QWebSocketPrivate::flush() */ qint64 QWebSocketPrivate::write(const char *message) { - //TODO: create a QByteArray from message, and directly call doWriteData + //TODO: create a QByteArray from message, and directly call doWriteFrames //now the data is converted to a string, and then converted back to a bytearray return write(QString::fromUtf8(message)); } @@ -226,7 +217,7 @@ qint64 QWebSocketPrivate::write(const char *message) */ qint64 QWebSocketPrivate::write(const char *message, qint64 maxSize) { - //TODO: create a QByteArray from message, and directly call doWriteData + //TODO: create a QByteArray from message, and directly call doWriteFrames //now the data is converted to a string, and then converted back to a bytearray return write(QString::fromUtf8(message, static_cast<int>(maxSize))); } @@ -236,7 +227,7 @@ qint64 QWebSocketPrivate::write(const char *message, qint64 maxSize) */ qint64 QWebSocketPrivate::write(const QString &message) { - return doWriteData(message.toUtf8(), false); + return doWriteFrames(message.toUtf8(), false); } /*! @@ -244,7 +235,7 @@ qint64 QWebSocketPrivate::write(const QString &message) */ qint64 QWebSocketPrivate::write(const QByteArray &data) { - return doWriteData(data, true); + return doWriteFrames(data, true); } #ifndef QT_NO_SSL @@ -278,11 +269,9 @@ void QWebSocketPrivate::ignoreSslErrors(const QList<QSslError> &errors) void QWebSocketPrivate::ignoreSslErrors() { m_configuration.m_ignoreSslErrors = true; - if (m_pSocket) - { + if (m_pSocket) { QSslSocket *pSslSocket = qobject_cast<QSslSocket *>(m_pSocket.data()); - if (pSslSocket) - { + if (pSslSocket) { pSslSocket->ignoreSslErrors(); } } @@ -316,38 +305,34 @@ QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket, */ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString reason) { - if (m_pSocket) - { - if (!m_isClosingHandshakeSent) - { - Q_Q(QWebSocket); - quint32 maskingKey = 0; - if (m_mustMask) - { - maskingKey = generateMaskingKey(); - } - const quint16 code = qToBigEndian<quint16>(closeCode); - QByteArray payload; - payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2); - if (!reason.isEmpty()) - { - payload.append(reason.toUtf8()); - } - if (m_mustMask) - { - QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey); - } - QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true); - frame.append(payload); - m_pSocket->write(frame); - m_pSocket->flush(); + if (!m_pSocket) { + return; + } + if (!m_isClosingHandshakeSent) { + Q_Q(QWebSocket); + quint32 maskingKey = 0; + if (m_mustMask) { + maskingKey = generateMaskingKey(); + } + const quint16 code = qToBigEndian<quint16>(closeCode); + QByteArray payload; + payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2); + if (!reason.isEmpty()) { + payload.append(reason.toUtf8()); + } + if (m_mustMask) { + QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey); + } + QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true); + frame.append(payload); + m_pSocket->write(frame); + m_pSocket->flush(); - m_isClosingHandshakeSent = true; + m_isClosingHandshakeSent = true; - Q_EMIT q->aboutToClose(); - } - m_pSocket->close(); + Q_EMIT q->aboutToClose(); } + m_pSocket->close(); } /*! @@ -357,14 +342,12 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) { //m_pSocket.reset(); //just delete the old socket for the moment; later, we can add more 'intelligent' handling by looking at the url QTcpSocket *pTcpSocket = m_pSocket.take(); - if (pTcpSocket) - { + if (pTcpSocket) { releaseConnections(pTcpSocket); pTcpSocket->deleteLater(); } //if (m_url != url) - if (!m_pSocket) - { + if (!m_pSocket) { Q_Q(QWebSocket); m_dataProcessor.clear(); @@ -373,33 +356,25 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) setRequestUrl(url); QString resourceName = url.path(); - if (!url.query().isEmpty()) - { - if (!resourceName.endsWith(QChar::fromLatin1('?'))) - { + if (!url.query().isEmpty()) { + if (!resourceName.endsWith(QChar::fromLatin1('?'))) { resourceName.append(QChar::fromLatin1('?')); } resourceName.append(url.query()); } - if (resourceName.isEmpty()) - { + if (resourceName.isEmpty()) { resourceName = QStringLiteral("/"); } setResourceName(resourceName); enableMasking(mask); #ifndef QT_NO_SSL - if (url.scheme() == QStringLiteral("wss")) - { - if (!QSslSocket::supportsSsl()) - { + if (url.scheme() == QStringLiteral("wss")) { + if (!QSslSocket::supportsSsl()) { const QString message = tr("SSL Sockets are not supported on this platform."); - qWarning() << message; setErrorString(message); emit q->error(QAbstractSocket::UnsupportedSocketOperationError); - } - else - { + } else { QSslSocket *sslSocket = new QSslSocket(this); m_pSocket.reset(sslSocket); @@ -408,12 +383,9 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) setSocketState(QAbstractSocket::ConnectingState); sslSocket->setSslConfiguration(m_configuration.m_sslConfiguration); - if (m_configuration.m_ignoreSslErrors) - { + if (m_configuration.m_ignoreSslErrors) { sslSocket->ignoreSslErrors(); - } - else - { + } else { sslSocket->ignoreSslErrors(m_configuration.m_ignoredSslErrors); } #ifndef QT_NO_NETWORKPROXY @@ -421,11 +393,9 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) #endif sslSocket->connectToHostEncrypted(url.host(), url.port(443)); } - } - else + } else #endif - if (url.scheme() == QStringLiteral("ws")) - { + if (url.scheme() == QStringLiteral("ws")) { m_pSocket.reset(new QTcpSocket(this)); makeConnections(m_pSocket.data()); @@ -435,11 +405,8 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) m_pSocket->setProxy(m_configuration.m_proxy); #endif m_pSocket->connectToHost(url.host(), url.port(80)); - } - else - { + } else { const QString message = tr("Unsupported websockets scheme: %1").arg(url.scheme()); - qWarning() << message; setErrorString(message); emit q->error(QAbstractSocket::UnsupportedSocketOperationError); } @@ -449,9 +416,11 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) /*! \internal */ -void QWebSocketPrivate::ping(const QByteArray &payload) +void QWebSocketPrivate::ping(QByteArray payload) { - Q_ASSERT(payload.length() < 126); + if (payload.length() > 125) { + payload.truncate(125); + } m_pingTimer.restart(); QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, payload.size(), 0 /*do not mask*/, true); pingFrame.append(payload); @@ -464,7 +433,9 @@ void QWebSocketPrivate::ping(const QByteArray &payload) */ void QWebSocketPrivate::setVersion(QWebSocketProtocol::Version version) { - m_version = version; + if (m_version != version) { + m_version = version; + } } /*! @@ -473,7 +444,9 @@ void QWebSocketPrivate::setVersion(QWebSocketProtocol::Version version) */ void QWebSocketPrivate::setResourceName(const QString &resourceName) { - m_resourceName = resourceName; + if (m_resourceName != resourceName) { + m_resourceName = resourceName; + } } /*! @@ -481,7 +454,9 @@ void QWebSocketPrivate::setResourceName(const QString &resourceName) */ void QWebSocketPrivate::setRequestUrl(const QUrl &requestUrl) { - m_requestUrl = requestUrl; + if (m_requestUrl != requestUrl) { + m_requestUrl = requestUrl; + } } /*! @@ -489,7 +464,9 @@ void QWebSocketPrivate::setRequestUrl(const QUrl &requestUrl) */ void QWebSocketPrivate::setOrigin(const QString &origin) { - m_origin = origin; + if (m_origin != origin) { + m_origin = origin; + } } /*! @@ -497,7 +474,9 @@ void QWebSocketPrivate::setOrigin(const QString &origin) */ void QWebSocketPrivate::setProtocol(const QString &protocol) { - m_protocol = protocol; + if (m_protocol != protocol) { + m_protocol = protocol; + } } /*! @@ -505,7 +484,9 @@ void QWebSocketPrivate::setProtocol(const QString &protocol) */ void QWebSocketPrivate::setExtension(const QString &extension) { - m_extension = extension; + if (m_extension != extension) { + m_extension = extension; + } } /*! @@ -513,15 +494,9 @@ void QWebSocketPrivate::setExtension(const QString &extension) */ void QWebSocketPrivate::enableMasking(bool enable) { - m_mustMask = enable; -} - -/*! - * \internal - */ -qint64 QWebSocketPrivate::doWriteData(const QByteArray &data, bool isBinary) -{ - return doWriteFrames(data, isBinary); + if (m_mustMask != enable) { + m_mustMask = enable; + } } /*! @@ -532,17 +507,18 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket) Q_ASSERT(pTcpSocket); Q_Q(QWebSocket); - //pass through signals - connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q, SIGNAL(error(QAbstractSocket::SocketError))); - connect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); - connect(pTcpSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished())); - connect(pTcpSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose())); - //connect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); - - //catch signals - connect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState))); - //!!!important to use a QueuedConnection here; with QTcpSocket there is no problem, but with QSslSocket the processing hangs - connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()), Qt::QueuedConnection); + if (pTcpSocket) { + //pass through signals + connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q, SIGNAL(error(QAbstractSocket::SocketError))); + connect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); + connect(pTcpSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished())); + connect(pTcpSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose())); + + //catch signals + connect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState))); + //!!!important to use a QueuedConnection here; with QTcpSocket there is no problem, but with QSslSocket the processing hangs + connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()), Qt::QueuedConnection); + } connect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q, SIGNAL(textFrameReceived(QString,bool))); connect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q, SIGNAL(binaryFrameReceived(QByteArray,bool))); @@ -559,28 +535,10 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket) */ void QWebSocketPrivate::releaseConnections(const QTcpSocket *pTcpSocket) { - Q_Q(QWebSocket); - if (pTcpSocket) - { - //pass through signals - disconnect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q, SIGNAL(error(QAbstractSocket::SocketError))); - disconnect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *))); - disconnect(pTcpSocket, SIGNAL(readChannelFinished()), q, SIGNAL(readChannelFinished())); - disconnect(pTcpSocket, SIGNAL(aboutToClose()), q, SIGNAL(aboutToClose())); - //disconnect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); - - //catched signals - disconnect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState))); - disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData())); + if (pTcpSocket) { + disconnect(pTcpSocket); } - disconnect(&m_dataProcessor, SIGNAL(pingReceived(QByteArray)), this, SLOT(processPing(QByteArray))); - disconnect(&m_dataProcessor, SIGNAL(pongReceived(QByteArray)), this, SLOT(processPong(QByteArray))); - disconnect(&m_dataProcessor, SIGNAL(closeReceived(QWebSocketProtocol::CloseCode,QString)), this, SLOT(processClose(QWebSocketProtocol::CloseCode,QString))); - disconnect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q, SIGNAL(textFrameReceived(QString,bool))); - disconnect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q, SIGNAL(binaryFrameReceived(QByteArray,bool))); - disconnect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q, SIGNAL(binaryMessageReceived(QByteArray))); - disconnect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q, SIGNAL(textMessageReceived(QString))); - disconnect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString))); + disconnect(&m_dataProcessor); } /*! @@ -650,58 +608,44 @@ QString QWebSocketPrivate::closeReason() const /*! * \internal */ -QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const +QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) { QByteArray header; quint8 byte = 0x00; bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL; - if (ok) - { + if (ok) { //FIN, RSV1-3, opcode byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00)); //FIN, opcode //RSV-1, RSV-2 and RSV-3 are zero header.append(static_cast<char>(byte)); - //Now write the masking bit and the payload length byte byte = 0x00; - if (maskingKey != 0) - { + if (maskingKey != 0) { byte |= 0x80; } - if (payloadLength <= 125) - { + if (payloadLength <= 125) { byte |= static_cast<quint8>(payloadLength); header.append(static_cast<char>(byte)); - } - else if (payloadLength <= 0xFFFFU) - { + } else if (payloadLength <= 0xFFFFU) { byte |= 126; header.append(static_cast<char>(byte)); quint16 swapped = qToBigEndian<quint16>(static_cast<quint16>(payloadLength)); header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 2); - } - else if (payloadLength <= 0x7FFFFFFFFFFFFFFFULL) - { + } else if (payloadLength <= 0x7FFFFFFFFFFFFFFFULL) { byte |= 127; header.append(static_cast<char>(byte)); quint64 swapped = qToBigEndian<quint64>(payloadLength); header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 8); } - //Write mask - if (maskingKey != 0) - { - //TODO: to big endian? + if (maskingKey != 0) { const quint32 mask = qToBigEndian<quint32>(maskingKey); header.append(static_cast<const char *>(static_cast<const void *>(&mask)), sizeof(quint32)); } - } - else - { - //setErrorString("WebSocket::getHeader: payload too big!"); - //Q_EMIT q_ptr->error(QAbstractSocket::DatagramTooLargeError); - qDebug() << "WebSocket::getHeader: payload too big!"; + } else { + setErrorString(QStringLiteral("WebSocket::getHeader: payload too big!")); + Q_EMIT q_ptr->error(QAbstractSocket::DatagramTooLargeError); } return header; @@ -713,77 +657,69 @@ QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary) { qint64 payloadWritten = 0; - if (m_pSocket) - { - Q_Q(QWebSocket); - const QWebSocketProtocol::OpCode firstOpCode = isBinary ? QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT; - - int numFrames = data.size() / FRAME_SIZE_IN_BYTES; - QByteArray tmpData(data); - tmpData.detach(); - char *payload = tmpData.data(); - quint64 sizeLeft = static_cast<quint64>(data.size()) % FRAME_SIZE_IN_BYTES; - if (sizeLeft) - { - ++numFrames; - } - if (numFrames == 0) //catch the case where the payload is zero bytes; in that case, we still need to send a frame - { - numFrames = 1; + if (!m_pSocket) { + return payloadWritten; + } + Q_Q(QWebSocket); + const QWebSocketProtocol::OpCode firstOpCode = isBinary ? + QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT; + + int numFrames = data.size() / FRAME_SIZE_IN_BYTES; + QByteArray tmpData(data); + //TODO: really necessary? + tmpData.detach(); + char *payload = tmpData.data(); + quint64 sizeLeft = quint64(data.size()) % FRAME_SIZE_IN_BYTES; + if (sizeLeft) { + ++numFrames; + } + //catch the case where the payload is zero bytes; + //in this case, we still need to send a frame + if (numFrames == 0) { + numFrames = 1; + } + quint64 currentPosition = 0; + qint64 bytesWritten = 0; + quint64 bytesLeft = data.size(); + + for (int i = 0; i < numFrames; ++i) { + quint32 maskingKey = 0; + if (m_mustMask) { + maskingKey = generateMaskingKey(); } - quint64 currentPosition = 0; - qint64 bytesWritten = 0; - quint64 bytesLeft = data.size(); - - for (int i = 0; i < numFrames; ++i) - { - quint32 maskingKey = 0; - if (m_mustMask) - { - maskingKey = generateMaskingKey(); - } - const bool isLastFrame = (i == (numFrames - 1)); - const bool isFirstFrame = (i == 0); + const bool isLastFrame = (i == (numFrames - 1)); + const bool isFirstFrame = (i == 0); - const quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES); - const QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE; + const quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES); + const QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE; - //write header - bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame)); + //write header + bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame)); - //write payload - if (size > 0) - { - char *currentData = payload + currentPosition; - if (m_mustMask) - { - QWebSocketProtocol::mask(currentData, size, maskingKey); - } - qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size)); - if (written > 0) - { - bytesWritten += written; - payloadWritten += written; - } - else - { - setErrorString(tr("Error writing bytes to socket: %1.").arg(m_pSocket->errorString())); - qDebug() << errorString(); - m_pSocket->flush(); - Q_EMIT q->error(QAbstractSocket::NetworkError); - break; - } + //write payload + if (size > 0) { + char *currentData = payload + currentPosition; + if (m_mustMask) { + QWebSocketProtocol::mask(currentData, size, maskingKey); + } + qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size)); + if (written > 0) { + bytesWritten += written; + payloadWritten += written; + } else { + m_pSocket->flush(); + setErrorString(tr("Error writing bytes to socket: %1.").arg(m_pSocket->errorString())); + Q_EMIT q->error(QAbstractSocket::NetworkError); + break; } - currentPosition += size; - bytesLeft -= size; - } - if (payloadWritten != data.size()) - { - setErrorString(tr("Bytes written %1 != %2.").arg(payloadWritten).arg(data.size())); - qDebug() << errorString(); - Q_EMIT q->error(QAbstractSocket::NetworkError); } + currentPosition += size; + bytesLeft -= size; + } + if (payloadWritten != data.size()) { + setErrorString(tr("Bytes written %1 != %2.").arg(payloadWritten).arg(data.size())); + Q_EMIT q->error(QAbstractSocket::NetworkError); } return payloadWritten; } @@ -793,7 +729,7 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary) */ quint32 QWebSocketPrivate::generateRandomNumber() const { - return static_cast<quint32>((static_cast<double>(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max()); + return quint32((double(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max()); } /*! @@ -811,9 +747,8 @@ QByteArray QWebSocketPrivate::generateKey() const { QByteArray key; - for (int i = 0; i < 4; ++i) - { - quint32 tmp = generateRandomNumber(); + for (int i = 0; i < 4; ++i) { + const quint32 tmp = generateRandomNumber(); key.append(static_cast<const char *>(static_cast<const void *>(&tmp)), sizeof(quint32)); } @@ -837,11 +772,10 @@ QString QWebSocketPrivate::calculateAcceptKey(const QString &key) const qint64 QWebSocketPrivate::writeFrames(const QList<QByteArray> &frames) { qint64 written = 0; - if (m_pSocket) - { - for (int i = 0; i < frames.size(); ++i) - { - written += writeFrame(frames[i]); + if (m_pSocket) { + QList<QByteArray>::const_iterator it; + for (it = frames.cbegin(); it < frames.cend(); ++it) { + written += writeFrame(*it); } } return written; @@ -853,8 +787,7 @@ qint64 QWebSocketPrivate::writeFrames(const QList<QByteArray> &frames) qint64 QWebSocketPrivate::writeFrame(const QByteArray &frame) { qint64 written = 0; - if (m_pSocket) - { + if (m_pSocket) { written = m_pSocket->write(frame); } return written; @@ -867,18 +800,13 @@ QString readLine(QTcpSocket *pSocket) { Q_ASSERT(pSocket); QString line; - if (pSocket) - { + if (pSocket) { char c; - while (pSocket->getChar(&c)) - { - if (c == '\r') - { + while (pSocket->getChar(&c)) { + if (c == char('\r')) { pSocket->getChar(&c); break; - } - else - { + } else { line.append(QChar::fromLatin1(c)); } } @@ -893,8 +821,7 @@ QString readLine(QTcpSocket *pSocket) void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket) { Q_Q(QWebSocket); - if (!pSocket) - { + if (!pSocket) { return; } @@ -908,28 +835,22 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket) int httpStatusCode; QString httpStatusMessage; const QRegularExpressionMatch match = regExp.match(statusLine); - if (match.hasMatch()) - { + if (match.hasMatch()) { QStringList tokens = match.capturedTexts(); tokens.removeFirst(); //remove the search string - if (tokens.length() == 3) - { + if (tokens.length() == 3) { httpProtocol = tokens[0]; httpStatusCode = tokens[1].toInt(); httpStatusMessage = tokens[2].trimmed(); ok = true; } } - if (!ok) - { + if (!ok) { errorDescription = tr("Invalid statusline in response: %1.").arg(statusLine); - } - else - { + } else { QString headerLine = readLine(pSocket); QMap<QString, QString> headers; - while (!headerLine.isEmpty()) - { + while (!headerLine.isEmpty()) { const QStringList headerField = headerLine.split(QStringLiteral(": "), QString::SkipEmptyParts); headers.insertMulti(headerField[0], headerField[1]); headerLine = readLine(pSocket); @@ -943,8 +864,8 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket) //const QString protocol = headers.value(QStringLiteral("Sec-WebSocket-Protocol"), QStringLiteral("")); const QString version = headers.value(QStringLiteral("Sec-WebSocket-Version"), QStringLiteral("")); - if (httpStatusCode == 101) //HTTP/x.y 101 Switching Protocols - { + if (httpStatusCode == 101) { + //HTTP/x.y 101 Switching Protocols bool conversionOk = false; const float version = httpProtocol.midRef(5).toFloat(&conversionOk); //TODO: do not check the httpStatusText right now @@ -952,54 +873,39 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket) (!conversionOk || (version < 1.1f)) || (upgrade.toLower() != QStringLiteral("websocket")) || (connection.toLower() != QStringLiteral("upgrade"))); - if (ok) - { + if (ok) { const QString accept = calculateAcceptKey(QString::fromLatin1(m_key)); ok = (accept == acceptKey); - if (!ok) - { + if (!ok) { errorDescription = tr("Accept-Key received from server %1 does not match the client key %2.").arg(acceptKey).arg(accept); } - } - else - { + } else { errorDescription = tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.").arg(statusLine); } - } - else if (httpStatusCode == 400) //HTTP/1.1 400 Bad Request - { - if (!version.isEmpty()) - { + } else if (httpStatusCode == 400) { + //HTTP/1.1 400 Bad Request + if (!version.isEmpty()) { const QStringList versions = version.split(QStringLiteral(", "), QString::SkipEmptyParts); - if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion()))) - { + if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion()))) { //if needed to switch protocol version, then we are finished here //because we cannot handle other protocols than the RFC one (v13) errorDescription = tr("Handshake: Server requests a version that we don't support: %1.").arg(versions.join(QStringLiteral(", "))); ok = false; - } - else - { + } else { //we tried v13, but something different went wrong errorDescription = tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection."); ok = false; } } - } - else - { + } else { errorDescription = tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).").arg(httpStatusCode).arg(httpStatusMessage); ok = false; } - if (!ok) - { - qDebug() << errorDescription; + if (!ok) { setErrorString(errorDescription); Q_EMIT q->error(QAbstractSocket::ConnectionRefusedError); - } - else - { + } else { //handshake succeeded setSocketState(QAbstractSocket::ConnectedState); Q_EMIT q->connected(); @@ -1019,26 +925,23 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS { case QAbstractSocket::ConnectedState: { - if (webSocketState == QAbstractSocket::ConnectingState) - { + if (webSocketState == QAbstractSocket::ConnectingState) { m_key = generateKey(); - QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() % QStringLiteral(":") % QString::number(m_requestUrl.port(80)), origin(), QStringLiteral(""), QStringLiteral(""), m_key); + const QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() % QStringLiteral(":") % QString::number(m_requestUrl.port(80)), origin(), QStringLiteral(""), QStringLiteral(""), m_key); m_pSocket->write(handshake.toLatin1()); } break; } case QAbstractSocket::ClosingState: { - if (webSocketState == QAbstractSocket::ConnectedState) - { + if (webSocketState == QAbstractSocket::ConnectedState) { setSocketState(QAbstractSocket::ClosingState); } break; } case QAbstractSocket::UnconnectedState: { - if (webSocketState != QAbstractSocket::UnconnectedState) - { + if (webSocketState != QAbstractSocket::UnconnectedState) { setSocketState(QAbstractSocket::UnconnectedState); Q_EMIT q->disconnected(); } @@ -1075,14 +978,10 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS void QWebSocketPrivate::processData() { Q_ASSERT(m_pSocket); - while (m_pSocket->bytesAvailable()) - { - if (state() == QAbstractSocket::ConnectingState) - { + while (m_pSocket->bytesAvailable()) { + if (state() == QAbstractSocket::ConnectingState) { processHandshake(m_pSocket.data()); - } - else - { + } else { m_dataProcessor.process(m_pSocket.data()); } } @@ -1095,15 +994,12 @@ void QWebSocketPrivate::processPing(QByteArray data) { Q_ASSERT(m_pSocket); quint32 maskingKey = 0; - if (m_mustMask) - { + if (m_mustMask) { maskingKey = generateMaskingKey(); } m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, data.size(), maskingKey, true)); - if (data.size() > 0) - { - if (m_mustMask) - { + if (data.size() > 0) { + if (m_mustMask) { QWebSocketProtocol::mask(&data, maskingKey); } m_pSocket->write(data); @@ -1145,17 +1041,14 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName, QStringLiteral("Upgrade: websocket") << QStringLiteral("Connection: Upgrade") << QStringLiteral("Sec-WebSocket-Key: ") % QString::fromLatin1(key); - if (!origin.isEmpty()) - { + if (!origin.isEmpty()) { handshakeRequest << QStringLiteral("Origin: ") % origin; } handshakeRequest << QStringLiteral("Sec-WebSocket-Version: ") % QString::number(QWebSocketProtocol::currentVersion()); - if (extensions.length() > 0) - { + if (extensions.length() > 0) { handshakeRequest << QStringLiteral("Sec-WebSocket-Extensions: ") % extensions; } - if (protocols.length() > 0) - { + if (protocols.length() > 0) { handshakeRequest << QStringLiteral("Sec-WebSocket-Protocol: ") % protocols; } handshakeRequest << QStringLiteral("\r\n"); @@ -1177,8 +1070,7 @@ QAbstractSocket::SocketState QWebSocketPrivate::state() const bool QWebSocketPrivate::waitForConnected(int msecs) { bool result = false; - if (m_pSocket) - { + if (m_pSocket) { result = m_pSocket->waitForConnected(msecs); } return result; @@ -1190,8 +1082,7 @@ bool QWebSocketPrivate::waitForConnected(int msecs) bool QWebSocketPrivate::waitForDisconnected(int msecs) { bool result = false; - if (m_pSocket) - { + if (m_pSocket) { result = m_pSocket->waitForDisconnected(msecs); } return result; @@ -1203,8 +1094,7 @@ bool QWebSocketPrivate::waitForDisconnected(int msecs) void QWebSocketPrivate::setSocketState(QAbstractSocket::SocketState state) { Q_Q(QWebSocket); - if (m_socketState != state) - { + if (m_socketState != state) { m_socketState = state; Q_EMIT q->stateChanged(m_socketState); } @@ -1215,7 +1105,9 @@ void QWebSocketPrivate::setSocketState(QAbstractSocket::SocketState state) */ void QWebSocketPrivate::setErrorString(const QString &errorString) { - m_errorString = errorString; + if (m_errorString != errorString) { + m_errorString = errorString; + } } /*! @@ -1224,8 +1116,7 @@ void QWebSocketPrivate::setErrorString(const QString &errorString) QHostAddress QWebSocketPrivate::localAddress() const { QHostAddress address; - if (m_pSocket) - { + if (m_pSocket) { address = m_pSocket->localAddress(); } return address; @@ -1237,8 +1128,7 @@ QHostAddress QWebSocketPrivate::localAddress() const quint16 QWebSocketPrivate::localPort() const { quint16 port = 0; - if (m_pSocket) - { + if (m_pSocket) { port = m_pSocket->localPort(); } return port; @@ -1250,8 +1140,7 @@ quint16 QWebSocketPrivate::localPort() const QAbstractSocket::PauseModes QWebSocketPrivate::pauseMode() const { QAbstractSocket::PauseModes mode = QAbstractSocket::PauseNever; - if (m_pSocket) - { + if (m_pSocket) { mode = m_pSocket->pauseMode(); } return mode; @@ -1263,8 +1152,7 @@ QAbstractSocket::PauseModes QWebSocketPrivate::pauseMode() const QHostAddress QWebSocketPrivate::peerAddress() const { QHostAddress address; - if (m_pSocket) - { + if (m_pSocket) { address = m_pSocket->peerAddress(); } return address; @@ -1276,8 +1164,7 @@ QHostAddress QWebSocketPrivate::peerAddress() const QString QWebSocketPrivate::peerName() const { QString name; - if (m_pSocket) - { + if (m_pSocket) { name = m_pSocket->peerName(); } return name; @@ -1289,8 +1176,7 @@ QString QWebSocketPrivate::peerName() const quint16 QWebSocketPrivate::peerPort() const { quint16 port = 0; - if (m_pSocket) - { + if (m_pSocket) { port = m_pSocket->peerPort(); } return port; @@ -1310,7 +1196,9 @@ QNetworkProxy QWebSocketPrivate::proxy() const */ void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy) { - m_configuration.m_proxy = networkProxy; + if (networkProxy != networkProxy) { + m_configuration.m_proxy = networkProxy; + } } #endif //QT_NO_NETWORKPROXY @@ -1320,8 +1208,7 @@ void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy) qint64 QWebSocketPrivate::readBufferSize() const { qint64 size = 0; - if (m_pSocket) - { + if (m_pSocket) { size = m_pSocket->readBufferSize(); } return size; @@ -1332,8 +1219,7 @@ qint64 QWebSocketPrivate::readBufferSize() const */ void QWebSocketPrivate::resume() { - if (m_pSocket) - { + if (m_pSocket) { m_pSocket->resume(); } } @@ -1343,8 +1229,7 @@ void QWebSocketPrivate::resume() */ void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode) { - if (m_pSocket) - { + if (m_pSocket) { m_pSocket->setPauseMode(pauseMode); } } @@ -1354,8 +1239,7 @@ void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode) */ void QWebSocketPrivate::setReadBufferSize(qint64 size) { - if (m_pSocket) - { + if (m_pSocket) { m_pSocket->setReadBufferSize(size); } } @@ -1365,8 +1249,7 @@ void QWebSocketPrivate::setReadBufferSize(qint64 size) */ void QWebSocketPrivate::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value) { - if (m_pSocket) - { + if (m_pSocket) { m_pSocket->setSocketOption(option, value); } } @@ -1377,8 +1260,7 @@ void QWebSocketPrivate::setSocketOption(QAbstractSocket::SocketOption option, co QVariant QWebSocketPrivate::socketOption(QAbstractSocket::SocketOption option) { QVariant val; - if (m_pSocket) - { + if (m_pSocket) { val = m_pSocket->socketOption(option); } return val; diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index 9fd686b..e21c274 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -77,6 +77,8 @@ class QWebSocket; struct QWebSocketConfiguration { + Q_DISABLE_COPY(QWebSocketConfiguration) + public: QWebSocketConfiguration(); @@ -154,7 +156,7 @@ public: public Q_SLOTS: void close(QWebSocketProtocol::CloseCode closeCode, QString reason); void open(const QUrl &url, bool mask); - void ping(const QByteArray &payload); + void ping(QByteArray payload); #ifndef QT_NO_SSL void ignoreSslErrors(); @@ -182,13 +184,12 @@ private: void setSocketState(QAbstractSocket::SocketState state); void setErrorString(const QString &errorString); - qint64 doWriteData(const QByteArray &data, bool isBinary); qint64 doWriteFrames(const QByteArray &data, bool isBinary); void makeConnections(const QTcpSocket *pTcpSocket); void releaseConnections(const QTcpSocket *pTcpSocket); - QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const; + QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame); QString calculateAcceptKey(const QString &key) const; QString createHandShakeRequest(QString resourceName, QString host, diff --git a/src/websockets/qwebsocketcorsauthenticator.cpp b/src/websockets/qwebsocketcorsauthenticator.cpp index c2117c6..f43447f 100644 --- a/src/websockets/qwebsocketcorsauthenticator.cpp +++ b/src/websockets/qwebsocketcorsauthenticator.cpp @@ -93,10 +93,6 @@ QWebSocketCorsAuthenticator::QWebSocketCorsAuthenticator(const QString &origin) */ QWebSocketCorsAuthenticator::~QWebSocketCorsAuthenticator() { - if (d_ptr) - { - delete d_ptr; - } } /*! @@ -121,6 +117,26 @@ QWebSocketCorsAuthenticator &QWebSocketCorsAuthenticator::operator =(const QWebS return *this; } +#ifdef Q_COMPILER_RVALUE_REFS +QWebSocketCorsAuthenticator::QWebSocketCorsAuthenticator(QWebSocketCorsAuthenticator &&other) : + d_ptr(other.d_ptr.take()) +{} + +QWebSocketCorsAuthenticator &QWebSocketCorsAuthenticator::operator =(QWebSocketCorsAuthenticator &&other) +{ + qSwap(d_ptr, other.d_ptr); + return *this; +} + +#endif + +void QWebSocketCorsAuthenticator::swap(QWebSocketCorsAuthenticator &other) +{ + if (&other != this) { + qSwap(d_ptr, other.d_ptr); + } +} + /*! Returns the origin this autenticator is handling about. */ diff --git a/src/websockets/qwebsocketcorsauthenticator.h b/src/websockets/qwebsocketcorsauthenticator.h index f050188..8816039 100644 --- a/src/websockets/qwebsocketcorsauthenticator.h +++ b/src/websockets/qwebsocketcorsauthenticator.h @@ -42,6 +42,7 @@ #define QWEBSOCKETCORSAUTHENTICATOR_H #include "QtWebSockets/qwebsockets_global.h" +#include <QtCore/QScopedPointer> QT_BEGIN_NAMESPACE @@ -56,6 +57,13 @@ public: ~QWebSocketCorsAuthenticator(); QWebSocketCorsAuthenticator(const QWebSocketCorsAuthenticator &other); +#ifdef Q_COMPILER_RVALUE_REFS + QWebSocketCorsAuthenticator(QWebSocketCorsAuthenticator &&other); + QWebSocketCorsAuthenticator &operator =(QWebSocketCorsAuthenticator &&other); +#endif + + void swap(QWebSocketCorsAuthenticator &other); + QWebSocketCorsAuthenticator &operator =(const QWebSocketCorsAuthenticator &other); QString origin() const; @@ -64,7 +72,7 @@ public: bool allowed() const; private: - QWebSocketCorsAuthenticatorPrivate * const d_ptr; + QScopedPointer<QWebSocketCorsAuthenticatorPrivate> d_ptr; }; QT_END_NAMESPACE diff --git a/src/websockets/qwebsocketdataprocessor_p.cpp b/src/websockets/qwebsocketdataprocessor_p.cpp index 0594fb1..340e84b 100644 --- a/src/websockets/qwebsocketdataprocessor_p.cpp +++ b/src/websockets/qwebsocketdataprocessor_p.cpp @@ -81,7 +81,7 @@ QWebSocketDataProcessor::QWebSocketDataProcessor(QObject *parent) : m_binaryMessage(), m_textMessage(), m_payloadLength(0), - m_pConverterState(0), + m_pConverterState(Q_NULLPTR), m_pTextCodec(QTextCodec::codecForName("UTF-8")) { clear(); @@ -93,10 +93,9 @@ QWebSocketDataProcessor::QWebSocketDataProcessor(QObject *parent) : QWebSocketDataProcessor::~QWebSocketDataProcessor() { clear(); - if (m_pConverterState) - { + if (m_pConverterState) { delete m_pConverterState; - m_pConverterState = 0; + m_pConverterState = Q_NULLPTR; } } @@ -123,81 +122,61 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice) { bool isDone = false; - while (!isDone) - { + while (!isDone) { QWebSocketFrame frame = QWebSocketFrame::readFrame(pIoDevice); - if (frame.isValid()) - { - if (frame.isControlFrame()) - { + if (frame.isValid()) { + if (frame.isControlFrame()) { isDone = processControlFrame(frame); - } - else //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY - { - if (!m_isFragmented && frame.isContinuationFrame()) - { + } else { + //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY + if (!m_isFragmented && frame.isContinuationFrame()) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, tr("Received Continuation frame, while there is nothing to continue.")); return; } - if (m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame()) - { + if (m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame()) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, tr("All data frames after the initial data frame must have opcode 0 (continuation).")); return; } - if (!frame.isContinuationFrame()) - { + if (!frame.isContinuationFrame()) { m_opCode = frame.opCode(); m_isFragmented = !frame.isFinalFrame(); } quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OC_TEXT) ? m_textMessage.length() : m_binaryMessage.length(); - if ((messageLength + quint64(frame.payload().length())) > MAX_MESSAGE_SIZE_IN_BYTES) - { + if ((messageLength + quint64(frame.payload().length())) > MAX_MESSAGE_SIZE_IN_BYTES) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CC_TOO_MUCH_DATA, tr("Received message is too big.")); return; } - if (m_opCode == QWebSocketProtocol::OC_TEXT) - { + if (m_opCode == QWebSocketProtocol::OC_TEXT) { QString frameTxt = m_pTextCodec->toUnicode(frame.payload().constData(), frame.payload().size(), m_pConverterState); bool failed = (m_pConverterState->invalidChars != 0) || (frame.isFinalFrame() && (m_pConverterState->remainingChars != 0)); - if (failed) - { + if (failed) { clear(); Q_EMIT errorEncountered(QWebSocketProtocol::CC_WRONG_DATATYPE, tr("Invalid UTF-8 code encountered.")); return; - } - else - { + } else { m_textMessage.append(frameTxt); Q_EMIT textFrameReceived(frameTxt, frame.isFinalFrame()); } - } - else - { + } else { m_binaryMessage.append(frame.payload()); Q_EMIT binaryFrameReceived(frame.payload(), frame.isFinalFrame()); } - if (frame.isFinalFrame()) - { - if (m_opCode == QWebSocketProtocol::OC_TEXT) - { + if (frame.isFinalFrame()) { + if (m_opCode == QWebSocketProtocol::OC_TEXT) { Q_EMIT textMessageReceived(m_textMessage); - } - else - { + } else { Q_EMIT binaryMessageReceived(m_binaryMessage); } clear(); isDone = true; } } - } - else - { + } else { Q_EMIT errorEncountered(frame.closeCode(), frame.closeReason()); clear(); isDone = true; @@ -219,12 +198,10 @@ void QWebSocketDataProcessor::clear() m_binaryMessage.clear(); m_textMessage.clear(); m_payloadLength = 0; - if (m_pConverterState) - { - if ((m_pConverterState->remainingChars != 0) || (m_pConverterState->invalidChars != 0)) - { + if (m_pConverterState) { + if ((m_pConverterState->remainingChars != 0) || (m_pConverterState->invalidChars != 0)) { delete m_pConverterState; - m_pConverterState = 0; + m_pConverterState = Q_NULLPTR; } } if (!m_pConverterState) @@ -256,29 +233,23 @@ bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame) quint16 closeCode = QWebSocketProtocol::CC_NORMAL; QString closeReason; QByteArray payload = frame.payload(); - if (payload.size() == 1) //size is either 0 (no close code and no reason) or >= 2 (at least a close code of 2 bytes) - { + if (payload.size() == 1) { + //size is either 0 (no close code and no reason) or >= 2 (at least a close code of 2 bytes) closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR; closeReason = tr("Payload of close frame is too small."); - } - else if (payload.size() > 1) //close frame can have a close code and reason - { + } else if (payload.size() > 1) { + //close frame can have a close code and reason closeCode = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(payload.constData())); - if (!QWebSocketProtocol::isCloseCodeValid(closeCode)) - { + if (!QWebSocketProtocol::isCloseCodeValid(closeCode)) { closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR; closeReason = tr("Invalid close code %1 detected.").arg(closeCode); - } - else - { - if (payload.size() > 2) - { + } else { + if (payload.size() > 2) { QTextCodec *tc = QTextCodec::codecForName("UTF-8"); QTextCodec::ConverterState state(QTextCodec::ConvertInvalidToNull); closeReason = tc->toUnicode(payload.constData() + 2, payload.size() - 2, &state); const bool failed = (state.invalidChars != 0) || (state.remainingChars != 0); - if (failed) - { + if (failed) { closeCode = QWebSocketProtocol::CC_WRONG_DATATYPE; closeReason = tr("Invalid UTF-8 code encountered."); } @@ -308,7 +279,7 @@ bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame) } default: { - qDebug() << "DataProcessor::processControlFrame: Invalid opcode detected:" << static_cast<int>(frame.opCode()); + Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, tr("Invalid opcode detected: %1").arg(int(frame.opCode()))); //Do nothing break; } diff --git a/src/websockets/qwebsocketframe_p.cpp b/src/websockets/qwebsocketframe_p.cpp index 4fab472..1376ed6 100644 --- a/src/websockets/qwebsocketframe_p.cpp +++ b/src/websockets/qwebsocketframe_p.cpp @@ -58,6 +58,8 @@ #include <QtCore/QtEndian> #include <QtCore/QDebug> +QT_BEGIN_NAMESPACE + /*! \internal */ @@ -114,6 +116,67 @@ QWebSocketFrame &QWebSocketFrame::operator =(const QWebSocketFrame &other) return *this; } +#ifdef Q_COMPILER_RVALUE_REFS +/*! + \internal + */ +QWebSocketFrame::QWebSocketFrame(QWebSocketFrame &&other) : + m_closeCode(qMove(other.m_closeCode)), + m_closeReason(qMove(other.m_closeReason)), + m_isFinalFrame(qMove(other.m_isFinalFrame)), + m_mask(qMove(other.m_mask)), + m_rsv1(qMove(other.m_rsv1)), + m_rsv2(qMove(other.m_rsv2)), + m_rsv3(qMove(other.m_rsv3)), + m_opCode(qMove(other.m_opCode)), + m_length(qMove(other.m_length)), + m_payload(qMove(other.m_payload)), + m_isValid(qMove(other.m_isValid)) +{} + + +/*! + \internal + */ +QWebSocketFrame &QWebSocketFrame::operator =(QWebSocketFrame &&other) +{ + qSwap(m_closeCode, other.m_closeCode); + qSwap(m_closeReason, other.m_closeReason); + qSwap(m_isFinalFrame, other.m_isFinalFrame); + qSwap(m_mask, other.m_mask); + qSwap(m_rsv1, other.m_rsv1); + qSwap(m_rsv2, other.m_rsv2); + qSwap(m_rsv3, other.m_rsv3); + qSwap(m_opCode, other.m_opCode); + qSwap(m_length, other.m_length); + qSwap(m_payload, other.m_payload); + qSwap(m_isValid, other.m_isValid); + + return *this; +} + +#endif + +/*! + \internal + */ +void QWebSocketFrame::swap(QWebSocketFrame &other) +{ + if (&other != this) { + qSwap(m_closeCode, other.m_closeCode); + qSwap(m_closeReason, other.m_closeReason); + qSwap(m_isFinalFrame, other.m_isFinalFrame); + qSwap(m_mask, other.m_mask); + qSwap(m_rsv1, other.m_rsv1); + qSwap(m_rsv2, other.m_rsv2); + qSwap(m_rsv3, other.m_rsv3); + qSwap(m_opCode, other.m_opCode); + qSwap(m_length, other.m_length); + qSwap(m_payload, other.m_payload); + qSwap(m_isValid, other.m_isValid); + } +} + /*! \internal */ @@ -272,21 +335,17 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) //the GUI will hang for at most 5 seconds //maybe, a QStateMachine should be used bool ok = pIoDevice->waitForReadyRead(5000); - if (!ok) - { + if (!ok) { frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Timeout when reading data from socket.")); processingState = PS_DISPATCH_RESULT; - } - else - { + } else { processingState = returnState; } break; } case PS_READ_HEADER: { - if (pIoDevice->bytesAvailable() >= 2) - { + if (pIoDevice->bytesAvailable() >= 2) { //FIN, RSV1-3, Opcode char header[2] = {0}; bytesRead = pIoDevice->read(header, 2); @@ -319,13 +378,10 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) break; } } - if (!frame.checkValidity()) - { + if (!frame.checkValidity()) { processingState = PS_DISPATCH_RESULT; } - } - else - { + } else { WAIT_FOR_MORE_DATA(2); } break; @@ -333,35 +389,26 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) case PS_READ_PAYLOAD_LENGTH: { - if (pIoDevice->bytesAvailable() >= 2) - { + if (pIoDevice->bytesAvailable() >= 2) { uchar length[2] = {0}; bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 2); - if (bytesRead == -1) - { + if (bytesRead == -1) { frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Error occurred while reading from the network: %1").arg(pIoDevice->errorString())); processingState = PS_DISPATCH_RESULT; - } - else - { + } else { payloadLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(length)); - if (payloadLength < 126) - { + if (payloadLength < 126) { //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 //"in all cases, the minimal number of bytes MUST be used to encode //the length, for example, the length of a 124-byte-long string //can't be encoded as the sequence 126, 0, 124" frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Lengths smaller than 126 must be expressed as one byte.")); processingState = PS_DISPATCH_RESULT; - } - else - { + } else { processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; } } - } - else - { + } else { WAIT_FOR_MORE_DATA(2); } break; @@ -369,37 +416,28 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) case PS_READ_BIG_PAYLOAD_LENGTH: { - if (pIoDevice->bytesAvailable() >= 8) - { + if (pIoDevice->bytesAvailable() >= 8) { uchar length[8] = {0}; bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 8); - if (bytesRead < 8) - { + if (bytesRead < 8) { frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, QObject::tr("Something went wrong during reading from the network.")); processingState = PS_DISPATCH_RESULT; - } - else - { + } else { //Most significant bit must be set to 0 as per http://tools.ietf.org/html/rfc6455#section-5.2 - //TODO: Do we check for that? Now we just strip off the highest bit + //We don't check for that. We just strip off the highest bit payloadLength = qFromBigEndian<quint64>(length) & ~(1ULL << 63); - if (payloadLength <= 0xFFFFu) - { + if (payloadLength <= 0xFFFFu) { //see http://tools.ietf.org/html/rfc6455#page-28 paragraph 5.2 //"in all cases, the minimal number of bytes MUST be used to encode //the length, for example, the length of a 124-byte-long string //can't be encoded as the sequence 126, 0, 124" frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Lengths smaller than 65536 (2^16) must be expressed as 2 bytes.")); processingState = PS_DISPATCH_RESULT; - } - else - { + } else { processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; } } - } - else - { + } else { WAIT_FOR_MORE_DATA(8); } @@ -408,22 +446,16 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) case PS_READ_MASK: { - if (pIoDevice->bytesAvailable() >= 4) - { + if (pIoDevice->bytesAvailable() >= 4) { bytesRead = pIoDevice->read(reinterpret_cast<char *>(&frame.m_mask), sizeof(frame.m_mask)); - if (bytesRead == -1) - { + if (bytesRead == -1) { frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Error while reading from the network: %1.").arg(pIoDevice->errorString())); processingState = PS_DISPATCH_RESULT; - } - else - { + } else { frame.m_mask = qFromBigEndian(frame.m_mask); processingState = PS_READ_PAYLOAD; } - } - else - { + } else { WAIT_FOR_MORE_DATA(4); } break; @@ -431,38 +463,27 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice) case PS_READ_PAYLOAD: { - if (!payloadLength) - { + if (!payloadLength) { processingState = PS_DISPATCH_RESULT; - } - else if (payloadLength > MAX_FRAME_SIZE_IN_BYTES) - { + } else if (payloadLength > MAX_FRAME_SIZE_IN_BYTES) { frame.setError(QWebSocketProtocol::CC_TOO_MUCH_DATA, QObject::tr("Maximum framesize exceeded.")); processingState = PS_DISPATCH_RESULT; - } - else - { - quint64 bytesAvailable = static_cast<quint64>(pIoDevice->bytesAvailable()); - if (bytesAvailable >= payloadLength) - { + } else { + quint64 bytesAvailable = quint64(pIoDevice->bytesAvailable()); + if (bytesAvailable >= payloadLength) { frame.m_payload = pIoDevice->read(payloadLength); //payloadLength can be safely cast to an integer, as the MAX_FRAME_SIZE_IN_BYTES = MAX_INT - if (frame.m_payload.length() != static_cast<int>(payloadLength)) //some error occurred; refer to the Qt documentation - { + if (frame.m_payload.length() != int(payloadLength)) { + //some error occurred; refer to the Qt documentation of QIODevice::read() frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, QObject::tr("Some serious error occurred while reading from the network.")); processingState = PS_DISPATCH_RESULT; - } - else - { - if (hasMask) - { + } else { + if (hasMask) { QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask); } processingState = PS_DISPATCH_RESULT; } - } - else - { + } else { WAIT_FOR_MORE_DATA(payloadLength); //if payload is too big, then this will timeout } } @@ -506,35 +527,25 @@ void QWebSocketFrame::setError(QWebSocketProtocol::CloseCode code, QString close */ bool QWebSocketFrame::checkValidity() { - if (!isValid()) - { - if (m_rsv1 || m_rsv2 || m_rsv3) - { - setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Rsv field is non-zero")); - } - else if (QWebSocketProtocol::isOpCodeReserved(m_opCode)) - { - setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Used reserved opcode")); - } - else if (isControlFrame()) - { - if (m_length > 125) - { - setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Controle frame is larger than 125 bytes")); - } - else if (!m_isFinalFrame) - { - setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Controle frames cannot be fragmented")); - } - else - { - m_isValid = true; - } - } - else - { + if (isValid()) { + return true; + } + if (m_rsv1 || m_rsv2 || m_rsv3) { + setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Rsv field is non-zero")); + } else if (QWebSocketProtocol::isOpCodeReserved(m_opCode)) { + setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Used reserved opcode")); + } else if (isControlFrame()) { + if (m_length > 125) { + setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Controle frame is larger than 125 bytes")); + } else if (!m_isFinalFrame) { + setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Controle frames cannot be fragmented")); + } else { m_isValid = true; } + } else { + m_isValid = true; } return m_isValid; } + +QT_END_NAMESPACE diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h index f05f602..fdb22ea 100644 --- a/src/websockets/qwebsocketframe_p.h +++ b/src/websockets/qwebsocketframe_p.h @@ -64,6 +64,13 @@ public: QWebSocketFrame &operator =(const QWebSocketFrame &other); +#ifdef Q_COMPILER_RVALUE_REFS + QWebSocketFrame(QWebSocketFrame &&other); + QWebSocketFrame &operator =(QWebSocketFrame &&other); +#endif + + void swap(QWebSocketFrame &other); + QWebSocketProtocol::CloseCode closeCode() const; QString closeReason() const; bool isFinalFrame() const; diff --git a/src/websockets/qwebsockethandshakerequest_p.cpp b/src/websockets/qwebsockethandshakerequest_p.cpp index e1c054d..79ab9a8 100644 --- a/src/websockets/qwebsockethandshakerequest_p.cpp +++ b/src/websockets/qwebsockethandshakerequest_p.cpp @@ -196,117 +196,106 @@ QTextStream &QWebSocketHandshakeRequest::readFromStream(QTextStream &textStream) { m_isValid = false; clear(); - if (textStream.status() == QTextStream::Ok) - { - const QString requestLine = textStream.readLine(); - const QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts); - if (tokens.length() < 3) - { - m_isValid = false; + if (textStream.status() != QTextStream::Ok) { + return textStream; + } + const QString requestLine = textStream.readLine(); + const QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts); + if (tokens.length() < 3) { + m_isValid = false; + clear(); + return textStream; + } + const QString verb(tokens.at(0)); + const QString resourceName(tokens.at(1)); + const QString httpProtocol(tokens.at(2)); + bool conversionOk = false; + const float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk); + + if (!conversionOk) { + clear(); + m_isValid = false; + return textStream; + } + QString headerLine = textStream.readLine(); + m_headers.clear(); + while (!headerLine.isEmpty()) { + const QStringList headerField = headerLine.split(QStringLiteral(": "), QString::SkipEmptyParts); + if (headerField.length() < 2) { clear(); + return textStream; } - else - { - const QString verb(tokens.at(0)); - const QString resourceName(tokens.at(1)); - const QString httpProtocol(tokens.at(2)); - bool conversionOk = false; - const float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk); - - if (conversionOk) - { - QString headerLine = textStream.readLine(); - m_headers.clear(); - while (!headerLine.isEmpty()) - { - const QStringList headerField = headerLine.split(QStringLiteral(": "), QString::SkipEmptyParts); - if (headerField.length() < 2) - { - clear(); - return textStream; - } - m_headers.insertMulti(headerField.at(0), headerField.at(1)); - headerLine = textStream.readLine(); - } - - const QString host = m_headers.value(QStringLiteral("Host"), QStringLiteral("")); - m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1()); - if (m_requestUrl.isRelative()) - { - m_requestUrl.setHost(host); - } - if (m_requestUrl.scheme().isEmpty()) - { - const QString scheme = isSecure() ? QStringLiteral("wss") : QStringLiteral("ws"); - m_requestUrl.setScheme(scheme); - } - - const QStringList versionLines = m_headers.values(QStringLiteral("Sec-WebSocket-Version")); - for (QStringList::const_iterator v = versionLines.begin(); v != versionLines.end(); ++v) - { - const QStringList versions = (*v).split(QStringLiteral(","), QString::SkipEmptyParts); - for (QStringList::const_iterator i = versions.begin(); i != versions.end(); ++i) - { - bool ok = false; - (void)(*i).toUInt(&ok); - if (!ok) - { - clear(); - return textStream; - } - const QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString((*i).trimmed()); - m_versions << ver; - } - } - std::sort(m_versions.begin(), m_versions.end(), std::greater<QWebSocketProtocol::Version>()); //sort in descending order - m_key = m_headers.value(QStringLiteral("Sec-WebSocket-Key"), QStringLiteral("")); - const QString upgrade = m_headers.value(QStringLiteral("Upgrade"), QStringLiteral("")); //must be equal to "websocket", case-insensitive - const QString connection = m_headers.value(QStringLiteral("Connection"), QStringLiteral("")); //must contain "Upgrade", case-insensitive - const QStringList connectionLine = connection.split(QStringLiteral(","), QString::SkipEmptyParts); - QStringList connectionValues; - for (QStringList::const_iterator c = connectionLine.begin(); c != connectionLine.end(); ++c) - { - connectionValues << (*c).trimmed(); - } - - //optional headers - m_origin = m_headers.value(QStringLiteral("Sec-WebSocket-Origin"), QStringLiteral("")); - const QStringList protocolLines = m_headers.values(QStringLiteral("Sec-WebSocket-Protocol")); - for (QStringList::const_iterator pl = protocolLines.begin(); pl != protocolLines.end(); ++pl) - { - QStringList protocols = (*pl).split(QStringLiteral(","), QString::SkipEmptyParts); - for (QStringList::const_iterator p = protocols.begin(); p != protocols.end(); ++p) - { - m_protocols << (*p).trimmed(); - } - } - const QStringList extensionLines = m_headers.values(QStringLiteral("Sec-WebSocket-Extensions")); - for (QStringList::const_iterator el = extensionLines.begin(); el != extensionLines.end(); ++el) - { - QStringList extensions = (*el).split(QStringLiteral(","), QString::SkipEmptyParts); - for (QStringList::const_iterator e = extensions.begin(); e != extensions.end(); ++e) - { - m_extensions << (*e).trimmed(); - } - } + m_headers.insertMulti(headerField.at(0), headerField.at(1)); + headerLine = textStream.readLine(); + } - //TODO: authentication field + const QString host = m_headers.value(QStringLiteral("Host"), QStringLiteral("")); + m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1()); + if (m_requestUrl.isRelative()) { + m_requestUrl.setHost(host); + } + if (m_requestUrl.scheme().isEmpty()) { + const QString scheme = isSecure() ? QStringLiteral("wss") : QStringLiteral("ws"); + m_requestUrl.setScheme(scheme); + } - m_isValid = !(host.isEmpty() || - resourceName.isEmpty() || - m_versions.isEmpty() || - m_key.isEmpty() || - (verb != QStringLiteral("GET")) || - (!conversionOk || (httpVersion < 1.1f)) || - (upgrade.toLower() != QStringLiteral("websocket")) || - (!connectionValues.contains(QStringLiteral("upgrade"), Qt::CaseInsensitive))); - } - if (!m_isValid) - { + const QStringList versionLines = m_headers.values(QStringLiteral("Sec-WebSocket-Version")); + for (QStringList::const_iterator v = versionLines.begin(); v != versionLines.end(); ++v) { + const QStringList versions = (*v).split(QStringLiteral(","), QString::SkipEmptyParts); + for (QStringList::const_iterator i = versions.begin(); i != versions.end(); ++i) { + bool ok = false; + (void)(*i).toUInt(&ok); + if (!ok) { clear(); + return textStream; } + const QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString((*i).trimmed()); + m_versions << ver; + } + } + //sort in descending order + std::sort(m_versions.begin(), m_versions.end(), std::greater<QWebSocketProtocol::Version>()); + m_key = m_headers.value(QStringLiteral("Sec-WebSocket-Key"), QStringLiteral("")); + //must contain "Upgrade", case-insensitive + const QString upgrade = m_headers.value(QStringLiteral("Upgrade"), QStringLiteral("")); + //must be equal to "websocket", case-insensitive + const QString connection = m_headers.value(QStringLiteral("Connection"), QStringLiteral("")); + const QStringList connectionLine = connection.split(QStringLiteral(","), QString::SkipEmptyParts); + QStringList connectionValues; + for (QStringList::const_iterator c = connectionLine.begin(); c != connectionLine.end(); ++c) { + connectionValues << (*c).trimmed(); + } + + //optional headers + m_origin = m_headers.value(QStringLiteral("Sec-WebSocket-Origin"), QStringLiteral("")); + const QStringList protocolLines = m_headers.values(QStringLiteral("Sec-WebSocket-Protocol")); + for (QStringList::const_iterator pl = protocolLines.begin(); pl != protocolLines.end(); ++pl) { + QStringList protocols = (*pl).split(QStringLiteral(","), QString::SkipEmptyParts); + for (QStringList::const_iterator p = protocols.begin(); p != protocols.end(); ++p) { + m_protocols << (*p).trimmed(); } } + const QStringList extensionLines = m_headers.values(QStringLiteral("Sec-WebSocket-Extensions")); + for (QStringList::const_iterator el = extensionLines.begin(); el != extensionLines.end(); ++el) { + QStringList extensions = (*el).split(QStringLiteral(","), QString::SkipEmptyParts); + for (QStringList::const_iterator e = extensions.begin(); e != extensions.end(); ++e) { + m_extensions << (*e).trimmed(); + } + } + + //TODO: authentication field + + m_isValid = !(host.isEmpty() || + resourceName.isEmpty() || + m_versions.isEmpty() || + m_key.isEmpty() || + (verb != QStringLiteral("GET")) || + (!conversionOk || (httpVersion < 1.1f)) || + (upgrade.toLower() != QStringLiteral("websocket")) || + (!connectionValues.contains(QStringLiteral("upgrade"), Qt::CaseInsensitive))); + if (!m_isValid) { + clear(); + } return textStream; } diff --git a/src/websockets/qwebsockethandshakeresponse_p.cpp b/src/websockets/qwebsockethandshakeresponse_p.cpp index 0049306..d4af4eb 100644 --- a/src/websockets/qwebsockethandshakeresponse_p.cpp +++ b/src/websockets/qwebsockethandshakeresponse_p.cpp @@ -41,6 +41,7 @@ #include "qwebsockethandshakeresponse_p.h" #include "qwebsockethandshakerequest_p.h" +#include "qwebsocketprotocol.h" #include <QtCore/QString> #include <QtCore/QTextStream> @@ -70,9 +71,13 @@ QWebSocketHandshakeResponse::QWebSocketHandshakeResponse(const QWebSocketHandsha m_response(), m_acceptedProtocol(), m_acceptedExtension(), - m_acceptedVersion(QWebSocketProtocol::V_Unknow) + m_acceptedVersion(QWebSocketProtocol::V_Unknow), + m_error(QWebSocketProtocol::CC_NORMAL), + m_errorString() { - m_response = getHandshakeResponse(request, serverName, isOriginAllowed, supportedVersions, supportedProtocols, supportedExtensions); + m_response = getHandshakeResponse(request, serverName, + isOriginAllowed, supportedVersions, + supportedProtocols, supportedExtensions); m_isValid = true; } @@ -112,7 +117,8 @@ QString QWebSocketHandshakeResponse::acceptedProtocol() const */ QString QWebSocketHandshakeResponse::calculateAcceptKey(const QString &key) const { - const QString tmpKey = key % QStringLiteral("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); //the UID comes from RFC6455 + //the UID comes from RFC6455 + const QString tmpKey = key % QStringLiteral("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"); const QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1); return QString::fromLatin1(hash.toBase64()); } @@ -130,46 +136,39 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandsh QStringList response; m_canUpgrade = false; - if (!isOriginAllowed) - { - if (!m_canUpgrade) - { + if (!isOriginAllowed) { + if (!m_canUpgrade) { + m_error = QWebSocketProtocol::CC_POLICY_VIOLATED; + m_errorString = tr("Access forbidden."); response << QStringLiteral("HTTP/1.1 403 Access Forbidden"); } - } - else - { - if (request.isValid()) - { + } else { + if (request.isValid()) { const QString acceptKey = calculateAcceptKey(request.key()); const QList<QString> matchingProtocols = supportedProtocols.toSet().intersect(request.protocols().toSet()).toList(); const QList<QString> matchingExtensions = supportedExtensions.toSet().intersect(request.extensions().toSet()).toList(); QList<QWebSocketProtocol::Version> matchingVersions = request.versions().toSet().intersect(supportedVersions.toSet()).toList(); std::sort(matchingVersions.begin(), matchingVersions.end(), std::greater<QWebSocketProtocol::Version>()); //sort in descending order - if (matchingVersions.isEmpty()) - { + if (matchingVersions.isEmpty()) { + m_error = QWebSocketProtocol::CC_PROTOCOL_ERROR; + m_errorString = tr("Unsupported version requested."); m_canUpgrade = false; - } - else - { + } else { response << QStringLiteral("HTTP/1.1 101 Switching Protocols") << QStringLiteral("Upgrade: websocket") << QStringLiteral("Connection: Upgrade") << QStringLiteral("Sec-WebSocket-Accept: ") % acceptKey; - if (!matchingProtocols.isEmpty()) - { + if (!matchingProtocols.isEmpty()) { m_acceptedProtocol = matchingProtocols.first(); response << QStringLiteral("Sec-WebSocket-Protocol: ") % m_acceptedProtocol; } - if (!matchingExtensions.isEmpty()) - { + if (!matchingExtensions.isEmpty()) { m_acceptedExtension = matchingExtensions.first(); response << QStringLiteral("Sec-WebSocket-Extensions: ") % m_acceptedExtension; } QString origin = request.origin().trimmed(); - if (origin.isEmpty()) - { + if (origin.isEmpty()) { origin = QStringLiteral("*"); } response << QStringLiteral("Server: ") % serverName << @@ -182,17 +181,15 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandsh m_acceptedVersion = QWebSocketProtocol::currentVersion(); m_canUpgrade = true; } - } - else - { + } else { + m_error = QWebSocketProtocol::CC_PROTOCOL_ERROR; + m_errorString = tr("Bad handshake request received."); m_canUpgrade = false; } - if (!m_canUpgrade) - { + if (!m_canUpgrade) { response << QStringLiteral("HTTP/1.1 400 Bad Request"); QStringList versions; - Q_FOREACH(QWebSocketProtocol::Version version, supportedVersions) - { + Q_FOREACH (QWebSocketProtocol::Version version, supportedVersions) { versions << QString::number(static_cast<int>(version)); } response << QStringLiteral("Sec-WebSocket-Version: ") % versions.join(QStringLiteral(", ")); @@ -207,12 +204,9 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandsh */ QTextStream &QWebSocketHandshakeResponse::writeToStream(QTextStream &textStream) const { - if (!m_response.isEmpty()) - { + if (!m_response.isEmpty()) { textStream << m_response.toLatin1().constData(); - } - else - { + } else { textStream.setStatus(QTextStream::WriteFailed); } return textStream; @@ -237,6 +231,22 @@ QWebSocketProtocol::Version QWebSocketHandshakeResponse::acceptedVersion() const /*! \internal */ +QWebSocketProtocol::CloseCode QWebSocketHandshakeResponse::error() const +{ + return m_error; +} + +/*! + \internal + */ +QString QWebSocketHandshakeResponse::errorString() const +{ + return m_errorString; +} + +/*! + \internal + */ QString QWebSocketHandshakeResponse::acceptedExtension() const { return m_acceptedExtension; diff --git a/src/websockets/qwebsockethandshakeresponse_p.h b/src/websockets/qwebsockethandshakeresponse_p.h index 7ee8179..799079a 100644 --- a/src/websockets/qwebsockethandshakeresponse_p.h +++ b/src/websockets/qwebsockethandshakeresponse_p.h @@ -83,6 +83,9 @@ public: QString acceptedExtension() const; QWebSocketProtocol::Version acceptedVersion() const; + QWebSocketProtocol::CloseCode error() const; + QString errorString() const; + public Q_SLOTS: Q_SIGNALS: @@ -94,6 +97,8 @@ private: QString m_acceptedProtocol; QString m_acceptedExtension; QWebSocketProtocol::Version m_acceptedVersion; + QWebSocketProtocol::CloseCode m_error; + QString m_errorString; QString calculateAcceptKey(const QString &key) const; QString getHandshakeResponse(const QWebSocketHandshakeRequest &request, diff --git a/src/websockets/qwebsocketprotocol_p.cpp b/src/websockets/qwebsocketprotocol_p.cpp index 8a08797..98d7b6f 100644 --- a/src/websockets/qwebsocketprotocol_p.cpp +++ b/src/websockets/qwebsocketprotocol_p.cpp @@ -140,10 +140,8 @@ Version versionFromString(const QString &versionString) const int ver = versionString.toInt(&ok); QSet<Version> supportedVersions; supportedVersions << V_0 << V_4 << V_5 << V_6 << V_7 << V_8 << V_13; - if (ok) - { - if (supportedVersions.contains(static_cast<Version>(ver))) - { + if (ok) { + if (supportedVersions.contains(static_cast<Version>(ver))) { version = static_cast<Version>(ver); } } @@ -156,6 +154,7 @@ Version versionFromString(const QString &versionString) */ void mask(QByteArray *payload, quint32 maskingKey) { + Q_ASSERT(payload); mask(payload->data(), payload->size(), maskingKey); } @@ -165,14 +164,14 @@ void mask(QByteArray *payload, quint32 maskingKey) */ void mask(char *payload, quint64 size, quint32 maskingKey) { - const quint8 mask[] = { static_cast<quint8>((maskingKey & 0xFF000000u) >> 24), - static_cast<quint8>((maskingKey & 0x00FF0000u) >> 16), - static_cast<quint8>((maskingKey & 0x0000FF00u) >> 8), - static_cast<quint8>((maskingKey & 0x000000FFu)) + Q_ASSERT(payload); + const quint8 mask[] = { quint8((maskingKey & 0xFF000000u) >> 24), + quint8((maskingKey & 0x00FF0000u) >> 16), + quint8((maskingKey & 0x0000FF00u) >> 8), + quint8((maskingKey & 0x000000FFu)) }; int i = 0; - while (size-- > 0) - { + while (size-- > 0) { *payload++ ^= mask[i++ % 4]; } } diff --git a/src/websockets/qwebsocketserver.cpp b/src/websockets/qwebsocketserver.cpp index 461e75f..3198c13 100644 --- a/src/websockets/qwebsocketserver.cpp +++ b/src/websockets/qwebsocketserver.cpp @@ -103,6 +103,14 @@ */ /*! + \fn void QWebSocketServer::serverError(QNetworkProtocol::CloseCode closeCode) + This signal is emitted when an error occurs during the setup of a web socket connection. + The \a closeCode parameter describes the type of error that occurred + + \sa errorString() +*/ + +/*! \fn void QWebSocketServer::newConnection() This signal is emitted every time a new connection is available. @@ -110,6 +118,13 @@ */ /*! + \fn void QWebSocketServer::closed() + This signal is emitted when the server closed it's connection. + + \sa close() +*/ + +/*! \fn void QWebSocketServer::originAuthenticationRequired(QWebSocketCorsAuthenticator *authenticator) This signal is emitted when a new connection is requested. The slot connected to this signal should indicate whether the origin (which can be determined by the origin() call) @@ -381,7 +396,7 @@ QWebSocketServer::SecureMode QWebSocketServer::secureMode() const Returns an error code for the last error that occurred. \sa errorString() */ -QAbstractSocket::SocketError QWebSocketServer::serverError() const +QWebSocketProtocol::CloseCode QWebSocketServer::error() const { Q_D(const QWebSocketServer); return d->serverError(); @@ -468,7 +483,7 @@ QList<QWebSocketProtocol::Version> QWebSocketServer::supportedVersions() const /*! Returns a list of websocket subprotocols that this server supports. */ -QList<QString> QWebSocketServer::supportedProtocols() const +QStringList QWebSocketServer::supportedProtocols() const { Q_D(const QWebSocketServer); return d->supportedProtocols(); @@ -477,7 +492,7 @@ QList<QString> QWebSocketServer::supportedProtocols() const /*! Returns a list of websocket extensions that this server supports. */ -QList<QString> QWebSocketServer::supportedExtensions() const +QStringList QWebSocketServer::supportedExtensions() const { Q_D(const QWebSocketServer); return d->supportedExtensions(); diff --git a/src/websockets/qwebsocketserver.h b/src/websockets/qwebsocketserver.h index c616c0b..bc7801a 100644 --- a/src/websockets/qwebsocketserver.h +++ b/src/websockets/qwebsocketserver.h @@ -99,7 +99,7 @@ public: bool hasPendingConnections() const; virtual QWebSocket *nextPendingConnection(); - QAbstractSocket::SocketError serverError() const; + QWebSocketProtocol::CloseCode error() const; QString errorString() const; void pauseAccepting(); @@ -118,11 +118,12 @@ public: #endif QList<QWebSocketProtocol::Version> supportedVersions() const; - QList<QString> supportedProtocols() const; - QList<QString> supportedExtensions() const; + QStringList supportedProtocols() const; + QStringList supportedExtensions() const; Q_SIGNALS: void acceptError(QAbstractSocket::SocketError socketError); + void serverError(QWebSocketProtocol::CloseCode closeCode); //TODO: should use a delegate iso of a synchronous signal void originAuthenticationRequired(QWebSocketCorsAuthenticator *pAuthenticator); void newConnection(); @@ -130,6 +131,7 @@ Q_SIGNALS: void peerVerifyError(const QSslError &error); void sslErrors(const QList<QSslError> &errors); #endif + void closed(); private: QWebSocketServerPrivate * const d_ptr; diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp index 86324b7..d59966d 100644 --- a/src/websockets/qwebsocketserver_p.cpp +++ b/src/websockets/qwebsocketserver_p.cpp @@ -67,15 +67,15 @@ QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWeb m_pTcpServer(Q_NULLPTR), m_serverName(serverName), m_secureMode(secureMode), - m_pendingConnections() + m_pendingConnections(), + m_error(QWebSocketProtocol::CC_NORMAL), + m_errorString() { Q_ASSERT(pWebSocketServer); - if (m_secureMode == NON_SECURE_MODE) - { + if (m_secureMode == NON_SECURE_MODE) { m_pTcpServer = new QTcpServer(this); connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection())); - } - else + } else { #ifndef QT_NO_SSL QSslServer *pSslServer = new QSslServer(this); @@ -83,6 +83,8 @@ QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWeb connect(pSslServer, SIGNAL(newEncryptedConnection()), this, SLOT(onNewConnection())); connect(pSslServer, SIGNAL(peerVerifyError(QSslError)), q_ptr, SIGNAL(peerVerifyError(QSslError))); connect(pSslServer, SIGNAL(sslErrors(QList<QSslError>)), q_ptr, SIGNAL(sslErrors(QList<QSslError>))); +#else + qFatal("SSL not supported on this platform."); #endif } connect(m_pTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), q_ptr, SIGNAL(acceptError(QAbstractSocket::SocketError))); @@ -93,12 +95,7 @@ QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWeb */ QWebSocketServerPrivate::~QWebSocketServerPrivate() { - while (!m_pendingConnections.isEmpty()) - { - QWebSocket *pWebSocket = m_pendingConnections.dequeue(); - pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, tr("Server closed.")); - pWebSocket->deleteLater(); - } + close(); m_pTcpServer->deleteLater(); } @@ -107,7 +104,16 @@ QWebSocketServerPrivate::~QWebSocketServerPrivate() */ void QWebSocketServerPrivate::close() { + Q_Q(QWebSocketServer); m_pTcpServer->close(); + while (!m_pendingConnections.isEmpty()) { + QWebSocket *pWebSocket = m_pendingConnections.dequeue(); + pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, tr("Server closed.")); + pWebSocket->deleteLater(); + } + //emit signal via the event queue, so the server gets time + //to process any hanging events, like flushing buffers aso + QMetaObject::invokeMethod(q, "closed", Qt::QueuedConnection); } /*! @@ -115,7 +121,11 @@ void QWebSocketServerPrivate::close() */ QString QWebSocketServerPrivate::errorString() const { - return m_pTcpServer->errorString(); + if (m_errorString.isEmpty()) { + return m_pTcpServer->errorString(); + } else { + return m_errorString; + } } /*! @@ -155,8 +165,7 @@ int QWebSocketServerPrivate::maxPendingConnections() const */ void QWebSocketServerPrivate::addPendingConnection(QWebSocket *pWebSocket) { - if (m_pendingConnections.size() < maxPendingConnections()) - { + if (m_pendingConnections.size() < maxPendingConnections()) { m_pendingConnections.enqueue(pWebSocket); } } @@ -167,8 +176,7 @@ void QWebSocketServerPrivate::addPendingConnection(QWebSocket *pWebSocket) QWebSocket *QWebSocketServerPrivate::nextPendingConnection() { QWebSocket *pWebSocket = Q_NULLPTR; - if (!m_pendingConnections.isEmpty()) - { + if (!m_pendingConnections.isEmpty()) { pWebSocket = m_pendingConnections.dequeue(); } return pWebSocket; @@ -218,9 +226,9 @@ QHostAddress QWebSocketServerPrivate::serverAddress() const /*! \internal */ -QAbstractSocket::SocketError QWebSocketServerPrivate::serverError() const +QWebSocketProtocol::CloseCode QWebSocketServerPrivate::serverError() const { - return m_pTcpServer->serverError(); + return m_error; } /*! @@ -276,7 +284,7 @@ QList<QWebSocketProtocol::Version> QWebSocketServerPrivate::supportedVersions() /*! \internal */ -QList<QString> QWebSocketServerPrivate::supportedProtocols() const +QStringList QWebSocketServerPrivate::supportedProtocols() const { QList<QString> supportedProtocols; return supportedProtocols; //no protocols are currently supported @@ -285,7 +293,7 @@ QList<QString> QWebSocketServerPrivate::supportedProtocols() const /*! \internal */ -QList<QString> QWebSocketServerPrivate::supportedExtensions() const +QStringList QWebSocketServerPrivate::supportedExtensions() const { QList<QString> supportedExtensions; return supportedExtensions; //no extensions are currently supported @@ -296,7 +304,9 @@ QList<QString> QWebSocketServerPrivate::supportedExtensions() const */ void QWebSocketServerPrivate::setServerName(const QString &serverName) { - m_serverName = serverName; + if (m_serverName != serverName) { + m_serverName = serverName; + } } /*! @@ -318,25 +328,33 @@ QWebSocketServerPrivate::SecureMode QWebSocketServerPrivate::secureMode() const #ifndef QT_NO_SSL void QWebSocketServerPrivate::setSslConfiguration(const QSslConfiguration &sslConfiguration) { - if (m_secureMode == SECURE_MODE) - { + if (m_secureMode == SECURE_MODE) { qobject_cast<QSslServer *>(m_pTcpServer)->setSslConfiguration(sslConfiguration); + } else { + qWarning() << tr("Cannot set SSL configuration for non-secure server."); } } QSslConfiguration QWebSocketServerPrivate::sslConfiguration() const { - if (m_secureMode == SECURE_MODE) - { + if (m_secureMode == SECURE_MODE) { return qobject_cast<QSslServer *>(m_pTcpServer)->sslConfiguration(); - } - else - { + } else { return QSslConfiguration::defaultConfiguration(); } } #endif +void QWebSocketServerPrivate::setError(QWebSocketProtocol::CloseCode code, QString errorString) +{ + if ((m_error != code) || (m_errorString != errorString)) { + Q_Q(QWebSocketServer); + m_error = code; + m_errorString = errorString; + Q_EMIT q->serverError(code); + } +} + /*! \internal */ @@ -352,8 +370,7 @@ void QWebSocketServerPrivate::onNewConnection() void QWebSocketServerPrivate::onCloseConnection() { QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender()); - if (pTcpSocket) - { + if (pTcpSocket) { pTcpSocket->close(); } } @@ -365,8 +382,7 @@ void QWebSocketServerPrivate::handshakeReceived() { Q_Q(QWebSocketServer); QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender()); - if (pTcpSocket) - { + if (pTcpSocket) { bool success = false; bool isSecure = false; @@ -376,8 +392,7 @@ void QWebSocketServerPrivate::handshakeReceived() QTextStream textStream(pTcpSocket); textStream >> request; - if (request.isValid()) - { + if (request.isValid()) { QWebSocketCorsAuthenticator corsAuthenticator(request.origin()); Q_EMIT q->originAuthenticationRequired(&corsAuthenticator); @@ -388,50 +403,35 @@ void QWebSocketServerPrivate::handshakeReceived() supportedProtocols(), supportedExtensions()); - if (response.isValid()) - { + if (response.isValid()) { QTextStream httpStream(pTcpSocket); httpStream << response; httpStream.flush(); - if (response.canUpgrade()) - { + if (response.canUpgrade()) { QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response); - if (pWebSocket) - { + if (pWebSocket) { pWebSocket->setParent(this); addPendingConnection(pWebSocket); Q_EMIT q->newConnection(); success = true; - } - else - { - //TODO: should set or emit error - qDebug() << tr("Upgrading to websocket failed."); + } else { + setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, tr("Upgrading to websocket failed.")); } } - else - { - //TODO: should set or emit error - qDebug() << tr("Cannot upgrade to websocket."); + else { + setError(response.error(), response.errorString()); } - } - else - { - //TODO: should set or emit error - qDebug() << tr("Invalid response received."); + } else { + setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, tr("Invalid response received.")); } } - if (!success) - { - //TODO: should set or emit error - qDebug() << tr("Closing socket because of invalid or unsupported request."); + if (!success) { + qWarning() << tr("Closing socket because of invalid or unsupported request."); pTcpSocket->close(); } - } - else - { - qWarning() << "Sender socket is NULL. This should not happen, otherwise it is a Qt bug!!!"; + } else { + qWarning() << tr("Sender socket is NULL. This should not happen, otherwise it is a Qt bug!!!"); } } diff --git a/src/websockets/qwebsocketserver_p.h b/src/websockets/qwebsocketserver_p.h index 5e089d7..ad76bbf 100644 --- a/src/websockets/qwebsocketserver_p.h +++ b/src/websockets/qwebsocketserver_p.h @@ -98,7 +98,7 @@ public: #endif void resumeAccepting(); QHostAddress serverAddress() const; - QAbstractSocket::SocketError serverError() const; + QWebSocketProtocol::CloseCode serverError() const; quint16 serverPort() const; void setMaxPendingConnections(int numConnections); bool setSocketDescriptor(qintptr socketDescriptor); @@ -106,8 +106,8 @@ public: bool waitForNewConnection(int msec = 0, bool *timedOut = Q_NULLPTR); QList<QWebSocketProtocol::Version> supportedVersions() const; - QList<QString> supportedProtocols() const; - QList<QString> supportedExtensions() const; + QStringList supportedProtocols() const; + QStringList supportedExtensions() const; void setServerName(const QString &serverName); QString serverName() const; @@ -119,6 +119,8 @@ public: QSslConfiguration sslConfiguration() const; #endif + void setError(QWebSocketProtocol::CloseCode code, QString errorString); + private Q_SLOTS: void onNewConnection(); void onCloseConnection(); @@ -131,6 +133,8 @@ private: QString m_serverName; SecureMode m_secureMode; QQueue<QWebSocket *> m_pendingConnections; + QWebSocketProtocol::CloseCode m_error; + QString m_errorString; void addPendingConnection(QWebSocket *pWebSocket); }; |