From 3501d4e9c315af97f0d7878d1af7f4300a815ea3 Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Thu, 31 Oct 2013 09:31:25 +0100 Subject: Implement of secure web sockets Change-Id: I1f96d5e4e327eae211fd6b458168e1f7607e2dcf Reviewed-by: Kurt Pattyn --- src/websockets/qwebsocket.cpp | 10 ++++++ src/websockets/qwebsocket.h | 12 ++++++- src/websockets/qwebsocket_p.cpp | 69 ++++++++++++++++++++++++++++++++++++++--- src/websockets/qwebsocket_p.h | 14 +++++++++ 4 files changed, 100 insertions(+), 5 deletions(-) diff --git a/src/websockets/qwebsocket.cpp b/src/websockets/qwebsocket.cpp index d209f37..b1fc57c 100644 --- a/src/websockets/qwebsocket.cpp +++ b/src/websockets/qwebsocket.cpp @@ -107,6 +107,16 @@ not been filled in with new information when the signal returns. \sa close() */ +/*! + \fn void QWebSocket::bytesWritten(qint64 bytes) + + This signal is emitted every time a payload of data has been written to the socket. + The \a bytes argument is set to the number of bytes that were written in this payload. + + \note This signal has the same meaning both for secure and non-secure websockets. + As opposed to QSslSocket, bytesWritten() is only emitted when encrypted data is effectively written (\sa {{QSslSocket:}}{{encryptedBytesWritten}}). + \sa close() +*/ /*! \fn void QWebSocket::textFrameReceived(QString frame, bool isLastFrame); diff --git a/src/websockets/qwebsocket.h b/src/websockets/qwebsocket.h index a820dcd..fbc3b36 100644 --- a/src/websockets/qwebsocket.h +++ b/src/websockets/qwebsocket.h @@ -24,7 +24,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #ifndef QT_NO_NETWORKPROXY #include #endif - +#ifndef QT_NO_SSL +#include +#include +#endif #include "qwebsockets_global.h" #include "qwebsocketprotocol.h" @@ -83,6 +86,12 @@ public: qint64 write(const QString &message); //send data as text qint64 write(const QByteArray &data); //send data as binary +#ifndef QT_NO_SSL + void ignoreSslErrors(const QList &errors); + void setSslConfiguration(const QSslConfiguration &sslConfiguration); + QSslConfiguration sslConfiguration() const; +#endif + public Q_SLOTS: void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL, const QString &reason = QString()); void open(const QUrl &url, bool mask = true); @@ -103,6 +112,7 @@ Q_SIGNALS: void binaryMessageReceived(QByteArray message); void error(QAbstractSocket::SocketError error); void pong(quint64 elapsedTime, QByteArray payload); + void bytesWritten(qint64 bytes); private: QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QObject *parent = Q_NULLPTR); diff --git a/src/websockets/qwebsocket_p.cpp b/src/websockets/qwebsocket_p.cpp index ca7e903..e47f4e6 100644 --- a/src/websockets/qwebsocket_p.cpp +++ b/src/websockets/qwebsocket_p.cpp @@ -48,7 +48,7 @@ const quint64 FRAME_SIZE_IN_BYTES = 512 * 512 * 2; //maximum size of a frame whe QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) : QObject(parent), q_ptr(pWebSocket), - m_pSocket(new QTcpSocket(this)), + m_pSocket(Q_NULLPTR), m_errorString(), m_version(version), m_resourceName(), @@ -65,7 +65,7 @@ QWebSocketPrivate::QWebSocketPrivate(const QString &origin, QWebSocketProtocol:: m_dataProcessor() { Q_ASSERT(pWebSocket); - makeConnections(m_pSocket); + //makeConnections(m_pSocket); qsrand(static_cast(QDateTime::currentMSecsSinceEpoch())); } @@ -184,7 +184,35 @@ qint64 QWebSocketPrivate::write(const QByteArray &data) return doWriteData(data, true); } +#ifndef QT_NO_SSL +/*! + \internal + */ +void QWebSocketPrivate::setSslConfiguration(const QSslConfiguration &sslConfiguration) +{ + m_sslConfiguration = sslConfiguration; +} + +/*! + \internal + */ +QSslConfiguration QWebSocketPrivate::sslConfiguration() const +{ + return m_sslConfiguration; +} + +/*! + \internal + */ +void QWebSocketPrivate::ignoreSslErrors(const QList &errors) +{ + m_ignoredSslErrors = errors; +} + +#endif + /*! + Called from QWebSocketServer \internal */ QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket, @@ -245,6 +273,8 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r */ void QWebSocketPrivate::open(const QUrl &url, bool mask) { + Q_Q(QWebSocket); + m_dataProcessor.clear(); m_isClosingHandshakeReceived = false; m_isClosingHandshakeSent = false; @@ -266,9 +296,40 @@ void QWebSocketPrivate::open(const QUrl &url, bool mask) setResourceName(resourceName); enableMasking(mask); - setSocketState(QAbstractSocket::ConnectingState); +#ifndef QT_NO_SSL + if (url.scheme() == QStringLiteral("wss")) + { + if (!QSslSocket::supportsSsl()) + { + qWarning() << tr("SSL Sockets are not supported on this platform."); + setErrorString(tr("SSL Sockets are not supported on this platform.")); + emit q->error(QAbstractSocket::UnsupportedSocketOperationError); + return; + } + else + { + QSslSocket *sslSocket = new QSslSocket(this); + m_pSocket = sslSocket; + + makeConnections(m_pSocket); + connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); + setSocketState(QAbstractSocket::ConnectingState); - m_pSocket->connectToHost(url.host(), url.port(80)); + sslSocket->setSslConfiguration(m_sslConfiguration); + sslSocket->ignoreSslErrors(m_ignoredSslErrors); + sslSocket->connectToHostEncrypted(url.host(), url.port(443)); + } + } + else +#endif + { + m_pSocket = new QTcpSocket(this); + + makeConnections(m_pSocket); + connect(m_pSocket, SIGNAL(bytesWritten(qint64)), q, SIGNAL(bytesWritten(qint64))); + setSocketState(QAbstractSocket::ConnectingState); + m_pSocket->connectToHost(url.host(), url.port(80)); + } } /*! diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index b2dcdb8..90543e3 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -35,6 +35,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #ifndef QT_NO_NETWORKPROXY #include #endif +#ifndef QT_NO_SSL +#include +#include +#endif #include #include "qwebsocketprotocol.h" @@ -98,6 +102,12 @@ public: qint64 write(const QString &message); //send data as text qint64 write(const QByteArray &data); //send data as binary +#ifndef QT_NO_SSL + void ignoreSslErrors(const QList &errors); + void setSslConfiguration(const QSslConfiguration &sslConfiguration); + QSslConfiguration sslConfiguration() const; +#endif + public Q_SLOTS: void close(QWebSocketProtocol::CloseCode closeCode, QString reason); void open(const QUrl &url, bool mask); @@ -113,6 +123,10 @@ private Q_SLOTS: private: QWebSocket * const q_ptr; +#ifndef QT_NO_SSL + QSslConfiguration m_sslConfiguration; + QList m_ignoredSslErrors; +#endif QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent = Q_NULLPTR); void setVersion(QWebSocketProtocol::Version version); -- cgit v1.2.1