diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2022-11-15 14:12:34 +0100 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2022-11-24 09:39:00 +0000 |
commit | 69e2b30057003c0ed17c3478d60fea249546a168 (patch) | |
tree | 34f8b7bdc7d23e55bfa5a6ddda1b6ff781e599be /src | |
parent | 0fbd3decd0dd694063edd06a174f137ec30d3741 (diff) | |
download | qtwebsockets-69e2b30057003c0ed17c3478d60fea249546a168.tar.gz |
QWebSocket: honor subprotocols specified with setRawHeader
We would error out with a ConnectionRejected if the server accepted
one of the protocols specified directly in the header since we
did not consider those at all.
Fixes: QTBUG-108276
Pick-to: 6.4
Change-Id: Ifbb316c9d4871fd764e03c74caefa10f5b757155
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/websockets/qwebsocket_p.cpp | 30 | ||||
-rw-r--r-- | src/websockets/qwebsocket_p.h | 2 | ||||
-rw-r--r-- | src/websockets/qwebsocket_wasm_p.cpp | 9 |
3 files changed, 29 insertions, 12 deletions
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index 294e361..4be504e 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -318,6 +318,24 @@ void QWebSocketPrivate::_q_updateSslConfiguration() #endif +QStringList QWebSocketPrivate::requestedSubProtocols() const +{ + auto subprotocolsRequestedInRawHeader = [this]() { + QStringList protocols; + QByteArray rawProtocols = m_request.rawHeader("Sec-WebSocket-Protocol"); + QLatin1StringView rawProtocolsView(rawProtocols); + const QStringList &optionsProtocols = m_options.subprotocols(); + for (auto &&entry : rawProtocolsView.tokenize(u',', Qt::SkipEmptyParts)) { + if (QLatin1StringView trimmed = entry.trimmed(); !trimmed.isEmpty()) { + if (!optionsProtocols.contains(trimmed)) + protocols << trimmed; + } + } + return protocols; + }; + return m_options.subprotocols() + subprotocolsRequestedInRawHeader(); +} + /*! Called from QWebSocketServer \internal @@ -1002,8 +1020,7 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket) #endif const QString protocol = QString::fromLatin1(parser.combinedHeaderValue( QByteArrayLiteral("sec-websocket-protocol"))); - - if (!protocol.isEmpty() && !handshakeOptions().subprotocols().contains(protocol)) { + if (!protocol.isEmpty() && !requestedSubProtocols().contains(protocol)) { setErrorString(QWebSocket::tr("WebSocket server has chosen protocol %1 which has not been " "requested") .arg(protocol)); @@ -1096,9 +1113,14 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS QList<QPair<QString, QString> > headers; const auto headerList = m_request.rawHeaderList(); - for (const QByteArray &key : headerList) + for (const QByteArray &key : headerList) { + // protocols handled separately below + if (key.compare("Sec-WebSocket-Protocol", Qt::CaseInsensitive) == 0) + continue; headers << qMakePair(QString::fromLatin1(key), QString::fromLatin1(m_request.rawHeader(key))); + } + const QStringList subProtocols = requestedSubProtocols(); const auto format = QUrl::RemoveScheme | QUrl::RemoveUserInfo | QUrl::RemovePath | QUrl::RemoveQuery @@ -1108,7 +1130,7 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS host, origin(), QString(), - m_options.subprotocols(), + subProtocols, m_key, headers); if (handshake.isEmpty()) { diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index 08770e4..08be774 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -152,6 +152,8 @@ private: void enableMasking(bool enable); void setErrorString(const QString &errorString); + QStringList requestedSubProtocols() const; + void socketDestroyed(QObject *socket); void processData(); diff --git a/src/websockets/qwebsocket_wasm_p.cpp b/src/websockets/qwebsocket_wasm_p.cpp index e0b2156..4255203 100644 --- a/src/websockets/qwebsocket_wasm_p.cpp +++ b/src/websockets/qwebsocket_wasm_p.cpp @@ -174,15 +174,8 @@ void QWebSocketPrivate::open(const QNetworkRequest &request, // required for some use cases like MQTT. // add user subprotocol options - QStringList protocols = handshakeOptions().subprotocols(); - + QStringList protocols = requestedSubProtocols(); QByteArray secProto; - if (request.hasRawHeader("Sec-WebSocket-Protocol")) { - secProto = request.rawHeader("Sec-WebSocket-Protocol"); - if (!protocols.contains(secProto)) { - protocols.append(QString::fromLatin1(secProto)); - } - } if (!protocols.isEmpty()) { // comma-separated list of protocol strings, no spaces secProto = protocols.join(QStringLiteral(",")).toLatin1(); |