From b795b7e6bf135571ca441b854616276f19114edc Mon Sep 17 00:00:00 2001 From: Kurt Pattyn Date: Sat, 31 Aug 2013 19:07:32 +0200 Subject: [PATCH] Moved processing of control frame from QWebSocketPrivate to DataProcessor. Added closeReceived(), pingReceived() and pongReceived() signals. Added processClose(), processPing() and processPong() slot to QWebSocketPrivate --- src/dataprocessor_p.cpp | 79 +++++++++++++++++++++++++++++++++- src/dataprocessor_p.h | 7 ++- src/qwebsocket_p.cpp | 111 ++++++++++++------------------------------------ src/qwebsocket_p.h | 4 +- 4 files changed, 114 insertions(+), 87 deletions(-) diff --git a/src/dataprocessor_p.cpp b/src/dataprocessor_p.cpp index ddd311a..674d701 100644 --- a/src/dataprocessor_p.cpp +++ b/src/dataprocessor_p.cpp @@ -637,8 +637,7 @@ void DataProcessor::process(QIODevice *pIoDevice) { if (frame.isControlFrame()) { - Q_EMIT controlFrameReceived(frame.getOpCode(), frame.getPayload()); - isDone = true; //exit the loop after a control frame, so we can get a chance to close the socket if necessary + isDone = processControlFrame(frame); } else //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY { @@ -741,4 +740,80 @@ void DataProcessor::clear() } } +bool DataProcessor::processControlFrame(const Frame &frame) +{ + bool mustStopProcessing = false; + switch (frame.getOpCode()) + { + case QWebSocketProtocol::OC_PING: + { + Q_EMIT pingReceived(frame.getPayload()); + break; + } + case QWebSocketProtocol::OC_PONG: + { + Q_EMIT pongReceived(frame.getPayload()); + break; + } + case QWebSocketProtocol::OC_CLOSE: + { + quint16 closeCode = QWebSocketProtocol::CC_NORMAL; + QString closeReason; + QByteArray payload = frame.getPayload(); + if (payload.size() > 0) //close frame can have a close code and reason + { + closeCode = qFromBigEndian(reinterpret_cast(payload.constData())); + if (!QWebSocketProtocol::isCloseCodeValid(closeCode)) + { + closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR; + closeReason = tr("Invalid close code %1 detected.").arg(closeCode); + } + else + { + if (payload.size() > 2) + { + QTextCodec *tc = QTextCodec::codecForName("UTF-8"); + QTextCodec::ConverterState state(QTextCodec::ConvertInvalidToNull); + closeReason = tc->toUnicode(payload.constData() + 2, payload.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."); + } + } + } + } + mustStopProcessing = true; + Q_EMIT closeReceived(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_C: + case QWebSocketProtocol::OC_RESERVED_B: + case QWebSocketProtocol::OC_RESERVED_D: + case QWebSocketProtocol::OC_RESERVED_E: + case QWebSocketProtocol::OC_RESERVED_F: + { + //do nothing + //case added to make C++ compiler happy + break; + } + default: + { + qDebug() << "DataProcessor::processControlFrame: Invalid opcode detected:" << static_cast(frame.getOpCode()); + //Do nothing + break; + } + } + return mustStopProcessing; +} + QT_END_NAMESPACE diff --git a/src/dataprocessor_p.h b/src/dataprocessor_p.h index 7cb7c04..c5850af 100644 --- a/src/dataprocessor_p.h +++ b/src/dataprocessor_p.h @@ -40,6 +40,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA QT_BEGIN_NAMESPACE class QIODevice; +class Frame; /*! \internal @@ -53,7 +54,9 @@ public: virtual ~DataProcessor(); Q_SIGNALS: - void controlFrameReceived(QWebSocketProtocol::OpCode opCode, QByteArray frame); + void pingReceived(QByteArray data); + void pongReceived(QByteArray data); + void closeReceived(QWebSocketProtocol::CloseCode closeCode, QString closeReason); void textFrameReceived(QString frame, bool lastFrame); void binaryFrameReceived(QByteArray frame, bool lastFrame); void textMessageReceived(QString message); @@ -87,6 +90,8 @@ private: quint64 m_payloadLength; QTextCodec::ConverterState *m_pConverterState; QTextCodec *m_pTextCodec; + + bool processControlFrame(const Frame &frame); }; QT_END_NAMESPACE diff --git a/src/qwebsocket_p.cpp b/src/qwebsocket_p.cpp index 8acb9e3..39737dc 100644 --- a/src/qwebsocket_p.cpp +++ b/src/qwebsocket_p.cpp @@ -351,12 +351,14 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket) connect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState))); connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData())); - connect(&m_dataProcessor, SIGNAL(controlFrameReceived(QWebSocketProtocol::OpCode, QByteArray)), this, SLOT(processControlFrame(QWebSocketProtocol::OpCode, QByteArray))); connect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q, SIGNAL(textFrameReceived(QString,bool))); connect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q, SIGNAL(binaryFrameReceived(QByteArray,bool))); connect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q, SIGNAL(binaryMessageReceived(QByteArray))); connect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q, SIGNAL(textMessageReceived(QString))); connect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString))); + connect(&m_dataProcessor, SIGNAL(pingReceived(QByteArray)), this, SLOT(processPing(QByteArray))); + connect(&m_dataProcessor, SIGNAL(pongReceived(QByteArray)), this, SLOT(processPong(QByteArray))); + connect(&m_dataProcessor, SIGNAL(closeReceived(QWebSocketProtocol::CloseCode,QString)), this, SLOT(processClose(QWebSocketProtocol::CloseCode,QString))); } /*! @@ -378,7 +380,9 @@ void QWebSocketPrivate::releaseConnections(const QTcpSocket *pTcpSocket) disconnect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState))); disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData())); } - disconnect(&m_dataProcessor, SIGNAL(controlFrameReceived(QWebSocketProtocol::OpCode,QByteArray)), this, SLOT(processControlFrame(QWebSocketProtocol::OpCode,QByteArray))); + disconnect(&m_dataProcessor, SIGNAL(pingReceived(QByteArray)), this, SLOT(processPing(QByteArray))); + disconnect(&m_dataProcessor, SIGNAL(pongReceived(QByteArray)), this, SLOT(processPong(QByteArray))); + disconnect(&m_dataProcessor, SIGNAL(closeReceived(QWebSocketProtocol::CloseCode,QString)), this, SLOT(processClose(QWebSocketProtocol::CloseCode,QString))); disconnect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q, SIGNAL(textFrameReceived(QString,bool))); disconnect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q, SIGNAL(binaryFrameReceived(QByteArray,bool))); disconnect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q, SIGNAL(binaryMessageReceived(QByteArray))); @@ -856,96 +860,37 @@ void QWebSocketPrivate::processData() } } -/*! - \internal - */ -void QWebSocketPrivate::processControlFrame(QWebSocketProtocol::OpCode opCode, QByteArray frame) +void QWebSocketPrivate::processPing(QByteArray data) { - Q_Q(QWebSocket); - switch (opCode) - { - 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) - { - if (m_mustMask) - { - QWebSocketProtocol::mask(&frame, maskingKey); - } - m_pSocket->write(frame); - } - break; - } - case QWebSocketProtocol::OC_PONG: + quint32 maskingKey = 0; + if (m_mustMask) { - Q_EMIT q->pong(static_cast(m_pingTimer.elapsed())); - break; + maskingKey = generateMaskingKey(); } - case QWebSocketProtocol::OC_CLOSE: + m_pSocket->write(getFrameHeader(QWebSocketProtocol::OC_PONG, data.size(), maskingKey, true)); + if (data.size() > 0) { - quint16 closeCode = QWebSocketProtocol::CC_NORMAL; - QString closeReason; - if (frame.size() > 0) //close frame can have a close code and reason + if (m_mustMask) { - 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 - { - 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) - { - closeCode = QWebSocketProtocol::CC_WRONG_DATATYPE; - closeReason = tr("Invalid UTF-8 code encountered."); - } - } - } + QWebSocketProtocol::mask(&data, maskingKey); } - 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_C: - case QWebSocketProtocol::OC_RESERVED_B: - case QWebSocketProtocol::OC_RESERVED_D: - case QWebSocketProtocol::OC_RESERVED_E: - case QWebSocketProtocol::OC_RESERVED_F: - { - //do nothing - //case added to make C++ compiler happy - break; - } - default: - { - qDebug() << "WebSocket::processData: Invalid opcode detected:" << static_cast(opCode); - //Do nothing - break; - } + m_pSocket->write(data); } } +void QWebSocketPrivate::processPong(QByteArray data) +{ + Q_UNUSED(data); + Q_Q(QWebSocket); + Q_EMIT q->pong(static_cast(m_pingTimer.elapsed())); +} + +void QWebSocketPrivate::processClose(QWebSocketProtocol::CloseCode closeCode, QString closeReason) +{ + m_isClosingHandshakeReceived = true; + close(closeCode, closeReason); +} + /*! \internal */ diff --git a/src/qwebsocket_p.h b/src/qwebsocket_p.h index 5a226bf..5a1ffec 100644 --- a/src/qwebsocket_p.h +++ b/src/qwebsocket_p.h @@ -104,7 +104,9 @@ public Q_SLOTS: private Q_SLOTS: void processData(); - void processControlFrame(QWebSocketProtocol::OpCode opCode, QByteArray frame); + void processPing(QByteArray data); + void processPong(QByteArray data); + void processClose(QWebSocketProtocol::CloseCode closeCode, QString closeReason); void processHandshake(QTcpSocket *pSocket); void processStateChanged(QAbstractSocket::SocketState socketState); -- 2.7.4