summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.qmake.conf2
-rw-r--r--examples/websockets/sslechoserver/sslechoserver.h2
-rw-r--r--src/websockets/doc/qtwebsockets.qdocconf2
-rw-r--r--src/websockets/qwebsocket_p.cpp67
-rw-r--r--src/websockets/qwebsockethandshakeresponse_p.h4
-rw-r--r--src/websockets/qwebsocketserver.cpp38
-rw-r--r--src/websockets/qwebsocketserver.h1
-rw-r--r--src/websockets/qwebsocketserver_p.cpp5
-rw-r--r--src/websockets/websockets.pro2
-rw-r--r--tests/auto/dataprocessor/tst_dataprocessor.cpp1
-rw-r--r--tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp16
11 files changed, 96 insertions, 44 deletions
diff --git a/.qmake.conf b/.qmake.conf
index e2217eb..cc1234c 100644
--- a/.qmake.conf
+++ b/.qmake.conf
@@ -3,4 +3,4 @@ load(qt_build_config)
CONFIG += qt_example_installs
CONFIG += warning_clean
-MODULE_VERSION = 5.3.1
+MODULE_VERSION = 5.4.0
diff --git a/examples/websockets/sslechoserver/sslechoserver.h b/examples/websockets/sslechoserver/sslechoserver.h
index 84dfeab..f4e9a9b 100644
--- a/examples/websockets/sslechoserver/sslechoserver.h
+++ b/examples/websockets/sslechoserver/sslechoserver.h
@@ -56,8 +56,6 @@ public:
explicit SslEchoServer(quint16 port, QObject *parent = Q_NULLPTR);
virtual ~SslEchoServer();
-Q_SIGNALS:
-
private Q_SLOTS:
void onNewConnection();
void processTextMessage(QString message);
diff --git a/src/websockets/doc/qtwebsockets.qdocconf b/src/websockets/doc/qtwebsockets.qdocconf
index db1553d..5358450 100644
--- a/src/websockets/doc/qtwebsockets.qdocconf
+++ b/src/websockets/doc/qtwebsockets.qdocconf
@@ -27,7 +27,7 @@ qhp.QtWebSockets.subprojects.classes.sortPages = true
qhp.QtWebSockets.subprojects.qml.title = QML Types
qhp.QtWebSockets.subprojects.qml.indexTitle = Qt WebSockets QML Types
-qhp.QtWebSockets.subprojects.qml.selectors = fake:qmlclass
+qhp.QtWebSockets.subprojects.qml.selectors = qmlclass
qhp.QtWebSockets.subprojects.qml.sortPages = true
qhp.QtWebSockets.subprojects.examples.title = Examples
diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp
index 18962ff..385ae71 100644
--- a/src/websockets/qwebsocket_p.cpp
+++ b/src/websockets/qwebsocket_p.cpp
@@ -848,6 +848,45 @@ QString readLine(QTcpSocket *pSocket)
return line;
}
+// this function is a copy of QHttpNetworkReplyPrivate::parseStatus
+static bool parseStatusLine(const QByteArray &status, int *majorVersion, int *minorVersion,
+ int *statusCode, QString *reasonPhrase)
+{
+ // from RFC 2616:
+ // Status-Line = HTTP-Version SP Status-Code SP Reason-Phrase CRLF
+ // HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT
+ // that makes: 'HTTP/n.n xxx Message'
+ // byte count: 0123456789012
+
+ static const int minLength = 11;
+ static const int dotPos = 6;
+ static const int spacePos = 8;
+ static const char httpMagic[] = "HTTP/";
+
+ if (status.length() < minLength
+ || !status.startsWith(httpMagic)
+ || status.at(dotPos) != '.'
+ || status.at(spacePos) != ' ') {
+ // I don't know how to parse this status line
+ return false;
+ }
+
+ // optimize for the valid case: defer checking until the end
+ *majorVersion = status.at(dotPos - 1) - '0';
+ *minorVersion = status.at(dotPos + 1) - '0';
+
+ int i = spacePos;
+ int j = status.indexOf(' ', i + 1); // j == -1 || at(j) == ' ' so j+1 == 0 && j+1 <= length()
+ const QByteArray code = status.mid(i + 1, j - i - 1);
+
+ bool ok;
+ *statusCode = code.toInt(&ok);
+ *reasonPhrase = QString::fromLatin1(status.constData() + j + 1);
+
+ return ok && uint(*majorVersion) <= 9 && uint(* minorVersion) <= 9;
+}
+
+
//called on the client for a server handshake response
/*!
\internal
@@ -861,25 +900,13 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
bool ok = false;
QString errorDescription;
- const QString regExpStatusLine(QStringLiteral("^(HTTP/[0-9]+\\.[0-9]+)\\s([0-9]+)\\s(.*)"));
- const QRegularExpression regExp(regExpStatusLine);
- const QString statusLine = readLine(pSocket);
- QString httpProtocol;
+ const QByteArray statusLine = pSocket->readLine();
+ int httpMajorVersion, httpMinorVersion;
int httpStatusCode;
QString httpStatusMessage;
- const QRegularExpressionMatch match = regExp.match(statusLine);
- if (Q_LIKELY(match.hasMatch())) {
- QStringList tokens = match.capturedTexts();
- tokens.removeFirst(); //remove the search string
- if (tokens.length() == 3) {
- httpProtocol = tokens[0];
- httpStatusCode = tokens[1].toInt();
- httpStatusMessage = tokens[2].trimmed();
- ok = true;
- }
- }
- if (Q_UNLIKELY(!ok)) {
- errorDescription = QWebSocket::tr("Invalid statusline in response: %1.").arg(statusLine);
+ if (Q_UNLIKELY(!parseStatusLine(statusLine, &httpMajorVersion, &httpMinorVersion,
+ &httpStatusCode, &httpStatusMessage))) {
+ errorDescription = QWebSocket::tr("Invalid statusline in response: %1.").arg(QString::fromLatin1(statusLine));
} else {
QString headerLine = readLine(pSocket);
QMap<QString, QString> headers;
@@ -906,11 +933,9 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
if (Q_LIKELY(httpStatusCode == 101)) {
//HTTP/x.y 101 Switching Protocols
- bool conversionOk = false;
- const float version = httpProtocol.midRef(5).toFloat(&conversionOk);
//TODO: do not check the httpStatusText right now
ok = !(acceptKey.isEmpty() ||
- (!conversionOk || (version < 1.1f)) ||
+ (httpMajorVersion < 1 || httpMinorVersion < 1) ||
(upgrade.toLower() != QStringLiteral("websocket")) ||
(connection.toLower() != QStringLiteral("upgrade")));
if (ok) {
@@ -923,7 +948,7 @@ void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
} else {
errorDescription =
QWebSocket::tr("QWebSocketPrivate::processHandshake: Invalid statusline in response: %1.")
- .arg(statusLine);
+ .arg(QString::fromLatin1(statusLine));
}
} else if (httpStatusCode == 400) {
//HTTP/1.1 400 Bad Request
diff --git a/src/websockets/qwebsockethandshakeresponse_p.h b/src/websockets/qwebsockethandshakeresponse_p.h
index 030d26f..bc98af2 100644
--- a/src/websockets/qwebsockethandshakeresponse_p.h
+++ b/src/websockets/qwebsockethandshakeresponse_p.h
@@ -86,10 +86,6 @@ public:
QWebSocketProtocol::CloseCode error() const;
QString errorString() const;
-public Q_SLOTS:
-
-Q_SIGNALS:
-
private:
bool m_isValid;
bool m_canUpgrade;
diff --git a/src/websockets/qwebsocketserver.cpp b/src/websockets/qwebsocketserver.cpp
index 20aa009..2d8f26b 100644
--- a/src/websockets/qwebsocketserver.cpp
+++ b/src/websockets/qwebsocketserver.cpp
@@ -495,6 +495,44 @@ quint16 QWebSocketServer::serverPort() const
}
/*!
+ Returns a URL clients can use to connect to this server if the server is listening for connections.
+ Otherwise an invalid URL is returned.
+
+ \sa serverPort(), serverAddress(), listen()
+ */
+QUrl QWebSocketServer::serverUrl() const
+{
+ QUrl url;
+
+ if (!isListening()) {
+ return url;
+ }
+
+ switch (secureMode()) {
+ case NonSecureMode:
+ url.setScheme(QStringLiteral("ws"));
+ break;
+ #ifndef QT_NO_SSL
+ case SecureMode:
+ url.setScheme(QStringLiteral("wss"));
+ break;
+ #endif
+ }
+
+ url.setPort(serverPort());
+
+ if (serverAddress() == QHostAddress(QHostAddress::Any)) {
+ // NOTE: On Windows at least, clients cannot connect to QHostAddress::Any
+ // so in that case we always return LocalHost instead.
+ url.setHost(QHostAddress(QHostAddress::LocalHost).toString());
+ } else {
+ url.setHost(serverAddress().toString());
+ }
+
+ return url;
+}
+
+/*!
Sets the maximum number of pending accepted connections to \a numConnections.
WebSocketServer will accept no more than \a numConnections incoming connections before
nextPendingConnection() is called.
diff --git a/src/websockets/qwebsocketserver.h b/src/websockets/qwebsocketserver.h
index 1f89ca9..4e76cd4 100644
--- a/src/websockets/qwebsocketserver.h
+++ b/src/websockets/qwebsocketserver.h
@@ -90,6 +90,7 @@ public:
quint16 serverPort() const;
QHostAddress serverAddress() const;
+ QUrl serverUrl() const;
SslMode secureMode() const;
diff --git a/src/websockets/qwebsocketserver_p.cpp b/src/websockets/qwebsocketserver_p.cpp
index 70bc5da..17cb565 100644
--- a/src/websockets/qwebsocketserver_p.cpp
+++ b/src/websockets/qwebsocketserver_p.cpp
@@ -407,12 +407,10 @@ void QWebSocketServerPrivate::onCloseConnection()
void QWebSocketServerPrivate::handshakeReceived()
{
if (Q_UNLIKELY(!currentSender)) {
- qWarning() << QWebSocketServer::tr("Sender is NULL. This is a Qt bug.");
return;
}
QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(currentSender->sender);
if (Q_UNLIKELY(!pTcpSocket)) {
- qWarning() << QWebSocketServer::tr("Sender is not a QTcpSocket. This is a Qt bug!!!");
return;
}
//When using Google Chrome the handshake in received in two parts.
@@ -434,8 +432,6 @@ void QWebSocketServerPrivate::handshakeReceived()
if (m_pendingConnections.length() >= maxPendingConnections()) {
pTcpSocket->close();
pTcpSocket->deleteLater();
- qWarning() << QWebSocketServer::tr("Too many pending connections: " \
- "New WebSocket connection not accepted.");
setError(QWebSocketProtocol::CloseCodeAbnormalDisconnection,
QWebSocketServer::tr("Too many pending connections."));
return;
@@ -483,7 +479,6 @@ void QWebSocketServerPrivate::handshakeReceived()
}
}
if (!success) {
- qWarning() << QWebSocketServer::tr("Closing socket because of invalid or unsupported request.");
pTcpSocket->close();
}
}
diff --git a/src/websockets/websockets.pro b/src/websockets/websockets.pro
index 99e84b6..5b5ff78 100644
--- a/src/websockets/websockets.pro
+++ b/src/websockets/websockets.pro
@@ -1,7 +1,7 @@
load(qt_build_config)
TARGET = QtWebSockets
-QT = core network core-private sql
+QT = core network core-private
TEMPLATE = lib
diff --git a/tests/auto/dataprocessor/tst_dataprocessor.cpp b/tests/auto/dataprocessor/tst_dataprocessor.cpp
index a63193a..de9b7a3 100644
--- a/tests/auto/dataprocessor/tst_dataprocessor.cpp
+++ b/tests/auto/dataprocessor/tst_dataprocessor.cpp
@@ -53,7 +53,6 @@ const quint8 FIN = 0x80;
const quint8 RSV1 = 0x40;
const quint8 RSV2 = 0x30;
const quint8 RSV3 = 0x10;
-const quint8 MASK = 0x80;
QT_USE_NAMESPACE
diff --git a/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp b/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp
index 2e2dcd6..78e7041 100644
--- a/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp
+++ b/tests/auto/qwebsocketserver/tst_qwebsocketserver.cpp
@@ -147,6 +147,7 @@ void tst_QWebSocketServer::tst_initialisation()
QCOMPARE(server.supportedVersions().count(), 1);
QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::VersionLatest);
QCOMPARE(server.supportedVersions().at(0), QWebSocketProtocol::Version13);
+ QCOMPARE(server.serverUrl(), QUrl());
}
{
@@ -254,9 +255,11 @@ void tst_QWebSocketServer::tst_connectivity()
QSignalSpy socketConnectedSpy(&socket, SIGNAL(connected()));
QVERIFY(server.listen());
+ QCOMPARE(server.serverAddress(), QHostAddress(QHostAddress::Any));
+ QCOMPARE(server.serverUrl(), QUrl(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
+ QStringLiteral(":").append(QString::number(server.serverPort()))));
- socket.open(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
- QStringLiteral(":").append(QString::number(server.serverPort())));
+ socket.open(server.serverUrl().toString());
if (socketConnectedSpy.count() == 0)
QVERIFY(socketConnectedSpy.wait());
@@ -305,23 +308,20 @@ void tst_QWebSocketServer::tst_maxPendingConnections()
QVERIFY(server.listen());
- socket1.open(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
- QStringLiteral(":").append(QString::number(server.serverPort())));
+ socket1.open(server.serverUrl().toString());
if (socket1ConnectedSpy.count() == 0)
QVERIFY(socket1ConnectedSpy.wait());
QCOMPARE(socket1.state(), QAbstractSocket::ConnectedState);
QCOMPARE(serverConnectionSpy.count(), 1);
QCOMPARE(corsAuthenticationSpy.count(), 1);
- socket2.open(QStringLiteral("ws://") + QHostAddress(QHostAddress::LocalHost).toString() +
- QStringLiteral(":").append(QString::number(server.serverPort())));
+ socket2.open(server.serverUrl().toString());
if (socket2ConnectedSpy.count() == 0)
QVERIFY(socket2ConnectedSpy.wait());
QCOMPARE(socket2.state(), QAbstractSocket::ConnectedState);
QCOMPARE(serverConnectionSpy.count(), 2);
QCOMPARE(corsAuthenticationSpy.count(), 2);
- socket3.open(QStringLiteral("ws://") + server.serverAddress().toString() +
- QStringLiteral(":").append(QString::number(server.serverPort())));
+ socket3.open(server.serverUrl().toString());
if (socket3ConnectedSpy.count() == 0)
QVERIFY(!socket3ConnectedSpy.wait(250));
QCOMPARE(socket3.state(), QAbstractSocket::UnconnectedState);