summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMårten Nordheim <marten.nordheim@qt.io>2022-11-15 14:12:34 +0100
committerMårten Nordheim <marten.nordheim@qt.io>2022-11-24 09:39:00 +0000
commit69e2b30057003c0ed17c3478d60fea249546a168 (patch)
tree34f8b7bdc7d23e55bfa5a6ddda1b6ff781e599be /src
parent0fbd3decd0dd694063edd06a174f137ec30d3741 (diff)
downloadqtwebsockets-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.cpp30
-rw-r--r--src/websockets/qwebsocket_p.h2
-rw-r--r--src/websockets/qwebsocket_wasm_p.cpp9
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();