summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/websockets/qsslserver_p.cpp6
-rw-r--r--src/websockets/qwebsocket.cpp130
-rw-r--r--src/websockets/qwebsocket.h14
-rw-r--r--src/websockets/qwebsocket_p.cpp146
-rw-r--r--src/websockets/qwebsocket_p.h6
-rw-r--r--src/websockets/qwebsocketcorsauthenticator.cpp30
-rw-r--r--src/websockets/qwebsocketdataprocessor_p.cpp54
-rw-r--r--src/websockets/qwebsocketframe_p.cpp66
-rw-r--r--src/websockets/qwebsocketframe_p.h10
-rw-r--r--src/websockets/qwebsockethandshakerequest_p.cpp12
-rw-r--r--src/websockets/qwebsockethandshakerequest_p.h6
-rw-r--r--src/websockets/qwebsockethandshakeresponse_p.cpp55
-rw-r--r--src/websockets/qwebsockethandshakeresponse_p.h6
-rw-r--r--src/websockets/qwebsocketprotocol.cpp59
-rw-r--r--src/websockets/qwebsocketserver.cpp89
-rw-r--r--src/websockets/qwebsocketserver.h3
-rw-r--r--src/websockets/qwebsocketserver_p.cpp31
-rw-r--r--src/websockets/qwebsocketserver_p.h4
18 files changed, 476 insertions, 251 deletions
diff --git a/src/websockets/qsslserver_p.cpp b/src/websockets/qsslserver_p.cpp
index 009922c..c4474d8 100644
--- a/src/websockets/qsslserver_p.cpp
+++ b/src/websockets/qsslserver_p.cpp
@@ -74,8 +74,10 @@ void QSslServer::incomingConnection(qintptr socket)
pSslSocket->setSslConfiguration(m_sslConfiguration);
if (Q_LIKELY(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(peerVerifyError(QSslError)),
+ this, SIGNAL(peerVerifyError(QSslError)));
+ connect(pSslSocket, SIGNAL(sslErrors(QList<QSslError>)),
+ this, SIGNAL(sslErrors(QList<QSslError>)));
connect(pSslSocket, SIGNAL(encrypted()), this, SIGNAL(newEncryptedConnection()));
addPendingConnection(pSslSocket);
diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp
index 2887b84..64abe27 100644
--- a/src/websockets/qwebsocket.cpp
+++ b/src/websockets/qwebsocket.cpp
@@ -45,8 +45,10 @@
\inmodule QtWebSockets
\brief Implements a TCP socket that talks the websocket protocol.
- WebSockets is a web technology providing full-duplex communications channels over a single TCP connection.
- The WebSocket protocol was standardized by the IETF as \l {http://tools.ietf.org/html/rfc6455} {RFC 6455} in 2011.
+ WebSockets is a web technology providing full-duplex communications channels over
+ a single TCP connection.
+ The WebSocket protocol was standardized by the IETF as
+ \l {http://tools.ietf.org/html/rfc6455} {RFC 6455} in 2011.
QWebSocket can both be used in a client application and server application.
This class was modeled after QAbstractSocket.
@@ -59,10 +61,12 @@
/*!
\page echoclient.html example
\title QWebSocket client example
- \brief A sample websocket client that sends a message and displays the message that it receives back.
+ \brief A sample websocket client that sends a message and displays the message that
+ it receives back.
\section1 Description
- The EchoClient example implements a web socket client that sends a message to a websocket server and dumps the answer that it gets back.
+ The EchoClient example implements a web socket client that sends a message to a websocket server
+ and dumps the answer that it gets back.
This example should ideally be used with the EchoServer example.
\section1 Code
We start by connecting to the `connected()` signal.
@@ -70,7 +74,8 @@
After the connection, we open the socket to the given \a url.
\snippet echoclient/echoclient.cpp onConnected
- When the client is connected successfully, we connect to the `onTextMessageReceived()` signal, and send out "Hello, world!".
+ When the client is connected successfully, we connect to the `onTextMessageReceived()` signal,
+ and send out "Hello, world!".
If connected with the EchoServer, we will receive the same message back.
\snippet echoclient/echoclient.cpp onTextMessageReceived
@@ -130,7 +135,8 @@ not been filled in with new information when the signal returns.
/*!
\fn void QWebSocket::readChannelFinished()
- This signal is emitted when the input (reading) stream is closed in this device. It is emitted as soon as the closing is detected.
+ This signal is emitted when the input (reading) stream is closed in this device.
+ It is emitted as soon as the closing is detected.
\sa close()
*/
@@ -141,7 +147,8 @@ not been filled in with new information when the signal returns.
The \a bytes argument is set to the number of bytes that were written in this payload.
\note This signal has the same meaning both for secure and non-secure websockets.
- As opposed to QSslSocket, bytesWritten() is only emitted when encrypted data is effectively written (see QSslSocket:encryptedBytesWritten()).
+ As opposed to QSslSocket, bytesWritten() is only emitted when encrypted data is effectively
+ written (see QSslSocket:encryptedBytesWritten()).
\sa close()
*/
@@ -151,8 +158,8 @@ not been filled in with new information when the signal returns.
This signal is emitted whenever a text frame is received. The \a frame contains the data and
\a isLastFrame indicates whether this is the last frame of the complete message.
- This signal can be used to process large messages frame by frame, instead of waiting for the complete
- message to arrive.
+ This signal can be used to process large messages frame by frame, instead of waiting for the
+ complete message to arrive.
\sa binaryFrameReceived()
*/
@@ -162,22 +169,24 @@ not been filled in with new information when the signal returns.
This signal is emitted whenever a binary frame is received. The \a frame contains the data and
\a isLastFrame indicates whether this is the last frame of the complete message.
- This signal can be used to process large messages frame by frame, instead of waiting for the complete
- message to arrive.
+ This signal can be used to process large messages frame by frame, instead of waiting for the
+ complete message to arrive.
\sa textFrameReceived()
*/
/*!
\fn void QWebSocket::textMessageReceived(QString message);
- This signal is emitted whenever a text message is received. The \a message contains the received text.
+ This signal is emitted whenever a text message is received. The \a message contains the
+ received text.
\sa binaryMessageReceived()
*/
/*!
\fn void QWebSocket::binaryMessageReceived(QByteArray message);
- This signal is emitted whenever a binary message is received. The \a message contains the received bytes.
+ This signal is emitted whenever a binary message is received. The \a message contains the
+ received bytes.
\sa textMessageReceived()
*/
@@ -195,22 +204,27 @@ not been filled in with new information when the signal returns.
*/
/*!
\fn void QWebSocket::sslErrors(const QList<QSslError> &errors)
- QWebSocket emits this signal after the SSL handshake to indicate that one or more errors have occurred
- while establishing the identity of the peer.
+ QWebSocket emits this signal after the SSL handshake to indicate that one or more errors have
+ occurred while establishing the identity of the peer.
The errors are usually an indication that QWebSocket is unable to securely identify the peer.
Unless any action is taken, the connection will be dropped after this signal has been emitted.
- If you want to continue connecting despite the errors that have occurred, you must call QWebSocket::ignoreSslErrors() from inside a slot connected to this signal.
- If you need to access the error list at a later point, you can call sslErrors() (without arguments).
+ If you want to continue connecting despite the errors that have occurred, you must call
+ QWebSocket::ignoreSslErrors() from inside a slot connected to this signal.
+ If you need to access the error list at a later point, you can call sslErrors()
+ (without arguments).
- \a errors contains one or more errors that prevent QWebSocket from verifying the identity of the peer.
+ \a errors contains one or more errors that prevent QWebSocket from verifying the identity of
+ the peer.
- \note You cannot use Qt::QueuedConnection when connecting to this signal, or calling QWebSocket::ignoreSslErrors() will have no effect.
+ \note You cannot use Qt::QueuedConnection when connecting to this signal, or calling
+ QWebSocket::ignoreSslErrors() will have no effect.
*/
/*!
\fn void QWebSocket::pong(quint64 elapsedTime, QByteArray payload)
Emitted when a pong message is received in reply to a previous ping.
- \a elapsedTime contains the roundtrip time in milliseconds and \a payload contains an optional payload that was sent with the ping.
+ \a elapsedTime contains the roundtrip time in milliseconds and \a payload contains an optional
+ payload that was sent with the ping.
\sa ping()
*/
@@ -229,20 +243,25 @@ not been filled in with new information when the signal returns.
QT_BEGIN_NAMESPACE
/*!
- * \brief Creates a new QWebSocket with the given \a origin, the \a version of the protocol to use and \a parent.
+ * \brief Creates a new QWebSocket with the given \a origin,
+ * the \a version of the protocol to use and \a parent.
*
- * The \a origin of the client is as specified \l {http://tools.ietf.org/html/rfc6454} {RFC 6454}.
- * (The \a origin is not required for non-web browser clients (see \l {http://tools.ietf.org/html/rfc6455} {RFC 6455})).
+ * The \a origin of the client is as specified \l {http://tools.ietf.org/html/rfc6454}{RFC 6454}.
+ * (The \a origin is not required for non-web browser clients
+ * (see \l {http://tools.ietf.org/html/rfc6455}{RFC 6455})).
* \note Currently only V13 (\l {http://tools.ietf.org/html/rfc6455} {RFC 6455}) is supported
*/
-QWebSocket::QWebSocket(const QString &origin, QWebSocketProtocol::Version version, QObject *parent) :
+QWebSocket::QWebSocket(const QString &origin,
+ QWebSocketProtocol::Version version,
+ QObject *parent) :
QObject(parent),
d_ptr(new QWebSocketPrivate(origin, version, this, this))
{
}
/*!
- * \brief Destroys the QWebSocket. Closes the socket if it is still open, and releases any used resources.
+ * \brief Destroys the QWebSocket. Closes the socket if it is still open,
+ * and releases any used resources.
*/
QWebSocket::~QWebSocket()
{
@@ -250,7 +269,9 @@ QWebSocket::~QWebSocket()
}
/*!
- * \brief Aborts the current socket and resets the socket. Unlike close(), this function immediately closes the socket, discarding any pending data in the write buffer.
+ * \brief Aborts the current socket and resets the socket.
+ * Unlike close(), this function immediately closes the socket,
+ * discarding any pending data in the write buffer.
*/
void QWebSocket::abort()
{
@@ -272,7 +293,8 @@ QAbstractSocket::SocketError QWebSocket::error() const
/*!
\internal
*/
-QWebSocket::QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QObject *parent) :
+QWebSocket::QWebSocket(QTcpSocket *pTcpSocket,
+ QWebSocketProtocol::Version version, QObject *parent) :
QObject(parent),
d_ptr(new QWebSocketPrivate(pTcpSocket, version, this, this))
{
@@ -290,11 +312,14 @@ QString QWebSocket::errorString() const
}
/*!
- This function writes as much as possible from the internal write buffer to the underlying network socket, without blocking.
+ This function writes as much as possible from the internal write buffer
+ to the underlying network socket, without blocking.
If any data was written, this function returns true; otherwise false is returned.
Call this function if you need QWebSocket to start sending buffered data immediately.
The number of bytes successfully written depends on the operating system.
- In most cases, you do not need to call this function, because QWebSocket will start sending data automatically once control goes back to the event loop.
+ In most cases, you do not need to call this function,
+ because QWebSocket will start sending data automatically
+ once control goes back to the event loop.
In the absence of an event loop, call waitForBytesWritten() instead.
*/
bool QWebSocket::flush()
@@ -304,7 +329,8 @@ bool QWebSocket::flush()
}
/*!
- Sends the given \a message over the socket as a text message and returns the number of bytes actually sent.
+ Sends the given \a message over the socket as a text message and returns the number of bytes
+ actually sent.
\a message must be '\\0' terminated and is considered to be in UTF-8 encoded format.
\note When \a message is null or has zero length, zero is returned.
@@ -319,12 +345,13 @@ qint64 QWebSocket::write(const char *message)
}
/*!
- Sends the most \a maxSize bytes of the given \a message over the socket as a text message and returns the number of bytes actually sent.
+ Sends the most \a maxSize bytes of the given \a message over the socket as a text message
+ and returns the number of bytes actually sent.
\a message is considered to be in UTF-8 encoded format.
\note When \a message is null, has zero length or \a maxSize < 0, zero is returned.
- \note The maximum size of message, is limited by \l {QString::}{size_type}. It the message is larger,
- it is truncated to the maximum value of \l {QString::}{size_type}.
+ \note The maximum size of message, is limited by \l {QString::}{size_type}.
+ If the message is larger, it is truncated to the maximum value of \l {QString::}{size_type}.
\sa QString::fromUtf8(), QString::size_type
*/
@@ -335,7 +362,8 @@ qint64 QWebSocket::write(const char *message, qint64 maxSize)
}
/*!
- \brief Sends the given \a message over the socket as a text message and returns the number of bytes actually sent.
+ \brief Sends the given \a message over the socket as a text message and
+ returns the number of bytes actually sent.
*/
qint64 QWebSocket::write(const QString &message)
{
@@ -344,7 +372,8 @@ qint64 QWebSocket::write(const QString &message)
}
/*!
- \brief Sends the given \a data over the socket as a binary message and returns the number of bytes actually sent.
+ \brief Sends the given \a data over the socket as a binary message and
+ returns the number of bytes actually sent.
*/
qint64 QWebSocket::write(const QByteArray &data)
{
@@ -353,7 +382,9 @@ qint64 QWebSocket::write(const QByteArray &data)
}
/*!
- \brief Gracefully closes the socket with the given \a closeCode and \a reason. Any data in the write buffer is flushed before the socket is closed.
+ \brief Gracefully closes the socket with the given \a closeCode and \a reason.
+
+ Any data in the write buffer is flushed before the socket is closed.
The \a closeCode is a QWebSocketProtocol::CloseCode indicating the reason to close, and
\a reason describes the reason of the closure more in detail
*/
@@ -365,8 +396,9 @@ void QWebSocket::close(QWebSocketProtocol::CloseCode closeCode, const QString &r
/*!
\brief Opens a websocket connection using the given \a url.
- If \a mask is true, all frames will be masked; this is only necessary for client side sockets; servers should never mask
- \note A client socket must *always* mask its frames; servers may *never* mask its frames
+ If \a mask is true, all frames will be masked; this is only necessary for client side sockets;
+ servers should never mask.
+ \note A client socket must *always* mask its frames; servers may *never* mask its frames.
*/
void QWebSocket::open(const QUrl &url, bool mask)
{
@@ -378,7 +410,8 @@ void QWebSocket::open(const QUrl &url, bool mask)
\brief Pings the server to indicate that the connection is still alive.
Additional \a payload can be sent along the ping message.
- The size of the \a payload cannot be bigger than 125. If it is larger, the \a payload is clipped to 125 bytes.
+ The size of the \a payload cannot be bigger than 125.
+ If it is larger, the \a payload is clipped to 125 bytes.
\sa pong()
*/
@@ -442,7 +475,8 @@ void QWebSocket::ignoreSslErrors(const QList<QSslError> &errors)
/*!
Sets the socket's SSL configuration to be the contents of \a sslConfiguration.
- This function sets the local certificate, the ciphers, the private key and the CA certificates to those stored in \a sslConfiguration.
+ This function sets the local certificate, the ciphers, the private key and
+ the CA certificates to those stored in \a sslConfiguration.
It is not possible to set the SSL-state related fields.
\sa sslConfiguration()
*/
@@ -454,7 +488,8 @@ void QWebSocket::setSslConfiguration(const QSslConfiguration &sslConfiguration)
/*!
Returns the socket's SSL configuration state.
- The default SSL configuration of a socket is to use the default ciphers, default CA certificates, no local private key or certificate.
+ The default SSL configuration of a socket is to use the default ciphers,
+ default CA certificates, no local private key or certificate.
The SSL configuration also contains fields that can change with time without notice.
\sa setSslConfiguration()
@@ -650,6 +685,7 @@ void QWebSocket::resume()
/*!
Controls whether to pause upon receiving a notification. The \a pauseMode parameter specifies
the conditions in which the socket should be paused.
+
The only notification currently supported is sslErrors().
If set to PauseOnSslErrors, data transfer on the socket will be paused
and needs to be enabled explicitly again by calling resume().
@@ -666,9 +702,15 @@ void QWebSocket::setPauseMode(QAbstractSocket::PauseModes pauseMode)
/*!
Sets the size of QWebSocket's internal read buffer to be \a size bytes.
- If the buffer size is limited to a certain size, QWebSocket won't buffer more than this size of data.
- Exceptionally, a buffer size of 0 means that the read buffer is unlimited and all incoming data is buffered. This is the default.
- This option is useful if you only read the data at certain points in time (e.g., in a real-time streaming application) or if you want to protect your socket against receiving too much data, which may eventually cause your application to run out of memory.
+
+ If the buffer size is limited to a certain size, QWebSocket won't buffer more than
+ this size of data.
+ Exceptionally, a buffer size of 0 means that the read buffer is unlimited and
+ all incoming data is buffered. This is the default.
+ This option is useful if you only read the data at certain points in time
+ (e.g., in a real-time streaming application) or if you want to protect your socket against
+ receiving too much data, which may eventually cause your application to run out of memory.
+
\sa readBufferSize()
*/
void QWebSocket::setReadBufferSize(qint64 size)
diff --git a/src/websockets/qwebsocket.h b/src/websockets/qwebsocket.h
index 927350a..dbb13cf 100644
--- a/src/websockets/qwebsocket.h
+++ b/src/websockets/qwebsocket.h
@@ -104,10 +104,10 @@ public:
QWebSocketProtocol::CloseCode closeCode() const;
QString closeReason() const;
- qint64 write(const char *message); //send data as text
- qint64 write(const char *message, qint64 maxSize); //send data as text
- qint64 write(const QString &message); //send data as text
- qint64 write(const QByteArray &data); //send data as binary
+ qint64 write(const char *message) Q_REQUIRED_RESULT;
+ qint64 write(const char *message, qint64 maxSize) Q_REQUIRED_RESULT;
+ qint64 write(const QString &message) Q_REQUIRED_RESULT;
+ qint64 write(const QByteArray &data) Q_REQUIRED_RESULT;
#ifndef QT_NO_SSL
void ignoreSslErrors(const QList<QSslError> &errors);
@@ -116,7 +116,8 @@ public:
#endif
public Q_SLOTS:
- void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL, const QString &reason = QString());
+ void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL,
+ const QString &reason = QString());
void open(const QUrl &url, bool mask = true);
void ping(const QByteArray &payload = QByteArray());
#ifndef QT_NO_SSL
@@ -145,7 +146,8 @@ Q_SIGNALS:
#endif
private:
- QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QObject *parent = Q_NULLPTR);
+ QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version,
+ QObject *parent = Q_NULLPTR);
QWebSocketPrivate * const d_ptr;
};
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index 8491999..2b63860 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -86,7 +86,8 @@ QWebSocketConfiguration::QWebSocketConfiguration() :
/*!
\internal
*/
-QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
+QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::Version version,
+ QWebSocket *pWebSocket, QObject *parent) :
QObject(parent),
q_ptr(pWebSocket),
m_pSocket(),
@@ -115,7 +116,8 @@ QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::
/*!
\internal
*/
-QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
+QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version,
+ QWebSocket *pWebSocket, QObject *parent) :
QObject(parent),
q_ptr(pWebSocket),
m_pSocket(pTcpSocket),
@@ -318,7 +320,8 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r
payload.append(reason.toUtf8());
if (m_mustMask)
QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey);
- QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true);
+ QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE,
+ payload.size(), maskingKey, true);
frame.append(payload);
m_pSocket->write(frame);
m_pSocket->flush();
@@ -335,7 +338,9 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r
*/
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
+ //just delete the old socket for the moment;
+ //later, we can add more 'intelligent' handling by looking at the url
+ //m_pSocket.reset();
QTcpSocket *pTcpSocket = m_pSocket.take();
if (pTcpSocket) {
releaseConnections(pTcpSocket);
@@ -376,7 +381,8 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
m_pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
makeConnections(m_pSocket.data());
- connect(sslSocket, &QSslSocket::encryptedBytesWritten, q, &QWebSocket::bytesWritten);
+ connect(sslSocket, &QSslSocket::encryptedBytesWritten, q,
+ &QWebSocket::bytesWritten);
setSocketState(QAbstractSocket::ConnectingState);
sslSocket->setSslConfiguration(m_configuration.m_sslConfiguration);
@@ -403,7 +409,8 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask)
m_pSocket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
makeConnections(m_pSocket.data());
- connect(m_pSocket.data(), &QAbstractSocket::bytesWritten, q, &QWebSocket::bytesWritten);
+ connect(m_pSocket.data(), &QAbstractSocket::bytesWritten, q,
+ &QWebSocket::bytesWritten);
setSocketState(QAbstractSocket::ConnectingState);
#ifndef QT_NO_NETWORKPROXY
m_pSocket->setProxy(m_configuration.m_proxy);
@@ -430,14 +437,16 @@ void QWebSocketPrivate::ping(QByteArray payload)
if (payload.length() > 125)
payload.truncate(125);
m_pingTimer.restart();
- QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, payload.size(), 0 /*do not mask*/, true);
+ QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, payload.size(),
+ 0 /*do not mask*/, true);
pingFrame.append(payload);
(void)writeFrame(pingFrame);
}
/*!
\internal
- Sets the version to use for the websocket protocol; this must be set before the socket is opened.
+ Sets the version to use for the websocket protocol;
+ this must be set before the socket is opened.
*/
void QWebSocketPrivate::setVersion(QWebSocketProtocol::Version version)
{
@@ -510,26 +519,42 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
if (Q_LIKELY(pTcpSocket)) {
//pass through signals
- connect(pTcpSocket, static_cast<void (QAbstractSocket::*)(QAbstractSocket::SocketError)>(&QAbstractSocket::error),
- q, static_cast<void (QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error));
- connect(pTcpSocket, &QAbstractSocket::proxyAuthenticationRequired, q, &QWebSocket::proxyAuthenticationRequired);
- connect(pTcpSocket, &QAbstractSocket::readChannelFinished, q, &QWebSocket::readChannelFinished);
+ typedef void (QAbstractSocket:: *ASErrorSignal)(QAbstractSocket::SocketError);
+ typedef void (QWebSocket:: *WSErrorSignal)(QAbstractSocket::SocketError);
+ connect(pTcpSocket,
+ static_cast<ASErrorSignal>(&QAbstractSocket::error),
+ q, static_cast<WSErrorSignal>(&QWebSocket::error));
+ connect(pTcpSocket, &QAbstractSocket::proxyAuthenticationRequired, q,
+ &QWebSocket::proxyAuthenticationRequired);
+ connect(pTcpSocket, &QAbstractSocket::readChannelFinished, q,
+ &QWebSocket::readChannelFinished);
connect(pTcpSocket, &QAbstractSocket::aboutToClose, q, &QWebSocket::aboutToClose);
//catch signals
- connect(pTcpSocket, &QAbstractSocket::stateChanged, this, &QWebSocketPrivate::processStateChanged);
- //!!!important to use a QueuedConnection here; with QTcpSocket there is no problem, but with QSslSocket the processing hangs
- connect(pTcpSocket, &QAbstractSocket::readyRead, this, &QWebSocketPrivate::processData, Qt::QueuedConnection);
+ connect(pTcpSocket, &QAbstractSocket::stateChanged, this,
+ &QWebSocketPrivate::processStateChanged);
+ //!!!important to use a QueuedConnection here;
+ //with QTcpSocket there is no problem, but with QSslSocket the processing hangs
+ connect(pTcpSocket, &QAbstractSocket::readyRead, this,
+ &QWebSocketPrivate::processData, Qt::QueuedConnection);
}
- connect(&m_dataProcessor, &QWebSocketDataProcessor::textFrameReceived, q, &QWebSocket::textFrameReceived);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryFrameReceived, q, &QWebSocket::binaryFrameReceived);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryMessageReceived, q, &QWebSocket::binaryMessageReceived);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::textMessageReceived, q, &QWebSocket::textMessageReceived);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::errorEncountered, this, &QWebSocketPrivate::close);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::pingReceived, this, &QWebSocketPrivate::processPing);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::pongReceived, this, &QWebSocketPrivate::processPong);
- connect(&m_dataProcessor, &QWebSocketDataProcessor::closeReceived, this, &QWebSocketPrivate::processClose);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::textFrameReceived, q,
+ &QWebSocket::textFrameReceived);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryFrameReceived, q,
+ &QWebSocket::binaryFrameReceived);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::binaryMessageReceived, q,
+ &QWebSocket::binaryMessageReceived);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::textMessageReceived, q,
+ &QWebSocket::textMessageReceived);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::errorEncountered, this,
+ &QWebSocketPrivate::close);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::pingReceived, this,
+ &QWebSocketPrivate::processPing);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::pongReceived, this,
+ &QWebSocketPrivate::processPong);
+ connect(&m_dataProcessor, &QWebSocketDataProcessor::closeReceived, this,
+ &QWebSocketPrivate::processClose);
}
/*!
@@ -609,7 +634,9 @@ QString QWebSocketPrivate::closeReason() const
/*!
* \internal
*/
-QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame)
+QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode,
+ quint64 payloadLength, quint32 maskingKey,
+ bool lastFrame)
{
QByteArray header;
quint8 byte = 0x00;
@@ -641,7 +668,8 @@ QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode,
if (maskingKey != 0) {
const quint32 mask = qToBigEndian<quint32>(maskingKey);
- header.append(static_cast<const char *>(static_cast<const void *>(&mask)), sizeof(quint32));
+ header.append(static_cast<const char *>(static_cast<const void *>(&mask)),
+ sizeof(quint32));
}
} else {
setErrorString(QStringLiteral("WebSocket::getHeader: payload too big!"));
@@ -689,7 +717,8 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
const bool isFirstFrame = (i == 0);
const quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
- const QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE;
+ const QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode
+ : QWebSocketProtocol::OC_CONTINUE;
//write header
bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
@@ -705,7 +734,8 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
payloadWritten += written;
} else {
m_pSocket->flush();
- setErrorString(tr("Error writing bytes to socket: %1.").arg(m_pSocket->errorString()));
+ setErrorString(tr("Error writing bytes to socket: %1.")
+ .arg(m_pSocket->errorString()));
Q_EMIT q->error(QAbstractSocket::NetworkError);
break;
}
@@ -842,18 +872,23 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
QString headerLine = readLine(pSocket);
QMap<QString, QString> headers;
while (!headerLine.isEmpty()) {
- const QStringList headerField = headerLine.split(QStringLiteral(": "), QString::SkipEmptyParts);
+ const QStringList headerField = headerLine.split(QStringLiteral(": "),
+ QString::SkipEmptyParts);
headers.insertMulti(headerField[0], headerField[1]);
headerLine = readLine(pSocket);
}
- const QString acceptKey = headers.value(QStringLiteral("Sec-WebSocket-Accept"), QStringLiteral(""));
+ const QString acceptKey = headers.value(QStringLiteral("Sec-WebSocket-Accept"),
+ QStringLiteral(""));
const QString upgrade = headers.value(QStringLiteral("Upgrade"), QStringLiteral(""));
const QString connection = headers.value(QStringLiteral("Connection"), QStringLiteral(""));
- //unused for the moment
- //const QString extensions = headers.value(QStringLiteral("Sec-WebSocket-Extensions"), QStringLiteral(""));
- //const QString protocol = headers.value(QStringLiteral("Sec-WebSocket-Protocol"), QStringLiteral(""));
- const QString version = headers.value(QStringLiteral("Sec-WebSocket-Version"), QStringLiteral(""));
+// unused for the moment
+// const QString extensions = headers.value(QStringLiteral("Sec-WebSocket-Extensions"),
+// QStringLiteral(""));
+// const QString protocol = headers.value(QStringLiteral("Sec-WebSocket-Protocol"),
+// QStringLiteral(""));
+ const QString version = headers.value(QStringLiteral("Sec-WebSocket-Version"),
+ QStringLiteral(""));
if (Q_LIKELY(httpStatusCode == 101)) {
//HTTP/x.y 101 Switching Protocols
@@ -868,27 +903,38 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
const QString accept = calculateAcceptKey(m_key);
ok = (accept == acceptKey);
if (!ok)
- errorDescription = tr("Accept-Key received from server %1 does not match the client key %2.").arg(acceptKey).arg(accept);
+ errorDescription =
+ tr("Accept-Key received from server %1 does not match the client key %2.")
+ .arg(acceptKey).arg(accept);
} else {
- errorDescription = tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.").arg(statusLine);
+ errorDescription =
+ tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
+ .arg(statusLine);
}
} else if (httpStatusCode == 400) {
//HTTP/1.1 400 Bad Request
if (!version.isEmpty()) {
- const QStringList versions = version.split(QStringLiteral(", "), QString::SkipEmptyParts);
+ const QStringList versions = version.split(QStringLiteral(", "),
+ QString::SkipEmptyParts);
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(", ")));
+ errorDescription =
+ tr("Handshake: Server requests a version that we don't support: %1.")
+ .arg(versions.join(QStringLiteral(", ")));
ok = false;
} else {
//we tried v13, but something different went wrong
- errorDescription = tr("QWebSocketPrivate::processHandshake: Unknown error condition encountered. Aborting connection.");
+ errorDescription =
+ tr("QWebSocketPrivate::processHandshake: Unknown error condition " \
+ "encountered. Aborting connection.");
ok = false;
}
}
} else {
- errorDescription = tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).").arg(httpStatusCode).arg(httpStatusMessage);
+ errorDescription =
+ tr("QWebSocketPrivate::processHandshake: Unhandled http status code: %1 (%2).")
+ .arg(httpStatusCode).arg(httpStatusMessage);
ok = false;
}
@@ -915,7 +961,15 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
case QAbstractSocket::ConnectedState:
if (webSocketState == QAbstractSocket::ConnectingState) {
m_key = generateKey();
- const 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;
@@ -944,15 +998,6 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
}
}
-//order of events:
-//connectToHost is called
-//our socket state is set to "connecting", and tcpSocket->connectToHost is called
-//the tcpsocket is opened, a handshake message is sent; a readyRead signal is thrown
-//this signal is catched by processData
-//when OUR socket state is in the "connecting state", this means that
-//we have received data from the server (response to handshake), and that we
-//should "upgrade" our socket to a websocket (connected state)
-//if our socket was already upgraded, then we need to process websocket data
/*!
\internal
*/
@@ -1021,7 +1066,8 @@ QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
QStringLiteral("Sec-WebSocket-Key: ") % QString::fromLatin1(key);
if (!origin.isEmpty())
handshakeRequest << QStringLiteral("Origin: ") % origin;
- handshakeRequest << QStringLiteral("Sec-WebSocket-Version: ") % QString::number(QWebSocketProtocol::currentVersion());
+ handshakeRequest << QStringLiteral("Sec-WebSocket-Version: ")
+ % QString::number(QWebSocketProtocol::currentVersion());
if (extensions.length() > 0)
handshakeRequest << QStringLiteral("Sec-WebSocket-Extensions: ") % extensions;
if (protocols.length() > 0)
diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h
index 544035f..68317ea 100644
--- a/src/websockets/qwebsocket_p.h
+++ b/src/websockets/qwebsocket_p.h
@@ -170,7 +170,8 @@ private Q_SLOTS:
private:
QWebSocket * const q_ptr;
- QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent = Q_NULLPTR);
+ QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version,
+ QWebSocket *pWebSocket, QObject *parent = Q_NULLPTR);
void setVersion(QWebSocketProtocol::Version version);
void setResourceName(const QString &resourceName);
void setRequestUrl(const QUrl &requestUrl);
@@ -186,7 +187,8 @@ private:
void makeConnections(const QTcpSocket *pTcpSocket);
void releaseConnections(const QTcpSocket *pTcpSocket);
- QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame);
+ QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength,
+ quint32 maskingKey, bool lastFrame);
QString calculateAcceptKey(const QByteArray &key) const;
QString createHandShakeRequest(QString resourceName,
QString host,
diff --git a/src/websockets/qwebsocketcorsauthenticator.cpp b/src/websockets/qwebsocketcorsauthenticator.cpp
index 72ccf7d..df7c6b9 100644
--- a/src/websockets/qwebsocketcorsauthenticator.cpp
+++ b/src/websockets/qwebsocketcorsauthenticator.cpp
@@ -43,14 +43,19 @@
\class QWebSocketCorsAuthenticator
\inmodule QtWebSockets
- \brief The QWebSocketCorsAuthenticator class provides an authenticator object for Cross Origin Requests (CORS).
+ \brief The QWebSocketCorsAuthenticator class provides an authenticator object for
+ Cross Origin Requests (CORS).
- The QWebSocketCorsAuthenticator class is used in the \l{QWebSocketServer::}{originAuthenticationRequired()} signal.
+ The QWebSocketCorsAuthenticator class is used in the
+ \l{QWebSocketServer::}{originAuthenticationRequired()} signal.
The class provides a way to pass back the required information to the QWebSocketServer.
- It provides applications with fine-grained control over which origin URLs are allowed and which aren't.
+ It provides applications with fine-grained control over which origin URLs are allowed
+ and which aren't.
By default, every origin is accepted.
- To get fine grained control, an application connects the \l{QWebSocketServer::}{originAuthenticationRequired()} signal to
- a slot. When the origin (QWebSocketCorsAuthenticator::origin()) is accepted, it calls QWebSocketCorsAuthenticator::setAllowed(true)
+ To get fine grained control, an application connects the
+ \l{QWebSocketServer::}{originAuthenticationRequired()} signal to a slot.
+ When the origin (QWebSocketCorsAuthenticator::origin()) is accepted,
+ it calls QWebSocketCorsAuthenticator::setAllowed(true)
\note Checking on the origin does not make much sense when the server is accessed
via a non-browser client, as that client can set whatever origin header it likes.
@@ -68,7 +73,8 @@ QT_BEGIN_NAMESPACE
/*!
\internal
*/
-QWebSocketCorsAuthenticatorPrivate::QWebSocketCorsAuthenticatorPrivate(const QString &origin, bool allowed) :
+QWebSocketCorsAuthenticatorPrivate::QWebSocketCorsAuthenticatorPrivate(const QString &origin,
+ bool allowed) :
m_origin(origin),
m_isAllowed(allowed)
{}
@@ -84,7 +90,7 @@ QWebSocketCorsAuthenticatorPrivate::~QWebSocketCorsAuthenticatorPrivate()
\note By default, allowed() returns true. This means that per default every origin is accepted.
*/
QWebSocketCorsAuthenticator::QWebSocketCorsAuthenticator(const QString &origin) :
- d_ptr(new QWebSocketCorsAuthenticatorPrivate(origin, true)) //all origins are per default allowed
+ d_ptr(new QWebSocketCorsAuthenticatorPrivate(origin, true))
{
}
@@ -106,7 +112,8 @@ QWebSocketCorsAuthenticator::QWebSocketCorsAuthenticator(const QWebSocketCorsAut
/*!
Assigns \a other to this authenticator object
*/
-QWebSocketCorsAuthenticator &QWebSocketCorsAuthenticator::operator =(const QWebSocketCorsAuthenticator &other)
+QWebSocketCorsAuthenticator &
+QWebSocketCorsAuthenticator::operator =(const QWebSocketCorsAuthenticator &other)
{
Q_D(QWebSocketCorsAuthenticator);
if (this != &other) {
@@ -128,7 +135,8 @@ QWebSocketCorsAuthenticator::QWebSocketCorsAuthenticator(QWebSocketCorsAuthentic
/*!
Move-assigns \a other to this instance.
*/
-QWebSocketCorsAuthenticator &QWebSocketCorsAuthenticator::operator =(QWebSocketCorsAuthenticator &&other)
+QWebSocketCorsAuthenticator &
+QWebSocketCorsAuthenticator::operator =(QWebSocketCorsAuthenticator &&other)
{
qSwap(d_ptr, other.d_ptr);
return *this;
@@ -157,7 +165,9 @@ QString QWebSocketCorsAuthenticator::origin() const
}
/*!
- Allows or disallows the origin. Setting \a allowed to true, will accept the connection request for the given origin.
+ Allows or disallows the origin. Setting \a allowed to true, will accept the connection request
+ for the given origin.
+
Setting \a allowed to false, will reject the connection request.
\note By default, all origins are accepted.
diff --git a/src/websockets/qwebsocketdataprocessor_p.cpp b/src/websockets/qwebsocketdataprocessor_p.cpp
index 68791ff..620f8c4 100644
--- a/src/websockets/qwebsocketdataprocessor_p.cpp
+++ b/src/websockets/qwebsocketdataprocessor_p.cpp
@@ -40,12 +40,16 @@
****************************************************************************/
/*!
\class QWebSocketDataProcessor
- The class QWebSocketDataProcessor is responsible for reading, validating and interpreting data from a websocket.
- It reads data from a QIODevice, validates it against RFC 6455, and parses it into frames (data, control).
- It emits signals that correspond to the type of the frame: textFrameReceived(), binaryFrameReceived(),
- textMessageReceived(), binaryMessageReceived(), pingReceived(), pongReceived() and closeReceived().
+ The class QWebSocketDataProcessor is responsible for reading, validating and
+ interpreting data from a websocket.
+ It reads data from a QIODevice, validates it against RFC 6455, and parses it into
+ frames (data, control).
+ It emits signals that correspond to the type of the frame: textFrameReceived(),
+ binaryFrameReceived(), textMessageReceived(), binaryMessageReceived(), pingReceived(),
+ pongReceived() and closeReceived().
Whenever an error is detected, the errorEncountered() signal is emitted.
- QWebSocketDataProcessor also checks if a frame is allowed in a sequence of frames (e.g. a continuation frame cannot follow a final frame).
+ QWebSocketDataProcessor also checks if a frame is allowed in a sequence of frames
+ (e.g. a continuation frame cannot follow a final frame).
This class is an internal class used by QWebSocketInternal for data processing and validation.
\sa Frame()
@@ -131,31 +135,44 @@ void QWebSocketDataProcessor::process(QIODevice *pIoDevice)
//we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY
if (Q_UNLIKELY(!m_isFragmented && frame.isContinuationFrame())) {
clear();
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, tr("Received Continuation frame, while there is nothing to continue."));
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR,
+ tr("Received Continuation frame, while there is " \
+ "nothing to continue."));
return;
}
- if (Q_UNLIKELY(m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame())) {
+ if (Q_UNLIKELY(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)."));
+ 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()) {
m_opCode = frame.opCode();
m_isFragmented = !frame.isFinalFrame();
}
- quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OC_TEXT) ? m_textMessage.length() : m_binaryMessage.length();
- if (Q_UNLIKELY((messageLength + quint64(frame.payload().length())) > MAX_MESSAGE_SIZE_IN_BYTES)) {
+ quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OC_TEXT)
+ ? m_textMessage.length()
+ : m_binaryMessage.length();
+ if (Q_UNLIKELY((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."));
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_TOO_MUCH_DATA,
+ tr("Received message is too big."));
return;
}
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));
+ 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 (Q_UNLIKELY(failed)) {
clear();
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_WRONG_DATATYPE, tr("Invalid UTF-8 code encountered."));
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_WRONG_DATATYPE,
+ tr("Invalid UTF-8 code encountered."));
return;
} else {
m_textMessage.append(frameTxt);
@@ -204,7 +221,8 @@ void QWebSocketDataProcessor::clear()
}
}
if (!m_pConverterState)
- m_pConverterState = new QTextCodec::ConverterState(QTextCodec::ConvertInvalidToNull | QTextCodec::IgnoreHeader);
+ m_pConverterState = new QTextCodec::ConverterState(QTextCodec::ConvertInvalidToNull |
+ QTextCodec::IgnoreHeader);
}
/*!
@@ -228,7 +246,8 @@ bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame)
QString closeReason;
QByteArray payload = frame.payload();
if (Q_UNLIKELY(payload.size() == 1)) {
- //size is either 0 (no close code and no reason) or >= 2 (at least a close code of 2 bytes)
+ //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 (Q_LIKELY(payload.size() > 1)) {
@@ -272,7 +291,8 @@ bool QWebSocketDataProcessor::processControlFrame(const QWebSocketFrame &frame)
break;
default:
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, tr("Invalid opcode detected: %1").arg(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 87011f5..9765027 100644
--- a/src/websockets/qwebsocketframe_p.cpp
+++ b/src/websockets/qwebsocketframe_p.cpp
@@ -41,11 +41,14 @@
/*!
\class QWebSocketFrame
- The class QWebSocketFrame is responsible for reading, validating and interpreting frames from a websocket.
- It reads data from a QIODevice, validates it against RFC 6455, and parses it into a frame (data, control).
+ The class QWebSocketFrame is responsible for reading, validating and
+ interpreting frames from a websocket.
+ It reads data from a QIODevice, validates it against RFC 6455, and parses it into a
+ frame (data, control).
Whenever an error is detected, isValid() returns false.
- \note The QWebSocketFrame class does not look at valid sequences of frames. It processes frames one at a time.
+ \note The QWebSocketFrame class does not look at valid sequences of frames.
+ It processes frames one at a time.
\note It is the QWebSocketDataProcessor that takes the sequence into account.
\sa DataProcessor()
@@ -282,6 +285,8 @@ QByteArray QWebSocketFrame::payload() const
}
/*!
+ Resets all member variables, and invalidates the object.
+
\internal
*/
void QWebSocketFrame::clear()
@@ -307,7 +312,9 @@ bool QWebSocketFrame::isValid() const
return m_isValid;
}
-#define WAIT_FOR_MORE_DATA(dataSizeInBytes) { returnState = processingState; processingState = PS_WAIT_FOR_MORE_DATA; dataWaitSize = dataSizeInBytes; }
+#define WAIT_FOR_MORE_DATA(dataSizeInBytes) \
+ { returnState = processingState; \
+ processingState = PS_WAIT_FOR_MORE_DATA; dataWaitSize = dataSizeInBytes; }
/*!
\internal
@@ -333,7 +340,8 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
//the GUI will hang for at most 5 seconds
//maybe, a QStateMachine should be used
if (!pIoDevice->waitForReadyRead(5000)) {
- frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Timeout when reading data from socket."));
+ frame.setError(QWebSocketProtocol::CC_GOING_AWAY,
+ QObject::tr("Timeout when reading data from socket."));
processingState = PS_DISPATCH_RESULT;
} else {
processingState = returnState;
@@ -386,7 +394,9 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
uchar length[2] = {0};
bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 2);
if (Q_UNLIKELY(bytesRead == -1)) {
- frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Error occurred while reading from the network: %1").arg(pIoDevice->errorString()));
+ frame.setError(QWebSocketProtocol::CC_GOING_AWAY,
+ QObject::tr("Error occurred while reading from the network: %1")
+ .arg(pIoDevice->errorString()));
processingState = PS_DISPATCH_RESULT;
} else {
payloadLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(length));
@@ -395,7 +405,9 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
//"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."));
+ frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
+ QObject::tr("Lengths smaller than 126 " \
+ "must be expressed as one byte."));
processingState = PS_DISPATCH_RESULT;
} else {
processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
@@ -411,20 +423,26 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
uchar length[8] = {0};
bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 8);
if (Q_UNLIKELY(bytesRead < 8)) {
- frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, QObject::tr("Something went wrong during reading from the network."));
+ frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION,
+ QObject::tr("Something went wrong during "\
+ "reading from the network."));
processingState = PS_DISPATCH_RESULT;
} else {
- //Most significant bit must be set to 0 as per http://tools.ietf.org/html/rfc6455#section-5.2
+ //Most significant bit must be set to 0 as
+ //per http://tools.ietf.org/html/rfc6455#section-5.2
payloadLength = qFromBigEndian<quint64>(length);
if (Q_UNLIKELY(payloadLength & (quint64(1) << 63))) {
- frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Highest bit of payload length is not 0."));
+ frame.setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
+ QObject::tr("Highest bit of payload length is not 0."));
processingState = PS_DISPATCH_RESULT;
} else if (Q_UNLIKELY(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."));
+ 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 {
processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
@@ -438,9 +456,12 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
case PS_READ_MASK:
if (Q_LIKELY(pIoDevice->bytesAvailable() >= 4)) {
- bytesRead = pIoDevice->read(reinterpret_cast<char *>(&frame.m_mask), sizeof(frame.m_mask));
+ bytesRead = pIoDevice->read(reinterpret_cast<char *>(&frame.m_mask),
+ sizeof(frame.m_mask));
if (bytesRead == -1) {
- frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Error while reading from the network: %1.").arg(pIoDevice->errorString()));
+ frame.setError(QWebSocketProtocol::CC_GOING_AWAY,
+ QObject::tr("Error while reading from the network: %1.")
+ .arg(pIoDevice->errorString()));
processingState = PS_DISPATCH_RESULT;
} else {
frame.m_mask = qFromBigEndian(frame.m_mask);
@@ -455,16 +476,20 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
if (!payloadLength) {
processingState = PS_DISPATCH_RESULT;
} else if (Q_UNLIKELY(payloadLength > MAX_FRAME_SIZE_IN_BYTES)) {
- frame.setError(QWebSocketProtocol::CC_TOO_MUCH_DATA, QObject::tr("Maximum framesize exceeded."));
+ frame.setError(QWebSocketProtocol::CC_TOO_MUCH_DATA,
+ QObject::tr("Maximum framesize exceeded."));
processingState = PS_DISPATCH_RESULT;
} 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
+ //payloadLength can be safely cast to an integer,
+ //because MAX_FRAME_SIZE_IN_BYTES = MAX_INT
if (Q_UNLIKELY(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."));
+ frame.setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION,
+ QObject::tr("Some serious error occurred " \
+ "while reading from the network."));
processingState = PS_DISPATCH_RESULT;
} else {
if (hasMask)
@@ -472,7 +497,8 @@ QWebSocketFrame QWebSocketFrame::readFrame(QIODevice *pIoDevice)
processingState = PS_DISPATCH_RESULT;
}
} else {
- WAIT_FOR_MORE_DATA(payloadLength); //if payload is too big, then this will timeout
+ //if payload is too big, then this will timeout
+ WAIT_FOR_MORE_DATA(payloadLength);
}
}
break;
@@ -518,9 +544,11 @@ bool QWebSocketFrame::checkValidity()
setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Used reserved opcode"));
} else if (isControlFrame()) {
if (Q_UNLIKELY(m_length > 125)) {
- setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Controle frame is larger than 125 bytes"));
+ setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
+ QObject::tr("Controle frame is larger than 125 bytes"));
} else if (Q_UNLIKELY(!m_isFinalFrame)) {
- setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, QObject::tr("Controle frames cannot be fragmented"));
+ setError(QWebSocketProtocol::CC_PROTOCOL_ERROR,
+ QObject::tr("Controle frames cannot be fragmented"));
} else {
m_isValid = true;
}
diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h
index fdb22ea..bf7e1d5 100644
--- a/src/websockets/qwebsocketframe_p.h
+++ b/src/websockets/qwebsocketframe_p.h
@@ -85,7 +85,7 @@ public:
QWebSocketProtocol::OpCode opCode() const;
QByteArray payload() const;
- void clear(); //resets all member variables, and invalidates the object
+ void clear();
bool isValid() const;
@@ -96,12 +96,12 @@ private:
QString m_closeReason;
bool m_isFinalFrame;
quint32 m_mask;
- int m_rsv1; //reserved field 1
- int m_rsv2; //reserved field 2
- int m_rsv3; //reserved field 3
+ int m_rsv1;
+ int m_rsv2;
+ int m_rsv3;
QWebSocketProtocol::OpCode m_opCode;
- quint8 m_length; //length field as read from the header; this is 1 byte, which when 126 or 127, indicates a large payload
+ quint8 m_length;
QByteArray m_payload;
bool m_isValid;
diff --git a/src/websockets/qwebsockethandshakerequest_p.cpp b/src/websockets/qwebsockethandshakerequest_p.cpp
index 5def894..6708d4b 100644
--- a/src/websockets/qwebsockethandshakerequest_p.cpp
+++ b/src/websockets/qwebsockethandshakerequest_p.cpp
@@ -219,7 +219,8 @@ QTextStream &QWebSocketHandshakeRequest::readFromStream(QTextStream &textStream)
QString headerLine = textStream.readLine();
m_headers.clear();
while (!headerLine.isEmpty()) {
- const QStringList headerField = headerLine.split(QStringLiteral(": "), QString::SkipEmptyParts);
+ const QStringList headerField = headerLine.split(QStringLiteral(": "),
+ QString::SkipEmptyParts);
if (Q_UNLIKELY(headerField.length() < 2)) {
clear();
return textStream;
@@ -247,7 +248,8 @@ QTextStream &QWebSocketHandshakeRequest::readFromStream(QTextStream &textStream)
clear();
return textStream;
}
- const QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString((*i).trimmed());
+ const QWebSocketProtocol::Version ver =
+ QWebSocketProtocol::versionFromString((*i).trimmed());
m_versions << ver;
}
}
@@ -258,7 +260,8 @@ QTextStream &QWebSocketHandshakeRequest::readFromStream(QTextStream &textStream)
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);
+ const QStringList connectionLine = connection.split(QStringLiteral(","),
+ QString::SkipEmptyParts);
QStringList connectionValues;
for (QStringList::const_iterator c = connectionLine.begin(); c != connectionLine.end(); ++c)
connectionValues << (*c).trimmed();
@@ -272,7 +275,8 @@ QTextStream &QWebSocketHandshakeRequest::readFromStream(QTextStream &textStream)
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) {
+ 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();
diff --git a/src/websockets/qwebsockethandshakerequest_p.h b/src/websockets/qwebsockethandshakerequest_p.h
index 9cd0ce5..a7829a0 100644
--- a/src/websockets/qwebsockethandshakerequest_p.h
+++ b/src/websockets/qwebsockethandshakerequest_p.h
@@ -88,7 +88,8 @@ public:
private:
QTextStream &readFromStream(QTextStream &textStream);
- Q_AUTOTEST_EXPORT friend QTextStream &operator >>(QTextStream &stream, QWebSocketHandshakeRequest &request);
+ Q_AUTOTEST_EXPORT friend QTextStream &operator >>(QTextStream &stream,
+ QWebSocketHandshakeRequest &request);
int m_port;
bool m_isSecure;
@@ -102,7 +103,8 @@ private:
QUrl m_requestUrl;
};
-Q_AUTOTEST_EXPORT QTextStream & operator >>(QTextStream &stream, QWebSocketHandshakeRequest &request);
+Q_AUTOTEST_EXPORT QTextStream & operator >>(QTextStream &stream,
+ QWebSocketHandshakeRequest &request);
QT_END_NAMESPACE
diff --git a/src/websockets/qwebsockethandshakeresponse_p.cpp b/src/websockets/qwebsockethandshakeresponse_p.cpp
index 2202234..dbf4b6f 100644
--- a/src/websockets/qwebsockethandshakeresponse_p.cpp
+++ b/src/websockets/qwebsockethandshakeresponse_p.cpp
@@ -60,12 +60,13 @@ QT_BEGIN_NAMESPACE
/*!
\internal
*/
-QWebSocketHandshakeResponse::QWebSocketHandshakeResponse(const QWebSocketHandshakeRequest &request,
- const QString &serverName,
- bool isOriginAllowed,
- const QList<QWebSocketProtocol::Version> &supportedVersions,
- const QList<QString> &supportedProtocols,
- const QList<QString> &supportedExtensions) :
+QWebSocketHandshakeResponse::QWebSocketHandshakeResponse(
+ const QWebSocketHandshakeRequest &request,
+ const QString &serverName,
+ bool isOriginAllowed,
+ const QList<QWebSocketProtocol::Version> &supportedVersions,
+ const QList<QString> &supportedProtocols,
+ const QList<QString> &supportedExtensions) :
m_isValid(false),
m_canUpgrade(false),
m_response(),
@@ -126,12 +127,13 @@ QString QWebSocketHandshakeResponse::calculateAcceptKey(const QString &key) cons
/*!
\internal
*/
-QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandshakeRequest &request,
- const QString &serverName,
- bool isOriginAllowed,
- const QList<QWebSocketProtocol::Version> &supportedVersions,
- const QList<QString> &supportedProtocols,
- const QList<QString> &supportedExtensions)
+QString QWebSocketHandshakeResponse::getHandshakeResponse(
+ const QWebSocketHandshakeRequest &request,
+ const QString &serverName,
+ bool isOriginAllowed,
+ const QList<QWebSocketProtocol::Version> &supportedVersions,
+ const QList<QString> &supportedProtocols,
+ const QList<QString> &supportedExtensions)
{
QStringList response;
m_canUpgrade = false;
@@ -145,10 +147,14 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandsh
} 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
+ 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 (Q_UNLIKELY(matchingVersions.isEmpty())) {
m_error = QWebSocketProtocol::CC_PROTOCOL_ERROR;
@@ -170,12 +176,14 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandsh
QString origin = request.origin().trimmed();
if (origin.isEmpty())
origin = QStringLiteral("*");
- response << QStringLiteral("Server: ") % serverName <<
- QStringLiteral("Access-Control-Allow-Credentials: false") << //do not allow credentialed request (containing cookies)
- QStringLiteral("Access-Control-Allow-Methods: GET") << //only GET is allowed during handshaking
- QStringLiteral("Access-Control-Allow-Headers: content-type") << //this is OK; only the content-type header is allowed, no other headers are accepted
- QStringLiteral("Access-Control-Allow-Origin: ") % origin <<
- QStringLiteral("Date: ") % QDateTime::currentDateTimeUtc().toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"));
+ response << QStringLiteral("Server: ") % serverName <<
+ QStringLiteral("Access-Control-Allow-Credentials: false") <<
+ QStringLiteral("Access-Control-Allow-Methods: GET") <<
+ QStringLiteral("Access-Control-Allow-Headers: content-type") <<
+ QStringLiteral("Access-Control-Allow-Origin: ") % origin <<
+ QStringLiteral("Date: ") %
+ QDateTime::currentDateTimeUtc()
+ .toString(QStringLiteral("ddd, dd MMM yyyy hh:mm:ss 'GMT'"));
m_acceptedVersion = QWebSocketProtocol::currentVersion();
m_canUpgrade = true;
@@ -190,7 +198,8 @@ QString QWebSocketHandshakeResponse::getHandshakeResponse(const QWebSocketHandsh
QStringList versions;
Q_FOREACH (QWebSocketProtocol::Version version, supportedVersions)
versions << QString::number(static_cast<int>(version));
- response << QStringLiteral("Sec-WebSocket-Version: ") % versions.join(QStringLiteral(", "));
+ response << QStringLiteral("Sec-WebSocket-Version: ")
+ % versions.join(QStringLiteral(", "));
}
}
response << QStringLiteral("\r\n"); //append empty line at end of header
diff --git a/src/websockets/qwebsockethandshakeresponse_p.h b/src/websockets/qwebsockethandshakeresponse_p.h
index 799079a..1c88d52 100644
--- a/src/websockets/qwebsockethandshakeresponse_p.h
+++ b/src/websockets/qwebsockethandshakeresponse_p.h
@@ -109,10 +109,12 @@ private:
const QList<QString> &supportedExtensions);
QTextStream &writeToStream(QTextStream &textStream) const;
- Q_AUTOTEST_EXPORT friend QTextStream & operator <<(QTextStream &stream, const QWebSocketHandshakeResponse &response);
+ Q_AUTOTEST_EXPORT friend QTextStream & operator <<(QTextStream &stream,
+ const QWebSocketHandshakeResponse &response);
};
-Q_AUTOTEST_EXPORT QTextStream & operator <<(QTextStream &stream, const QWebSocketHandshakeResponse &response);
+Q_AUTOTEST_EXPORT QTextStream & operator <<(QTextStream &stream,
+ const QWebSocketHandshakeResponse &response);
QT_END_NAMESPACE
diff --git a/src/websockets/qwebsocketprotocol.cpp b/src/websockets/qwebsocketprotocol.cpp
index e25767a..cd95438 100644
--- a/src/websockets/qwebsocketprotocol.cpp
+++ b/src/websockets/qwebsocketprotocol.cpp
@@ -86,52 +86,58 @@ QT_BEGIN_NAMESPACE
<http://code.google.com/p/pywebsocket/wiki/WebSocketProtocolSpec>
\value V_Unknow
- \value V_0 hixie76: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 & hybi-00: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00.
- Works with key1, key2 and a key in the payload.
- Attribute: Sec-WebSocket-Draft value 0.
- \value V_4 hybi-04: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-04.txt.
- Changed handshake: key1, key2, key3 ==> Sec-WebSocket-Key, Sec-WebSocket-Nonce, Sec-WebSocket-Accept
- Sec-WebSocket-Draft renamed to Sec-WebSocket-Version
- Sec-WebSocket-Version = 4
- \value V_5 hybi-05: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-05.txt.
- Sec-WebSocket-Version = 5
- Removed Sec-WebSocket-Nonce
- Added Sec-WebSocket-Accept
- \value V_6 Sec-WebSocket-Version = 6.
- \value V_7 hybi-07: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07.
- Sec-WebSocket-Version = 7
- \value V_8 hybi-8, hybi-9, hybi-10, hybi-11 and hybi-12.
- Status codes 1005 and 1006 are added and all codes are now unsigned
- Internal error results in 1006
- \value V_13 hybi-13, hybi14, hybi-15, hybi-16, hybi-17 and RFC 6455.
- Sec-WebSocket-Version = 13
- Status code 1004 is now reserved
- Added 1008, 1009 and 1010
- Must support TLS
- Clarify multiple version support
- \value V_LATEST Refers to the latest know version to QWebSockets.
+ \value V_0 hixie76: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 &
+ hybi-00: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00.
+ Works with key1, key2 and a key in the payload.
+ Attribute: Sec-WebSocket-Draft value 0.
+ \value V_4 hybi-04: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-04.txt.
+ Changed handshake: key1, key2, key3
+ ==> Sec-WebSocket-Key, Sec-WebSocket-Nonce, Sec-WebSocket-Accept
+ Sec-WebSocket-Draft renamed to Sec-WebSocket-Version
+ Sec-WebSocket-Version = 4
+ \value V_5 hybi-05: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-05.txt.
+ Sec-WebSocket-Version = 5
+ Removed Sec-WebSocket-Nonce
+ Added Sec-WebSocket-Accept
+ \value V_6 Sec-WebSocket-Version = 6.
+ \value V_7 hybi-07: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07.
+ Sec-WebSocket-Version = 7
+ \value V_8 hybi-8, hybi-9, hybi-10, hybi-11 and hybi-12.
+ Status codes 1005 and 1006 are added and all codes are now unsigned
+ Internal error results in 1006
+ \value V_13 hybi-13, hybi14, hybi-15, hybi-16, hybi-17 and RFC 6455.
+ Sec-WebSocket-Version = 13
+ Status code 1004 is now reserved
+ Added 1008, 1009 and 1010
+ Must support TLS
+ Clarify multiple version support
+ \value V_LATEST Refers to the latest know version to QWebSockets.
*/
/*!
\fn QWebSocketProtocol::isOpCodeReserved(OpCode code)
Checks if \a code is a valid OpCode
+
\internal
*/
/*!
\fn QWebSocketProtocol::isCloseCodeValid(int closeCode)
Checks if \a closeCode is a valid web socket close code
+
\internal
*/
/*!
\fn QWebSocketProtocol::currentVersion()
Returns the latest version that WebSocket is supporting
+
\internal
*/
/*!
Parses the \a versionString and converts it to a Version value
+
\internal
*/
QWebSocketProtocol::Version QWebSocketProtocol::versionFromString(const QString &versionString)
@@ -148,6 +154,7 @@ QWebSocketProtocol::Version QWebSocketProtocol::versionFromString(const QString
/*!
Mask the \a payload with the given \a maskingKey and stores the result back in \a payload.
+
\internal
*/
void QWebSocketProtocol::mask(QByteArray *payload, quint32 maskingKey)
@@ -157,7 +164,9 @@ void QWebSocketProtocol::mask(QByteArray *payload, quint32 maskingKey)
}
/*!
- Masks the \a payload of length \a size with the given \a maskingKey and stores the result back in \a payload.
+ Masks the \a payload of length \a size with the given \a maskingKey and
+ stores the result back in \a payload.
+
\internal
*/
void QWebSocketProtocol::mask(char *payload, quint64 size, quint32 maskingKey)
diff --git a/src/websockets/qwebsocketserver.cpp b/src/websockets/qwebsocketserver.cpp
index e811e3a..ea7144d 100644
--- a/src/websockets/qwebsocketserver.cpp
+++ b/src/websockets/qwebsocketserver.cpp
@@ -46,7 +46,8 @@
\brief Implements a websocket-based server.
- It is modeled after QTcpServer, and behaves the same. So, if you know how to use QTcpServer, you know how to use QWebSocketServer.
+ It is modeled after QTcpServer, and behaves the same. So, if you know how to use QTcpServer,
+ you know how to use QWebSocketServer.
This class makes it possible to accept incoming websocket connections.
You can specify the port or have QWebSocketServer pick one automatically.
You can listen on a specific address or on all the machine's addresses.
@@ -54,9 +55,12 @@
The newConnection() signal is then emitted each time a client connects to the server.
Call nextPendingConnection() to accept the pending connection as a connected QWebSocket.
- The function returns a pointer to a QWebSocket in QAbstractSocket::ConnectedState that you can use for communicating with the client.
- If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human readable description of what happened.
- When listening for connections, the address and port on which the server is listening are available as serverAddress() and serverPort().
+ The function returns a pointer to a QWebSocket in QAbstractSocket::ConnectedState that you can
+ use for communicating with the client.
+ If an error occurs, serverError() returns the type of error, and errorString() can be called
+ to get a human readable description of what happened.
+ When listening for connections, the address and port on which the server is listening are
+ available as serverAddress() and serverPort().
Calling close() makes QWebSocketServer stop listening for incoming connections.
\sa echoserver.html
@@ -70,20 +74,27 @@
\brief A sample websocket server echoing back messages sent to it.
\section1 Description
- The echoserver example implements a web socket server that echoes back everything that is sent to it.
+ The echoserver example implements a web socket server that echoes back everything that is sent
+ to it.
\section1 Code
- We start by creating a QWebSocketServer (`new QWebSocketServer()`). After the creation, we listen on all local network interfaces (`QHostAddress::Any`) on the specified \a port.
+ We start by creating a QWebSocketServer (`new QWebSocketServer()`). After the creation, we listen
+ on all local network interfaces (`QHostAddress::Any`) on the specified \a port.
\snippet echoserver/echoserver.cpp constructor
- If listening is successful, we connect the `newConnection()` signal to the slot `onNewConnection()`.
- The `newConnection()` signal will be thrown whenever a new web socket client is connected to our server.
+ If listening is successful, we connect the `newConnection()` signal to the slot
+ `onNewConnection()`.
+ The `newConnection()` signal will be thrown whenever a new web socket client is connected to our
+ server.
\snippet echoserver/echoserver.cpp onNewConnection
- When a new connection is received, the client QWebSocket is retrieved (`nextPendingConnection()`), and the signals we are interested in
- are connected to our slots (`textMessageReceived()`, `binaryMessageReceived()` and `disconnected()`).
- The client socket is remembered in a list, in case we would like to use it later (in this example, nothing is done with it).
+ When a new connection is received, the client QWebSocket is retrieved (`nextPendingConnection()`),
+ and the signals we are interested in are connected to our slots
+ (`textMessageReceived()`, `binaryMessageReceived()` and `disconnected()`).
+ The client socket is remembered in a list, in case we would like to use it later
+ (in this example, nothing is done with it).
\snippet echoserver/echoserver.cpp processMessage
- Whenever `processMessage()` is triggered, we retrieve the sender, and if valid, send back the original message (`send()`).
+ Whenever `processMessage()` is triggered, we retrieve the sender, and if valid, send back the
+ original message (`send()`).
The same is done with binary messages.
\snippet echoserver/echoserver.cpp processBinaryMessage
The only difference is that the message now is a QByteArray instead of a QString.
@@ -126,8 +137,9 @@
/*!
\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)
- is allowed in the \a authenticator object (by issuing \l{QWebSocketCorsAuthenticator::}{setAllowed()})
+ The slot connected to this signal should indicate whether the origin
+ (which can be determined by the origin() call) is allowed in the \a authenticator object
+ (by issuing \l{QWebSocketCorsAuthenticator::}{setAllowed()})
If no slot is connected to this signal, all origins will be accepted by default.
@@ -199,11 +211,14 @@ QT_BEGIN_NAMESPACE
\a parent is passed to the QObject constructor.
*/
-QWebSocketServer::QWebSocketServer(const QString &serverName, SecureMode secureMode, QObject *parent) :
+QWebSocketServer::QWebSocketServer(const QString &serverName, SecureMode secureMode,
+ QObject *parent) :
QObject(parent),
d_ptr(new QWebSocketServerPrivate(serverName,
#ifndef QT_NO_SSL
- (secureMode == SECURE_MODE) ? QWebSocketServerPrivate::SECURE_MODE : QWebSocketServerPrivate::NON_SECURE_MODE,
+ (secureMode == SECURE_MODE) ?
+ QWebSocketServerPrivate::SECURE_MODE :
+ QWebSocketServerPrivate::NON_SECURE_MODE,
#else
QWebSocketServerPrivate::NON_SECURE_MODE,
#endif
@@ -216,7 +231,8 @@ QWebSocketServer::QWebSocketServer(const QString &serverName, SecureMode secureM
}
/*!
- Destroys the WebSocketServer object. If the server is listening for connections, the socket is automatically closed.
+ Destroys the WebSocketServer object. If the server is listening for connections,
+ the socket is automatically closed.
Any client WebSockets that are still connected are closed and deleted.
\sa close()
@@ -258,7 +274,8 @@ bool QWebSocketServer::hasPendingConnections() const
}
/*!
- Returns true if the server is currently listening for incoming connections; otherwise returns false.
+ Returns true if the server is currently listening for incoming connections;
+ otherwise returns false.
\sa listen()
*/
@@ -296,8 +313,11 @@ int QWebSocketServer::maxPendingConnections() const
/*!
Returns the next pending connection as a connected WebSocket object.
- The socket is created as a child of the server, which means that it is automatically deleted when the WebSocketServer object is destroyed. It is still a good idea to delete the object explicitly when you are done with it, to avoid wasting memory.
- 0 is returned if this function is called when there are no pending connections.
+ The socket is created as a child of the server, which means that it is automatically
+ deleted when the WebSocketServer object is destroyed.
+ It is still a good idea to delete the object explicitly when you are done with it,
+ to avoid wasting memory.
+ Q_NULLPTR is returned if this function is called when there are no pending connections.
Note: The returned WebSocket object cannot be used from another thread..
@@ -352,7 +372,8 @@ void QWebSocketServer::setProxy(const QNetworkProxy &networkProxy)
#ifndef QT_NO_SSL
/*!
Sets the SSL configuration for the websocket server to \a sslConfiguration.
- This method has no effect if QWebSocketServer runs in non-secure mode (QWebSocketServer::NON_SECURE_MODE).
+ This method has no effect if QWebSocketServer runs in non-secure mode
+ (QWebSocketServer::NON_SECURE_MODE).
\sa sslConfiguration(), SecureMode
*/
@@ -387,7 +408,8 @@ void QWebSocketServer::resumeAccepting()
}
/*!
- Sets the server name that will be used during the http handshake phase to the given \a serverName.
+ Sets the server name that will be used during the http handshake phase to the given
+ \a serverName.
Existing connected clients will not be notified of this change, only newly connecting clients
will see this new name.
*/
@@ -407,7 +429,8 @@ QString QWebSocketServer::serverName() const
}
/*!
- Returns the server's address if the server is listening for connections; otherwise returns QHostAddress::Null.
+ Returns the server's address if the server is listening for connections; otherwise returns
+ QHostAddress::Null.
\sa serverPort(), listen()
*/
@@ -435,6 +458,7 @@ QWebSocketServer::SecureMode QWebSocketServer::secureMode() const
/*!
Returns an error code for the last error that occurred.
+
\sa errorString()
*/
QWebSocketProtocol::CloseCode QWebSocketServer::error() const
@@ -445,6 +469,7 @@ QWebSocketProtocol::CloseCode QWebSocketServer::error() const
/*!
Returns the server's port if the server is listening for connections; otherwise returns 0.
+
\sa serverAddress(), listen()
*/
quint16 QWebSocketServer::serverPort() const
@@ -455,10 +480,15 @@ quint16 QWebSocketServer::serverPort() const
/*!
Sets the maximum number of pending accepted connections to \a numConnections.
- WebSocketServer will accept no more than \a numConnections incoming connections before nextPendingConnection() is called.
+ WebSocketServer will accept no more than \a numConnections incoming connections before
+ nextPendingConnection() is called.
By default, the limit is 30 pending connections.
- Clients may still able to connect after the server has reached its maximum number of pending connections (i.e., WebSocket can still emit the connected() signal). WebSocketServer will stop accepting the new connections, but the operating system may still keep them in queue.
+ Clients may still able to connect after the server has reached its maximum number of
+ pending connections (i.e., WebSocket can still emit the connected() signal).
+ WebSocketServer will stop accepting the new connections, but the operating system may still
+ keep them in queue.
+
\sa maxPendingConnections(), hasPendingConnections()
*/
void QWebSocketServer::setMaxPendingConnections(int numConnections)
@@ -468,7 +498,8 @@ void QWebSocketServer::setMaxPendingConnections(int numConnections)
}
/*!
- Sets the socket descriptor this server should use when listening for incoming connections to \a socketDescriptor.
+ Sets the socket descriptor this server should use when listening for incoming connections to
+ \a socketDescriptor.
Returns true if the socket is set successfully; otherwise returns false.
The socket is assumed to be in listening state.
@@ -482,8 +513,10 @@ bool QWebSocketServer::setSocketDescriptor(int socketDescriptor)
}
/*!
- Returns the native socket descriptor the server uses to listen for incoming instructions, or -1 if the server is not listening.
- If the server is using QNetworkProxy, the returned descriptor may not be usable with native socket functions.
+ Returns the native socket descriptor the server uses to listen for incoming instructions,
+ or -1 if the server is not listening.
+ If the server is using QNetworkProxy, the returned descriptor may not be usable with
+ native socket functions.
\sa setSocketDescriptor(), isListening()
*/
diff --git a/src/websockets/qwebsocketserver.h b/src/websockets/qwebsocketserver.h
index c34cab3..35ca3aa 100644
--- a/src/websockets/qwebsocketserver.h
+++ b/src/websockets/qwebsocketserver.h
@@ -76,7 +76,8 @@ public:
NON_SECURE_MODE
};
- explicit QWebSocketServer(const QString &serverName, SecureMode secureMode, QObject *parent = Q_NULLPTR);
+ explicit QWebSocketServer(const QString &serverName, SecureMode secureMode,
+ QObject *parent = Q_NULLPTR);
virtual ~QWebSocketServer();
bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index d5d98bd..0eecd15 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -60,8 +60,10 @@ QT_BEGIN_NAMESPACE
/*!
\internal
*/
-QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWebSocketServerPrivate::SecureMode secureMode,
- QWebSocketServer * const pWebSocketServer, QObject *parent) :
+QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName,
+ QWebSocketServerPrivate::SecureMode secureMode,
+ QWebSocketServer * const pWebSocketServer,
+ QObject *parent) :
QObject(parent),
q_ptr(pWebSocketServer),
m_pTcpServer(Q_NULLPTR),
@@ -84,14 +86,17 @@ QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWeb
m_pTcpServer = pSslServer;
if (Q_LIKELY(m_pTcpServer)) {
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>)));
+ 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)));
+ connect(m_pTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), q_ptr,
+ SIGNAL(acceptError(QAbstractSocket::SocketError)));
}
/*!
@@ -379,8 +384,10 @@ void QWebSocketServerPrivate::handshakeReceived()
if (m_pendingConnections.length() >= maxPendingConnections()) {
pTcpSocket->close();
- qWarning() << tr("Too many pending connections: new websocket connection not accepted.");
- setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, tr("Too many pending connections."));
+ qWarning() <<
+ tr("Too many pending connections: new websocket connection not accepted.");
+ setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION,
+ tr("Too many pending connections."));
return;
}
@@ -405,14 +412,17 @@ void QWebSocketServerPrivate::handshakeReceived()
httpStream.flush();
if (response.canUpgrade()) {
- QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
+ QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket,
+ request,
+ response);
if (pWebSocket) {
pWebSocket->setParent(this);
addPendingConnection(pWebSocket);
Q_EMIT q->newConnection();
success = true;
} else {
- setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION, tr("Upgrading to websocket failed."));
+ setError(QWebSocketProtocol::CC_ABNORMAL_DISCONNECTION,
+ tr("Upgrading to websocket failed."));
}
}
else {
@@ -427,7 +437,8 @@ void QWebSocketServerPrivate::handshakeReceived()
pTcpSocket->close();
}
} else {
- qWarning() << tr("Sender socket is NULL. This should not happen, otherwise it is a Qt bug!!!");
+ 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 b9d382e..8bf5725 100644
--- a/src/websockets/qwebsocketserver_p.h
+++ b/src/websockets/qwebsocketserver_p.h
@@ -81,7 +81,9 @@ public:
NON_SECURE_MODE
};
- explicit QWebSocketServerPrivate(const QString &serverName, SecureMode secureMode, QWebSocketServer * const pWebSocketServer, QObject *parent = Q_NULLPTR);
+ explicit QWebSocketServerPrivate(const QString &serverName, SecureMode secureMode,
+ QWebSocketServer * const pWebSocketServer,
+ QObject *parent = Q_NULLPTR);
virtual ~QWebSocketServerPrivate();
void close();