#include "dataprocessor_p.h"
#include "qwebsocketprotocol.h"
-#include <QTcpSocket>
+#include <QIODevice>
#include <QtEndian>
#include <limits.h>
#include <QTextCodec>
#include <QTextDecoder>
+#include <QDebug>
QT_BEGIN_NAMESPACE
bool isValid() const;
- static Frame readFrame(QTcpSocket *pSocket);
+ static Frame readFrame(QIODevice *pIoDevice);
private:
QWebSocketProtocol::CloseCode m_closeCode;
/*!
\internal
*/
-Frame Frame::readFrame(QTcpSocket *pSocket)
+Frame Frame::readFrame(QIODevice *pIoDevice)
{
bool isDone = false;
qint64 bytesRead = 0;
{
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."));
}
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);
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<char *>(length), 2);
+ bytesRead = pIoDevice->read(reinterpret_cast<char *>(length), 2);
payloadLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(length));
processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
}
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<char *>(length), 8);
+ bytesRead = pIoDevice->read(reinterpret_cast<char *>(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<quint64>(length) & ~(1ULL << 63);
case PS_READ_MASK:
{
- if (pSocket->bytesAvailable() >= 4)
+ if (pIoDevice->bytesAvailable() >= 4)
{
//TODO: Handle return value
- bytesRead = pSocket->read(reinterpret_cast<char *>(&frame.m_mask), sizeof(frame.m_mask));
+ bytesRead = pIoDevice->read(reinterpret_cast<char *>(&frame.m_mask), sizeof(frame.m_mask));
processingState = PS_READ_PAYLOAD;
}
else
}
else
{
- quint64 bytesAvailable = static_cast<quint64>(pSocket->bytesAvailable());
+ quint64 bytesAvailable = static_cast<quint64>(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);
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;
/*!
\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())
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;
+ }
}
}
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<quint64>(m_pingTimer.elapsed()));
- break;
+ m_pSocket->write(frame);
}
- case QWebSocketProtocol::OC_CLOSE:
+ break;
+ }
+ case QWebSocketProtocol::OC_PONG:
+ {
+ Q_EMIT q->pong(static_cast<quint64>(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<quint16>(reinterpret_cast<const uchar *>(frame.constData()));
+ if (!QWebSocketProtocol::isCloseCodeValid(closeCode))
{
- 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
+ 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<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_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<int>(opCode);
- //Do nothing
- break;
}
+ 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_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<int>(opCode);
+ //Do nothing
+ break;
+ }
}
}