From 7d8d55c3d5745714909c5f9fdd9bb1142388441b Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Mon, 26 Aug 2013 19:04:27 +0200 Subject: [PATCH] Replaced QTcpSocket * with a QIODevice * to make network independent unit tests possible. --- src/dataprocessor_p.cpp | 35 +++++---- src/dataprocessor_p.h | 10 +-- src/qwebsocket_p.cpp | 200 ++++++++++++++++++++++++------------------------ 3 files changed, 123 insertions(+), 122 deletions(-) diff --git a/src/dataprocessor_p.cpp b/src/dataprocessor_p.cpp index fb7f5aa..214e581 100644 --- a/src/dataprocessor_p.cpp +++ b/src/dataprocessor_p.cpp @@ -19,11 +19,12 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA #include "dataprocessor_p.h" #include "qwebsocketprotocol.h" -#include +#include #include #include #include #include +#include QT_BEGIN_NAMESPACE @@ -59,7 +60,7 @@ public: bool isValid() const; - static Frame readFrame(QTcpSocket *pSocket); + static Frame readFrame(QIODevice *pIoDevice); private: QWebSocketProtocol::CloseCode m_closeCode; @@ -282,7 +283,7 @@ bool Frame::isValid() const /*! \internal */ -Frame Frame::readFrame(QTcpSocket *pSocket) +Frame Frame::readFrame(QIODevice *pIoDevice) { bool isDone = false; qint64 bytesRead = 0; @@ -299,7 +300,7 @@ Frame Frame::readFrame(QTcpSocket *pSocket) { case PS_WAIT_FOR_MORE_DATA: { - bool ok = pSocket->waitForReadyRead(5000); + bool ok = pIoDevice->waitForReadyRead(5000); if (!ok) { frame.setError(QWebSocketProtocol::CC_GOING_AWAY, QObject::tr("Timeout when reading data from socket.")); @@ -313,11 +314,11 @@ Frame Frame::readFrame(QTcpSocket *pSocket) } case PS_READ_HEADER: { - if (pSocket->bytesAvailable() >= 2) + if (pIoDevice->bytesAvailable() >= 2) { //FIN, RSV1-3, Opcode char header[2] = {0}; - bytesRead = pSocket->read(header, 2); + bytesRead = pIoDevice->read(header, 2); frame.m_isFinalFrame = (header[0] & 0x80) != 0; frame.m_rsv1 = (header[0] & 0x40); frame.m_rsv2 = (header[0] & 0x20); @@ -361,11 +362,11 @@ Frame Frame::readFrame(QTcpSocket *pSocket) case PS_READ_PAYLOAD_LENGTH: { - if (pSocket->bytesAvailable() >= 2) + if (pIoDevice->bytesAvailable() >= 2) { uchar length[2] = {0}; //TODO: Handle return value - bytesRead = pSocket->read(reinterpret_cast(length), 2); + bytesRead = pIoDevice->read(reinterpret_cast(length), 2); payloadLength = qFromBigEndian(reinterpret_cast(length)); processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD; } @@ -378,11 +379,11 @@ Frame Frame::readFrame(QTcpSocket *pSocket) case PS_READ_BIG_PAYLOAD_LENGTH: { - if (pSocket->bytesAvailable() >= 8) + if (pIoDevice->bytesAvailable() >= 8) { uchar length[8] = {0}; //TODO: Handle return value - bytesRead = pSocket->read(reinterpret_cast(length), 8); + bytesRead = pIoDevice->read(reinterpret_cast(length), 8); //Most significant bit must be set to 0 as per http://tools.ietf.org/html/rfc6455#section-5.2 //TODO: Do we check for that? payloadLength = qFromBigEndian(length) & ~(1ULL << 63); @@ -398,10 +399,10 @@ Frame Frame::readFrame(QTcpSocket *pSocket) case PS_READ_MASK: { - if (pSocket->bytesAvailable() >= 4) + if (pIoDevice->bytesAvailable() >= 4) { //TODO: Handle return value - bytesRead = pSocket->read(reinterpret_cast(&frame.m_mask), sizeof(frame.m_mask)); + bytesRead = pIoDevice->read(reinterpret_cast(&frame.m_mask), sizeof(frame.m_mask)); processingState = PS_READ_PAYLOAD; } else @@ -424,10 +425,10 @@ Frame Frame::readFrame(QTcpSocket *pSocket) } else { - quint64 bytesAvailable = static_cast(pSocket->bytesAvailable()); + quint64 bytesAvailable = static_cast(pIoDevice->bytesAvailable()); if (bytesAvailable >= payloadLength) { - frame.m_payload = pSocket->read(payloadLength); + frame.m_payload = pIoDevice->read(payloadLength); if (hasMask) { QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask); @@ -452,7 +453,7 @@ Frame Frame::readFrame(QTcpSocket *pSocket) default: { //should not come here - qDebug() << "DataProcessor::process: Found invalid state. This should not happen!"; + qWarning() << "DataProcessor::process: Found invalid state. This should not happen!"; frame.clear(); isDone = true; break; @@ -549,13 +550,13 @@ DataProcessor::~DataProcessor() /*! \internal */ -void DataProcessor::process(QTcpSocket *pSocket) +void DataProcessor::process(QIODevice *pIoDevice) { bool isDone = false; while (!isDone) { - Frame frame = Frame::readFrame(pSocket); + Frame frame = Frame::readFrame(pIoDevice); if (frame.isValid()) { if (frame.isControlFrame()) diff --git a/src/dataprocessor_p.h b/src/dataprocessor_p.h index 0c102d1..7cb7c04 100644 --- a/src/dataprocessor_p.h +++ b/src/dataprocessor_p.h @@ -39,11 +39,11 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA QT_BEGIN_NAMESPACE -class QTcpSocket; +class QIODevice; -/** - * @internal - * @brief The DataProcessor class +/*! + \internal + The DataProcessor class reads and interprets incoming websocket messages, and emits appropriate signals. */ class DataProcessor: public QObject { @@ -61,7 +61,7 @@ Q_SIGNALS: void errorEncountered(QWebSocketProtocol::CloseCode code, QString description); public Q_SLOTS: - void process(QTcpSocket *pSocket); + void process(QIODevice *pIoDevice); void clear(); private: diff --git a/src/qwebsocket_p.cpp b/src/qwebsocket_p.cpp index f0fbf51..a433fc2 100644 --- a/src/qwebsocket_p.cpp +++ b/src/qwebsocket_p.cpp @@ -786,46 +786,46 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS QAbstractSocket::SocketState webSocketState = this->state(); switch (socketState) { - case QAbstractSocket::ConnectedState: - { - if (webSocketState == QAbstractSocket::ConnectingState) - { - m_key = generateKey(); - QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() % ":" % QString::number(m_requestUrl.port(80)), origin(), "", "", m_key); - m_pSocket->write(handshake.toLatin1()); - } - break; - } - case QAbstractSocket::ClosingState: + case QAbstractSocket::ConnectedState: + { + if (webSocketState == QAbstractSocket::ConnectingState) { - if (webSocketState == QAbstractSocket::ConnectedState) - { - setSocketState(QAbstractSocket::ClosingState); - } - break; + m_key = generateKey(); + QString handshake = createHandShakeRequest(m_resourceName, m_requestUrl.host() % ":" % QString::number(m_requestUrl.port(80)), origin(), "", "", m_key); + m_pSocket->write(handshake.toLatin1()); } - case QAbstractSocket::UnconnectedState: + break; + } + case QAbstractSocket::ClosingState: + { + if (webSocketState == QAbstractSocket::ConnectedState) { - if (webSocketState != QAbstractSocket::UnconnectedState) - { - setSocketState(QAbstractSocket::UnconnectedState); - Q_EMIT q->disconnected(); - } - break; + setSocketState(QAbstractSocket::ClosingState); } - case QAbstractSocket::HostLookupState: - case QAbstractSocket::ConnectingState: - case QAbstractSocket::BoundState: - case QAbstractSocket::ListeningState: - { - //do nothing - //to make C++ compiler happy; - break; - } - default: + break; + } + case QAbstractSocket::UnconnectedState: + { + if (webSocketState != QAbstractSocket::UnconnectedState) { - break; + setSocketState(QAbstractSocket::UnconnectedState); + Q_EMIT q->disconnected(); } + break; + } + case QAbstractSocket::HostLookupState: + case QAbstractSocket::ConnectingState: + case QAbstractSocket::BoundState: + case QAbstractSocket::ListeningState: + { + //do nothing + //to make C++ compiler happy; + break; + } + default: + { + break; + } } } @@ -864,85 +864,85 @@ void QWebSocketPrivate::processControlFrame(QWebSocketProtocol::OpCode opCode, Q Q_Q(QWebSocket); switch (opCode) { - case QWebSocketProtocol::OC_PING: + case QWebSocketProtocol::OC_PING: + { + quint32 maskingKey = 0; + if (m_mustMask) + { + maskingKey = generateMaskingKey(); + } + m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, frame.size(), maskingKey, true)); + if (frame.size() > 0) { - quint32 maskingKey = 0; if (m_mustMask) { - maskingKey = generateMaskingKey(); + QWebSocketProtocol::mask(&frame, maskingKey); } - m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, frame.size(), maskingKey, true)); - if (frame.size() > 0) - { - if (m_mustMask) - { - QWebSocketProtocol::mask(&frame, maskingKey); - } - m_pSocket->write(frame); - } - break; - } - case QWebSocketProtocol::OC_PONG: - { - Q_EMIT q->pong(static_cast(m_pingTimer.elapsed())); - break; + m_pSocket->write(frame); } - case QWebSocketProtocol::OC_CLOSE: + break; + } + case QWebSocketProtocol::OC_PONG: + { + Q_EMIT q->pong(static_cast(m_pingTimer.elapsed())); + break; + } + case QWebSocketProtocol::OC_CLOSE: + { + quint16 closeCode = QWebSocketProtocol::CC_NORMAL; + QString closeReason; + if (frame.size() > 0) //close frame can have a close code and reason { - quint16 closeCode = QWebSocketProtocol::CC_NORMAL; - QString closeReason; - if (frame.size() > 0) //close frame can have a close code and reason + closeCode = qFromBigEndian(reinterpret_cast(frame.constData())); + if (!QWebSocketProtocol::isCloseCodeValid(closeCode)) { - closeCode = qFromBigEndian(reinterpret_cast(frame.constData())); - if (!QWebSocketProtocol::isCloseCodeValid(closeCode)) - { - closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR; - closeReason = tr("Invalid close code %1 detected.").arg(closeCode); - } - else + closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR; + closeReason = tr("Invalid close code %1 detected.").arg(closeCode); + } + else + { + if (frame.size() > 2) { - if (frame.size() > 2) + QTextCodec *tc = QTextCodec::codecForName("UTF-8"); + QTextCodec::ConverterState state(QTextCodec::ConvertInvalidToNull); + closeReason = tc->toUnicode(frame.constData() + 2, frame.size() - 2, &state); + bool failed = (state.invalidChars != 0) || (state.remainingChars != 0); + if (failed) { - QTextCodec *tc = QTextCodec::codecForName("UTF-8"); - QTextCodec::ConverterState state(QTextCodec::ConvertInvalidToNull); - closeReason = tc->toUnicode(frame.constData() + 2, frame.size() - 2, &state); - bool failed = (state.invalidChars != 0) || (state.remainingChars != 0); - if (failed) - { - closeCode = QWebSocketProtocol::CC_WRONG_DATATYPE; - closeReason = tr("Invalid UTF-8 code encountered."); - } + closeCode = QWebSocketProtocol::CC_WRONG_DATATYPE; + closeReason = tr("Invalid UTF-8 code encountered."); } } } - m_isClosingHandshakeReceived = true; - close(static_cast(closeCode), closeReason); - break; - } - case QWebSocketProtocol::OC_CONTINUE: - case QWebSocketProtocol::OC_BINARY: - case QWebSocketProtocol::OC_TEXT: - case QWebSocketProtocol::OC_RESERVED_3: - case QWebSocketProtocol::OC_RESERVED_4: - case QWebSocketProtocol::OC_RESERVED_5: - case QWebSocketProtocol::OC_RESERVED_6: - case QWebSocketProtocol::OC_RESERVED_7: - case QWebSocketProtocol::OC_RESERVED_B: - case QWebSocketProtocol::OC_RESERVED_D: - case QWebSocketProtocol::OC_RESERVED_E: - case QWebSocketProtocol::OC_RESERVED_F: - case QWebSocketProtocol::OC_RESERVED_V: - { - //do nothing - //case added to make C++ compiler happy - break; - } - default: - { - qDebug() << "WebSocket::processData: Invalid opcode detected:" << static_cast(opCode); - //Do nothing - break; } + m_isClosingHandshakeReceived = true; + close(static_cast(closeCode), closeReason); + break; + } + case QWebSocketProtocol::OC_CONTINUE: + case QWebSocketProtocol::OC_BINARY: + case QWebSocketProtocol::OC_TEXT: + case QWebSocketProtocol::OC_RESERVED_3: + case QWebSocketProtocol::OC_RESERVED_4: + case QWebSocketProtocol::OC_RESERVED_5: + case QWebSocketProtocol::OC_RESERVED_6: + case QWebSocketProtocol::OC_RESERVED_7: + case QWebSocketProtocol::OC_RESERVED_B: + case QWebSocketProtocol::OC_RESERVED_D: + case QWebSocketProtocol::OC_RESERVED_E: + case QWebSocketProtocol::OC_RESERVED_F: + case QWebSocketProtocol::OC_RESERVED_V: + { + //do nothing + //case added to make C++ compiler happy + break; + } + default: + { + qDebug() << "WebSocket::processData: Invalid opcode detected:" << static_cast(opCode); + //Do nothing + break; + } } } -- 2.7.4