aboutsummaryrefslogtreecommitdiffstats
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)
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);
}