summaryrefslogtreecommitdiff
path: root/src/websockets/qwebsocketserver_p.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/websockets/qwebsocketserver_p.cpp')
-rw-r--r--src/websockets/qwebsocketserver_p.cpp56
1 files changed, 45 insertions, 11 deletions
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index 8225b59..f922098 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -107,6 +107,12 @@ void QWebSocketServerPrivate::init()
q, &QWebSocketServer::sslErrors);
QObject::connect(pSslServer, &QSslServer::preSharedKeyAuthenticationRequired,
q, &QWebSocketServer::preSharedKeyAuthenticationRequired);
+ QObject::connect(pSslServer, &QSslServer::alertSent,
+ q, &QWebSocketServer::alertSent);
+ QObject::connect(pSslServer, &QSslServer::alertReceived,
+ q, &QWebSocketServer::alertReceived);
+ QObject::connect(pSslServer, &QSslServer::handshakeInterruptedOnError,
+ q, &QWebSocketServer::handshakeInterruptedOnError);
}
#else
qFatal("SSL not supported on this platform.");
@@ -430,24 +436,50 @@ 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 (Q_UNLIKELY(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;
bool isSecure = (m_secureMode == SecureMode);
- if (m_pendingConnections.length() >= maxPendingConnections()) {
+ if (Q_UNLIKELY(m_pendingConnections.length() >= maxPendingConnections())) {
pTcpSocket->close();
- pTcpSocket->deleteLater();
setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection,
QWebSocketServer::tr("Too many pending connections."));
return;
}
+ //don't read past the header
+ header.resize(headerSize);
+ //remove our header from the tcpSocket
+ qint64 skippedSize = pTcpSocket->skip(headerSize);
+
+ if (Q_UNLIKELY(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()) {
@@ -461,16 +493,16 @@ void QWebSocketServerPrivate::handshakeReceived()
supportedProtocols(),
supportedExtensions());
- if (response.isValid()) {
+ if (Q_LIKELY(response.isValid())) {
QTextStream httpStream(pTcpSocket);
httpStream << response;
httpStream.flush();
- if (response.canUpgrade()) {
+ if (Q_LIKELY(response.canUpgrade())) {
QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket,
request,
response);
- if (pWebSocket) {
+ if (Q_LIKELY(pWebSocket)) {
finishHandshakeTimeout(pTcpSocket);
addPendingConnection(pWebSocket);
Q_EMIT q->newConnection();
@@ -501,11 +533,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);
}