summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/websockets/sslechoserver/sslechoserver.cpp1
-rw-r--r--src/websockets/qwebsocket_p.cpp12
-rw-r--r--src/websockets/qwebsocket_p.h4
-rw-r--r--src/websockets/qwebsocketframe.cpp122
-rw-r--r--src/websockets/qwebsocketframe_p.h40
-rw-r--r--src/websockets/qwebsockethandshakerequest.cpp4
-rw-r--r--src/websockets/qwebsockethandshakerequest_p.h2
-rw-r--r--src/websockets/qwebsocketserver_p.cpp41
-rw-r--r--tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp1
-rw-r--r--tests/auto/websockets/websocketframe/tst_websocketframe.cpp26
11 files changed, 75 insertions, 180 deletions
diff --git a/.qmake.conf b/.qmake.conf
index 5c26162..1121008 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -3,4 +3,4 @@ load(qt_build_config)
CONFIG += warning_clean
DEFINES += QT_NO_FOREACH
-MODULE_VERSION = 5.14.2
+MODULE_VERSION = 5.15.0
diff --git a/examples/websockets/sslechoserver/sslechoserver.cpp b/examples/websockets/sslechoserver/sslechoserver.cpp
index 00bc6c1..5dc41e0 100644
--- a/examples/websockets/sslechoserver/sslechoserver.cpp
+++ b/examples/websockets/sslechoserver/sslechoserver.cpp
@@ -77,7 +77,6 @@ SslEchoServer::SslEchoServer(quint16 port, QObject *parent) :
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
sslConfiguration.setLocalCertificate(certificate);
sslConfiguration.setPrivateKey(sslKey);
- sslConfiguration.setProtocol(QSsl::TlsV1SslV3);
m_pWebSocketServer->setSslConfiguration(sslConfiguration);
if (m_pWebSocketServer->listen(QHostAddress::Any, port))
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index bca4ccd..1493e15 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -198,7 +198,7 @@ QAbstractSocket::SocketError QWebSocketPrivate::error() const
{
QAbstractSocket::SocketError err = QAbstractSocket::UnknownSocketError;
if (Q_LIKELY(m_pSocket))
- err = m_pSocket->error();
+ err = m_pSocket->socketError();
return err;
}
@@ -569,7 +569,7 @@ void QWebSocketPrivate::enableMasking(bool enable)
/*!
* \internal
*/
-void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
+void QWebSocketPrivate::makeConnections(QTcpSocket *pTcpSocket)
{
Q_ASSERT(pTcpSocket);
Q_Q(QWebSocket);
@@ -636,6 +636,10 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
&QWebSocketPrivate::processPong);
QObjectPrivate::connect(&m_dataProcessor, &QWebSocketDataProcessor::closeReceived, this,
&QWebSocketPrivate::processClose);
+
+ //fire readyread, in case we already have data inside the tcpSocket
+ if (pTcpSocket->bytesAvailable())
+ Q_EMIT pTcpSocket->readyRead();
}
/*!
@@ -1000,8 +1004,8 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
errorDescription = QWebSocket::tr("Malformed header in response: %1.").arg(headerLine);
break;
}
- lastHeader = m_headers.insertMulti(headerLine.left(colonPos).trimmed().toLower(),
- headerLine.mid(colonPos + 1).trimmed());
+ lastHeader = m_headers.insert(headerLine.left(colonPos).trimmed().toLower(),
+ headerLine.mid(colonPos + 1).trimmed());
}
}
diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h
index e72daa5..2d56f8a 100644
--- a/src/websockets/qwebsocket_p.h
+++ b/src/websockets/qwebsocket_p.h
@@ -182,7 +182,7 @@ private:
Q_REQUIRED_RESULT qint64 doWriteFrames(const QByteArray &data, bool isBinary);
- void makeConnections(const QTcpSocket *pTcpSocket);
+ void makeConnections(QTcpSocket *pTcpSocket);
void releaseConnections(const QTcpSocket *pTcpSocket);
QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength,
@@ -248,7 +248,7 @@ private:
int m_httpStatusCode;
int m_httpMajorVersion, m_httpMinorVersion;
QString m_httpStatusMessage;
- QMap<QString, QString> m_headers;
+ QMultiMap<QString, QString> m_headers;
friend class QWebSocketServerPrivate;
#ifdef Q_OS_WASM
diff --git a/src/websockets/qwebsocketframe.cpp b/src/websockets/qwebsocketframe.cpp
index 11373a7..cfa63ed 100644
--- a/src/websockets/qwebsocketframe.cpp
+++ b/src/websockets/qwebsocketframe.cpp
@@ -64,128 +64,6 @@ QT_BEGIN_NAMESPACE
/*!
\internal
*/
-QWebSocketFrame::QWebSocketFrame() :
- m_closeCode(QWebSocketProtocol::CloseCodeNormal),
- m_closeReason(),
- m_mask(0),
- m_opCode(QWebSocketProtocol::OpCodeReservedC),
- m_length(0),
- m_payload(),
- m_isFinalFrame(true),
- m_rsv1(false),
- m_rsv2(false),
- m_rsv3(false),
- m_isValid(false)
-{
-}
-
-/*!
- \internal
- */
-QWebSocketFrame::QWebSocketFrame(const QWebSocketFrame &other) :
- m_closeCode(other.m_closeCode),
- m_closeReason(other.m_closeReason),
- m_mask(other.m_mask),
- m_opCode(other.m_opCode),
- m_length(other.m_length),
- m_payload(other.m_payload),
- m_isFinalFrame(other.m_isFinalFrame),
- m_rsv1(other.m_rsv1),
- m_rsv2(other.m_rsv2),
- m_rsv3(other.m_rsv3),
- m_isValid(other.m_isValid),
- m_processingState(other.m_processingState)
-{
-}
-
-/*!
- \internal
- */
-QWebSocketFrame &QWebSocketFrame::operator =(const QWebSocketFrame &other)
-{
- m_closeCode = other.m_closeCode;
- m_closeReason = other.m_closeReason;
- m_isFinalFrame = other.m_isFinalFrame;
- m_mask = other.m_mask;
- m_rsv1 = other.m_rsv1;
- m_rsv2 = other.m_rsv2;
- m_rsv3 = other.m_rsv3;
- m_opCode = other.m_opCode;
- m_length = other.m_length;
- m_payload = other.m_payload;
- m_isValid = other.m_isValid;
- m_processingState = other.m_processingState;
-
- 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_mask(qMove(other.m_mask)),
- m_opCode(qMove(other.m_opCode)),
- m_length(qMove(other.m_length)),
- m_payload(qMove(other.m_payload)),
- m_isFinalFrame(qMove(other.m_isFinalFrame)),
- m_rsv1(qMove(other.m_rsv1)),
- m_rsv2(qMove(other.m_rsv2)),
- m_rsv3(qMove(other.m_rsv3)),
- m_isValid(qMove(other.m_isValid)),
- m_processingState(qMove(other.m_processingState))
-{}
-
-
-/*!
- \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);
- qSwap(m_processingState, other.m_processingState);
-
- 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);
- qSwap(m_processingState, other.m_processingState);
- }
-}
-
-/*!
- \internal
- */
QWebSocketProtocol::CloseCode QWebSocketFrame::closeCode() const
{
return isDone() ? m_closeCode : QWebSocketProtocol::CloseCodeGoingAway;
diff --git a/src/websockets/qwebsocketframe_p.h b/src/websockets/qwebsocketframe_p.h
index e2b4e9f..a8b9684 100644
--- a/src/websockets/qwebsocketframe_p.h
+++ b/src/websockets/qwebsocketframe_p.h
@@ -54,7 +54,7 @@
#include <QtCore/QString>
#include <QtCore/QByteArray>
#include <QtCore/QCoreApplication>
-#include <limits.h>
+#include <limits>
#include "qwebsockets_global.h"
#include "qwebsocketprotocol.h"
@@ -64,25 +64,15 @@ QT_BEGIN_NAMESPACE
class QIODevice;
-const quint64 MAX_FRAME_SIZE_IN_BYTES = INT_MAX - 1;
-const quint64 MAX_MESSAGE_SIZE_IN_BYTES = INT_MAX - 1;
+const quint64 MAX_FRAME_SIZE_IN_BYTES = std::numeric_limits<int>::max() - 1;
+const quint64 MAX_MESSAGE_SIZE_IN_BYTES = std::numeric_limits<int>::max() - 1;
class Q_AUTOTEST_EXPORT QWebSocketFrame
{
Q_DECLARE_TR_FUNCTIONS(QWebSocketFrame)
public:
- QWebSocketFrame();
- QWebSocketFrame(const QWebSocketFrame &other);
-
- QWebSocketFrame &operator =(const QWebSocketFrame &other);
-
-#ifdef Q_COMPILER_RVALUE_REFS
- QWebSocketFrame(QWebSocketFrame &&other);
- QWebSocketFrame &operator =(QWebSocketFrame &&other);
-#endif
-
- void swap(QWebSocketFrame &other);
+ QWebSocketFrame() = default;
QWebSocketProtocol::CloseCode closeCode() const;
QString closeReason() const;
@@ -106,18 +96,12 @@ public:
void readFrame(QIODevice *pIoDevice);
private:
- QWebSocketProtocol::CloseCode m_closeCode;
QString m_closeReason;
- quint32 m_mask;
- QWebSocketProtocol::OpCode m_opCode;
- quint64 m_length;
QByteArray m_payload;
-
- bool m_isFinalFrame;
- bool m_rsv1;
- bool m_rsv2;
- bool m_rsv3;
- bool m_isValid;
+ quint64 m_length = 0;
+ quint32 m_mask = 0;
+ QWebSocketProtocol::CloseCode m_closeCode = QWebSocketProtocol::CloseCodeNormal;
+ QWebSocketProtocol::OpCode m_opCode = QWebSocketProtocol::OpCodeReservedC;
enum ProcessingState
{
@@ -127,7 +111,13 @@ private:
PS_READ_PAYLOAD,
PS_DISPATCH_RESULT,
PS_WAIT_FOR_MORE_DATA
- } m_processingState{PS_READ_HEADER};
+ } m_processingState = PS_READ_HEADER;
+
+ bool m_isFinalFrame = true;
+ bool m_rsv1 = false;
+ bool m_rsv2 = false;
+ bool m_rsv3 = false;
+ bool m_isValid = false;
ProcessingState readFrameHeader(QIODevice *pIoDevice);
ProcessingState readFramePayloadLength(QIODevice *pIoDevice);
diff --git a/src/websockets/qwebsockethandshakerequest.cpp b/src/websockets/qwebsockethandshakerequest.cpp
index bfc8a3d..19df09b 100644
--- a/src/websockets/qwebsockethandshakerequest.cpp
+++ b/src/websockets/qwebsockethandshakerequest.cpp
@@ -268,8 +268,8 @@ void QWebSocketHandshakeRequest::readHandshake(QTextStream &textStream, int maxH
clear();
return;
}
- lastHeader = m_headers.insertMulti(headerLine.left(colonPos).trimmed().toLower(),
- headerLine.mid(colonPos + 1).trimmed());
+ lastHeader = m_headers.insert(headerLine.left(colonPos).trimmed().toLower(),
+ headerLine.mid(colonPos + 1).trimmed());
}
if (m_headers.size() > maxHeaders) {
clear();
diff --git a/src/websockets/qwebsockethandshakerequest_p.h b/src/websockets/qwebsockethandshakerequest_p.h
index e5762df..e14c05d 100644
--- a/src/websockets/qwebsockethandshakerequest_p.h
+++ b/src/websockets/qwebsockethandshakerequest_p.h
@@ -91,7 +91,7 @@ private:
int m_port;
bool m_isSecure;
bool m_isValid;
- QMap<QString, QString> m_headers;
+ QMultiMap<QString, QString> m_headers;
QList<QWebSocketProtocol::Version> m_versions;
QString m_key;
QString m_origin;
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index 966126d..8c75721 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -430,9 +430,24 @@ void QWebSocketServerPrivate::handshakeReceived()
//This is a bug in FireFox (see https://bugzilla.mozilla.org/show_bug.cgi?id=594502)
// According to RFC822 the body is separated from the headers by a null line (CRLF)
- if (!pTcpSocket->peek(pTcpSocket->bytesAvailable()).endsWith(QByteArrayLiteral("\r\n\r\n"))) {
+ const QByteArray& endOfHeaderMarker = QByteArrayLiteral("\r\n\r\n");
+
+ const qint64 byteAvailable = pTcpSocket->bytesAvailable();
+ QByteArray header = pTcpSocket->peek(byteAvailable);
+ const int endOfHeaderIndex = header.indexOf(endOfHeaderMarker);
+ if (endOfHeaderIndex < 0) {
+ //then we don't have our header complete yet
+ //check that no one is trying to exhaust our virtual memory
+ const qint64 maxHeaderLength = MAX_HEADERLINE_LENGTH * MAX_HEADERLINES + endOfHeaderMarker.size();
+ if (byteAvailable > maxHeaderLength) {
+ pTcpSocket->close();
+ setError(QWebSocketProtocol::CloseCodeTooMuchData,
+ QWebSocketServer::tr("Header is too large."));
+ }
return;
}
+ const int headerSize = endOfHeaderIndex + endOfHeaderMarker.size();
+
disconnect(pTcpSocket, &QTcpSocket::readyRead,
this, &QWebSocketServerPrivate::handshakeReceived);
bool success = false;
@@ -445,8 +460,20 @@ void QWebSocketServerPrivate::handshakeReceived()
return;
}
+ //don't read past the header
+ header.resize(headerSize);
+ //remove our header from the tcpSocket
+ qint64 skippedSize = pTcpSocket->skip(headerSize);
+
+ if (skippedSize != headerSize) {
+ pTcpSocket->close();
+ setError(QWebSocketProtocol::CloseCodeProtocolError,
+ QWebSocketServer::tr("Read handshake request header failed."));
+ return;
+ }
+
QWebSocketHandshakeRequest request(pTcpSocket->peerPort(), isSecure);
- QTextStream textStream(pTcpSocket);
+ QTextStream textStream(header, QIODevice::ReadOnly);
request.readHandshake(textStream, MAX_HEADERLINE_LENGTH, MAX_HEADERLINES);
if (request.isValid()) {
@@ -500,11 +527,13 @@ void QWebSocketServerPrivate::handleConnection(QTcpSocket *pTcpSocket) const
QObjectPrivate::connect(pTcpSocket, &QTcpSocket::readyRead,
this, &QWebSocketServerPrivate::handshakeReceived,
Qt::QueuedConnection);
- if (pTcpSocket->canReadLine()) {
- // We received some data! We must emit now to be sure that handshakeReceived is called
- // since the data could have been received before the signal and slot was connected.
- emit pTcpSocket->readyRead();
+
+ // We received some data! We must emit now to be sure that handshakeReceived is called
+ // since the data could have been received before the signal and slot was connected.
+ if (pTcpSocket->bytesAvailable()) {
+ Q_EMIT pTcpSocket->readyRead();
}
+
QObjectPrivate::connect(pTcpSocket, &QTcpSocket::disconnected,
this, &QWebSocketServerPrivate::onSocketDisconnected);
}
diff --git a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
index c40bb01..a56594c 100644
--- a/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
+++ b/tests/auto/websockets/qwebsocketserver/tst_qwebsocketserver.cpp
@@ -604,7 +604,6 @@ static void setupSecureServer(QWebSocketServer *secureServer)
sslConfiguration.setPeerVerifyMode(QSslSocket::VerifyNone);
sslConfiguration.setLocalCertificate(certificate);
sslConfiguration.setPrivateKey(sslKey);
- sslConfiguration.setProtocol(QSsl::TlsV1SslV3);
secureServer->setSslConfiguration(sslConfiguration);
}
#endif
diff --git a/tests/auto/websockets/websocketframe/tst_websocketframe.cpp b/tests/auto/websockets/websocketframe/tst_websocketframe.cpp
index 6b9aaaf..bbf0e5f 100644
--- a/tests/auto/websockets/websocketframe/tst_websocketframe.cpp
+++ b/tests/auto/websockets/websocketframe/tst_websocketframe.cpp
@@ -201,8 +201,8 @@ void tst_WebSocketFrame::tst_copyConstructorAndAssignment()
frame.readFrame(&buffer);
buffer.close();
+ auto compareFrames = [](const QWebSocketFrame &other, const QWebSocketFrame &frame)
{
- QWebSocketFrame other(frame);
QCOMPARE(other.closeCode(), frame.closeCode());
QCOMPARE(other.closeReason(), frame.closeReason());
QCOMPARE(other.hasMask(), frame.hasMask());
@@ -217,24 +217,20 @@ void tst_WebSocketFrame::tst_copyConstructorAndAssignment()
QCOMPARE(other.rsv1(), frame.rsv1());
QCOMPARE(other.rsv2(), frame.rsv2());
QCOMPARE(other.rsv3(), frame.rsv3());
+ };
+
+ {
+ QWebSocketFrame other(frame);
+ compareFrames(other, frame);
}
{
QWebSocketFrame other;
other = frame;
- QCOMPARE(other.closeCode(), frame.closeCode());
- QCOMPARE(other.closeReason(), frame.closeReason());
- QCOMPARE(other.hasMask(), frame.hasMask());
- QCOMPARE(other.isContinuationFrame(), frame.isContinuationFrame());
- QCOMPARE(other.isControlFrame(), frame.isControlFrame());
- QCOMPARE(other.isDataFrame(), frame.isDataFrame());
- QCOMPARE(other.isFinalFrame(), frame.isFinalFrame());
- QCOMPARE(other.isValid(), frame.isValid());
- QCOMPARE(other.mask(), frame.mask());
- QCOMPARE(other.opCode(), frame.opCode());
- QCOMPARE(other.payload(), frame.payload());
- QCOMPARE(other.rsv1(), frame.rsv1());
- QCOMPARE(other.rsv2(), frame.rsv2());
- QCOMPARE(other.rsv3(), frame.rsv3());
+ compareFrames(other, frame);
+ QWebSocketFrame other2 = std::move(other);
+ compareFrames(other2, frame);
+ QWebSocketFrame other3(std::move(other2));
+ compareFrames(other3, frame);
}
}