summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Pattyn <pattyn.kurt@gmail.com>2013-12-07 12:54:09 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-12-10 11:46:11 +0100
commit7d35f5c6b7b8b187388523674b4a95585f369d78 (patch)
tree9c56fc7bc7eddc0da37e0d144e054eef288eb1e2
parent7c8d645c4759f7290fd31fe439abf0a99aac9161 (diff)
downloadqtwebsockets-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>
-rw-r--r--examples/echoclient/echoclient.cpp1
-rw-r--r--examples/echoclient/echoclient.h1
-rw-r--r--examples/echoclient/main.cpp1
-rw-r--r--examples/echoserver/echoserver.cpp28
-rw-r--r--examples/echoserver/echoserver.h2
-rw-r--r--examples/echoserver/main.cpp5
-rw-r--r--src/websockets/qsslserver_p.cpp11
-rw-r--r--src/websockets/qwebsocket.cpp4
-rw-r--r--src/websockets/qwebsocket_p.cpp570
-rw-r--r--src/websockets/qwebsocket_p.h7
-rw-r--r--src/websockets/qwebsocketcorsauthenticator.cpp24
-rw-r--r--src/websockets/qwebsocketcorsauthenticator.h10
-rw-r--r--src/websockets/qwebsocketdataprocessor_p.cpp93
-rw-r--r--src/websockets/qwebsocketframe_p.cpp213
-rw-r--r--src/websockets/qwebsocketframe_p.h7
-rw-r--r--src/websockets/qwebsockethandshakerequest_p.cpp195
-rw-r--r--src/websockets/qwebsockethandshakeresponse_p.cpp80
-rw-r--r--src/websockets/qwebsockethandshakeresponse_p.h5
-rw-r--r--src/websockets/qwebsocketprotocol_p.cpp19
-rw-r--r--src/websockets/qwebsocketserver.cpp21
-rw-r--r--src/websockets/qwebsocketserver.h8
-rw-r--r--src/websockets/qwebsocketserver_p.cpp124
-rw-r--r--src/websockets/qwebsocketserver_p.h10
-rw-r--r--tests/auto/websocketprotocol/tst_websocketprotocol.cpp4
-rw-r--r--tests/manual/compliance/tst_compliance.cpp6
25 files changed, 685 insertions, 764 deletions
diff --git a/examples/echoclient/echoclient.cpp b/examples/echoclient/echoclient.cpp
index 64a95ea..452b20e 100644
--- a/examples/echoclient/echoclient.cpp
+++ b/examples/echoclient/echoclient.cpp
@@ -50,6 +50,7 @@ EchoClient::EchoClient(const QUrl &url, QObject *parent) :
m_url(url)
{
connect(&m_webSocket, SIGNAL(connected()), this, SLOT(onConnected()));
+ connect(&m_webSocket, SIGNAL(disconnected()), this, SIGNAL(closed()));
m_webSocket.open(QUrl(url));
}
//! [constructor]
diff --git a/examples/echoclient/echoclient.h b/examples/echoclient/echoclient.h
index dd71497..497d7c5 100644
--- a/examples/echoclient/echoclient.h
+++ b/examples/echoclient/echoclient.h
@@ -53,6 +53,7 @@ public:
explicit EchoClient(const QUrl &url, QObject *parent = Q_NULLPTR);
Q_SIGNALS:
+ void closed();
public Q_SLOTS:
diff --git a/examples/echoclient/main.cpp b/examples/echoclient/main.cpp
index d93fd24..a13097d 100644
--- a/examples/echoclient/main.cpp
+++ b/examples/echoclient/main.cpp
@@ -45,6 +45,7 @@ int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
EchoClient client(QUrl("ws://localhost:1234"));
+ QObject::connect(&client, SIGNAL(closed()), &a, SLOT(quit()));
Q_UNUSED(client);
diff --git a/examples/echoserver/echoserver.cpp b/examples/echoserver/echoserver.cpp
index 0825f5d..8a2676c 100644
--- a/examples/echoserver/echoserver.cpp
+++ b/examples/echoserver/echoserver.cpp
@@ -48,18 +48,27 @@ QT_USE_NAMESPACE
//! [constructor]
EchoServer::EchoServer(quint16 port, QObject *parent) :
QObject(parent),
- m_pWebSocketServer(Q_NULLPTR),
+ m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"),
+ QWebSocketServer::NON_SECURE_MODE, this)),
m_clients()
{
- m_pWebSocketServer = new QWebSocketServer("Echo Server", QWebSocketServer::NON_SECURE_MODE, this);
- if (m_pWebSocketServer->listen(QHostAddress::Any, port))
- {
+ if (m_pWebSocketServer->listen(QHostAddress::Any, port)) {
qDebug() << "Echoserver listening on port" << port;
connect(m_pWebSocketServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
+ connect(m_pWebSocketServer, SIGNAL(closed()), this, SIGNAL(closed()));
}
}
//! [constructor]
+EchoServer::~EchoServer()
+{
+ m_pWebSocketServer->close();
+ while (!m_clients.isEmpty()) {
+ QWebSocket *pWebSocket = m_clients.takeFirst();
+ delete pWebSocket;
+ }
+}
+
//! [onNewConnection]
void EchoServer::onNewConnection()
{
@@ -68,7 +77,6 @@ void EchoServer::onNewConnection()
connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processMessage(QString)));
connect(pSocket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(processBinaryMessage(QByteArray)));
connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
- //connect(pSocket, SIGNAL(pong(quint64)), this, SLOT(processPong(quint64)));
m_clients << pSocket;
}
@@ -78,10 +86,10 @@ void EchoServer::onNewConnection()
void EchoServer::processMessage(QString message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
- if (pClient)
- {
+ if (pClient) {
pClient->write(message);
}
+ m_pWebSocketServer->close();
}
//! [processMessage]
@@ -89,8 +97,7 @@ void EchoServer::processMessage(QString message)
void EchoServer::processBinaryMessage(QByteArray message)
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
- if (pClient)
- {
+ if (pClient) {
pClient->write(message);
}
}
@@ -100,8 +107,7 @@ void EchoServer::processBinaryMessage(QByteArray message)
void EchoServer::socketDisconnected()
{
QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
- if (pClient)
- {
+ if (pClient) {
m_clients.removeAll(pClient);
pClient->deleteLater();
}
diff --git a/examples/echoserver/echoserver.h b/examples/echoserver/echoserver.h
index 0333f8f..2cd8922 100644
--- a/examples/echoserver/echoserver.h
+++ b/examples/echoserver/echoserver.h
@@ -53,8 +53,10 @@ class EchoServer : public QObject
Q_OBJECT
public:
explicit EchoServer(quint16 port, QObject *parent = Q_NULLPTR);
+ ~EchoServer();
Q_SIGNALS:
+ void closed();
private Q_SLOTS:
void onNewConnection();
diff --git a/examples/echoserver/main.cpp b/examples/echoserver/main.cpp
index b424666..def405f 100644
--- a/examples/echoserver/main.cpp
+++ b/examples/echoserver/main.cpp
@@ -44,9 +44,8 @@
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
- EchoServer server(1234);
-
- Q_UNUSED(server);
+ EchoServer *server = new EchoServer(1234);
+ QObject::connect(server, SIGNAL(closed()), &a, SLOT(quit()));
return a.exec();
}
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);
};
diff --git a/tests/auto/websocketprotocol/tst_websocketprotocol.cpp b/tests/auto/websocketprotocol/tst_websocketprotocol.cpp
index f088166..8e73921 100644
--- a/tests/auto/websocketprotocol/tst_websocketprotocol.cpp
+++ b/tests/auto/websocketprotocol/tst_websocketprotocol.cpp
@@ -117,10 +117,6 @@ void tst_WebSocketProtocol::tst_validMasks()
//otherwise, the intermediate object is deleted and the data pointer becomes invalid
QByteArray latin1 = inputdata.toLatin1();
char *data = latin1.data();
- //char *data = inputdata.toLatin1().data();
-
- qDebug() << hex << mask;
- qDebug() << QByteArray(data, inputdata.size()).toHex();
QWebSocketProtocol::mask(data, inputdata.size(), mask);
QCOMPARE(QByteArray::fromRawData(data, inputdata.size()), result);
diff --git a/tests/manual/compliance/tst_compliance.cpp b/tests/manual/compliance/tst_compliance.cpp
index 28fb54f..bd4f120 100644
--- a/tests/manual/compliance/tst_compliance.cpp
+++ b/tests/manual/compliance/tst_compliance.cpp
@@ -116,13 +116,13 @@ void tst_ComplianceTest::runTestCase(int nbr, int total)
url.setPath("/runCase?");
QUrlQuery query;
query.addQueryItem("case", QString::number(nbr + 1));
- query.addQueryItem("agent", "QWebSockets/0.9");
+ query.addQueryItem("agent", "QtWebSockets/1.0");
url.setQuery(query);
pWebSocket->open(url);
spy.wait(60000);
pWebSocket->close();
delete pWebSocket;
- pWebSocket = 0;
+ pWebSocket = Q_NULLPTR;
runTestCase(nbr + 1, total);
}
@@ -148,7 +148,6 @@ void tst_ComplianceTest::autobahnTest()
QVERIFY(numberOfTestCases > 0);
QObject::disconnect(pWebSocket, &QWebSocket::textMessageReceived, 0, 0);
-
runTestCases(0, numberOfTestCases);
url.setPath("/updateReports?");
@@ -158,7 +157,6 @@ void tst_ComplianceTest::autobahnTest()
pWebSocket->open(url);
spy.wait(60000);
delete pWebSocket;
- pWebSocket = 0;
}
QTEST_MAIN(tst_ComplianceTest)