{
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
{
}
}
+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<quint16>(reinterpret_cast<const uchar *>(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<QWebSocketProtocol::CloseCode>(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<int>(frame.getOpCode());
+ //Do nothing
+ break;
+ }
+ }
+ return mustStopProcessing;
+}
+
QT_END_NAMESPACE
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)));
}
/*!
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)));
}
}
-/*!
- \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<quint64>(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<quint16>(reinterpret_cast<const uchar *>(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<QWebSocketProtocol::CloseCode>(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<int>(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<quint64>(m_pingTimer.elapsed()));
+}
+
+void QWebSocketPrivate::processClose(QWebSocketProtocol::CloseCode closeCode, QString closeReason)
+{
+ m_isClosingHandshakeReceived = true;
+ close(closeCode, closeReason);
+}
+
/*!
\internal
*/