summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFranck Dude <enstone83@gmail.com>2019-12-07 16:46:52 +0100
committerFranck Dude <enstone83@gmail.com>2019-12-13 20:09:40 +0100
commitcea5603ee1a56bb5d177f35ed3f884345875099e (patch)
treec7c942c55fc767d8a3f3beed93dcea0bfb8b4b63
parent92cec7af3ee88673d58e70e5b9a84a0cf55aa734 (diff)
downloadqtwebsockets-cea5603ee1a56bb5d177f35ed3f884345875099e.tar.gz
Fix websocket handshake request header parsing
Header ends with \r\n\r\n but there might be more data inside the tcpbuffer Never read past the header Task-number: QTBUG-70000 Change-Id: If3d4cb362646e43a91faf00f89e50510ff00fa56 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
-rw-r--r--src/websockets/qwebsocket_p.cpp6
-rw-r--r--src/websockets/qwebsocket_p.h2
-rw-r--r--src/websockets/qwebsocketserver_p.cpp33
3 files changed, 33 insertions, 8 deletions
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index 36aefd9..c9dbb1f 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -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();
}
/*!
diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h
index e72daa5..1db1077 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,
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index 8225b59..574adf5 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -430,9 +430,16 @@ 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");
+
+ QByteArray header = pTcpSocket->peek(pTcpSocket->bytesAvailable());
+ const int endOfHeaderIndex = header.indexOf(endOfHeaderMarker);
+ if (endOfHeaderIndex < 0) {
+ //then we don't have our header complete yet
return;
}
+ const int headerSize = endOfHeaderIndex + endOfHeaderMarker.size();
+
disconnect(pTcpSocket, &QTcpSocket::readyRead,
this, &QWebSocketServerPrivate::handshakeReceived);
bool success = false;
@@ -446,8 +453,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()) {
@@ -501,11 +520,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);
}