summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKurt Pattyn <pattyn.kurt@gmail.com>2013-08-25 22:35:13 +0200
committerKurt Pattyn <pattyn.kurt@gmail.com>2013-08-25 22:35:13 +0200
commit433b23a5207bd3922785f41356d7029d1b275cf0 (patch)
tree6730467afa097ff98f7d6ae9a9622449ae3e1815
parenta6c7dbfef8283be12698ae304d4ef1af5aa4cc60 (diff)
downloadqtwebsockets-433b23a5207bd3922785f41356d7029d1b275cf0.tar.gz
Replaced tabs by spaces
-rw-r--r--examples/echoclient/echoclient.cpp16
-rw-r--r--examples/echoclient/echoclient.h10
-rw-r--r--examples/echoclient/main.cpp8
-rw-r--r--examples/echoserver/echoserver.cpp62
-rw-r--r--examples/echoserver/echoserver.h16
-rw-r--r--examples/echoserver/main.cpp8
-rw-r--r--src/dataprocessor_p.cpp936
-rw-r--r--src/dataprocessor_p.h64
-rw-r--r--src/handshakerequest_p.cpp262
-rw-r--r--src/handshakerequest_p.h62
-rw-r--r--src/handshakeresponse_p.cpp242
-rw-r--r--src/handshakeresponse_p.h62
-rw-r--r--src/qwebsocket.cpp360
-rw-r--r--src/qwebsocket.h110
-rw-r--r--src/qwebsocket_p.cpp1542
-rw-r--r--src/qwebsocket_p.h230
-rw-r--r--src/qwebsocketprotocol.cpp274
-rw-r--r--src/qwebsocketprotocol.h142
-rw-r--r--src/qwebsocketserver.cpp232
-rw-r--r--src/qwebsocketserver.h60
-rw-r--r--src/qwebsocketserver_p.cpp282
-rw-r--r--src/qwebsocketserver_p.h70
-rw-r--r--tests/tst_compliance.cpp142
-rw-r--r--tests/tst_websockets.cpp194
-rw-r--r--tests/unittests.h76
25 files changed, 2731 insertions, 2731 deletions
diff --git a/examples/echoclient/echoclient.cpp b/examples/echoclient/echoclient.cpp
index 0e6983a..56925be 100644
--- a/examples/echoclient/echoclient.cpp
+++ b/examples/echoclient/echoclient.cpp
@@ -3,26 +3,26 @@
//! [constructor]
EchoClient::EchoClient(const QUrl &url, QObject *parent) :
- QObject(parent),
- m_webSocket()
+ QObject(parent),
+ m_webSocket()
{
- connect(&m_webSocket, SIGNAL(connected()), this, SLOT(onConnected()));
- m_webSocket.open(QUrl(url));
+ connect(&m_webSocket, SIGNAL(connected()), this, SLOT(onConnected()));
+ m_webSocket.open(QUrl(url));
}
//! [constructor]
//! [onConnected]
void EchoClient::onConnected()
{
- qDebug() << "Websocket connected";
- connect(&m_webSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
- m_webSocket.write("Hello, world!");
+ qDebug() << "Websocket connected";
+ connect(&m_webSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(onTextMessageReceived(QString)));
+ m_webSocket.write("Hello, world!");
}
//! [onConnected]
//! [onTextMessageReceived]
void EchoClient::onTextMessageReceived(QString message)
{
- qDebug() << "Message received:" << message;
+ qDebug() << "Message received:" << message;
}
//! [onTextMessageReceived]
diff --git a/examples/echoclient/echoclient.h b/examples/echoclient/echoclient.h
index 36a3cad..f7a0c12 100644
--- a/examples/echoclient/echoclient.h
+++ b/examples/echoclient/echoclient.h
@@ -6,20 +6,20 @@
class EchoClient : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit EchoClient(const QUrl &url, QObject *parent = 0);
+ explicit EchoClient(const QUrl &url, QObject *parent = 0);
Q_SIGNALS:
public Q_SLOTS:
private Q_SLOTS:
- void onConnected();
- void onTextMessageReceived(QString message);
+ void onConnected();
+ void onTextMessageReceived(QString message);
private:
- QWebSocket m_webSocket;
+ QWebSocket m_webSocket;
};
#endif // ECHOCLIENT_H
diff --git a/examples/echoclient/main.cpp b/examples/echoclient/main.cpp
index 4a94284..b796368 100644
--- a/examples/echoclient/main.cpp
+++ b/examples/echoclient/main.cpp
@@ -3,10 +3,10 @@
int main(int argc, char *argv[])
{
- QCoreApplication a(argc, argv);
- EchoClient client(QUrl("ws://localhost:1234"));
+ QCoreApplication a(argc, argv);
+ EchoClient client(QUrl("ws://localhost:1234"));
- Q_UNUSED(client);
+ Q_UNUSED(client);
- return a.exec();
+ return a.exec();
}
diff --git a/examples/echoserver/echoserver.cpp b/examples/echoserver/echoserver.cpp
index 6afac50..ca4be81 100644
--- a/examples/echoserver/echoserver.cpp
+++ b/examples/echoserver/echoserver.cpp
@@ -5,63 +5,63 @@
//! [constructor]
EchoServer::EchoServer(quint16 port, QObject *parent) :
- QObject(parent),
- m_pWebSocketServer(0),
- m_clients()
+ QObject(parent),
+ m_pWebSocketServer(0),
+ m_clients()
{
- m_pWebSocketServer = new QWebSocketServer("Echo Server", this);
- if (m_pWebSocketServer->listen(QHostAddress::Any, port))
- {
- qDebug() << "Echoserver listening on port" << port;
- connect(m_pWebSocketServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
- }
+ m_pWebSocketServer = new QWebSocketServer("Echo Server", this);
+ if (m_pWebSocketServer->listen(QHostAddress::Any, port))
+ {
+ qDebug() << "Echoserver listening on port" << port;
+ connect(m_pWebSocketServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
+ }
}
//! [constructor]
//! [onNewConnection]
void EchoServer::onNewConnection()
{
- QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
+ QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection();
- connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processMessage(QString)));
- connect(pSocket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(processBinaryMessage(QByteArray)));
- connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
- //connect(pSocket, SIGNAL(pong(quint64)), this, SLOT(processPong(quint64)));
+ connect(pSocket, SIGNAL(textMessageReceived(QString)), this, SLOT(processMessage(QString)));
+ connect(pSocket, SIGNAL(binaryMessageReceived(QByteArray)), this, SLOT(processBinaryMessage(QByteArray)));
+ connect(pSocket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
+ //connect(pSocket, SIGNAL(pong(quint64)), this, SLOT(processPong(quint64)));
- m_clients << pSocket;
+ m_clients << pSocket;
}
//! [onNewConnection]
//! [processMessage]
void EchoServer::processMessage(QString message)
{
- QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
- if (pClient != 0)
- {
- pClient->write(message);
- }
+ QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+ if (pClient != 0)
+ {
+ pClient->write(message);
+ }
}
//! [processMessage]
//! [processBinaryMessage]
void EchoServer::processBinaryMessage(QByteArray message)
{
- QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
- if (pClient != 0)
- {
- pClient->write(message);
- }
+ QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+ if (pClient != 0)
+ {
+ pClient->write(message);
+ }
}
//! [processBinaryMessage]
//! [socketDisconnected]
void EchoServer::socketDisconnected()
{
- QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
- if (pClient != 0)
- {
- m_clients.removeAll(pClient);
- pClient->deleteLater();
- }
+ QWebSocket *pClient = qobject_cast<QWebSocket *>(sender());
+ if (pClient != 0)
+ {
+ m_clients.removeAll(pClient);
+ pClient->deleteLater();
+ }
}
//! [socketDisconnected]
diff --git a/examples/echoserver/echoserver.h b/examples/echoserver/echoserver.h
index aa8c2ba..227e398 100644
--- a/examples/echoserver/echoserver.h
+++ b/examples/echoserver/echoserver.h
@@ -10,21 +10,21 @@ class QWebSocket;
class EchoServer : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit EchoServer(quint16 port, QObject *parent = 0);
+ explicit EchoServer(quint16 port, QObject *parent = 0);
Q_SIGNALS:
private Q_SLOTS:
- void onNewConnection();
- void processMessage(QString message);
- void processBinaryMessage(QByteArray message);
- void socketDisconnected();
+ void onNewConnection();
+ void processMessage(QString message);
+ void processBinaryMessage(QByteArray message);
+ void socketDisconnected();
private:
- QWebSocketServer *m_pWebSocketServer;
- QList<QWebSocket *> m_clients;
+ QWebSocketServer *m_pWebSocketServer;
+ QList<QWebSocket *> m_clients;
};
#endif //ECHOSERVER_H
diff --git a/examples/echoserver/main.cpp b/examples/echoserver/main.cpp
index 390cbb0..ce4474d 100644
--- a/examples/echoserver/main.cpp
+++ b/examples/echoserver/main.cpp
@@ -3,10 +3,10 @@
int main(int argc, char *argv[])
{
- QCoreApplication a(argc, argv);
- EchoServer server(1234);
+ QCoreApplication a(argc, argv);
+ EchoServer server(1234);
- Q_UNUSED(server);
+ Q_UNUSED(server);
- return a.exec();
+ return a.exec();
}
diff --git a/src/dataprocessor_p.cpp b/src/dataprocessor_p.cpp
index d504b20..ef32ff5 100644
--- a/src/dataprocessor_p.cpp
+++ b/src/dataprocessor_p.cpp
@@ -31,637 +31,637 @@ const quint64 MAX_FRAME_SIZE_IN_BYTES = INT_MAX - 1;
const quint64 MAX_MESSAGE_SIZE_IN_BYTES = INT_MAX - 1;
/*!
- \internal
+ \internal
*/
class Frame
{
public:
- Frame();
- Frame(const Frame &other);
+ Frame();
+ Frame(const Frame &other);
- const Frame &operator =(const Frame &other);
+ const Frame &operator =(const Frame &other);
- QWebSocketProtocol::CloseCode getCloseCode() const;
- QString getCloseReason() const;
- bool isFinalFrame() const;
- bool isControlFrame() const;
- bool isDataFrame() const;
- bool isContinuationFrame() const;
- bool hasMask() const;
- quint32 getMask() const; //returns 0 if no mask
- int getRsv1() const;
- int getRsv2() const;
- int getRsv3() const;
- QWebSocketProtocol::OpCode getOpCode() const;
- QByteArray getPayload() const;
+ QWebSocketProtocol::CloseCode getCloseCode() const;
+ QString getCloseReason() const;
+ bool isFinalFrame() const;
+ bool isControlFrame() const;
+ bool isDataFrame() const;
+ bool isContinuationFrame() const;
+ bool hasMask() const;
+ quint32 getMask() const; //returns 0 if no mask
+ int getRsv1() const;
+ int getRsv2() const;
+ int getRsv3() const;
+ QWebSocketProtocol::OpCode getOpCode() const;
+ QByteArray getPayload() const;
- void clear(); //resets all member variables, and invalidates the object
+ void clear(); //resets all member variables, and invalidates the object
- bool isValid() const;
+ bool isValid() const;
- static Frame readFrame(QTcpSocket *pSocket);
+ static Frame readFrame(QTcpSocket *pSocket);
private:
- QWebSocketProtocol::CloseCode m_closeCode;
- QString m_closeReason;
- bool m_isFinalFrame;
- quint32 m_mask;
- int m_rsv1; //reserved field 1
- int m_rsv2; //reserved field 2
- int m_rsv3; //reserved field 3
- QWebSocketProtocol::OpCode m_opCode;
-
- quint8 m_length; //length field as read from the header; this is 1 byte, which when 126 or 127, indicates a large payload
- QByteArray m_payload;
-
- bool m_isValid;
-
- enum ProcessingState
- {
- PS_READ_HEADER,
- PS_READ_PAYLOAD_LENGTH,
- PS_READ_BIG_PAYLOAD_LENGTH,
- PS_READ_MASK,
- PS_READ_PAYLOAD,
- PS_DISPATCH_RESULT,
- PS_WAIT_FOR_MORE_DATA
- };
-
- void setError(QWebSocketProtocol::CloseCode code, QString closeReason);
- bool checkValidity();
+ QWebSocketProtocol::CloseCode m_closeCode;
+ QString m_closeReason;
+ bool m_isFinalFrame;
+ quint32 m_mask;
+ int m_rsv1; //reserved field 1
+ int m_rsv2; //reserved field 2
+ int m_rsv3; //reserved field 3
+ QWebSocketProtocol::OpCode m_opCode;
+
+ quint8 m_length; //length field as read from the header; this is 1 byte, which when 126 or 127, indicates a large payload
+ QByteArray m_payload;
+
+ bool m_isValid;
+
+ enum ProcessingState
+ {
+ PS_READ_HEADER,
+ PS_READ_PAYLOAD_LENGTH,
+ PS_READ_BIG_PAYLOAD_LENGTH,
+ PS_READ_MASK,
+ PS_READ_PAYLOAD,
+ PS_DISPATCH_RESULT,
+ PS_WAIT_FOR_MORE_DATA
+ };
+
+ void setError(QWebSocketProtocol::CloseCode code, QString closeReason);
+ bool checkValidity();
};
/*!
- \internal
+ \internal
*/
Frame::Frame() :
- m_closeCode(QWebSocketProtocol::CC_NORMAL),
- m_closeReason(),
- m_isFinalFrame(true),
- m_mask(0),
- m_rsv1(0),
- m_rsv2(0),
- m_rsv3(0),
- m_opCode(QWebSocketProtocol::OC_RESERVED_V),
- m_length(0),
- m_payload(),
- m_isValid(false)
+ m_closeCode(QWebSocketProtocol::CC_NORMAL),
+ m_closeReason(),
+ m_isFinalFrame(true),
+ m_mask(0),
+ m_rsv1(0),
+ m_rsv2(0),
+ m_rsv3(0),
+ m_opCode(QWebSocketProtocol::OC_RESERVED_V),
+ m_length(0),
+ m_payload(),
+ m_isValid(false)
{
}
/*!
- \internal
+ \internal
*/
Frame::Frame(const Frame &other) :
- m_closeCode(other.m_closeCode),
- m_closeReason(other.m_closeReason),
- m_isFinalFrame(other.m_isFinalFrame),
- m_mask(other.m_mask),
- m_rsv1(other.m_rsv1),
- m_rsv2(other.m_rsv2),
- m_rsv3(other.m_rsv3),
- m_opCode(other.m_opCode),
- m_length(other.m_length),
- m_payload(other.m_payload),
- m_isValid(other.m_isValid)
+ m_closeCode(other.m_closeCode),
+ m_closeReason(other.m_closeReason),
+ m_isFinalFrame(other.m_isFinalFrame),
+ m_mask(other.m_mask),
+ m_rsv1(other.m_rsv1),
+ m_rsv2(other.m_rsv2),
+ m_rsv3(other.m_rsv3),
+ m_opCode(other.m_opCode),
+ m_length(other.m_length),
+ m_payload(other.m_payload),
+ m_isValid(other.m_isValid)
{
}
/*!
- \internal
+ \internal
*/
const Frame &Frame::operator =(const Frame &other)
{
- m_closeCode = other.m_closeCode;
- m_closeReason = other.m_closeReason;
- m_isFinalFrame = other.m_isFinalFrame;
- m_mask = other.m_mask;
- m_rsv1 = other.m_rsv1;
- m_rsv2 = other.m_rsv2;
- m_rsv3 = other.m_rsv2;
- m_opCode = other.m_opCode;
- m_length = other.m_length;
- m_payload = other.m_payload;
- m_isValid = other.m_isValid;
-
- return *this;
+ m_closeCode = other.m_closeCode;
+ m_closeReason = other.m_closeReason;
+ m_isFinalFrame = other.m_isFinalFrame;
+ m_mask = other.m_mask;
+ m_rsv1 = other.m_rsv1;
+ m_rsv2 = other.m_rsv2;
+ m_rsv3 = other.m_rsv2;
+ m_opCode = other.m_opCode;
+ m_length = other.m_length;
+ m_payload = other.m_payload;
+ m_isValid = other.m_isValid;
+
+ return *this;
}
/*!
- \internal
+ \internal
*/
QWebSocketProtocol::CloseCode Frame::getCloseCode() const
{
- return m_closeCode;
+ return m_closeCode;
}
/*!
- \internal
+ \internal
*/
QString Frame::getCloseReason() const
{
- return m_closeReason;
+ return m_closeReason;
}
/*!
- \internal
+ \internal
*/
bool Frame::isFinalFrame() const
{
- return m_isFinalFrame;
+ return m_isFinalFrame;
}
/*!
- \internal
+ \internal
*/
bool Frame::isControlFrame() const
{
- return (m_opCode & 0x08) == 0x08;
+ return (m_opCode & 0x08) == 0x08;
}
/*!
- \internal
+ \internal
*/
bool Frame::isDataFrame() const
{
- return !isControlFrame();
+ return !isControlFrame();
}
/*!
- \internal
+ \internal
*/
bool Frame::isContinuationFrame() const
{
- return isDataFrame() && (m_opCode == QWebSocketProtocol::OC_CONTINUE);
+ return isDataFrame() && (m_opCode == QWebSocketProtocol::OC_CONTINUE);
}
/*!
- \internal
+ \internal
*/
bool Frame::hasMask() const
{
- return m_mask != 0;
+ return m_mask != 0;
}
/*!
- \internal
+ \internal
*/
quint32 Frame::getMask() const
{
- return m_mask;
+ return m_mask;
}
/*!
- \internal
+ \internal
*/
int Frame::getRsv1() const
{
- return m_rsv1;
+ return m_rsv1;
}
/*!
- \internal
+ \internal
*/
int Frame::getRsv2() const
{
- return m_rsv2;
+ return m_rsv2;
}
/*!
- \internal
+ \internal
*/
int Frame::getRsv3() const
{
- return m_rsv3;
+ return m_rsv3;
}
/*!
- \internal
+ \internal
*/
QWebSocketProtocol::OpCode Frame::getOpCode() const
{
- return m_opCode;
+ return m_opCode;
}
/*!
- \internal
+ \internal
*/
QByteArray Frame::getPayload() const
{
- return m_payload;
+ return m_payload;
}
/*!
- \internal
+ \internal
*/
void Frame::clear()
{
- m_closeCode = QWebSocketProtocol::CC_NORMAL;
- m_closeReason.clear();
- m_isFinalFrame = true;
- m_mask = 0;
- m_rsv1 = 0;
- m_rsv2 =0;
- m_rsv3 = 0;
- m_opCode = QWebSocketProtocol::OC_RESERVED_V;
- m_length = 0;
- m_payload.clear();
- m_isValid = false;
+ m_closeCode = QWebSocketProtocol::CC_NORMAL;
+ m_closeReason.clear();
+ m_isFinalFrame = true;
+ m_mask = 0;
+ m_rsv1 = 0;
+ m_rsv2 =0;
+ m_rsv3 = 0;
+ m_opCode = QWebSocketProtocol::OC_RESERVED_V;
+ m_length = 0;
+ m_payload.clear();
+ m_isValid = false;
}
/*!
- \internal
+ \internal
*/
bool Frame::isValid() const
{
- return m_isValid;
+ return m_isValid;
}
#define WAIT_FOR_MORE_DATA(dataSizeInBytes) { returnState = processingState; processingState = PS_WAIT_FOR_MORE_DATA; dataWaitSize = dataSizeInBytes; }
/*!
- \internal
+ \internal
*/
Frame Frame::readFrame(QTcpSocket *pSocket)
{
- bool isDone = false;
- qint64 bytesRead = 0;
- Frame frame;
- quint64 dataWaitSize = 0;
- ProcessingState processingState = PS_READ_HEADER;
- ProcessingState returnState = PS_READ_HEADER;
- bool hasMask = false;
- quint64 payloadLength = 0;
-
- while (!isDone)
- {
- switch (processingState)
- {
- case PS_WAIT_FOR_MORE_DATA:
- {
- bool ok = pSocket->waitForReadyRead(5000);
- if (!ok)
- {
- frame.setError(QWebSocketProtocol::CC_GOING_AWAY, "Timeout when reading data from socket.");
- isDone = true;
- }
- else
- {
- processingState = returnState;
- }
- break;
- }
- case PS_READ_HEADER:
- {
- if (pSocket->bytesAvailable() >= 2)
- {
- //FIN, RSV1-3, Opcode
- char header[2] = {0};
- bytesRead = pSocket->read(header, 2);
- frame.m_isFinalFrame = (header[0] & 0x80) != 0;
- frame.m_rsv1 = (header[0] & 0x40);
- frame.m_rsv2 = (header[0] & 0x20);
- frame.m_rsv3 = (header[0] & 0x10);
- frame.m_opCode = static_cast<QWebSocketProtocol::OpCode>(header[0] & 0x0F);
-
- //Mask, PayloadLength
- hasMask = (header[1] & 0x80) != 0;
- frame.m_length = (header[1] & 0x7F);
-
- switch (frame.m_length)
- {
- case 126:
- {
- processingState = PS_READ_PAYLOAD_LENGTH;
- break;
- }
- case 127:
- {
- processingState = PS_READ_BIG_PAYLOAD_LENGTH;
- break;
- }
- default:
- {
- payloadLength = frame.m_length;
- processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
- break;
- }
- }
- if (!frame.checkValidity())
- {
- isDone = true;
- }
- }
- else
- {
- WAIT_FOR_MORE_DATA(2);
- }
- break;
- }
-
- case PS_READ_PAYLOAD_LENGTH:
- {
- if (pSocket->bytesAvailable() >= 2)
- {
- uchar length[2] = {0};
- //TODO: Handle return value
- bytesRead = pSocket->read(reinterpret_cast<char *>(length), 2);
- payloadLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(length));
- processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
- }
- else
- {
- WAIT_FOR_MORE_DATA(2);
- }
- break;
- }
-
- case PS_READ_BIG_PAYLOAD_LENGTH:
- {
- if (pSocket->bytesAvailable() >= 8)
- {
- uchar length[8] = {0};
- //TODO: Handle return value
- bytesRead = pSocket->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);
- processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
- }
- else
- {
- WAIT_FOR_MORE_DATA(8);
- }
-
- break;
- }
-
- case PS_READ_MASK:
- {
- if (pSocket->bytesAvailable() >= 4)
- {
- //TODO: Handle return value
- bytesRead = pSocket->read(reinterpret_cast<char *>(&frame.m_mask), sizeof(frame.m_mask));
- processingState = PS_READ_PAYLOAD;
- }
- else
- {
- WAIT_FOR_MORE_DATA(4);
- }
- break;
- }
-
- case PS_READ_PAYLOAD:
- {
- if (!payloadLength)
- {
- processingState = PS_DISPATCH_RESULT;
- }
- else if (payloadLength > MAX_FRAME_SIZE_IN_BYTES)
- {
- frame.setError(QWebSocketProtocol::CC_TOO_MUCH_DATA, "Maximum framesize exceeded.");
- processingState = PS_DISPATCH_RESULT;
- }
- else
- {
- quint64 bytesAvailable = static_cast<quint64>(pSocket->bytesAvailable());
- if (bytesAvailable >= payloadLength)
- {
- frame.m_payload = pSocket->read(payloadLength);
- if (hasMask)
- {
- QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask);
- }
- processingState = PS_DISPATCH_RESULT;
- }
- else
- {
- WAIT_FOR_MORE_DATA(payloadLength);
- }
- }
- break;
- }
-
- case PS_DISPATCH_RESULT:
- {
- processingState = PS_READ_HEADER;
- isDone = true;
- break;
- }
-
- default:
- {
- //should not come here
- qDebug() << "DataProcessor::process: Found invalid state. This should not happen!";
- frame.clear();
- isDone = true;
- break;
- }
- } //end switch
- }
-
- return frame;
+ bool isDone = false;
+ qint64 bytesRead = 0;
+ Frame frame;
+ quint64 dataWaitSize = 0;
+ ProcessingState processingState = PS_READ_HEADER;
+ ProcessingState returnState = PS_READ_HEADER;
+ bool hasMask = false;
+ quint64 payloadLength = 0;
+
+ while (!isDone)
+ {
+ switch (processingState)
+ {
+ case PS_WAIT_FOR_MORE_DATA:
+ {
+ bool ok = pSocket->waitForReadyRead(5000);
+ if (!ok)
+ {
+ frame.setError(QWebSocketProtocol::CC_GOING_AWAY, "Timeout when reading data from socket.");
+ isDone = true;
+ }
+ else
+ {
+ processingState = returnState;
+ }
+ break;
+ }
+ case PS_READ_HEADER:
+ {
+ if (pSocket->bytesAvailable() >= 2)
+ {
+ //FIN, RSV1-3, Opcode
+ char header[2] = {0};
+ bytesRead = pSocket->read(header, 2);
+ frame.m_isFinalFrame = (header[0] & 0x80) != 0;
+ frame.m_rsv1 = (header[0] & 0x40);
+ frame.m_rsv2 = (header[0] & 0x20);
+ frame.m_rsv3 = (header[0] & 0x10);
+ frame.m_opCode = static_cast<QWebSocketProtocol::OpCode>(header[0] & 0x0F);
+
+ //Mask, PayloadLength
+ hasMask = (header[1] & 0x80) != 0;
+ frame.m_length = (header[1] & 0x7F);
+
+ switch (frame.m_length)
+ {
+ case 126:
+ {
+ processingState = PS_READ_PAYLOAD_LENGTH;
+ break;
+ }
+ case 127:
+ {
+ processingState = PS_READ_BIG_PAYLOAD_LENGTH;
+ break;
+ }
+ default:
+ {
+ payloadLength = frame.m_length;
+ processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
+ break;
+ }
+ }
+ if (!frame.checkValidity())
+ {
+ isDone = true;
+ }
+ }
+ else
+ {
+ WAIT_FOR_MORE_DATA(2);
+ }
+ break;
+ }
+
+ case PS_READ_PAYLOAD_LENGTH:
+ {
+ if (pSocket->bytesAvailable() >= 2)
+ {
+ uchar length[2] = {0};
+ //TODO: Handle return value
+ bytesRead = pSocket->read(reinterpret_cast<char *>(length), 2);
+ payloadLength = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(length));
+ processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
+ }
+ else
+ {
+ WAIT_FOR_MORE_DATA(2);
+ }
+ break;
+ }
+
+ case PS_READ_BIG_PAYLOAD_LENGTH:
+ {
+ if (pSocket->bytesAvailable() >= 8)
+ {
+ uchar length[8] = {0};
+ //TODO: Handle return value
+ bytesRead = pSocket->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);
+ processingState = hasMask ? PS_READ_MASK : PS_READ_PAYLOAD;
+ }
+ else
+ {
+ WAIT_FOR_MORE_DATA(8);
+ }
+
+ break;
+ }
+
+ case PS_READ_MASK:
+ {
+ if (pSocket->bytesAvailable() >= 4)
+ {
+ //TODO: Handle return value
+ bytesRead = pSocket->read(reinterpret_cast<char *>(&frame.m_mask), sizeof(frame.m_mask));
+ processingState = PS_READ_PAYLOAD;
+ }
+ else
+ {
+ WAIT_FOR_MORE_DATA(4);
+ }
+ break;
+ }
+
+ case PS_READ_PAYLOAD:
+ {
+ if (!payloadLength)
+ {
+ processingState = PS_DISPATCH_RESULT;
+ }
+ else if (payloadLength > MAX_FRAME_SIZE_IN_BYTES)
+ {
+ frame.setError(QWebSocketProtocol::CC_TOO_MUCH_DATA, "Maximum framesize exceeded.");
+ processingState = PS_DISPATCH_RESULT;
+ }
+ else
+ {
+ quint64 bytesAvailable = static_cast<quint64>(pSocket->bytesAvailable());
+ if (bytesAvailable >= payloadLength)
+ {
+ frame.m_payload = pSocket->read(payloadLength);
+ if (hasMask)
+ {
+ QWebSocketProtocol::mask(&frame.m_payload, frame.m_mask);
+ }
+ processingState = PS_DISPATCH_RESULT;
+ }
+ else
+ {
+ WAIT_FOR_MORE_DATA(payloadLength);
+ }
+ }
+ break;
+ }
+
+ case PS_DISPATCH_RESULT:
+ {
+ processingState = PS_READ_HEADER;
+ isDone = true;
+ break;
+ }
+
+ default:
+ {
+ //should not come here
+ qDebug() << "DataProcessor::process: Found invalid state. This should not happen!";
+ frame.clear();
+ isDone = true;
+ break;
+ }
+ } //end switch
+ }
+
+ return frame;
}
/*!
- \internal
+ \internal
*/
void Frame::setError(QWebSocketProtocol::CloseCode code, QString closeReason)
{
- clear();
- m_closeCode = code;
- m_closeReason = closeReason;
- m_isValid = false;
+ clear();
+ m_closeCode = code;
+ m_closeReason = closeReason;
+ m_isValid = false;
}
/*!
- \internal
+ \internal
*/
bool Frame::checkValidity()
{
- if (!isValid())
- {
- if (m_rsv1 || m_rsv2 || m_rsv3)
- {
- setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Rsv field is non-zero");
- }
- else if (QWebSocketProtocol::isOpCodeReserved(m_opCode))
- {
- setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Used reserved opcode");
- }
- else if (isControlFrame())
- {
- if (m_length > 125)
- {
- setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Controle frame is larger than 125 bytes");
- }
- else if (!m_isFinalFrame)
- {
- setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Controle frames cannot be fragmented");
- }
- else
- {
- m_isValid = true;
- }
- }
- else
- {
- m_isValid = true;
- }
- }
- return m_isValid;
+ if (!isValid())
+ {
+ if (m_rsv1 || m_rsv2 || m_rsv3)
+ {
+ setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Rsv field is non-zero");
+ }
+ else if (QWebSocketProtocol::isOpCodeReserved(m_opCode))
+ {
+ setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Used reserved opcode");
+ }
+ else if (isControlFrame())
+ {
+ if (m_length > 125)
+ {
+ setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Controle frame is larger than 125 bytes");
+ }
+ else if (!m_isFinalFrame)
+ {
+ setError(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Controle frames cannot be fragmented");
+ }
+ else
+ {
+ m_isValid = true;
+ }
+ }
+ else
+ {
+ m_isValid = true;
+ }
+ }
+ return m_isValid;
}
/*!
- \internal
+ \internal
*/
DataProcessor::DataProcessor(QObject *parent) :
- QObject(parent),
- m_processingState(PS_READ_HEADER),
- m_isFinalFrame(false),
- m_isFragmented(false),
- m_opCode(QWebSocketProtocol::OC_CLOSE),
- m_isControlFrame(false),
- m_hasMask(false),
- m_mask(0),
- m_binaryMessage(),
- m_textMessage(),
- m_payloadLength(0),
- m_pConverterState(0),
- m_pTextCodec(QTextCodec::codecForName("UTF-8"))
+ QObject(parent),
+ m_processingState(PS_READ_HEADER),
+ m_isFinalFrame(false),
+ m_isFragmented(false),
+ m_opCode(QWebSocketProtocol::OC_CLOSE),
+ m_isControlFrame(false),
+ m_hasMask(false),
+ m_mask(0),
+ m_binaryMessage(),
+ m_textMessage(),
+ m_payloadLength(0),
+ m_pConverterState(0),
+ m_pTextCodec(QTextCodec::codecForName("UTF-8"))
{
- clear();
+ clear();
}
/*!
- \internal
+ \internal
*/
DataProcessor::~DataProcessor()
{
- clear();
- if (m_pConverterState)
- {
- delete m_pConverterState;
- m_pConverterState = 0;
- }
+ clear();
+ if (m_pConverterState)
+ {
+ delete m_pConverterState;
+ m_pConverterState = 0;
+ }
}
/*!
- \internal
+ \internal
*/
void DataProcessor::process(QTcpSocket *pSocket)
{
- bool isDone = false;
-
- while (!isDone)
- {
- Frame frame = Frame::readFrame(pSocket);
- if (frame.isValid())
- {
- 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
- }
- else //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY
- {
- if (!m_isFragmented && frame.isContinuationFrame())
- {
- clear();
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Received Continuation frame /*with FIN=true*/, while there is nothing to continue.");
- return;
- }
- if (m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame())
- {
- clear();
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, "All data frames after the initial data frame must have opcode 0 (continuation).");
- return;
- }
- if (!frame.isContinuationFrame())
- {
- m_opCode = frame.getOpCode();
- m_isFragmented = !frame.isFinalFrame();
- }
- quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OC_TEXT) ? m_textMessage.length() : m_binaryMessage.length();
- if ((messageLength + quint64(frame.getPayload().length())) > MAX_MESSAGE_SIZE_IN_BYTES)
- {
- clear();
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_TOO_MUCH_DATA, "Received message is too big.");
- return;
- }
-
- if (m_opCode == QWebSocketProtocol::OC_TEXT)
- {
- QString frameTxt = m_pTextCodec->toUnicode(frame.getPayload().constData(), frame.getPayload().size(), m_pConverterState);
- bool failed = (m_pConverterState->invalidChars != 0) || (frame.isFinalFrame() && (m_pConverterState->remainingChars != 0));
- if (failed)
- {
- clear();
- Q_EMIT errorEncountered(QWebSocketProtocol::CC_WRONG_DATATYPE, "Invalid UTF-8 code encountered.");
- return;
- }
- else
- {
- m_textMessage.append(frameTxt);
- Q_EMIT textFrameReceived(frameTxt, frame.isFinalFrame());
- }
- }
- else
- {
- m_binaryMessage.append(frame.getPayload());
- Q_EMIT binaryFrameReceived(frame.getPayload(), frame.isFinalFrame());
- }
-
- if (frame.isFinalFrame())
- {
- if (m_opCode == QWebSocketProtocol::OC_TEXT)
- {
- Q_EMIT textMessageReceived(m_textMessage);
- }
- else
- {
- Q_EMIT binaryMessageReceived(m_binaryMessage);
- }
- clear();
- isDone = true;
- }
- }
- }
- else
- {
- Q_EMIT errorEncountered(frame.getCloseCode(), frame.getCloseReason());
- clear();
- isDone = true;
- }
- }
+ bool isDone = false;
+
+ while (!isDone)
+ {
+ Frame frame = Frame::readFrame(pSocket);
+ if (frame.isValid())
+ {
+ 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
+ }
+ else //we have a dataframe; opcode can be OC_CONTINUE, OC_TEXT or OC_BINARY
+ {
+ if (!m_isFragmented && frame.isContinuationFrame())
+ {
+ clear();
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, "Received Continuation frame /*with FIN=true*/, while there is nothing to continue.");
+ return;
+ }
+ if (m_isFragmented && frame.isDataFrame() && !frame.isContinuationFrame())
+ {
+ clear();
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_PROTOCOL_ERROR, "All data frames after the initial data frame must have opcode 0 (continuation).");
+ return;
+ }
+ if (!frame.isContinuationFrame())
+ {
+ m_opCode = frame.getOpCode();
+ m_isFragmented = !frame.isFinalFrame();
+ }
+ quint64 messageLength = (quint64)(m_opCode == QWebSocketProtocol::OC_TEXT) ? m_textMessage.length() : m_binaryMessage.length();
+ if ((messageLength + quint64(frame.getPayload().length())) > MAX_MESSAGE_SIZE_IN_BYTES)
+ {
+ clear();
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_TOO_MUCH_DATA, "Received message is too big.");
+ return;
+ }
+
+ if (m_opCode == QWebSocketProtocol::OC_TEXT)
+ {
+ QString frameTxt = m_pTextCodec->toUnicode(frame.getPayload().constData(), frame.getPayload().size(), m_pConverterState);
+ bool failed = (m_pConverterState->invalidChars != 0) || (frame.isFinalFrame() && (m_pConverterState->remainingChars != 0));
+ if (failed)
+ {
+ clear();
+ Q_EMIT errorEncountered(QWebSocketProtocol::CC_WRONG_DATATYPE, "Invalid UTF-8 code encountered.");
+ return;
+ }
+ else
+ {
+ m_textMessage.append(frameTxt);
+ Q_EMIT textFrameReceived(frameTxt, frame.isFinalFrame());
+ }
+ }
+ else
+ {
+ m_binaryMessage.append(frame.getPayload());
+ Q_EMIT binaryFrameReceived(frame.getPayload(), frame.isFinalFrame());
+ }
+
+ if (frame.isFinalFrame())
+ {
+ if (m_opCode == QWebSocketProtocol::OC_TEXT)
+ {
+ Q_EMIT textMessageReceived(m_textMessage);
+ }
+ else
+ {
+ Q_EMIT binaryMessageReceived(m_binaryMessage);
+ }
+ clear();
+ isDone = true;
+ }
+ }
+ }
+ else
+ {
+ Q_EMIT errorEncountered(frame.getCloseCode(), frame.getCloseReason());
+ clear();
+ isDone = true;
+ }
+ }
}
/*!
- \internal
+ \internal
*/
void DataProcessor::clear()
{
- m_processingState = PS_READ_HEADER;
- m_isFinalFrame = false;
- m_isFragmented = false;
- m_opCode = QWebSocketProtocol::OC_CLOSE;
- m_hasMask = false;
- m_mask = 0;
- m_binaryMessage.clear();
- m_textMessage.clear();
- m_payloadLength = 0;
- if (m_pConverterState)
- {
- if ((m_pConverterState->remainingChars != 0) || (m_pConverterState->invalidChars != 0))
- {
- delete m_pConverterState;
- m_pConverterState = 0;
- }
- }
- if (!m_pConverterState)
- {
- m_pConverterState = new QTextCodec::ConverterState(QTextCodec::ConvertInvalidToNull | QTextCodec::IgnoreHeader);
- }
+ m_processingState = PS_READ_HEADER;
+ m_isFinalFrame = false;
+ m_isFragmented = false;
+ m_opCode = QWebSocketProtocol::OC_CLOSE;
+ m_hasMask = false;
+ m_mask = 0;
+ m_binaryMessage.clear();
+ m_textMessage.clear();
+ m_payloadLength = 0;
+ if (m_pConverterState)
+ {
+ if ((m_pConverterState->remainingChars != 0) || (m_pConverterState->invalidChars != 0))
+ {
+ delete m_pConverterState;
+ m_pConverterState = 0;
+ }
+ }
+ if (!m_pConverterState)
+ {
+ m_pConverterState = new QTextCodec::ConverterState(QTextCodec::ConvertInvalidToNull | QTextCodec::IgnoreHeader);
+ }
}
QT_END_NAMESPACE
diff --git a/src/dataprocessor_p.h b/src/dataprocessor_p.h
index 7c1dd2d..0c102d1 100644
--- a/src/dataprocessor_p.h
+++ b/src/dataprocessor_p.h
@@ -47,46 +47,46 @@ class QTcpSocket;
*/
class DataProcessor: public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit DataProcessor(QObject *parent = 0);
- virtual ~DataProcessor();
+ explicit DataProcessor(QObject *parent = 0);
+ virtual ~DataProcessor();
Q_SIGNALS:
- void controlFrameReceived(QWebSocketProtocol::OpCode opCode, QByteArray frame);
- void textFrameReceived(QString frame, bool lastFrame);
- void binaryFrameReceived(QByteArray frame, bool lastFrame);
- void textMessageReceived(QString message);
- void binaryMessageReceived(QByteArray message);
- void errorEncountered(QWebSocketProtocol::CloseCode code, QString description);
+ void controlFrameReceived(QWebSocketProtocol::OpCode opCode, QByteArray frame);
+ void textFrameReceived(QString frame, bool lastFrame);
+ void binaryFrameReceived(QByteArray frame, bool lastFrame);
+ void textMessageReceived(QString message);
+ void binaryMessageReceived(QByteArray message);
+ void errorEncountered(QWebSocketProtocol::CloseCode code, QString description);
public Q_SLOTS:
- void process(QTcpSocket *pSocket);
- void clear();
+ void process(QTcpSocket *pSocket);
+ void clear();
private:
- Q_DISABLE_COPY(DataProcessor)
- enum
- {
- PS_READ_HEADER,
- PS_READ_PAYLOAD_LENGTH,
- PS_READ_BIG_PAYLOAD_LENGTH,
- PS_READ_MASK,
- PS_READ_PAYLOAD,
- PS_DISPATCH_RESULT
- } m_processingState;
+ Q_DISABLE_COPY(DataProcessor)
+ enum
+ {
+ PS_READ_HEADER,
+ PS_READ_PAYLOAD_LENGTH,
+ PS_READ_BIG_PAYLOAD_LENGTH,
+ PS_READ_MASK,
+ PS_READ_PAYLOAD,
+ PS_DISPATCH_RESULT
+ } m_processingState;
- bool m_isFinalFrame;
- bool m_isFragmented;
- QWebSocketProtocol::OpCode m_opCode;
- bool m_isControlFrame;
- bool m_hasMask;
- quint32 m_mask;
- QByteArray m_binaryMessage;
- QString m_textMessage;
- quint64 m_payloadLength;
- QTextCodec::ConverterState *m_pConverterState;
- QTextCodec *m_pTextCodec;
+ bool m_isFinalFrame;
+ bool m_isFragmented;
+ QWebSocketProtocol::OpCode m_opCode;
+ bool m_isControlFrame;
+ bool m_hasMask;
+ quint32 m_mask;
+ QByteArray m_binaryMessage;
+ QString m_textMessage;
+ quint64 m_payloadLength;
+ QTextCodec::ConverterState *m_pConverterState;
+ QTextCodec *m_pTextCodec;
};
QT_END_NAMESPACE
diff --git a/src/handshakerequest_p.cpp b/src/handshakerequest_p.cpp
index 2d51e25..5243a6e 100644
--- a/src/handshakerequest_p.cpp
+++ b/src/handshakerequest_p.cpp
@@ -29,241 +29,241 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
QT_BEGIN_NAMESPACE
/*!
- \internal
+ \internal
*/
HandshakeRequest::HandshakeRequest(int port, bool isSecure) :
- m_port(port),
- m_isSecure(isSecure),
- m_isValid(false),
- m_headers(),
- m_versions(),
- m_key(),
- m_origin(),
- m_protocols(),
- m_extensions(),
- m_requestUrl()
+ m_port(port),
+ m_isSecure(isSecure),
+ m_isValid(false),
+ m_headers(),
+ m_versions(),
+ m_key(),
+ m_origin(),
+ m_protocols(),
+ m_extensions(),
+ m_requestUrl()
{
}
/*!
- \internal
+ \internal
*/
HandshakeRequest::~HandshakeRequest()
{
}
/*!
- \internal
+ \internal
*/
void HandshakeRequest::clear()
{
- m_port = -1;
- m_isSecure = false;
- m_isValid = false;
- m_headers.clear();
- m_versions.clear();
- m_key.clear();
- m_origin.clear();
- m_protocols.clear();
- m_extensions.clear();
- m_requestUrl.clear();
+ m_port = -1;
+ m_isSecure = false;
+ m_isValid = false;
+ m_headers.clear();
+ m_versions.clear();
+ m_key.clear();
+ m_origin.clear();
+ m_protocols.clear();
+ m_extensions.clear();
+ m_requestUrl.clear();
}
/*!
- \internal
+ \internal
*/
int HandshakeRequest::getPort() const
{
- return m_requestUrl.port(m_port);
+ return m_requestUrl.port(m_port);
}
/*!
- \internal
+ \internal
*/
bool HandshakeRequest::isSecure() const
{
- return m_isSecure;
+ return m_isSecure;
}
/*!
- \internal
+ \internal
*/
bool HandshakeRequest::isValid() const
{
- return m_isValid;
+ return m_isValid;
}
/*!
- \internal
+ \internal
*/
QMap<QString, QString> HandshakeRequest::getHeaders() const
{
- return m_headers;
+ return m_headers;
}
/*!
- \internal
+ \internal
*/
QList<QWebSocketProtocol::Version> HandshakeRequest::getVersions() const
{
- return m_versions;
+ return m_versions;
}
/*!
- \internal
+ \internal
*/
QString HandshakeRequest::getResourceName() const
{
- return m_requestUrl.path();
+ return m_requestUrl.path();
}
/*!
- \internal
+ \internal
*/
QString HandshakeRequest::getKey() const
{
- return m_key;
+ return m_key;
}
/*!
- \internal
+ \internal
*/
QString HandshakeRequest::getHost() const
{
- return m_requestUrl.host();
+ return m_requestUrl.host();
}
/*!
- \internal
+ \internal
*/
QString HandshakeRequest::getOrigin() const
{
- return m_origin;
+ return m_origin;
}
/*!
- \internal
+ \internal
*/
QList<QString> HandshakeRequest::getProtocols() const
{
- return m_protocols;
+ return m_protocols;
}
/*!
- \internal
+ \internal
*/
QList<QString> HandshakeRequest::getExtensions() const
{
- return m_extensions;
+ return m_extensions;
}
/*!
- \internal
+ \internal
*/
QUrl HandshakeRequest::getRequestUrl() const
{
- return m_requestUrl;
+ return m_requestUrl;
}
/*!
- \internal
+ \internal
*/
QTextStream &HandshakeRequest::readFromStream(QTextStream &textStream)
{
- m_isValid = false;
- clear();
- if (textStream.status() == QTextStream::Ok)
- {
- QString requestLine = textStream.readLine();
- QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts);
- QString verb = tokens[0];
- QString resourceName = tokens[1];
- QString httpProtocol = tokens[2];
- bool conversionOk = false;
- float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk);
+ m_isValid = false;
+ clear();
+ if (textStream.status() == QTextStream::Ok)
+ {
+ QString requestLine = textStream.readLine();
+ QStringList tokens = requestLine.split(' ', QString::SkipEmptyParts);
+ QString verb = tokens[0];
+ QString resourceName = tokens[1];
+ QString httpProtocol = tokens[2];
+ bool conversionOk = false;
+ float httpVersion = httpProtocol.midRef(5).toFloat(&conversionOk);
- QString headerLine = textStream.readLine();
- m_headers.clear();
- while (!headerLine.isEmpty())
- {
- QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
- m_headers.insertMulti(headerField[0], headerField[1]);
- headerLine = textStream.readLine();
- }
+ QString headerLine = textStream.readLine();
+ m_headers.clear();
+ while (!headerLine.isEmpty())
+ {
+ QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
+ m_headers.insertMulti(headerField[0], headerField[1]);
+ headerLine = textStream.readLine();
+ }
- QString host = m_headers.value("Host", "");
- m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1());
- if (m_requestUrl.isRelative())
- {
- m_requestUrl.setHost(host);
- }
- if (m_requestUrl.scheme().isEmpty())
- {
- QString scheme = isSecure() ? "wss://" : "ws://";
- m_requestUrl.setScheme(scheme);
- }
+ QString host = m_headers.value("Host", "");
+ m_requestUrl = QUrl::fromEncoded(resourceName.toLatin1());
+ if (m_requestUrl.isRelative())
+ {
+ m_requestUrl.setHost(host);
+ }
+ if (m_requestUrl.scheme().isEmpty())
+ {
+ QString scheme = isSecure() ? "wss://" : "ws://";
+ m_requestUrl.setScheme(scheme);
+ }
- QStringList versionLines = m_headers.values("Sec-WebSocket-Version");
- Q_FOREACH(QString versionLine, versionLines)
- {
- QStringList versions = versionLine.split(",", QString::SkipEmptyParts);
- Q_FOREACH(QString version, versions)
- {
- QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString(version.trimmed());
- m_versions << ver;
- }
- }
- qStableSort(m_versions.begin(), m_versions.end(), qGreater<QWebSocketProtocol::Version>()); //sort in descending order
- m_key = m_headers.value("Sec-WebSocket-Key", "");
- QString upgrade = m_headers.value("Upgrade", ""); //must be equal to "websocket", case-insensitive
- QString connection = m_headers.value("Connection", ""); //must contain "Upgrade", case-insensitive
- QStringList connectionLine = connection.split(",", QString::SkipEmptyParts);
- QStringList connectionValues;
- Q_FOREACH(QString connection, connectionLine)
- {
- connectionValues << connection.trimmed();
- }
+ QStringList versionLines = m_headers.values("Sec-WebSocket-Version");
+ Q_FOREACH(QString versionLine, versionLines)
+ {
+ QStringList versions = versionLine.split(",", QString::SkipEmptyParts);
+ Q_FOREACH(QString version, versions)
+ {
+ QWebSocketProtocol::Version ver = QWebSocketProtocol::versionFromString(version.trimmed());
+ m_versions << ver;
+ }
+ }
+ qStableSort(m_versions.begin(), m_versions.end(), qGreater<QWebSocketProtocol::Version>()); //sort in descending order
+ m_key = m_headers.value("Sec-WebSocket-Key", "");
+ QString upgrade = m_headers.value("Upgrade", ""); //must be equal to "websocket", case-insensitive
+ QString connection = m_headers.value("Connection", ""); //must contain "Upgrade", case-insensitive
+ QStringList connectionLine = connection.split(",", QString::SkipEmptyParts);
+ QStringList connectionValues;
+ Q_FOREACH(QString connection, connectionLine)
+ {
+ connectionValues << connection.trimmed();
+ }
- //optional headers
- m_origin = m_headers.value("Sec-WebSocket-Origin", "");
- QStringList protocolLines = m_headers.values("Sec-WebSocket-Protocol");
- Q_FOREACH(QString protocolLine, protocolLines)
- {
- QStringList protocols = protocolLine.split(",", QString::SkipEmptyParts);
- Q_FOREACH(QString protocol, protocols)
- {
- m_protocols << protocol.trimmed();
- }
- }
- QStringList extensionLines = m_headers.values("Sec-WebSocket-Extensions");
- Q_FOREACH(QString extensionLine, extensionLines)
- {
- QStringList extensions = extensionLine.split(",", QString::SkipEmptyParts);
- Q_FOREACH(QString extension, extensions)
- {
- m_extensions << extension.trimmed();
- }
- }
- //TODO: authentication field
+ //optional headers
+ m_origin = m_headers.value("Sec-WebSocket-Origin", "");
+ QStringList protocolLines = m_headers.values("Sec-WebSocket-Protocol");
+ Q_FOREACH(QString protocolLine, protocolLines)
+ {
+ QStringList protocols = protocolLine.split(",", QString::SkipEmptyParts);
+ Q_FOREACH(QString protocol, protocols)
+ {
+ m_protocols << protocol.trimmed();
+ }
+ }
+ QStringList extensionLines = m_headers.values("Sec-WebSocket-Extensions");
+ Q_FOREACH(QString extensionLine, extensionLines)
+ {
+ QStringList extensions = extensionLine.split(",", QString::SkipEmptyParts);
+ Q_FOREACH(QString extension, extensions)
+ {
+ m_extensions << extension.trimmed();
+ }
+ }
+ //TODO: authentication field
- m_isValid = !(host.isEmpty() ||
- resourceName.isEmpty() ||
- m_versions.isEmpty() ||
- m_key.isEmpty() ||
- (verb != "GET") ||
- (!conversionOk || (httpVersion < 1.1f)) ||
- (upgrade.toLower() != "websocket") ||
- (!connectionValues.contains("upgrade", Qt::CaseInsensitive)));
- }
- return textStream;
+ m_isValid = !(host.isEmpty() ||
+ resourceName.isEmpty() ||
+ m_versions.isEmpty() ||
+ m_key.isEmpty() ||
+ (verb != "GET") ||
+ (!conversionOk || (httpVersion < 1.1f)) ||
+ (upgrade.toLower() != "websocket") ||
+ (!connectionValues.contains("upgrade", Qt::CaseInsensitive)));
+ }
+ return textStream;
}
/*!
- \internal
+ \internal
*/
QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request)
{
- return request.readFromStream(stream);
+ return request.readFromStream(stream);
}
QT_END_NAMESPACE
diff --git a/src/handshakerequest_p.h b/src/handshakerequest_p.h
index 6345a91..c2cc154 100644
--- a/src/handshakerequest_p.h
+++ b/src/handshakerequest_p.h
@@ -45,39 +45,39 @@ class QTextStream;
class HandshakeRequest
{
public:
- HandshakeRequest(int port, bool isSecure);
- virtual ~HandshakeRequest();
-
- void clear();
-
- int getPort() const;
- bool isSecure() const;
- bool isValid() const;
- QMap<QString, QString> getHeaders() const;
- QList<QWebSocketProtocol::Version> getVersions() const;
- QString getKey() const;
- QString getOrigin() const;
- QList<QString> getProtocols() const;
- QList<QString> getExtensions() const;
- QUrl getRequestUrl() const;
- QString getResourceName() const;
- QString getHost() const;
+ HandshakeRequest(int port, bool isSecure);
+ virtual ~HandshakeRequest();
+
+ void clear();
+
+ int getPort() const;
+ bool isSecure() const;
+ bool isValid() const;
+ QMap<QString, QString> getHeaders() const;
+ QList<QWebSocketProtocol::Version> getVersions() const;
+ QString getKey() const;
+ QString getOrigin() const;
+ QList<QString> getProtocols() const;
+ QList<QString> getExtensions() const;
+ QUrl getRequestUrl() const;
+ QString getResourceName() const;
+ QString getHost() const;
private:
- Q_DISABLE_COPY(HandshakeRequest)
- QTextStream &readFromStream(QTextStream &textStream);
- friend QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request);
-
- int m_port;
- bool m_isSecure;
- bool m_isValid;
- QMap<QString, QString> m_headers;
- QList<QWebSocketProtocol::Version> m_versions;
- QString m_key;
- QString m_origin;
- QList<QString> m_protocols;
- QList<QString> m_extensions;
- QUrl m_requestUrl;
+ Q_DISABLE_COPY(HandshakeRequest)
+ QTextStream &readFromStream(QTextStream &textStream);
+ friend QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request);
+
+ int m_port;
+ bool m_isSecure;
+ bool m_isValid;
+ QMap<QString, QString> m_headers;
+ QList<QWebSocketProtocol::Version> m_versions;
+ QString m_key;
+ QString m_origin;
+ QList<QString> m_protocols;
+ QList<QString> m_extensions;
+ QUrl m_requestUrl;
};
QTextStream &operator >>(QTextStream &stream, HandshakeRequest &request);
diff --git a/src/handshakeresponse_p.cpp b/src/handshakeresponse_p.cpp
index c48af00..32d77cb 100644
--- a/src/handshakeresponse_p.cpp
+++ b/src/handshakeresponse_p.cpp
@@ -31,190 +31,190 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
QT_BEGIN_NAMESPACE
/*!
- \internal
+ \internal
*/
HandshakeResponse::HandshakeResponse(const HandshakeRequest &request,
- const QString &serverName,
- bool isOriginAllowed,
- const QList<QWebSocketProtocol::Version> &supportedVersions,
- const QList<QString> &supportedProtocols,
- const QList<QString> &supportedExtensions) :
- m_isValid(false),
- m_canUpgrade(false),
- m_response(),
- m_acceptedProtocol(),
- m_acceptedExtension(),
- m_acceptedVersion(QWebSocketProtocol::V_Unknow)
+ const QString &serverName,
+ bool isOriginAllowed,
+ const QList<QWebSocketProtocol::Version> &supportedVersions,
+ const QList<QString> &supportedProtocols,
+ const QList<QString> &supportedExtensions) :
+ m_isValid(false),
+ m_canUpgrade(false),
+ m_response(),
+ m_acceptedProtocol(),
+ m_acceptedExtension(),
+ m_acceptedVersion(QWebSocketProtocol::V_Unknow)
{
- m_response = getHandshakeResponse(request, serverName, isOriginAllowed, supportedVersions, supportedProtocols, supportedExtensions);
- m_isValid = true;
+ m_response = getHandshakeResponse(request, serverName, isOriginAllowed, supportedVersions, supportedProtocols, supportedExtensions);
+ m_isValid = true;
}
/*!
- \internal
+ \internal
*/
HandshakeResponse::~HandshakeResponse()
{
}
/*!
- \internal
+ \internal
*/
bool HandshakeResponse::isValid() const
{
- return m_isValid;
+ return m_isValid;
}
/*!
- \internal
+ \internal
*/
bool HandshakeResponse::canUpgrade() const
{
- return m_isValid && m_canUpgrade;
+ return m_isValid && m_canUpgrade;
}
/*!
- \internal
+ \internal
*/
QString HandshakeResponse::getAcceptedProtocol() const
{
- return m_acceptedProtocol;
+ return m_acceptedProtocol;
}
/*!
- \internal
+ \internal
*/
QString HandshakeResponse::calculateAcceptKey(const QString &key) const
{
- QString tmpKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; //the UID comes from RFC6455
- QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1);
- return QString(hash.toBase64());
+ QString tmpKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; //the UID comes from RFC6455
+ QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1);
+ return QString(hash.toBase64());
}
/*!
- \internal
+ \internal
*/
QString HandshakeResponse::getHandshakeResponse(const HandshakeRequest &request,
- const QString &serverName,
- bool isOriginAllowed,
- const QList<QWebSocketProtocol::Version> &supportedVersions,
- const QList<QString> &supportedProtocols,
- const QList<QString> &supportedExtensions)
+ const QString &serverName,
+ bool isOriginAllowed,
+ const QList<QWebSocketProtocol::Version> &supportedVersions,
+ const QList<QString> &supportedProtocols,
+ const QList<QString> &supportedExtensions)
{
- QStringList response;
- m_canUpgrade = false;
-
- if (!isOriginAllowed)
- {
- if (!m_canUpgrade)
- {
- response << "HTTP/1.1 403 Access Forbidden";
- }
- }
- else
- {
- if (request.isValid())
- {
- QString acceptKey = calculateAcceptKey(request.getKey());
- QList<QString> matchingProtocols = supportedProtocols.toSet().intersect(request.getProtocols().toSet()).toList();
- QList<QString> matchingExtensions = supportedExtensions.toSet().intersect(request.getExtensions().toSet()).toList();
- QList<QWebSocketProtocol::Version> matchingVersions = request.getVersions().toSet().intersect(supportedVersions.toSet()).toList();
- qStableSort(matchingVersions.begin(), matchingVersions.end(), qGreater<QWebSocketProtocol::Version>()); //sort in descending order
-
- if (matchingVersions.isEmpty())
- {
- m_canUpgrade = false;
- }
- else
- {
- response << "HTTP/1.1 101 Switching Protocols" <<
- "Upgrade: websocket" <<
- "Connection: Upgrade" <<
- "Sec-WebSocket-Accept: " + acceptKey;
- if (!matchingProtocols.isEmpty())
- {
- m_acceptedProtocol = matchingProtocols.first();
- response << "Sec-WebSocket-Protocol: " + m_acceptedProtocol;
- }
- if (!matchingExtensions.isEmpty())
- {
- m_acceptedExtension = matchingExtensions.first();
- response << "Sec-WebSocket-Extensions: " + m_acceptedExtension;
- }
- QString origin = request.getOrigin().trimmed();
- if (origin.isEmpty())
- {
- origin = "*";
- }
- //TODO: header values should be configurable; i.e. Server, Allow-Credentials, Allow-Headers
- response << "Server: " + serverName <<
- "Access-Control-Allow-Credentials: false" << //do not allow credentialed request (containing cookies)
- "Access-Control-Allow-Methods: GET" << //only GET is allowed during handshaking
- "Access-Control-Allow-Headers: content-type" << //this is OK to be fixed; only the content-type header is allowed, no other headers are accepted
- "Access-Control-Allow-Origin: " + origin <<
- "Date: " + QDateTime::currentDateTimeUtc().toString("ddd, dd MMM yyyy hh:mm:ss 'GMT'");
-
- m_acceptedVersion = QWebSocketProtocol::currentVersion();
- m_canUpgrade = true;
- }
- }
- else
- {
- m_canUpgrade = false;
- }
- if (!m_canUpgrade)
- {
- response << "HTTP/1.1 400 Bad Request";
- QStringList versions;
- Q_FOREACH(QWebSocketProtocol::Version version, supportedVersions)
- {
- versions << QString::number(static_cast<int>(version));
- }
- response << "Sec-WebSocket-Version: " + versions.join(", ");
- }
- }
- response << "\r\n"; //append empty line at end of header
- return response.join("\r\n");
+ QStringList response;
+ m_canUpgrade = false;
+
+ if (!isOriginAllowed)
+ {
+ if (!m_canUpgrade)
+ {
+ response << "HTTP/1.1 403 Access Forbidden";
+ }
+ }
+ else
+ {
+ if (request.isValid())
+ {
+ QString acceptKey = calculateAcceptKey(request.getKey());
+ QList<QString> matchingProtocols = supportedProtocols.toSet().intersect(request.getProtocols().toSet()).toList();
+ QList<QString> matchingExtensions = supportedExtensions.toSet().intersect(request.getExtensions().toSet()).toList();
+ QList<QWebSocketProtocol::Version> matchingVersions = request.getVersions().toSet().intersect(supportedVersions.toSet()).toList();
+ qStableSort(matchingVersions.begin(), matchingVersions.end(), qGreater<QWebSocketProtocol::Version>()); //sort in descending order
+
+ if (matchingVersions.isEmpty())
+ {
+ m_canUpgrade = false;
+ }
+ else
+ {
+ response << "HTTP/1.1 101 Switching Protocols" <<
+ "Upgrade: websocket" <<
+ "Connection: Upgrade" <<
+ "Sec-WebSocket-Accept: " + acceptKey;
+ if (!matchingProtocols.isEmpty())
+ {
+ m_acceptedProtocol = matchingProtocols.first();
+ response << "Sec-WebSocket-Protocol: " + m_acceptedProtocol;
+ }
+ if (!matchingExtensions.isEmpty())
+ {
+ m_acceptedExtension = matchingExtensions.first();
+ response << "Sec-WebSocket-Extensions: " + m_acceptedExtension;
+ }
+ QString origin = request.getOrigin().trimmed();
+ if (origin.isEmpty())
+ {
+ origin = "*";
+ }
+ //TODO: header values should be configurable; i.e. Server, Allow-Credentials, Allow-Headers
+ response << "Server: " + serverName <<
+ "Access-Control-Allow-Credentials: false" << //do not allow credentialed request (containing cookies)
+ "Access-Control-Allow-Methods: GET" << //only GET is allowed during handshaking
+ "Access-Control-Allow-Headers: content-type" << //this is OK to be fixed; only the content-type header is allowed, no other headers are accepted
+ "Access-Control-Allow-Origin: " + origin <<
+ "Date: " + QDateTime::currentDateTimeUtc().toString("ddd, dd MMM yyyy hh:mm:ss 'GMT'");
+
+ m_acceptedVersion = QWebSocketProtocol::currentVersion();
+ m_canUpgrade = true;
+ }
+ }
+ else
+ {
+ m_canUpgrade = false;
+ }
+ if (!m_canUpgrade)
+ {
+ response << "HTTP/1.1 400 Bad Request";
+ QStringList versions;
+ Q_FOREACH(QWebSocketProtocol::Version version, supportedVersions)
+ {
+ versions << QString::number(static_cast<int>(version));
+ }
+ response << "Sec-WebSocket-Version: " + versions.join(", ");
+ }
+ }
+ response << "\r\n"; //append empty line at end of header
+ return response.join("\r\n");
}
/*!
- \internal
+ \internal
*/
QTextStream &HandshakeResponse::writeToStream(QTextStream &textStream) const
{
- if (!m_response.isEmpty())
- {
- textStream << m_response.toLatin1().constData();
- }
- else
- {
- textStream.setStatus(QTextStream::WriteFailed);
- }
- return textStream;
+ if (!m_response.isEmpty())
+ {
+ textStream << m_response.toLatin1().constData();
+ }
+ else
+ {
+ textStream.setStatus(QTextStream::WriteFailed);
+ }
+ return textStream;
}
/*!
- \internal
+ \internal
*/
QTextStream &operator <<(QTextStream &stream, const HandshakeResponse &response)
{
- return response.writeToStream(stream);
+ return response.writeToStream(stream);
}
/*!
- \internal
+ \internal
*/
QWebSocketProtocol::Version HandshakeResponse::getAcceptedVersion() const
{
- return m_acceptedVersion;
+ return m_acceptedVersion;
}
/*!
- \internal
+ \internal
*/
QString HandshakeResponse::getAcceptedExtension() const
{
- return m_acceptedExtension;
+ return m_acceptedExtension;
}
QT_END_NAMESPACE
diff --git a/src/handshakeresponse_p.h b/src/handshakeresponse_p.h
index 74ddc65..7b1179b 100644
--- a/src/handshakeresponse_p.h
+++ b/src/handshakeresponse_p.h
@@ -41,46 +41,46 @@ class QTextStream;
class HandshakeResponse:public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- HandshakeResponse(const HandshakeRequest &request,
- const QString &serverName,
- bool isOriginAllowed,
- const QList<QWebSocketProtocol::Version> &supportedVersions,
- const QList<QString> &supportedProtocols,
- const QList<QString> &supportedExtensions);
+ HandshakeResponse(const HandshakeRequest &request,
+ const QString &serverName,
+ bool isOriginAllowed,
+ const QList<QWebSocketProtocol::Version> &supportedVersions,
+ const QList<QString> &supportedProtocols,
+ const QList<QString> &supportedExtensions);
- virtual ~HandshakeResponse();
+ virtual ~HandshakeResponse();
- bool isValid() const;
- bool canUpgrade() const;
- QString getAcceptedProtocol() const;
- QString getAcceptedExtension() const;
- QWebSocketProtocol::Version getAcceptedVersion() const;
+ bool isValid() const;
+ bool canUpgrade() const;
+ QString getAcceptedProtocol() const;
+ QString getAcceptedExtension() const;
+ QWebSocketProtocol::Version getAcceptedVersion() const;
public Q_SLOTS:
Q_SIGNALS:
private:
- Q_DISABLE_COPY(HandshakeResponse)
- bool m_isValid;
- bool m_canUpgrade;
- QString m_response;
- QString m_acceptedProtocol;
- QString m_acceptedExtension;
- QWebSocketProtocol::Version m_acceptedVersion;
-
- QString calculateAcceptKey(const QString &key) const;
- QString getHandshakeResponse(const HandshakeRequest &request,
- const QString &serverName,
- bool isOriginAllowed,
- const QList<QWebSocketProtocol::Version> &supportedVersions,
- const QList<QString> &supportedProtocols,
- const QList<QString> &supportedExtensions);
-
- QTextStream &writeToStream(QTextStream &textStream) const;
- friend QTextStream &operator <<(QTextStream &stream, const HandshakeResponse &response);
+ Q_DISABLE_COPY(HandshakeResponse)
+ bool m_isValid;
+ bool m_canUpgrade;
+ QString m_response;
+ QString m_acceptedProtocol;
+ QString m_acceptedExtension;
+ QWebSocketProtocol::Version m_acceptedVersion;
+
+ QString calculateAcceptKey(const QString &key) const;
+ QString getHandshakeResponse(const HandshakeRequest &request,
+ const QString &serverName,
+ bool isOriginAllowed,
+ const QList<QWebSocketProtocol::Version> &supportedVersions,
+ const QList<QString> &supportedProtocols,
+ const QList<QString> &supportedExtensions);
+
+ QTextStream &writeToStream(QTextStream &textStream) const;
+ friend QTextStream &operator <<(QTextStream &stream, const HandshakeResponse &response);
};
QT_END_NAMESPACE
diff --git a/src/qwebsocket.cpp b/src/qwebsocket.cpp
index a2a4283..822d4a2 100644
--- a/src/qwebsocket.cpp
+++ b/src/qwebsocket.cpp
@@ -18,41 +18,41 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
- \class QWebSocket
+ \class QWebSocket
- \inmodule QWebSockets
- \brief Implements a TCP socket that talks the websocket protocol.
+ \inmodule QWebSockets
+ \brief Implements a TCP socket that talks the websocket protocol.
- WebSockets is a web technology providing full-duplex communications channels over a single TCP connection.
- The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011 (see http://tools.ietf.org/html/rfc6455).
- It can both be used in a client application and server application.
+ WebSockets is a web technology providing full-duplex communications channels over a single TCP connection.
+ The WebSocket protocol was standardized by the IETF as RFC 6455 in 2011 (see http://tools.ietf.org/html/rfc6455).
+ It can both be used in a client application and server application.
- This class was modeled after QAbstractSocket.
+ This class was modeled after QAbstractSocket.
- \sa QAbstractSocket, QTcpSocket
+ \sa QAbstractSocket, QTcpSocket
- \sa echoclient.html
+ \sa echoclient.html
*/
/*!
- \page echoclient.html example
- \title QWebSocket client example
- \brief A sample websocket client that sends a message and displays the message that it receives back.
+ \page echoclient.html example
+ \title QWebSocket client example
+ \brief A sample websocket client that sends a message and displays the message that it receives back.
- \section1 Description
- The EchoClient example implements a web socket client that sends a message to a websocket server and dumps the answer that it gets back.
- This example should ideally be used with the EchoServer example.
- \section1 Code
- We start by connecting to the `connected()` signal.
- \snippet echoclient.cpp constructor
- After the connection, we open the socket to the given \a url.
+ \section1 Description
+ The EchoClient example implements a web socket client that sends a message to a websocket server and dumps the answer that it gets back.
+ This example should ideally be used with the EchoServer example.
+ \section1 Code
+ We start by connecting to the `connected()` signal.
+ \snippet echoclient.cpp constructor
+ After the connection, we open the socket to the given \a url.
- \snippet echoclient.cpp onConnected
- When the client is connected successfully, we connect to the `onTextMessageReceived()` signal, and send out "Hello, world!".
- If connected with the EchoServer, we will receive the same message back.
+ \snippet echoclient.cpp onConnected
+ When the client is connected successfully, we connect to the `onTextMessageReceived()` signal, and send out "Hello, world!".
+ If connected with the EchoServer, we will receive the same message back.
- \snippet echoclient.cpp onTextMessageReceived
- Whenever a message is received, we write it out.
+ \snippet echoclient.cpp onTextMessageReceived
+ Whenever a message is received, we write it out.
*/
/*!
@@ -66,13 +66,13 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
\sa close(), connected()
*/
/*!
- \fn void QWebSocket::aboutToClose()
+ \fn void QWebSocket::aboutToClose()
- This signal is emitted when the socket is about to close.
- Connect this signal if you have operations that need to be performed before the socket closes
- (e.g., if you have data in a separate buffer that needs to be written to the device).
+ This signal is emitted when the socket is about to close.
+ Connect this signal if you have operations that need to be performed before the socket closes
+ (e.g., if you have data in a separate buffer that needs to be written to the device).
- \sa close()
+ \sa close()
*/
/*!
\fn void QWebSocket::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
@@ -89,80 +89,80 @@ not been filled in with new information when the signal returns.
\sa QAuthenticator, QNetworkProxy
*/
/*!
- \fn void QWebSocket::stateChanged(QAbstractSocket::SocketState state);
+ \fn void QWebSocket::stateChanged(QAbstractSocket::SocketState state);
- This signal is emitted whenever QWebSocket's state changes.
- The \a state parameter is the new state.
+ This signal is emitted whenever QWebSocket's state changes.
+ The \a state parameter is the new state.
- QAbstractSocket::SocketState is not a registered metatype, so for queued
- connections, you will have to register it with Q_REGISTER_METATYPE() and
- qRegisterMetaType().
+ QAbstractSocket::SocketState is not a registered metatype, so for queued
+ connections, you will have to register it with Q_REGISTER_METATYPE() and
+ qRegisterMetaType().
- \sa state()
+ \sa state()
*/
/*!
- \fn void QWebSocket::readChannelFinished()
+ \fn void QWebSocket::readChannelFinished()
- This signal is emitted when the input (reading) stream is closed in this device. It is emitted as soon as the closing is detected.
+ This signal is emitted when the input (reading) stream is closed in this device. It is emitted as soon as the closing is detected.
- \sa close()
+ \sa close()
*/
/*!
- \fn void QWebSocket::textFrameReceived(QString frame, bool isLastFrame);
+ \fn void QWebSocket::textFrameReceived(QString frame, bool isLastFrame);
- This signal is emitted whenever a text frame is received. The \a frame contains the data and
- \a isLastFrame indicates whether this is the last frame of the complete message.
+ This signal is emitted whenever a text frame is received. The \a frame contains the data and
+ \a isLastFrame indicates whether this is the last frame of the complete message.
- This signal can be used to process large messages frame by frame, instead of waiting for the complete
- message to arrive.
+ This signal can be used to process large messages frame by frame, instead of waiting for the complete
+ message to arrive.
- \sa binaryFrameReceived()
+ \sa binaryFrameReceived()
*/
/*!
- \fn void QWebSocket::binaryFrameReceived(QByteArray frame, bool isLastFrame);
+ \fn void QWebSocket::binaryFrameReceived(QByteArray frame, bool isLastFrame);
- This signal is emitted whenever a binary frame is received. The \a frame contains the data and
- \a isLastFrame indicates whether this is the last frame of the complete message.
+ This signal is emitted whenever a binary frame is received. The \a frame contains the data and
+ \a isLastFrame indicates whether this is the last frame of the complete message.
- This signal can be used to process large messages frame by frame, instead of waiting for the complete
- message to arrive.
+ This signal can be used to process large messages frame by frame, instead of waiting for the complete
+ message to arrive.
- \sa textFrameReceived()
+ \sa textFrameReceived()
*/
/*!
- \fn void QWebSocket::textMessageReceived(QString message);
+ \fn void QWebSocket::textMessageReceived(QString message);
- This signal is emitted whenever a text message is received. The \a message contains the received text.
+ This signal is emitted whenever a text message is received. The \a message contains the received text.
- \sa binaryMessageReceived()
+ \sa binaryMessageReceived()
*/
/*!
- \fn void QWebSocket::binaryMessageReceived(QByteArray message);
+ \fn void QWebSocket::binaryMessageReceived(QByteArray message);
- This signal is emitted whenever a binary message is received. The \a message contains the received bytes.
+ This signal is emitted whenever a binary message is received. The \a message contains the received bytes.
- \sa textMessageReceived()
+ \sa textMessageReceived()
*/
/*!
- \fn void QWebSocket::error(QAbstractSocket::SocketError error);
+ \fn void QWebSocket::error(QAbstractSocket::SocketError error);
- This signal is emitted after an error occurred. The \a error
- parameter describes the type of error that occurred.
+ This signal is emitted after an error occurred. The \a error
+ parameter describes the type of error that occurred.
- QAbstractSocket::SocketError is not a registered metatype, so for queued
- connections, you will have to register it with Q_DECLARE_METATYPE() and
- qRegisterMetaType().
+ QAbstractSocket::SocketError is not a registered metatype, so for queued
+ connections, you will have to register it with Q_DECLARE_METATYPE() and
+ qRegisterMetaType().
- \sa error(), errorString()
+ \sa error(), errorString()
*/
/*!
- \fn void QWebSocket::pong(quint64 elapsedTime)
+ \fn void QWebSocket::pong(quint64 elapsedTime)
- Emitted when a pong message is received in reply to a previous ping.
- \a elapsedTime contains the roundtrip time in milliseconds
+ Emitted when a pong message is received in reply to a previous ping.
+ \a elapsedTime contains the roundtrip time in milliseconds
- \sa ping()
+ \sa ping()
*/
#include "qwebsocket.h"
#include "qwebsocket_p.h"
@@ -187,8 +187,8 @@ const quint64 FRAME_SIZE_IN_BYTES = 512 * 512 * 2; //maximum size of a frame whe
* \note Currently only V13 (RFC 6455) is supported
*/
QWebSocket::QWebSocket(QString origin, QWebSocketProtocol::Version version, QObject *parent) :
- QObject(parent),
- d_ptr(new QWebSocketPrivate(origin, version, this, this))
+ QObject(parent),
+ d_ptr(new QWebSocketPrivate(origin, version, this, this))
{
}
@@ -197,8 +197,8 @@ QWebSocket::QWebSocket(QString origin, QWebSocketProtocol::Version version, QObj
*/
QWebSocket::~QWebSocket()
{
- delete d_ptr;
- //d_ptr = 0;
+ delete d_ptr;
+ //d_ptr = 0;
}
/*!
@@ -206,7 +206,7 @@ QWebSocket::~QWebSocket()
*/
void QWebSocket::abort()
{
- d_ptr->abort();
+ d_ptr->abort();
}
/*!
@@ -215,7 +215,7 @@ void QWebSocket::abort()
*/
QAbstractSocket::SocketError QWebSocket::error() const
{
- return d_ptr->error();
+ return d_ptr->error();
}
//only called by QWebSocketPrivate::upgradeFrom
@@ -223,8 +223,8 @@ QAbstractSocket::SocketError QWebSocket::error() const
\internal
*/
QWebSocket::QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QObject *parent) :
- QObject(parent),
- d_ptr(new QWebSocketPrivate(pTcpSocket, version, this, this))
+ QObject(parent),
+ d_ptr(new QWebSocketPrivate(pTcpSocket, version, this, this))
{
}
@@ -235,162 +235,162 @@ QWebSocket::QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version versi
*/
QString QWebSocket::errorString() const
{
- return d_ptr->errorString();
+ return d_ptr->errorString();
}
/*!
- This function writes as much as possible from the internal write buffer to the underlying network socket, without blocking.
- If any data was written, this function returns true; otherwise false is returned.
- Call this function if you need QWebSocket to start sending buffered data immediately.
- The number of bytes successfully written depends on the operating system.
- In most cases, you do not need to call this function, because QWebSocket will start sending data automatically once control goes back to the event loop.
- In the absence of an event loop, call waitForBytesWritten() instead.
+ This function writes as much as possible from the internal write buffer to the underlying network socket, without blocking.
+ If any data was written, this function returns true; otherwise false is returned.
+ Call this function if you need QWebSocket to start sending buffered data immediately.
+ The number of bytes successfully written depends on the operating system.
+ In most cases, you do not need to call this function, because QWebSocket will start sending data automatically once control goes back to the event loop.
+ In the absence of an event loop, call waitForBytesWritten() instead.
*/
bool QWebSocket::flush()
{
- return d_ptr->flush();
+ return d_ptr->flush();
}
/*!
- Sends the given \a message over the socket as a text message and returns the number of bytes actually sent.
- \a message must be '\\0' terminated.
+ Sends the given \a message over the socket as a text message and returns the number of bytes actually sent.
+ \a message must be '\\0' terminated.
*/
qint64 QWebSocket::write(const char *message)
{
- return d_ptr->write(message);
+ return d_ptr->write(message);
}
/*!
- Sends the most \a maxSize bytes of the given \a message over the socket as a text message and returns the number of bytes actually sent.
+ Sends the most \a maxSize bytes of the given \a message over the socket as a text message and returns the number of bytes actually sent.
*/
qint64 QWebSocket::write(const char *message, qint64 maxSize)
{
- return d_ptr->write(message, maxSize);
+ return d_ptr->write(message, maxSize);
}
/*!
- \brief Sends the given \a message over the socket as a text message and returns the number of bytes actually sent.
+ \brief Sends the given \a message over the socket as a text message and returns the number of bytes actually sent.
*/
qint64 QWebSocket::write(const QString &message)
{
- return d_ptr->write(message);
+ return d_ptr->write(message);
}
/*!
- \brief Sends the given \a data over the socket as a binary message and returns the number of bytes actually sent.
+ \brief Sends the given \a data over the socket as a binary message and returns the number of bytes actually sent.
*/
qint64 QWebSocket::write(const QByteArray &data)
{
- return d_ptr->write(data);
+ return d_ptr->write(data);
}
/*!
- \brief Gracefully closes the socket with the given \a closeCode and \a reason. Any data in the write buffer is flushed before the socket is closed.
- The \a closeCode is a QWebSocketProtocol::CloseCode indicating the reason to close, and
- \a reason describes the reason of the closure more in detail
+ \brief Gracefully closes the socket with the given \a closeCode and \a reason. Any data in the write buffer is flushed before the socket is closed.
+ The \a closeCode is a QWebSocketProtocol::CloseCode indicating the reason to close, and
+ \a reason describes the reason of the closure more in detail
*/
void QWebSocket::close(QWebSocketProtocol::CloseCode closeCode, QString reason)
{
- d_ptr->close(closeCode, reason);
+ d_ptr->close(closeCode, reason);
}
/*!
- \brief Opens a websocket connection using the given \a url.
- If \a mask is true, all frames will be masked; this is only necessary for client side sockets; servers should never mask
- \note A client socket must *always* mask its frames; servers may *never* mask its frames
+ \brief Opens a websocket connection using the given \a url.
+ If \a mask is true, all frames will be masked; this is only necessary for client side sockets; servers should never mask
+ \note A client socket must *always* mask its frames; servers may *never* mask its frames
*/
void QWebSocket::open(const QUrl &url, bool mask)
{
- d_ptr->open(url, mask);
+ d_ptr->open(url, mask);
}
/*!
- \brief Pings the server to indicate that the connection is still alive.
+ \brief Pings the server to indicate that the connection is still alive.
- \sa pong()
+ \sa pong()
*/
void QWebSocket::ping()
{
- d_ptr->ping();
+ d_ptr->ping();
}
/*!
- \brief Returns the version the socket is currently using
+ \brief Returns the version the socket is currently using
*/
QWebSocketProtocol::Version QWebSocket::version()
{
- return d_ptr->version();
+ return d_ptr->version();
}
/*!
- \brief Returns the name of the resource currently accessed.
+ \brief Returns the name of the resource currently accessed.
*/
QString QWebSocket::resourceName()
{
- return d_ptr->resourceName();
+ return d_ptr->resourceName();
}
/*!
- \brief Returns the url the socket is connected to or will connect to.
+ \brief Returns the url the socket is connected to or will connect to.
*/
QUrl QWebSocket::requestUrl()
{
- return d_ptr->requestUrl();
+ return d_ptr->requestUrl();
}
/*!
- \brief Returns the current origin
+ \brief Returns the current origin
*/
QString QWebSocket::origin()
{
- return d_ptr->origin();
+ return d_ptr->origin();
}
/*!
- \brief Returns the currently used protocol.
+ \brief Returns the currently used protocol.
*/
QString QWebSocket::protocol()
{
- return d_ptr->protocol();
+ return d_ptr->protocol();
}
/*!
- \brief Returns the currently used extension.
+ \brief Returns the currently used extension.
*/
QString QWebSocket::extension()
{
- return d_ptr->extension();
+ return d_ptr->extension();
}
/*!
- \brief Returns the current state of the socket
+ \brief Returns the current state of the socket
*/
QAbstractSocket::SocketState QWebSocket::state() const
{
- return d_ptr->state();
+ return d_ptr->state();
}
/*!
- \brief Waits until the socket is connected, up to \a msecs milliseconds. If the connection has been established, this function returns true; otherwise it returns false. In the case where it returns false, you can call error() to determine the cause of the error.
- The following example waits up to one second for a connection to be established:
+ \brief Waits until the socket is connected, up to \a msecs milliseconds. If the connection has been established, this function returns true; otherwise it returns false. In the case where it returns false, you can call error() to determine the cause of the error.
+ The following example waits up to one second for a connection to be established:
- ~~~{.cpp}
- socket->open("ws://localhost:1234", false);
- if (socket->waitForConnected(1000))
- {
- qDebug("Connected!");
- }
- ~~~
+ ~~~{.cpp}
+ socket->open("ws://localhost:1234", false);
+ if (socket->waitForConnected(1000))
+ {
+ qDebug("Connected!");
+ }
+ ~~~
- If \a msecs is -1, this function will not time out.
- @note This function may wait slightly longer than msecs, depending on the time it takes to complete the host lookup.
- @note Multiple calls to this functions do not accumulate the time. If the function times out, the connecting process will be aborted.
+ If \a msecs is -1, this function will not time out.
+ @note This function may wait slightly longer than msecs, depending on the time it takes to complete the host lookup.
+ @note Multiple calls to this functions do not accumulate the time. If the function times out, the connecting process will be aborted.
- \sa connected(), open(), state()
+ \sa connected(), open(), state()
*/
bool QWebSocket::waitForConnected(int msecs)
{
- return d_ptr->waitForConnected(msecs);
+ return d_ptr->waitForConnected(msecs);
}
/*!
@@ -403,148 +403,148 @@ bool QWebSocket::waitForConnected(int msecs)
*/
bool QWebSocket::waitForDisconnected(int msecs)
{
- return d_ptr->waitForDisconnected(msecs);
+ return d_ptr->waitForDisconnected(msecs);
}
/*!
- Returns the local address
+ Returns the local address
*/
QHostAddress QWebSocket::localAddress() const
{
- return d_ptr->localAddress();
+ return d_ptr->localAddress();
}
/*!
- Returns the local port
+ Returns the local port
*/
quint16 QWebSocket::localPort() const
{
- return d_ptr->localPort();
+ return d_ptr->localPort();
}
/*!
- Returns the pause mode of this socket
+ Returns the pause mode of this socket
*/
QAbstractSocket::PauseModes QWebSocket::pauseMode() const
{
- return d_ptr->pauseMode();
+ return d_ptr->pauseMode();
}
/*!
- Returns the peer address
+ Returns the peer address
*/
QHostAddress QWebSocket::peerAddress() const
{
- return d_ptr->peerAddress();
+ return d_ptr->peerAddress();
}
/*!
- Returns the peerName
+ Returns the peerName
*/
QString QWebSocket::peerName() const
{
- return d_ptr->peerName();
+ return d_ptr->peerName();
}
/*!
- Returns the peerport
+ Returns the peerport
*/
quint16 QWebSocket::peerPort() const
{
- return d_ptr->peerPort();
+ return d_ptr->peerPort();
}
#ifndef QT_NO_NETWORKPROXY
/*!
- Returns the currently configured proxy
+ Returns the currently configured proxy
*/
QNetworkProxy QWebSocket::proxy() const
{
- return d_ptr->proxy();
+ return d_ptr->proxy();
}
/*!
- Sets the proxy to \a networkProxy
+ Sets the proxy to \a networkProxy
*/
void QWebSocket::setProxy(const QNetworkProxy &networkProxy)
{
- d_ptr->setProxy(networkProxy);
+ d_ptr->setProxy(networkProxy);
}
#endif
/*!
- Returns the size in bytes of the readbuffer that is used by the socket.
+ Returns the size in bytes of the readbuffer that is used by the socket.
*/
qint64 QWebSocket::readBufferSize() const
{
- return d_ptr->readBufferSize();
+ return d_ptr->readBufferSize();
}
/*!
- Continues data transfer on the socket. This method should only be used after the socket
- has been set to pause upon notifications and a notification has been received.
- The only notification currently supported is sslErrors().
- Calling this method if the socket is not paused results in undefined behavior.
+ Continues data transfer on the socket. This method should only be used after the socket
+ has been set to pause upon notifications and a notification has been received.
+ The only notification currently supported is sslErrors().
+ Calling this method if the socket is not paused results in undefined behavior.
- \sa pauseMode(), setPauseMode()
+ \sa pauseMode(), setPauseMode()
*/
void QWebSocket::resume()
{
- d_ptr->resume();
+ d_ptr->resume();
}
/*!
- Controls whether to pause upon receiving a notification. The \a pauseMode parameter specifies
- the conditions in which the socket should be paused.
- The only notification currently supported is sslErrors().
- If set to PauseOnSslErrors, data transfer on the socket will be paused
- and needs to be enabled explicitly again by calling resume().
- By default, this option is set to PauseNever. This option must be called
- before connecting to the server, otherwise it will result in undefined behavior.
+ Controls whether to pause upon receiving a notification. The \a pauseMode parameter specifies
+ the conditions in which the socket should be paused.
+ The only notification currently supported is sslErrors().
+ If set to PauseOnSslErrors, data transfer on the socket will be paused
+ and needs to be enabled explicitly again by calling resume().
+ By default, this option is set to PauseNever. This option must be called
+ before connecting to the server, otherwise it will result in undefined behavior.
- \sa pauseMode(), resume()
+ \sa pauseMode(), resume()
*/
void QWebSocket::setPauseMode(QAbstractSocket::PauseModes pauseMode)
{
- d_ptr->setPauseMode(pauseMode);
+ d_ptr->setPauseMode(pauseMode);
}
/*!
- Sets the size of QWebSocket's internal read buffer to be \a size bytes.
- If the buffer size is limited to a certain size, QWebSocket won't buffer more than this size of data.
- Exceptionally, a buffer size of 0 means that the read buffer is unlimited and all incoming data is buffered. This is the default.
- This option is useful if you only read the data at certain points in time (e.g., in a real-time streaming application) or if you want to protect your socket against receiving too much data, which may eventually cause your application to run out of memory.
- \sa readBufferSize()
+ Sets the size of QWebSocket's internal read buffer to be \a size bytes.
+ If the buffer size is limited to a certain size, QWebSocket won't buffer more than this size of data.
+ Exceptionally, a buffer size of 0 means that the read buffer is unlimited and all incoming data is buffered. This is the default.
+ This option is useful if you only read the data at certain points in time (e.g., in a real-time streaming application) or if you want to protect your socket against receiving too much data, which may eventually cause your application to run out of memory.
+ \sa readBufferSize()
*/
void QWebSocket::setReadBufferSize(qint64 size)
{
- d_ptr->setReadBufferSize(size);
+ d_ptr->setReadBufferSize(size);
}
/*!
- Sets the given \a option to the value described by \a value.
- \sa socketOption()
+ Sets the given \a option to the value described by \a value.
+ \sa socketOption()
*/
void QWebSocket::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
{
- d_ptr->setSocketOption(option, value);
+ d_ptr->setSocketOption(option, value);
}
/*!
- Returns the value of the option \a option.
- \sa setSocketOption()
+ Returns the value of the option \a option.
+ \sa setSocketOption()
*/
QVariant QWebSocket::socketOption(QAbstractSocket::SocketOption option)
{
- return d_ptr->socketOption(option);
+ return d_ptr->socketOption(option);
}
/*!
- Returns true if the QWebSocket is valid.
+ Returns true if the QWebSocket is valid.
*/
bool QWebSocket::isValid()
{
- return d_ptr->isValid();
+ return d_ptr->isValid();
}
QT_END_NAMESPACE
diff --git a/src/qwebsocket.h b/src/qwebsocket.h
index 2443e01..d244783 100644
--- a/src/qwebsocket.h
+++ b/src/qwebsocket.h
@@ -37,79 +37,79 @@ class QWebSocketPrivate;
class Q_WEBSOCKETS_EXPORT QWebSocket:public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit QWebSocket(QString origin = QString(), QWebSocketProtocol::Version version = QWebSocketProtocol::V_LATEST, QObject *parent = 0);
- virtual ~QWebSocket();
-
- void abort();
- QAbstractSocket::SocketError error() const;
- QString errorString() const;
- bool flush();
- bool isValid();
- QHostAddress localAddress() const;
- quint16 localPort() const;
- QAbstractSocket::PauseModes pauseMode() const;
- QHostAddress peerAddress() const;
- QString peerName() const;
- quint16 peerPort() const;
+ explicit QWebSocket(QString origin = QString(), QWebSocketProtocol::Version version = QWebSocketProtocol::V_LATEST, QObject *parent = 0);
+ virtual ~QWebSocket();
+
+ void abort();
+ QAbstractSocket::SocketError error() const;
+ QString errorString() const;
+ bool flush();
+ bool isValid();
+ QHostAddress localAddress() const;
+ quint16 localPort() const;
+ QAbstractSocket::PauseModes pauseMode() const;
+ QHostAddress peerAddress() const;
+ QString peerName() const;
+ quint16 peerPort() const;
#ifndef QT_NO_NETWORKPROXY
- QNetworkProxy proxy() const;
- void setProxy(const QNetworkProxy &networkProxy);
+ QNetworkProxy proxy() const;
+ void setProxy(const QNetworkProxy &networkProxy);
#endif
- qint64 readBufferSize() const;
- void setReadBufferSize(qint64 size);
+ qint64 readBufferSize() const;
+ void setReadBufferSize(qint64 size);
- void resume();
- void setPauseMode(QAbstractSocket::PauseModes pauseMode);
+ void resume();
+ void setPauseMode(QAbstractSocket::PauseModes pauseMode);
- void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value);
- QVariant socketOption(QAbstractSocket::SocketOption option);
- QAbstractSocket::SocketState state() const;
+ void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value);
+ QVariant socketOption(QAbstractSocket::SocketOption option);
+ QAbstractSocket::SocketState state() const;
- bool waitForConnected(int msecs = 30000);
- bool waitForDisconnected(int msecs = 30000);
+ bool waitForConnected(int msecs = 30000);
+ bool waitForDisconnected(int msecs = 30000);
- QWebSocketProtocol::Version version();
- QString resourceName();
- QUrl requestUrl();
- QString origin();
- QString protocol();
- QString extension();
+ QWebSocketProtocol::Version version();
+ QString resourceName();
+ QUrl requestUrl();
+ QString origin();
+ QString protocol();
+ QString extension();
- qint64 write(const char *message); //send data as text
- qint64 write(const char *message, qint64 maxSize); //send data as text
- qint64 write(const QString &message); //send data as text
- qint64 write(const QByteArray &data); //send data as binary
+ qint64 write(const char *message); //send data as text
+ qint64 write(const char *message, qint64 maxSize); //send data as text
+ qint64 write(const QString &message); //send data as text
+ qint64 write(const QByteArray &data); //send data as binary
public Q_SLOTS:
- virtual void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL, QString reason = QString());
- virtual void open(const QUrl &url, bool mask = true);
- void ping();
+ virtual void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL, QString reason = QString());
+ virtual void open(const QUrl &url, bool mask = true);
+ void ping();
Q_SIGNALS:
- void aboutToClose();
- void connected();
- void disconnected();
- void stateChanged(QAbstractSocket::SocketState state);
+ void aboutToClose();
+ void connected();
+ void disconnected();
+ void stateChanged(QAbstractSocket::SocketState state);
#ifndef QT_NO_NETWORKPROXY
- void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *pAuthenticator);
+ void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *pAuthenticator);
#endif
- void readChannelFinished();
- void textFrameReceived(QString frame, bool isLastFrame);
- void binaryFrameReceived(QByteArray frame, bool isLastFrame);
- void textMessageReceived(QString message);
- void binaryMessageReceived(QByteArray message);
- void error(QAbstractSocket::SocketError error);
- void pong(quint64 elapsedTime);
+ void readChannelFinished();
+ void textFrameReceived(QString frame, bool isLastFrame);
+ void binaryFrameReceived(QByteArray frame, bool isLastFrame);
+ void textMessageReceived(QString message);
+ void binaryMessageReceived(QByteArray message);
+ void error(QAbstractSocket::SocketError error);
+ void pong(quint64 elapsedTime);
private:
- Q_DISABLE_COPY(QWebSocket)
- QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QObject *parent = 0);
- QWebSocketPrivate * const d_ptr;
+ Q_DISABLE_COPY(QWebSocket)
+ QWebSocket(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QObject *parent = 0);
+ QWebSocketPrivate * const d_ptr;
- friend class QWebSocketPrivate;
+ friend class QWebSocketPrivate;
};
QT_END_NAMESPACE
diff --git a/src/qwebsocket_p.cpp b/src/qwebsocket_p.cpp
index ed9586b..c2786d0 100644
--- a/src/qwebsocket_p.cpp
+++ b/src/qwebsocket_p.cpp
@@ -42,246 +42,246 @@ QT_BEGIN_NAMESPACE
const quint64 FRAME_SIZE_IN_BYTES = 512 * 512 * 2; //maximum size of a frame when sending a message
/*!
- \internal
+ \internal
*/
QWebSocketPrivate::QWebSocketPrivate(QString origin, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
- QObject(parent),
- q_ptr(pWebSocket),
- m_pSocket(new QTcpSocket(this)),
- m_errorString(),
- m_version(version),
- m_resourceName(),
- m_requestUrl(),
- m_origin(origin),
- m_protocol(""),
- m_extension(""),
- m_socketState(QAbstractSocket::UnconnectedState),
- m_key(),
- m_mustMask(true),
- m_isClosingHandshakeSent(false),
- m_isClosingHandshakeReceived(false),
- m_pingTimer(),
- m_dataProcessor()
-{
- Q_ASSERT(pWebSocket != 0);
- makeConnections(m_pSocket);
- qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
-}
-
-/*!
- \internal
+ QObject(parent),
+ q_ptr(pWebSocket),
+ m_pSocket(new QTcpSocket(this)),
+ m_errorString(),
+ m_version(version),
+ m_resourceName(),
+ m_requestUrl(),
+ m_origin(origin),
+ m_protocol(""),
+ m_extension(""),
+ m_socketState(QAbstractSocket::UnconnectedState),
+ m_key(),
+ m_mustMask(true),
+ m_isClosingHandshakeSent(false),
+ m_isClosingHandshakeReceived(false),
+ m_pingTimer(),
+ m_dataProcessor()
+{
+ Q_ASSERT(pWebSocket != 0);
+ makeConnections(m_pSocket);
+ qsrand(static_cast<uint>(QDateTime::currentMSecsSinceEpoch()));
+}
+
+/*!
+ \internal
*/
QWebSocketPrivate::QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent) :
- QObject(parent),
- q_ptr(pWebSocket),
- m_pSocket(pTcpSocket),
- m_errorString(pTcpSocket->errorString()),
- m_version(version),
- m_resourceName(),
- m_requestUrl(),
- m_origin(),
- m_protocol(),
- m_extension(),
- m_socketState(pTcpSocket->state()),
- m_key(),
- m_mustMask(true),
- m_isClosingHandshakeSent(false),
- m_isClosingHandshakeReceived(false),
- m_pingTimer(),
- m_dataProcessor()
-{
- Q_ASSERT(pWebSocket != 0);
- makeConnections(m_pSocket);
-}
-
-/*!
- \internal
+ QObject(parent),
+ q_ptr(pWebSocket),
+ m_pSocket(pTcpSocket),
+ m_errorString(pTcpSocket->errorString()),
+ m_version(version),
+ m_resourceName(),
+ m_requestUrl(),
+ m_origin(),
+ m_protocol(),
+ m_extension(),
+ m_socketState(pTcpSocket->state()),
+ m_key(),
+ m_mustMask(true),
+ m_isClosingHandshakeSent(false),
+ m_isClosingHandshakeReceived(false),
+ m_pingTimer(),
+ m_dataProcessor()
+{
+ Q_ASSERT(pWebSocket != 0);
+ makeConnections(m_pSocket);
+}
+
+/*!
+ \internal
*/
QWebSocketPrivate::~QWebSocketPrivate()
{
- if (state() == QAbstractSocket::ConnectedState)
- {
- close(QWebSocketProtocol::CC_GOING_AWAY, "Connection closed");
- }
- releaseConnections(m_pSocket);
- m_pSocket->deleteLater();
- m_pSocket = 0;
+ if (state() == QAbstractSocket::ConnectedState)
+ {
+ close(QWebSocketProtocol::CC_GOING_AWAY, "Connection closed");
+ }
+ releaseConnections(m_pSocket);
+ m_pSocket->deleteLater();
+ m_pSocket = 0;
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::abort()
{
- m_pSocket->abort();
+ m_pSocket->abort();
}
/*!
- \internal
+ \internal
*/
QAbstractSocket::SocketError QWebSocketPrivate::error() const
{
- return m_pSocket->error();
+ return m_pSocket->error();
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::errorString() const
{
- if (!m_errorString.isEmpty())
- {
- return m_errorString;
- }
- else
- {
- return m_pSocket->errorString();
- }
+ if (!m_errorString.isEmpty())
+ {
+ return m_errorString;
+ }
+ else
+ {
+ return m_pSocket->errorString();
+ }
}
/*!
- \internal
+ \internal
*/
bool QWebSocketPrivate::flush()
{
- return m_pSocket->flush();
+ return m_pSocket->flush();
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::write(const char *message)
{
- return write(QString::fromUtf8(message));
+ return write(QString::fromUtf8(message));
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::write(const char *message, qint64 maxSize)
{
- return write(QString::fromUtf8(message, static_cast<int>(maxSize)));
+ return write(QString::fromUtf8(message, static_cast<int>(maxSize)));
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::write(const QString &message)
{
- return doWriteData(message.toUtf8(), false);
+ return doWriteData(message.toUtf8(), false);
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::write(const QByteArray &data)
{
- return doWriteData(data, true);
+ return doWriteData(data, true);
}
/*!
\internal
*/
QWebSocket *QWebSocketPrivate::upgradeFrom(QTcpSocket *pTcpSocket,
- const HandshakeRequest &request,
- const HandshakeResponse &response,
- QObject *parent)
+ const HandshakeRequest &request,
+ const HandshakeResponse &response,
+ QObject *parent)
{
- QWebSocket *pWebSocket = new QWebSocket(pTcpSocket, response.getAcceptedVersion(), parent);
- pWebSocket->d_ptr->setExtension(response.getAcceptedExtension());
- pWebSocket->d_ptr->setOrigin(request.getOrigin());
- pWebSocket->d_ptr->setRequestUrl(request.getRequestUrl());
- pWebSocket->d_ptr->setProtocol(response.getAcceptedProtocol());
- pWebSocket->d_ptr->setResourceName(request.getRequestUrl().toString(QUrl::RemoveUserInfo));
- pWebSocket->d_ptr->enableMasking(false); //a server should not send masked frames
+ QWebSocket *pWebSocket = new QWebSocket(pTcpSocket, response.getAcceptedVersion(), parent);
+ pWebSocket->d_ptr->setExtension(response.getAcceptedExtension());
+ pWebSocket->d_ptr->setOrigin(request.getOrigin());
+ pWebSocket->d_ptr->setRequestUrl(request.getRequestUrl());
+ pWebSocket->d_ptr->setProtocol(response.getAcceptedProtocol());
+ pWebSocket->d_ptr->setResourceName(request.getRequestUrl().toString(QUrl::RemoveUserInfo));
+ pWebSocket->d_ptr->enableMasking(false); //a server should not send masked frames
- return pWebSocket;
+ return pWebSocket;
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString reason)
{
- if (!m_isClosingHandshakeSent)
- {
- quint32 maskingKey = 0;
- if (m_mustMask)
- {
- maskingKey = generateMaskingKey();
- }
- quint16 code = qToBigEndian<quint16>(closeCode);
- QByteArray payload;
- payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2);
- if (!reason.isEmpty())
- {
- payload.append(reason.toUtf8());
- }
- if (m_mustMask)
- {
- QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey);
- }
- QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true);
- frame.append(payload);
- m_pSocket->write(frame);
- m_pSocket->flush();
-
- m_isClosingHandshakeSent = true;
-
- Q_EMIT q_ptr->aboutToClose();
- }
- m_pSocket->close();
-}
-
-/*!
- \internal
+ if (!m_isClosingHandshakeSent)
+ {
+ quint32 maskingKey = 0;
+ if (m_mustMask)
+ {
+ maskingKey = generateMaskingKey();
+ }
+ quint16 code = qToBigEndian<quint16>(closeCode);
+ QByteArray payload;
+ payload.append(static_cast<const char *>(static_cast<const void *>(&code)), 2);
+ if (!reason.isEmpty())
+ {
+ payload.append(reason.toUtf8());
+ }
+ if (m_mustMask)
+ {
+ QWebSocketProtocol::mask(payload.data(), payload.size(), maskingKey);
+ }
+ QByteArray frame = getFrameHeader(QWebSocketProtocol::OC_CLOSE, payload.size(), maskingKey, true);
+ frame.append(payload);
+ m_pSocket->write(frame);
+ m_pSocket->flush();
+
+ m_isClosingHandshakeSent = true;
+
+ Q_EMIT q_ptr->aboutToClose();
+ }
+ m_pSocket->close();
+}
+
+/*!
+ \internal
*/
void QWebSocketPrivate::open(const QUrl &url, bool mask)
{
- m_dataProcessor.clear();
- m_isClosingHandshakeReceived = false;
- m_isClosingHandshakeSent = false;
+ m_dataProcessor.clear();
+ m_isClosingHandshakeReceived = false;
+ m_isClosingHandshakeSent = false;
- setRequestUrl(url);
- QString resourceName = url.path() + url.query();
- if (resourceName.isEmpty())
- {
- resourceName = "/";
- }
- setResourceName(resourceName);
- enableMasking(mask);
+ setRequestUrl(url);
+ QString resourceName = url.path() + url.query();
+ if (resourceName.isEmpty())
+ {
+ resourceName = "/";
+ }
+ setResourceName(resourceName);
+ enableMasking(mask);
- setSocketState(QAbstractSocket::ConnectingState);
+ setSocketState(QAbstractSocket::ConnectingState);
- m_pSocket->connectToHost(url.host(), url.port(80));
+ m_pSocket->connectToHost(url.host(), url.port(80));
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::ping()
{
- m_pingTimer.restart();
- QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, 0, 0, true);
- writeFrame(pingFrame);
+ m_pingTimer.restart();
+ QByteArray pingFrame = getFrameHeader(QWebSocketProtocol::OC_PING, 0, 0, true);
+ writeFrame(pingFrame);
}
/*!
\internal
- Sets the version to use for the websocket protocol; this must be set before the socket is opened.
+ Sets the version to use for the websocket protocol; this must be set before the socket is opened.
*/
void QWebSocketPrivate::setVersion(QWebSocketProtocol::Version version)
{
- m_version = version;
+ m_version = version;
}
/*!
- \internal
- Sets the resource name of the connection; must be set before the socket is openend
+ \internal
+ Sets the resource name of the connection; must be set before the socket is openend
*/
void QWebSocketPrivate::setResourceName(QString resourceName)
{
- m_resourceName = resourceName;
+ m_resourceName = resourceName;
}
/*!
@@ -289,7 +289,7 @@ void QWebSocketPrivate::setResourceName(QString resourceName)
*/
void QWebSocketPrivate::setRequestUrl(QUrl requestUrl)
{
- m_requestUrl = requestUrl;
+ m_requestUrl = requestUrl;
}
/*!
@@ -297,7 +297,7 @@ void QWebSocketPrivate::setRequestUrl(QUrl requestUrl)
*/
void QWebSocketPrivate::setOrigin(QString origin)
{
- m_origin = origin;
+ m_origin = origin;
}
/*!
@@ -305,7 +305,7 @@ void QWebSocketPrivate::setOrigin(QString origin)
*/
void QWebSocketPrivate::setProtocol(QString protocol)
{
- m_protocol = protocol;
+ m_protocol = protocol;
}
/*!
@@ -313,7 +313,7 @@ void QWebSocketPrivate::setProtocol(QString protocol)
*/
void QWebSocketPrivate::setExtension(QString extension)
{
- m_extension = extension;
+ m_extension = extension;
}
/*!
@@ -321,7 +321,7 @@ void QWebSocketPrivate::setExtension(QString extension)
*/
void QWebSocketPrivate::enableMasking(bool enable)
{
- m_mustMask = enable;
+ m_mustMask = enable;
}
/*!
@@ -329,7 +329,7 @@ void QWebSocketPrivate::enableMasking(bool enable)
*/
qint64 QWebSocketPrivate::doWriteData(const QByteArray &data, bool isBinary)
{
- return doWriteFrames(data, isBinary);
+ return doWriteFrames(data, isBinary);
}
/*!
@@ -337,23 +337,23 @@ qint64 QWebSocketPrivate::doWriteData(const QByteArray &data, bool isBinary)
*/
void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
{
- //pass through signals
- connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q_ptr, SIGNAL(error(QAbstractSocket::SocketError)));
- connect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q_ptr, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
- connect(pTcpSocket, SIGNAL(readChannelFinished()), q_ptr, SIGNAL(readChannelFinished()));
- connect(pTcpSocket, SIGNAL(aboutToClose()), q_ptr, SIGNAL(aboutToClose()));
- //connect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q_ptr, SIGNAL(bytesWritten(qint64)));
+ //pass through signals
+ connect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q_ptr, SIGNAL(error(QAbstractSocket::SocketError)));
+ connect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q_ptr, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
+ connect(pTcpSocket, SIGNAL(readChannelFinished()), q_ptr, SIGNAL(readChannelFinished()));
+ connect(pTcpSocket, SIGNAL(aboutToClose()), q_ptr, SIGNAL(aboutToClose()));
+ //connect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q_ptr, SIGNAL(bytesWritten(qint64)));
- //catch signals
- connect(pTcpSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(processStateChanged(QAbstractSocket::SocketState)));
- connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(processData()));
+ //catch signals
+ 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_ptr, SIGNAL(textFrameReceived(QString,bool)));
- connect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q_ptr, SIGNAL(binaryFrameReceived(QByteArray,bool)));
- connect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q_ptr, SIGNAL(binaryMessageReceived(QByteArray)));
- connect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q_ptr, SIGNAL(textMessageReceived(QString)));
- connect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
+ connect(&m_dataProcessor, SIGNAL(controlFrameReceived(QWebSocketProtocol::OpCode, QByteArray)), this, SLOT(processControlFrame(QWebSocketProtocol::OpCode, QByteArray)));
+ connect(&m_dataProcessor, SIGNAL(textFrameReceived(QString,bool)), q_ptr, SIGNAL(textFrameReceived(QString,bool)));
+ connect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q_ptr, SIGNAL(binaryFrameReceived(QByteArray,bool)));
+ connect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q_ptr, SIGNAL(binaryMessageReceived(QByteArray)));
+ connect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q_ptr, SIGNAL(textMessageReceived(QString)));
+ connect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
}
/*!
@@ -361,73 +361,73 @@ void QWebSocketPrivate::makeConnections(const QTcpSocket *pTcpSocket)
*/
void QWebSocketPrivate::releaseConnections(const QTcpSocket *pTcpSocket)
{
- if (pTcpSocket)
- {
- //pass through signals
- disconnect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q_ptr, SIGNAL(error(QAbstractSocket::SocketError)));
- disconnect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q_ptr, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
- disconnect(pTcpSocket, SIGNAL(readChannelFinished()), q_ptr, SIGNAL(readChannelFinished()));
- //disconnect(pTcpSocket, SIGNAL(aboutToClose()), q_ptr, SIGNAL(aboutToClose()));
- //disconnect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q_ptr, SIGNAL(bytesWritten(qint64)));
-
- //catched signals
- 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(textFrameReceived(QString,bool)), q_ptr, SIGNAL(textFrameReceived(QString,bool)));
- disconnect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q_ptr, SIGNAL(binaryFrameReceived(QByteArray,bool)));
- disconnect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q_ptr, SIGNAL(binaryMessageReceived(QByteArray)));
- disconnect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q_ptr, SIGNAL(textMessageReceived(QString)));
- disconnect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
-}
-
-/*!
- \internal
+ if (pTcpSocket)
+ {
+ //pass through signals
+ disconnect(pTcpSocket, SIGNAL(error(QAbstractSocket::SocketError)), q_ptr, SIGNAL(error(QAbstractSocket::SocketError)));
+ disconnect(pTcpSocket, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)), q_ptr, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *)));
+ disconnect(pTcpSocket, SIGNAL(readChannelFinished()), q_ptr, SIGNAL(readChannelFinished()));
+ //disconnect(pTcpSocket, SIGNAL(aboutToClose()), q_ptr, SIGNAL(aboutToClose()));
+ //disconnect(pTcpSocket, SIGNAL(bytesWritten(qint64)), q_ptr, SIGNAL(bytesWritten(qint64)));
+
+ //catched signals
+ 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(textFrameReceived(QString,bool)), q_ptr, SIGNAL(textFrameReceived(QString,bool)));
+ disconnect(&m_dataProcessor, SIGNAL(binaryFrameReceived(QByteArray,bool)), q_ptr, SIGNAL(binaryFrameReceived(QByteArray,bool)));
+ disconnect(&m_dataProcessor, SIGNAL(binaryMessageReceived(QByteArray)), q_ptr, SIGNAL(binaryMessageReceived(QByteArray)));
+ disconnect(&m_dataProcessor, SIGNAL(textMessageReceived(QString)), q_ptr, SIGNAL(textMessageReceived(QString)));
+ disconnect(&m_dataProcessor, SIGNAL(errorEncountered(QWebSocketProtocol::CloseCode,QString)), this, SLOT(close(QWebSocketProtocol::CloseCode,QString)));
+}
+
+/*!
+ \internal
*/
QWebSocketProtocol::Version QWebSocketPrivate::version()
{
- return m_version;
+ return m_version;
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::resourceName()
{
- return m_resourceName;
+ return m_resourceName;
}
/*!
- \internal
+ \internal
*/
QUrl QWebSocketPrivate::requestUrl()
{
- return m_requestUrl;
+ return m_requestUrl;
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::origin()
{
- return m_origin;
+ return m_origin;
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::protocol()
{
- return m_protocol;
+ return m_protocol;
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::extension()
{
- return m_extension;
+ return m_extension;
}
/*!
@@ -435,57 +435,57 @@ QString QWebSocketPrivate::extension()
*/
QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const
{
- QByteArray header;
- quint8 byte = 0x00;
- bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL;
-
- if (ok)
- {
- //FIN, RSV1-3, opcode
- byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00)); //FIN, opcode
- //RSV-1, RSV-2 and RSV-3 are zero
- header.append(static_cast<char>(byte));
-
- //Now write the masking bit and the payload length byte
- byte = 0x00;
- if (maskingKey != 0)
- {
- byte |= 0x80;
- }
- if (payloadLength <= 125)
- {
- byte |= static_cast<quint8>(payloadLength);
- header.append(static_cast<char>(byte));
- }
- else if (payloadLength <= 0xFFFFU)
- {
- byte |= 126;
- header.append(static_cast<char>(byte));
- quint16 swapped = qToBigEndian<quint16>(static_cast<quint16>(payloadLength));
- header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 2);
- }
- else if (payloadLength <= 0x7FFFFFFFFFFFFFFFULL)
- {
- byte |= 127;
- header.append(static_cast<char>(byte));
- quint64 swapped = qToBigEndian<quint64>(payloadLength);
- header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 8);
- }
-
- //Write mask
- if (maskingKey != 0)
- {
- header.append(static_cast<const char *>(static_cast<const void *>(&maskingKey)), sizeof(quint32));
- }
- }
- else
- {
- //setErrorString("WebSocket::getHeader: payload too big!");
- //Q_EMIT q_ptr->error(QAbstractSocket::DatagramTooLargeError);
- qDebug() << "WebSocket::getHeader: payload too big!";
- }
-
- return header;
+ QByteArray header;
+ quint8 byte = 0x00;
+ bool ok = payloadLength <= 0x7FFFFFFFFFFFFFFFULL;
+
+ if (ok)
+ {
+ //FIN, RSV1-3, opcode
+ byte = static_cast<quint8>((opCode & 0x0F) | (lastFrame ? 0x80 : 0x00)); //FIN, opcode
+ //RSV-1, RSV-2 and RSV-3 are zero
+ header.append(static_cast<char>(byte));
+
+ //Now write the masking bit and the payload length byte
+ byte = 0x00;
+ if (maskingKey != 0)
+ {
+ byte |= 0x80;
+ }
+ if (payloadLength <= 125)
+ {
+ byte |= static_cast<quint8>(payloadLength);
+ header.append(static_cast<char>(byte));
+ }
+ else if (payloadLength <= 0xFFFFU)
+ {
+ byte |= 126;
+ header.append(static_cast<char>(byte));
+ quint16 swapped = qToBigEndian<quint16>(static_cast<quint16>(payloadLength));
+ header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 2);
+ }
+ else if (payloadLength <= 0x7FFFFFFFFFFFFFFFULL)
+ {
+ byte |= 127;
+ header.append(static_cast<char>(byte));
+ quint64 swapped = qToBigEndian<quint64>(payloadLength);
+ header.append(static_cast<const char *>(static_cast<const void *>(&swapped)), 8);
+ }
+
+ //Write mask
+ if (maskingKey != 0)
+ {
+ header.append(static_cast<const char *>(static_cast<const void *>(&maskingKey)), sizeof(quint32));
+ }
+ }
+ else
+ {
+ //setErrorString("WebSocket::getHeader: payload too big!");
+ //Q_EMIT q_ptr->error(QAbstractSocket::DatagramTooLargeError);
+ qDebug() << "WebSocket::getHeader: payload too big!";
+ }
+
+ return header;
}
/*!
@@ -493,76 +493,76 @@ QByteArray QWebSocketPrivate::getFrameHeader(QWebSocketProtocol::OpCode opCode,
*/
qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
{
- const QWebSocketProtocol::OpCode firstOpCode = isBinary ? QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT;
-
- int numFrames = data.size() / FRAME_SIZE_IN_BYTES;
- QByteArray tmpData(data);
- tmpData.detach();
- char *payload = tmpData.data();
- quint64 sizeLeft = static_cast<quint64>(data.size()) % FRAME_SIZE_IN_BYTES;
- if (sizeLeft)
- {
- ++numFrames;
- }
- if (numFrames == 0) //catch the case where the payload is zero bytes; in that case, we still need to send a frame
- {
- numFrames = 1;
- }
- quint64 currentPosition = 0;
- qint64 bytesWritten = 0;
- qint64 payloadWritten = 0;
- quint64 bytesLeft = data.size();
-
- for (int i = 0; i < numFrames; ++i)
- {
- quint32 maskingKey = 0;
- if (m_mustMask)
- {
- maskingKey = generateMaskingKey();
- }
-
- bool isLastFrame = (i == (numFrames - 1));
- bool isFirstFrame = (i == 0);
-
- quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
- QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE;
-
- //write header
- bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
-
- //write payload
- if (size > 0)
- {
- char *currentData = payload + currentPosition;
- if (m_mustMask)
- {
- QWebSocketProtocol::mask(currentData, size, maskingKey);
- }
- qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size));
- if (written > 0)
- {
- bytesWritten += written;
- payloadWritten += written;
- }
- else
- {
- setErrorString("WebSocket::doWriteFrames: Error writing bytes to socket: " + m_pSocket->errorString());
- qDebug() << errorString();
- m_pSocket->flush();
- Q_EMIT q_ptr->error(QAbstractSocket::NetworkError);
- break;
- }
- }
- currentPosition += size;
- bytesLeft -= size;
- }
- if (payloadWritten != data.size())
- {
- setErrorString("Bytes written " + QString::number(payloadWritten) + " != " + QString::number(data.size()));
- qDebug() << errorString();
- Q_EMIT q_ptr->error(QAbstractSocket::NetworkError);
- }
- return payloadWritten;
+ const QWebSocketProtocol::OpCode firstOpCode = isBinary ? QWebSocketProtocol::OC_BINARY : QWebSocketProtocol::OC_TEXT;
+
+ int numFrames = data.size() / FRAME_SIZE_IN_BYTES;
+ QByteArray tmpData(data);
+ tmpData.detach();
+ char *payload = tmpData.data();
+ quint64 sizeLeft = static_cast<quint64>(data.size()) % FRAME_SIZE_IN_BYTES;
+ if (sizeLeft)
+ {
+ ++numFrames;
+ }
+ if (numFrames == 0) //catch the case where the payload is zero bytes; in that case, we still need to send a frame
+ {
+ numFrames = 1;
+ }
+ quint64 currentPosition = 0;
+ qint64 bytesWritten = 0;
+ qint64 payloadWritten = 0;
+ quint64 bytesLeft = data.size();
+
+ for (int i = 0; i < numFrames; ++i)
+ {
+ quint32 maskingKey = 0;
+ if (m_mustMask)
+ {
+ maskingKey = generateMaskingKey();
+ }
+
+ bool isLastFrame = (i == (numFrames - 1));
+ bool isFirstFrame = (i == 0);
+
+ quint64 size = qMin(bytesLeft, FRAME_SIZE_IN_BYTES);
+ QWebSocketProtocol::OpCode opcode = isFirstFrame ? firstOpCode : QWebSocketProtocol::OC_CONTINUE;
+
+ //write header
+ bytesWritten += m_pSocket->write(getFrameHeader(opcode, size, maskingKey, isLastFrame));
+
+ //write payload
+ if (size > 0)
+ {
+ char *currentData = payload + currentPosition;
+ if (m_mustMask)
+ {
+ QWebSocketProtocol::mask(currentData, size, maskingKey);
+ }
+ qint64 written = m_pSocket->write(currentData, static_cast<qint64>(size));
+ if (written > 0)
+ {
+ bytesWritten += written;
+ payloadWritten += written;
+ }
+ else
+ {
+ setErrorString("WebSocket::doWriteFrames: Error writing bytes to socket: " + m_pSocket->errorString());
+ qDebug() << errorString();
+ m_pSocket->flush();
+ Q_EMIT q_ptr->error(QAbstractSocket::NetworkError);
+ break;
+ }
+ }
+ currentPosition += size;
+ bytesLeft -= size;
+ }
+ if (payloadWritten != data.size())
+ {
+ setErrorString("Bytes written " + QString::number(payloadWritten) + " != " + QString::number(data.size()));
+ qDebug() << errorString();
+ Q_EMIT q_ptr->error(QAbstractSocket::NetworkError);
+ }
+ return payloadWritten;
}
/*!
@@ -570,256 +570,256 @@ qint64 QWebSocketPrivate::doWriteFrames(const QByteArray &data, bool isBinary)
*/
quint32 QWebSocketPrivate::generateRandomNumber() const
{
- return static_cast<quint32>((static_cast<double>(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max());
+ return static_cast<quint32>((static_cast<double>(qrand()) / RAND_MAX) * std::numeric_limits<quint32>::max());
}
/*!
- \internal
+ \internal
*/
quint32 QWebSocketPrivate::generateMaskingKey() const
{
- return generateRandomNumber();
+ return generateRandomNumber();
}
/*!
- \internal
+ \internal
*/
QByteArray QWebSocketPrivate::generateKey() const
{
- QByteArray key;
+ QByteArray key;
- for (int i = 0; i < 4; ++i)
- {
- quint32 tmp = generateRandomNumber();
- key.append(static_cast<const char *>(static_cast<const void *>(&tmp)), sizeof(quint32));
- }
+ for (int i = 0; i < 4; ++i)
+ {
+ quint32 tmp = generateRandomNumber();
+ key.append(static_cast<const char *>(static_cast<const void *>(&tmp)), sizeof(quint32));
+ }
- return key.toBase64();
+ return key.toBase64();
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::calculateAcceptKey(const QString &key) const
{
- QString tmpKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1);
- return QString(hash.toBase64());
+ QString tmpKey = key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
+ QByteArray hash = QCryptographicHash::hash(tmpKey.toLatin1(), QCryptographicHash::Sha1);
+ return QString(hash.toBase64());
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::writeFrames(const QList<QByteArray> &frames)
{
- qint64 written = 0;
- for (int i = 0; i < frames.size(); ++i)
- {
- written += writeFrame(frames[i]);
- }
- return written;
+ qint64 written = 0;
+ for (int i = 0; i < frames.size(); ++i)
+ {
+ written += writeFrame(frames[i]);
+ }
+ return written;
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::writeFrame(const QByteArray &frame)
{
- return m_pSocket->write(frame);
+ return m_pSocket->write(frame);
}
/*!
- \internal
+ \internal
*/
QString readLine(QTcpSocket *pSocket)
{
- QString line;
- char c;
- while (pSocket->getChar(&c))
- {
- if (c == '\r')
- {
- pSocket->getChar(&c);
- break;
- }
- else
- {
- line.append(QChar(c));
- }
- }
- return line;
+ QString line;
+ char c;
+ while (pSocket->getChar(&c))
+ {
+ if (c == '\r')
+ {
+ pSocket->getChar(&c);
+ break;
+ }
+ else
+ {
+ line.append(QChar(c));
+ }
+ }
+ return line;
}
//called on the client for a server handshake response
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::processHandshake(QTcpSocket *pSocket)
{
- if (pSocket == 0)
- {
- return;
- }
-
- bool ok = false;
- QString errorDescription;
-
- const QString regExpStatusLine("^(HTTP/[0-9]+\\.[0-9]+)\\s([0-9]+)\\s(.*)");
- const QRegularExpression regExp(regExpStatusLine);
- QString statusLine = readLine(pSocket);
- QString httpProtocol;
- int httpStatusCode;
- QString httpStatusMessage;
- QRegularExpressionMatch match = regExp.match(statusLine);
- if (match.hasMatch())
- {
- QStringList tokens = match.capturedTexts();
- tokens.removeFirst(); //remove the search string
- if (tokens.length() == 3)
- {
- httpProtocol = tokens[0];
- httpStatusCode = tokens[1].toInt();
- httpStatusMessage = tokens[2].trimmed();
- ok = true;
- }
- }
- if (!ok)
- {
- errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
- }
- else
- {
- QString headerLine = readLine(pSocket);
- QMap<QString, QString> headers;
- while (!headerLine.isEmpty())
- {
- QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
- headers.insertMulti(headerField[0], headerField[1]);
- headerLine = readLine(pSocket);
- }
-
- QString acceptKey = headers.value("Sec-WebSocket-Accept", "");
- QString upgrade = headers.value("Upgrade", "");
- QString connection = headers.value("Connection", "");
- //unused for the moment
- //QString extensions = headers.value("Sec-WebSocket-Extensions", "");
- //QString protocol = headers.value("Sec-WebSocket-Protocol", "");
- QString version = headers.value("Sec-WebSocket-Version", "");
-
- if (httpStatusCode == 101) //HTTP/x.y 101 Switching Protocols
- {
- bool conversionOk = false;
- float version = httpProtocol.midRef(5).toFloat(&conversionOk);
- //TODO: do not check the httpStatusText right now
- ok = !(acceptKey.isEmpty() ||
- (!conversionOk || (version < 1.1f)) ||
- (upgrade.toLower() != "websocket") ||
- (connection.toLower() != "upgrade"));
- if (ok)
- {
- QString accept = calculateAcceptKey(m_key);
- ok = (accept == acceptKey);
- if (!ok)
- {
- errorDescription = "WebSocket::processHandshake: Accept-Key received from server " + acceptKey + " does not match the client key " + accept;
- }
- }
- else
- {
- errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
- }
- }
- else if (httpStatusCode == 400) //HTTP/1.1 400 Bad Request
- {
- if (!version.isEmpty())
- {
- QStringList versions = version.split(", ", QString::SkipEmptyParts);
- if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion())))
- {
- //if needed to switch protocol version, then we are finished here
- //because we cannot handle other protocols than the RFC one (v13)
- errorDescription = "WebSocket::processHandshake: Server requests a version that we don't support: " + versions.join(", ");
- ok = false;
- }
- else
- {
- //we tried v13, but something different went wrong
- errorDescription = "WebSocket::processHandshake: Unknown error condition encountered. Aborting connection.";
- ok = false;
- }
- }
- }
- else
- {
- errorDescription = "WebSocket::processHandshake: Unhandled http status code " + QString::number(httpStatusCode);
- ok = false;
- }
-
- if (!ok)
- {
- qDebug() << errorDescription;
- setErrorString(errorDescription);
- Q_EMIT q_ptr->error(QAbstractSocket::ConnectionRefusedError);
- }
- else
- {
- //handshake succeeded
- setSocketState(QAbstractSocket::ConnectedState);
- Q_EMIT q_ptr->connected();
- }
- }
-}
-
-/*!
- \internal
+ if (pSocket == 0)
+ {
+ return;
+ }
+
+ bool ok = false;
+ QString errorDescription;
+
+ const QString regExpStatusLine("^(HTTP/[0-9]+\\.[0-9]+)\\s([0-9]+)\\s(.*)");
+ const QRegularExpression regExp(regExpStatusLine);
+ QString statusLine = readLine(pSocket);
+ QString httpProtocol;
+ int httpStatusCode;
+ QString httpStatusMessage;
+ QRegularExpressionMatch match = regExp.match(statusLine);
+ if (match.hasMatch())
+ {
+ QStringList tokens = match.capturedTexts();
+ tokens.removeFirst(); //remove the search string
+ if (tokens.length() == 3)
+ {
+ httpProtocol = tokens[0];
+ httpStatusCode = tokens[1].toInt();
+ httpStatusMessage = tokens[2].trimmed();
+ ok = true;
+ }
+ }
+ if (!ok)
+ {
+ errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
+ }
+ else
+ {
+ QString headerLine = readLine(pSocket);
+ QMap<QString, QString> headers;
+ while (!headerLine.isEmpty())
+ {
+ QStringList headerField = headerLine.split(QString(": "), QString::SkipEmptyParts);
+ headers.insertMulti(headerField[0], headerField[1]);
+ headerLine = readLine(pSocket);
+ }
+
+ QString acceptKey = headers.value("Sec-WebSocket-Accept", "");
+ QString upgrade = headers.value("Upgrade", "");
+ QString connection = headers.value("Connection", "");
+ //unused for the moment
+ //QString extensions = headers.value("Sec-WebSocket-Extensions", "");
+ //QString protocol = headers.value("Sec-WebSocket-Protocol", "");
+ QString version = headers.value("Sec-WebSocket-Version", "");
+
+ if (httpStatusCode == 101) //HTTP/x.y 101 Switching Protocols
+ {
+ bool conversionOk = false;
+ float version = httpProtocol.midRef(5).toFloat(&conversionOk);
+ //TODO: do not check the httpStatusText right now
+ ok = !(acceptKey.isEmpty() ||
+ (!conversionOk || (version < 1.1f)) ||
+ (upgrade.toLower() != "websocket") ||
+ (connection.toLower() != "upgrade"));
+ if (ok)
+ {
+ QString accept = calculateAcceptKey(m_key);
+ ok = (accept == acceptKey);
+ if (!ok)
+ {
+ errorDescription = "WebSocket::processHandshake: Accept-Key received from server " + acceptKey + " does not match the client key " + accept;
+ }
+ }
+ else
+ {
+ errorDescription = "WebSocket::processHandshake: Invalid statusline in response: " + statusLine;
+ }
+ }
+ else if (httpStatusCode == 400) //HTTP/1.1 400 Bad Request
+ {
+ if (!version.isEmpty())
+ {
+ QStringList versions = version.split(", ", QString::SkipEmptyParts);
+ if (!versions.contains(QString::number(QWebSocketProtocol::currentVersion())))
+ {
+ //if needed to switch protocol version, then we are finished here
+ //because we cannot handle other protocols than the RFC one (v13)
+ errorDescription = "WebSocket::processHandshake: Server requests a version that we don't support: " + versions.join(", ");
+ ok = false;
+ }
+ else
+ {
+ //we tried v13, but something different went wrong
+ errorDescription = "WebSocket::processHandshake: Unknown error condition encountered. Aborting connection.";
+ ok = false;
+ }
+ }
+ }
+ else
+ {
+ errorDescription = "WebSocket::processHandshake: Unhandled http status code " + QString::number(httpStatusCode);
+ ok = false;
+ }
+
+ if (!ok)
+ {
+ qDebug() << errorDescription;
+ setErrorString(errorDescription);
+ Q_EMIT q_ptr->error(QAbstractSocket::ConnectionRefusedError);
+ }
+ else
+ {
+ //handshake succeeded
+ setSocketState(QAbstractSocket::ConnectedState);
+ Q_EMIT q_ptr->connected();
+ }
+ }
+}
+
+/*!
+ \internal
*/
void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketState)
{
- 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:
- {
- if (webSocketState == QAbstractSocket::ConnectedState)
- {
- setSocketState(QAbstractSocket::ClosingState);
- }
- break;
- }
- case QAbstractSocket::UnconnectedState:
- {
- if (webSocketState != QAbstractSocket::UnconnectedState)
- {
- setSocketState(QAbstractSocket::UnconnectedState);
- Q_EMIT q_ptr->disconnected();
- }
- break;
- }
- case QAbstractSocket::HostLookupState:
- case QAbstractSocket::ConnectingState:
- case QAbstractSocket::BoundState:
- case QAbstractSocket::ListeningState:
- {
- //do nothing
- //to make C++ compiler happy;
- break;
- }
- default:
- {
- break;
- }
- }
+ 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:
+ {
+ if (webSocketState == QAbstractSocket::ConnectedState)
+ {
+ setSocketState(QAbstractSocket::ClosingState);
+ }
+ break;
+ }
+ case QAbstractSocket::UnconnectedState:
+ {
+ if (webSocketState != QAbstractSocket::UnconnectedState)
+ {
+ setSocketState(QAbstractSocket::UnconnectedState);
+ Q_EMIT q_ptr->disconnected();
+ }
+ break;
+ }
+ case QAbstractSocket::HostLookupState:
+ case QAbstractSocket::ConnectingState:
+ case QAbstractSocket::BoundState:
+ case QAbstractSocket::ListeningState:
+ {
+ //do nothing
+ //to make C++ compiler happy;
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
}
//order of events:
@@ -836,310 +836,310 @@ void QWebSocketPrivate::processStateChanged(QAbstractSocket::SocketState socketS
*/
void QWebSocketPrivate::processData()
{
- while (m_pSocket->bytesAvailable())
- {
- if (state() == QAbstractSocket::ConnectingState)
- {
- processHandshake(m_pSocket);
- }
- else
- {
- m_dataProcessor.process(m_pSocket);
- }
- }
+ while (m_pSocket->bytesAvailable())
+ {
+ if (state() == QAbstractSocket::ConnectingState)
+ {
+ processHandshake(m_pSocket);
+ }
+ else
+ {
+ m_dataProcessor.process(m_pSocket);
+ }
+ }
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::processControlFrame(QWebSocketProtocol::OpCode opCode, QByteArray frame)
{
- 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:
- {
- Q_EMIT q_ptr->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
- {
- closeCode = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(frame.constData()));
- if (!QWebSocketProtocol::isCloseCodeValid(closeCode))
- {
- closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR;
- closeReason = QString("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 = "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;
- }
- }
-}
-
-/*!
- \internal
+ 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:
+ {
+ Q_EMIT q_ptr->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
+ {
+ closeCode = qFromBigEndian<quint16>(reinterpret_cast<const uchar *>(frame.constData()));
+ if (!QWebSocketProtocol::isCloseCodeValid(closeCode))
+ {
+ closeCode = QWebSocketProtocol::CC_PROTOCOL_ERROR;
+ closeReason = QString("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 = "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;
+ }
+ }
+}
+
+/*!
+ \internal
*/
QString QWebSocketPrivate::createHandShakeRequest(QString resourceName,
- QString host,
- QString origin,
- QString extensions,
- QString protocols,
- QByteArray key)
-{
- QStringList handshakeRequest;
-
- handshakeRequest << "GET " + resourceName + " HTTP/1.1" <<
- "Host: " + host <<
- "Upgrade: websocket" <<
- "Connection: Upgrade" <<
- "Sec-WebSocket-Key: " + QString(key);
- if (!origin.isEmpty())
- {
- handshakeRequest << "Origin: " + origin;
- }
- handshakeRequest << "Sec-WebSocket-Version: " + QString::number(QWebSocketProtocol::currentVersion());
- if (extensions.length() > 0)
- {
- handshakeRequest << "Sec-WebSocket-Extensions: " + extensions;
- }
- if (protocols.length() > 0)
- {
- handshakeRequest << "Sec-WebSocket-Protocol: " + protocols;
- }
- handshakeRequest << "\r\n";
-
- return handshakeRequest.join("\r\n");
-}
-
-/*!
- \internal
+ QString host,
+ QString origin,
+ QString extensions,
+ QString protocols,
+ QByteArray key)
+{
+ QStringList handshakeRequest;
+
+ handshakeRequest << "GET " + resourceName + " HTTP/1.1" <<
+ "Host: " + host <<
+ "Upgrade: websocket" <<
+ "Connection: Upgrade" <<
+ "Sec-WebSocket-Key: " + QString(key);
+ if (!origin.isEmpty())
+ {
+ handshakeRequest << "Origin: " + origin;
+ }
+ handshakeRequest << "Sec-WebSocket-Version: " + QString::number(QWebSocketProtocol::currentVersion());
+ if (extensions.length() > 0)
+ {
+ handshakeRequest << "Sec-WebSocket-Extensions: " + extensions;
+ }
+ if (protocols.length() > 0)
+ {
+ handshakeRequest << "Sec-WebSocket-Protocol: " + protocols;
+ }
+ handshakeRequest << "\r\n";
+
+ return handshakeRequest.join("\r\n");
+}
+
+/*!
+ \internal
*/
QAbstractSocket::SocketState QWebSocketPrivate::state() const
{
- return m_socketState;
+ return m_socketState;
}
/*!
- \internal
+ \internal
*/
bool QWebSocketPrivate::waitForConnected(int msecs)
{
- bool retVal = false;
- if (m_pSocket)
- {
- retVal = m_pSocket->waitForConnected(msecs);
- }
- return retVal;
+ bool retVal = false;
+ if (m_pSocket)
+ {
+ retVal = m_pSocket->waitForConnected(msecs);
+ }
+ return retVal;
}
/*!
- \internal
+ \internal
*/
bool QWebSocketPrivate::waitForDisconnected(int msecs)
{
- bool retVal = true;
- if (m_pSocket)
- {
- retVal = m_pSocket->waitForDisconnected(msecs);
- }
- return retVal;
+ bool retVal = true;
+ if (m_pSocket)
+ {
+ retVal = m_pSocket->waitForDisconnected(msecs);
+ }
+ return retVal;
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::setSocketState(QAbstractSocket::SocketState state)
{
- if (m_socketState != state)
- {
- m_socketState = state;
- Q_EMIT q_ptr->stateChanged(m_socketState);
- }
+ if (m_socketState != state)
+ {
+ m_socketState = state;
+ Q_EMIT q_ptr->stateChanged(m_socketState);
+ }
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::setErrorString(QString errorString)
{
- m_errorString = errorString;
+ m_errorString = errorString;
}
/*!
- \internal
+ \internal
*/
QHostAddress QWebSocketPrivate::localAddress() const
{
- QHostAddress address;
- if (m_pSocket)
- {
- address = m_pSocket->localAddress();
- }
- return address;
+ QHostAddress address;
+ if (m_pSocket)
+ {
+ address = m_pSocket->localAddress();
+ }
+ return address;
}
/*!
- \internal
+ \internal
*/
quint16 QWebSocketPrivate::localPort() const
{
- quint16 port = 0;
- if (m_pSocket)
- {
- port = m_pSocket->localPort();
- }
- return port;
+ quint16 port = 0;
+ if (m_pSocket)
+ {
+ port = m_pSocket->localPort();
+ }
+ return port;
}
/*!
- \internal
+ \internal
*/
QAbstractSocket::PauseModes QWebSocketPrivate::pauseMode() const
{
- QAbstractSocket::PauseModes mode = QAbstractSocket::PauseNever;
- if (m_pSocket)
- {
- mode = m_pSocket->pauseMode();
- }
- return mode;
+ QAbstractSocket::PauseModes mode = QAbstractSocket::PauseNever;
+ if (m_pSocket)
+ {
+ mode = m_pSocket->pauseMode();
+ }
+ return mode;
}
/*!
- \internal
+ \internal
*/
QHostAddress QWebSocketPrivate::peerAddress() const
{
- QHostAddress peer;
- if (m_pSocket)
- {
- peer = m_pSocket->peerAddress();
- }
- return peer;
+ QHostAddress peer;
+ if (m_pSocket)
+ {
+ peer = m_pSocket->peerAddress();
+ }
+ return peer;
}
/*!
- \internal
+ \internal
*/
QString QWebSocketPrivate::peerName() const
{
- QString name;
- if (m_pSocket)
- {
- name = m_pSocket->peerName();
- }
- return name;
+ QString name;
+ if (m_pSocket)
+ {
+ name = m_pSocket->peerName();
+ }
+ return name;
}
/*!
- \internal
+ \internal
*/
quint16 QWebSocketPrivate::peerPort() const
{
- quint16 port = 0;
- if (m_pSocket)
- {
- port = m_pSocket->peerPort();
- }
- return port;
+ quint16 port = 0;
+ if (m_pSocket)
+ {
+ port = m_pSocket->peerPort();
+ }
+ return port;
}
/*!
- \internal
+ \internal
*/
QNetworkProxy QWebSocketPrivate::proxy() const
{
- QNetworkProxy proxy;
- if (m_pSocket)
- {
- proxy = m_pSocket->proxy();
- }
- return proxy;
+ QNetworkProxy proxy;
+ if (m_pSocket)
+ {
+ proxy = m_pSocket->proxy();
+ }
+ return proxy;
}
/*!
- \internal
+ \internal
*/
qint64 QWebSocketPrivate::readBufferSize() const
{
- qint64 readBuffer = 0;
- if (m_pSocket)
- {
- readBuffer = m_pSocket->readBufferSize();
- }
- return readBuffer;
+ qint64 readBuffer = 0;
+ if (m_pSocket)
+ {
+ readBuffer = m_pSocket->readBufferSize();
+ }
+ return readBuffer;
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::resume()
{
- if (m_pSocket)
- {
- m_pSocket->resume();
- }
+ if (m_pSocket)
+ {
+ m_pSocket->resume();
+ }
}
/*!
@@ -1147,69 +1147,69 @@ void QWebSocketPrivate::resume()
*/
void QWebSocketPrivate::setPauseMode(QAbstractSocket::PauseModes pauseMode)
{
- if (m_pSocket)
- {
- m_pSocket->setPauseMode(pauseMode);
- }
+ if (m_pSocket)
+ {
+ m_pSocket->setPauseMode(pauseMode);
+ }
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::setProxy(const QNetworkProxy &networkProxy)
{
- if (m_pSocket)
- {
- m_pSocket->setProxy(networkProxy);
- }
+ if (m_pSocket)
+ {
+ m_pSocket->setProxy(networkProxy);
+ }
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::setReadBufferSize(qint64 size)
{
- if (m_pSocket)
- {
- m_pSocket->setReadBufferSize(size);
- }
+ if (m_pSocket)
+ {
+ m_pSocket->setReadBufferSize(size);
+ }
}
/*!
- \internal
+ \internal
*/
void QWebSocketPrivate::setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value)
{
- if (m_pSocket)
- {
- m_pSocket->setSocketOption(option, value);
- }
+ if (m_pSocket)
+ {
+ m_pSocket->setSocketOption(option, value);
+ }
}
/*!
- \internal
+ \internal
*/
QVariant QWebSocketPrivate::socketOption(QAbstractSocket::SocketOption option)
{
- QVariant result;
- if (m_pSocket)
- {
- result = m_pSocket->socketOption(option);
- }
- return result;
+ QVariant result;
+ if (m_pSocket)
+ {
+ result = m_pSocket->socketOption(option);
+ }
+ return result;
}
/*!
- \internal
+ \internal
*/
bool QWebSocketPrivate::isValid()
{
- bool valid = false;
- if (m_pSocket)
- {
- valid = m_pSocket->isValid();
- }
- return valid;
+ bool valid = false;
+ if (m_pSocket)
+ {
+ valid = m_pSocket->isValid();
+ }
+ return valid;
}
QT_END_NAMESPACE
diff --git a/src/qwebsocket_p.h b/src/qwebsocket_p.h
index 1d40fd1..83278ac 100644
--- a/src/qwebsocket_p.h
+++ b/src/qwebsocket_p.h
@@ -50,131 +50,131 @@ class QWebSocket;
class QWebSocketPrivate:public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit QWebSocketPrivate(QString origin,
- QWebSocketProtocol::Version version,
- QWebSocket * const pWebSocket,
- QObject *parent = 0);
- virtual ~QWebSocketPrivate();
-
- void abort();
- QAbstractSocket::SocketError error() const;
- QString errorString() const;
- bool flush();
- bool isValid();
- QHostAddress localAddress() const;
- quint16 localPort() const;
- QAbstractSocket::PauseModes pauseMode() const;
- QHostAddress peerAddress() const;
- QString peerName() const;
- quint16 peerPort() const;
+ explicit QWebSocketPrivate(QString origin,
+ QWebSocketProtocol::Version version,
+ QWebSocket * const pWebSocket,
+ QObject *parent = 0);
+ virtual ~QWebSocketPrivate();
+
+ void abort();
+ QAbstractSocket::SocketError error() const;
+ QString errorString() const;
+ bool flush();
+ bool isValid();
+ QHostAddress localAddress() const;
+ quint16 localPort() const;
+ QAbstractSocket::PauseModes pauseMode() const;
+ QHostAddress peerAddress() const;
+ QString peerName() const;
+ quint16 peerPort() const;
#ifndef QT_NO_NETWORKPROXY
- QNetworkProxy proxy() const;
- void setProxy(const QNetworkProxy &networkProxy);
+ QNetworkProxy proxy() const;
+ void setProxy(const QNetworkProxy &networkProxy);
#endif
- qint64 readBufferSize() const;
- void resume();
- void setPauseMode(QAbstractSocket::PauseModes pauseMode);
- void setReadBufferSize(qint64 size);
- void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value);
- QVariant socketOption(QAbstractSocket::SocketOption option);
- QAbstractSocket::SocketState state() const;
-
- bool waitForConnected(int msecs = 30000);
- bool waitForDisconnected(int msecs = 30000);
-
- QWebSocketProtocol::Version version();
- QString resourceName();
- QUrl requestUrl();
- QString origin();
- QString protocol();
- QString extension();
-
- qint64 write(const char *message); //send data as text
- qint64 write(const char *message, qint64 maxSize); //send data as text
- qint64 write(const QString &message); //send data as text
- qint64 write(const QByteArray &data); //send data as binary
+ qint64 readBufferSize() const;
+ void resume();
+ void setPauseMode(QAbstractSocket::PauseModes pauseMode);
+ void setReadBufferSize(qint64 size);
+ void setSocketOption(QAbstractSocket::SocketOption option, const QVariant &value);
+ QVariant socketOption(QAbstractSocket::SocketOption option);
+ QAbstractSocket::SocketState state() const;
+
+ bool waitForConnected(int msecs = 30000);
+ bool waitForDisconnected(int msecs = 30000);
+
+ QWebSocketProtocol::Version version();
+ QString resourceName();
+ QUrl requestUrl();
+ QString origin();
+ QString protocol();
+ QString extension();
+
+ qint64 write(const char *message); //send data as text
+ qint64 write(const char *message, qint64 maxSize); //send data as text
+ qint64 write(const QString &message); //send data as text
+ qint64 write(const QByteArray &data); //send data as binary
public Q_SLOTS:
- virtual void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL, QString reason = QString());
- virtual void open(const QUrl &url, bool mask = true);
- void ping();
+ virtual void close(QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CC_NORMAL, QString reason = QString());
+ virtual void open(const QUrl &url, bool mask = true);
+ void ping();
private Q_SLOTS:
- void processData();
- void processControlFrame(QWebSocketProtocol::OpCode opCode, QByteArray frame);
- void processHandshake(QTcpSocket *pSocket);
- void processStateChanged(QAbstractSocket::SocketState socketState);
+ void processData();
+ void processControlFrame(QWebSocketProtocol::OpCode opCode, QByteArray frame);
+ void processHandshake(QTcpSocket *pSocket);
+ void processStateChanged(QAbstractSocket::SocketState socketState);
private:
- Q_DISABLE_COPY(QWebSocketPrivate)
-
- QWebSocket * const q_ptr;
-
- QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent = 0);
- void setVersion(QWebSocketProtocol::Version version);
- void setResourceName(QString resourceName);
- void setRequestUrl(QUrl requestUrl);
- void setOrigin(QString origin);
- void setProtocol(QString protocol);
- void setExtension(QString extension);
- void enableMasking(bool enable);
- void setSocketState(QAbstractSocket::SocketState state);
- void setErrorString(QString errorString);
-
- qint64 doWriteData(const QByteArray &data, bool isBinary);
- qint64 doWriteFrames(const QByteArray &data, bool isBinary);
-
- void makeConnections(const QTcpSocket *pTcpSocket);
- void releaseConnections(const QTcpSocket *pTcpSocket);
-
- QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const;
- QString calculateAcceptKey(const QString &key) const;
- QString createHandShakeRequest(QString resourceName,
- QString host,
- QString origin,
- QString extensions,
- QString protocols,
- QByteArray key);
-
- static QWebSocket *upgradeFrom(QTcpSocket *tcpSocket,
- const HandshakeRequest &request,
- const HandshakeResponse &response,
- QObject *parent = 0);
-
- quint32 generateMaskingKey() const;
- QByteArray generateKey() const;
- quint32 generateRandomNumber() const;
- qint64 writeFrames(const QList<QByteArray> &frames);
- qint64 writeFrame(const QByteArray &frame);
-
- QTcpSocket *m_pSocket;
- QString m_errorString;
- QWebSocketProtocol::Version m_version;
- QUrl m_resource;
- QString m_resourceName;
- QUrl m_requestUrl;
- QString m_origin;
- QString m_protocol;
- QString m_extension;
- QAbstractSocket::SocketState m_socketState;
-
- QByteArray m_key; //identification key used in handshake requests
-
- bool m_mustMask; //a server must not mask the frames it sends
-
- bool m_isClosingHandshakeSent;
- bool m_isClosingHandshakeReceived;
-
- QTime m_pingTimer;
-
- DataProcessor m_dataProcessor;
-
-
- friend class QWebSocketServerPrivate;
- friend class QWebSocket;
+ Q_DISABLE_COPY(QWebSocketPrivate)
+
+ QWebSocket * const q_ptr;
+
+ QWebSocketPrivate(QTcpSocket *pTcpSocket, QWebSocketProtocol::Version version, QWebSocket *pWebSocket, QObject *parent = 0);
+ void setVersion(QWebSocketProtocol::Version version);
+ void setResourceName(QString resourceName);
+ void setRequestUrl(QUrl requestUrl);
+ void setOrigin(QString origin);
+ void setProtocol(QString protocol);
+ void setExtension(QString extension);
+ void enableMasking(bool enable);
+ void setSocketState(QAbstractSocket::SocketState state);
+ void setErrorString(QString errorString);
+
+ qint64 doWriteData(const QByteArray &data, bool isBinary);
+ qint64 doWriteFrames(const QByteArray &data, bool isBinary);
+
+ void makeConnections(const QTcpSocket *pTcpSocket);
+ void releaseConnections(const QTcpSocket *pTcpSocket);
+
+ QByteArray getFrameHeader(QWebSocketProtocol::OpCode opCode, quint64 payloadLength, quint32 maskingKey, bool lastFrame) const;
+ QString calculateAcceptKey(const QString &key) const;
+ QString createHandShakeRequest(QString resourceName,
+ QString host,
+ QString origin,
+ QString extensions,
+ QString protocols,
+ QByteArray key);
+
+ static QWebSocket *upgradeFrom(QTcpSocket *tcpSocket,
+ const HandshakeRequest &request,
+ const HandshakeResponse &response,
+ QObject *parent = 0);
+
+ quint32 generateMaskingKey() const;
+ QByteArray generateKey() const;
+ quint32 generateRandomNumber() const;
+ qint64 writeFrames(const QList<QByteArray> &frames);
+ qint64 writeFrame(const QByteArray &frame);
+
+ QTcpSocket *m_pSocket;
+ QString m_errorString;
+ QWebSocketProtocol::Version m_version;
+ QUrl m_resource;
+ QString m_resourceName;
+ QUrl m_requestUrl;
+ QString m_origin;
+ QString m_protocol;
+ QString m_extension;
+ QAbstractSocket::SocketState m_socketState;
+
+ QByteArray m_key; //identification key used in handshake requests
+
+ bool m_mustMask; //a server must not mask the frames it sends
+
+ bool m_isClosingHandshakeSent;
+ bool m_isClosingHandshakeReceived;
+
+ QTime m_pingTimer;
+
+ DataProcessor m_dataProcessor;
+
+
+ friend class QWebSocketServerPrivate;
+ friend class QWebSocket;
};
QT_END_NAMESPACE
diff --git a/src/qwebsocketprotocol.cpp b/src/qwebsocketprotocol.cpp
index 6c61ed1..00254bd 100644
--- a/src/qwebsocketprotocol.cpp
+++ b/src/qwebsocketprotocol.cpp
@@ -23,121 +23,121 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include <QtEndian>
/*!
- \enum WebSocketProtocol::CloseCode
+ \enum WebSocketProtocol::CloseCode
- The close codes supported by WebSockets V13
- \sa WebSocket::close()
+ The close codes supported by WebSockets V13
+ \sa WebSocket::close()
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_NORMAL
- Normal closure
+ \var WebSocketProtocol::CloseCode::CC_NORMAL
+ Normal closure
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_GOING_AWAY
- Going away
+ \var WebSocketProtocol::CloseCode::CC_GOING_AWAY
+ Going away
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_PROTOCOL_ERROR
- Protocol error
+ \var WebSocketProtocol::CloseCode::CC_PROTOCOL_ERROR
+ Protocol error
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_DATATYPE_NOT_SUPPORTED
- Unsupported data
+ \var WebSocketProtocol::CloseCode::CC_DATATYPE_NOT_SUPPORTED
+ Unsupported data
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_RESERVED_1004
- Reserved
+ \var WebSocketProtocol::CloseCode::CC_RESERVED_1004
+ Reserved
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_MISSING_STATUS_CODE
- No status received
+ \var WebSocketProtocol::CloseCode::CC_MISSING_STATUS_CODE
+ No status received
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_ABNORMAL_DISCONNECTION
- Abnormal closure
+ \var WebSocketProtocol::CloseCode::CC_ABNORMAL_DISCONNECTION
+ Abnormal closure
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_WRONG_DATATYPE
- Invalid frame payload data
+ \var WebSocketProtocol::CloseCode::CC_WRONG_DATATYPE
+ Invalid frame payload data
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_POLICY_VIOLATED
- Policy violation
+ \var WebSocketProtocol::CloseCode::CC_POLICY_VIOLATED
+ Policy violation
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_TOO_MUCH_DATA
- Message too big
+ \var WebSocketProtocol::CloseCode::CC_TOO_MUCH_DATA
+ Message too big
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_MISSING_EXTENSION
- Mandatory extension missing
+ \var WebSocketProtocol::CloseCode::CC_MISSING_EXTENSION
+ Mandatory extension missing
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_BAD_OPERATION
- Internal server error
+ \var WebSocketProtocol::CloseCode::CC_BAD_OPERATION
+ Internal server error
*/
/*!
- \var WebSocketProtocol::CloseCode::CC_TLS_HANDSHAKE_FAILED
- TLS handshake failed
+ \var WebSocketProtocol::CloseCode::CC_TLS_HANDSHAKE_FAILED
+ TLS handshake failed
*/
/*!
- \enum WebSocketProtocol::Version
+ \enum WebSocketProtocol::Version
- \brief The different defined versions of the Websocket protocol.
+ \brief The different defined versions of the Websocket protocol.
- For an overview of the differences between the different protocols, see
- <http://code.google.com/p/pywebsocket/wiki/WebSocketProtocolSpec>
+ For an overview of the differences between the different protocols, see
+ <http://code.google.com/p/pywebsocket/wiki/WebSocketProtocolSpec>
*/
/*!
- \var WebSocketProtocol::Version::V_Unknow
+ \var WebSocketProtocol::Version::V_Unknow
*/
/*!
- \var WebSocketProtocol::Version::V_0
- hixie76: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 & hybi-00: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00.
- Works with key1, key2 and a key in the payload.\n
- Attribute: Sec-WebSocket-Draft value 0.
+ \var WebSocketProtocol::Version::V_0
+ hixie76: http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76 & hybi-00: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-00.
+ Works with key1, key2 and a key in the payload.\n
+ Attribute: Sec-WebSocket-Draft value 0.
*/
/*!
- \var WebSocketProtocol::Version::V_4
- hybi-04: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-04.txt.
- Changed handshake: key1, key2, key3 ==> Sec-WebSocket-Key, Sec-WebSocket-Nonce, Sec-WebSocket-Accept\n
- Sec-WebSocket-Draft renamed to Sec-WebSocket-Version\n
- Sec-WebSocket-Version = 4
+ \var WebSocketProtocol::Version::V_4
+ hybi-04: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-04.txt.
+ Changed handshake: key1, key2, key3 ==> Sec-WebSocket-Key, Sec-WebSocket-Nonce, Sec-WebSocket-Accept\n
+ Sec-WebSocket-Draft renamed to Sec-WebSocket-Version\n
+ Sec-WebSocket-Version = 4
*/
/*!
- \var WebSocketProtocol::Version::V_5
- hybi-05: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-05.txt.
- Sec-WebSocket-Version = 5\n
- Removed Sec-WebSocket-Nonce\n
- Added Sec-WebSocket-Accept\n
+ \var WebSocketProtocol::Version::V_5
+ hybi-05: http://tools.ietf.org/id/draft-ietf-hybi-thewebsocketprotocol-05.txt.
+ Sec-WebSocket-Version = 5\n
+ Removed Sec-WebSocket-Nonce\n
+ Added Sec-WebSocket-Accept\n
*/
/*!
- \var WebSocketProtocol::Version::V_6
- Sec-WebSocket-Version = 6.
+ \var WebSocketProtocol::Version::V_6
+ Sec-WebSocket-Version = 6.
*/
/*!
- \var WebSocketProtocol::Version::V_7
- hybi-07: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07.
- Sec-WebSocket-Version = 7
+ \var WebSocketProtocol::Version::V_7
+ hybi-07: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-07.
+ Sec-WebSocket-Version = 7
*/
/*!
- \var WebSocketProtocol::Version::V_8
- hybi-8, hybi-9, hybi-10, hybi-11 and hybi-12.
- Status codes 1005 and 1006 are added and all codes are now unsigned\n
- Internal error results in 1006
+ \var WebSocketProtocol::Version::V_8
+ hybi-8, hybi-9, hybi-10, hybi-11 and hybi-12.
+ Status codes 1005 and 1006 are added and all codes are now unsigned\n
+ Internal error results in 1006
*/
/*!
- \var WebSocketProtocol::Version::V_13
- hybi-13, hybi14, hybi-15, hybi-16, hybi-17 and RFC 6455.
- Sec-WebSocket-Version = 13\n
- Status code 1004 is now reserved\n
- Added 1008, 1009 and 1010\n
- Must support TLS\n
- Clarify multiple version support
+ \var WebSocketProtocol::Version::V_13
+ hybi-13, hybi14, hybi-15, hybi-16, hybi-17 and RFC 6455.
+ Sec-WebSocket-Version = 13\n
+ Status code 1004 is now reserved\n
+ Added 1008, 1009 and 1010\n
+ Must support TLS\n
+ Clarify multiple version support
*/
/*!
- \var WebSocketProtocol::Version::V_LATEST
- Refers to the latest know version to QWebSockets.
+ \var WebSocketProtocol::Version::V_LATEST
+ Refers to the latest know version to QWebSockets.
*/
/*!
@@ -165,77 +165,77 @@ QT_BEGIN_NAMESPACE
*/
namespace QWebSocketProtocol
{
- /*!
- Parses the \a versionString and converts it to a Version value
- \internal
- */
- Version versionFromString(const QString &versionString)
- {
- bool ok = false;
- Version version = V_Unknow;
- int ver = versionString.toInt(&ok);
- QSet<Version> supportedVersions;
- supportedVersions << V_0 << V_4 << V_5 << V_6 << V_7 << V_8 << V_13;
- if (ok)
- {
- if (supportedVersions.contains(static_cast<Version>(ver)))
- {
- version = static_cast<Version>(ver);
- }
- }
- return version;
- }
-
- /*!
- Mask the \a payload with the given \a maskingKey and stores the result back in \a payload.
- \internal
- */
- void mask(QByteArray *payload, quint32 maskingKey)
- {
- quint32 *payloadData = reinterpret_cast<quint32 *>(payload->data());
- quint32 numIterations = static_cast<quint32>(payload->size()) / sizeof(quint32);
- quint32 remainder = static_cast<quint32>(payload->size()) % sizeof(quint32);
- quint32 i;
- for (i = 0; i < numIterations; ++i)
- {
- *(payloadData + i) ^= maskingKey;
- }
- if (remainder)
- {
- const quint32 offset = i * static_cast<quint32>(sizeof(quint32));
- char *payloadBytes = payload->data();
- uchar *mask = reinterpret_cast<uchar *>(&maskingKey);
- for (quint32 i = 0; i < remainder; ++i)
- {
- *(payloadBytes + offset + i) ^= static_cast<char>(mask[(i + offset) % 4]);
- }
- }
- }
-
- /*!
- Masks the \a payload of length \a size with the given \a maskingKey and stores the result back in \a payload.
- \internal
- */
- void mask(char *payload, quint64 size, quint32 maskingKey)
- {
- quint32 *payloadData = reinterpret_cast<quint32 *>(payload);
- quint32 numIterations = static_cast<quint32>(size / sizeof(quint32));
- quint32 remainder = size % sizeof(quint32);
- quint32 i;
- for (i = 0; i < numIterations; ++i)
- {
- *(payloadData + i) ^= maskingKey;
- }
- if (remainder)
- {
- const quint32 offset = i * static_cast<quint32>(sizeof(quint32));
- uchar *mask = reinterpret_cast<uchar *>(&maskingKey);
- for (quint32 i = 0; i < remainder; ++i)
- {
- *(payload + offset + i) ^= static_cast<char>(mask[(i + offset) % 4]);
- }
- }
- }
+/*!
+ Parses the \a versionString and converts it to a Version value
+ \internal
+ */
+Version versionFromString(const QString &versionString)
+{
+ bool ok = false;
+ Version version = V_Unknow;
+ int ver = versionString.toInt(&ok);
+ QSet<Version> supportedVersions;
+ supportedVersions << V_0 << V_4 << V_5 << V_6 << V_7 << V_8 << V_13;
+ if (ok)
+ {
+ if (supportedVersions.contains(static_cast<Version>(ver)))
+ {
+ version = static_cast<Version>(ver);
+ }
+ }
+ return version;
+}
+
+/*!
+ Mask the \a payload with the given \a maskingKey and stores the result back in \a payload.
+ \internal
+ */
+void mask(QByteArray *payload, quint32 maskingKey)
+{
+ quint32 *payloadData = reinterpret_cast<quint32 *>(payload->data());
+ quint32 numIterations = static_cast<quint32>(payload->size()) / sizeof(quint32);
+ quint32 remainder = static_cast<quint32>(payload->size()) % sizeof(quint32);
+ quint32 i;
+ for (i = 0; i < numIterations; ++i)
+ {
+ *(payloadData + i) ^= maskingKey;
+ }
+ if (remainder)
+ {
+ const quint32 offset = i * static_cast<quint32>(sizeof(quint32));
+ char *payloadBytes = payload->data();
+ uchar *mask = reinterpret_cast<uchar *>(&maskingKey);
+ for (quint32 i = 0; i < remainder; ++i)
+ {
+ *(payloadBytes + offset + i) ^= static_cast<char>(mask[(i + offset) % 4]);
+ }
+ }
+}
+
+/*!
+ Masks the \a payload of length \a size with the given \a maskingKey and stores the result back in \a payload.
+ \internal
+ */
+void mask(char *payload, quint64 size, quint32 maskingKey)
+{
+ quint32 *payloadData = reinterpret_cast<quint32 *>(payload);
+ quint32 numIterations = static_cast<quint32>(size / sizeof(quint32));
+ quint32 remainder = size % sizeof(quint32);
+ quint32 i;
+ for (i = 0; i < numIterations; ++i)
+ {
+ *(payloadData + i) ^= maskingKey;
+ }
+ if (remainder)
+ {
+ const quint32 offset = i * static_cast<quint32>(sizeof(quint32));
+ uchar *mask = reinterpret_cast<uchar *>(&maskingKey);
+ for (quint32 i = 0; i < remainder; ++i)
+ {
+ *(payload + offset + i) ^= static_cast<char>(mask[(i + offset) % 4]);
+ }
+ }
+}
} //end namespace WebSocketProtocol
QT_END_NAMESPACE
diff --git a/src/qwebsocketprotocol.h b/src/qwebsocketprotocol.h
index 26584eb..7604fbc 100644
--- a/src/qwebsocketprotocol.h
+++ b/src/qwebsocketprotocol.h
@@ -29,77 +29,77 @@ class QByteArray;
namespace QWebSocketProtocol
{
- enum Version
- {
- V_Unknow = -1,
- V_0 = 0,
- //hybi-01, hybi-02 and hybi-03 not supported
- V_4 = 4,
- V_5 = 5,
- V_6 = 6,
- V_7 = 7,
- V_8 = 8,
- V_13 = 13,
- V_LATEST = V_13
- };
-
- Version versionFromString(const QString &versionString);
-
- enum CloseCode
- {
- CC_NORMAL = 1000,
- CC_GOING_AWAY = 1001,
- CC_PROTOCOL_ERROR = 1002,
- CC_DATATYPE_NOT_SUPPORTED = 1003,
- CC_RESERVED_1004 = 1004,
- CC_MISSING_STATUS_CODE = 1005,
- CC_ABNORMAL_DISCONNECTION = 1006,
- CC_WRONG_DATATYPE = 1007,
- CC_POLICY_VIOLATED = 1008,
- CC_TOO_MUCH_DATA = 1009,
- CC_MISSING_EXTENSION = 1010,
- CC_BAD_OPERATION = 1011,
- CC_TLS_HANDSHAKE_FAILED = 1015
- };
-
- enum OpCode
- {
- OC_CONTINUE = 0x0,
- OC_TEXT = 0x1,
- OC_BINARY = 0x2,
- OC_RESERVED_3 = 0x3,
- OC_RESERVED_4 = 0x4,
- OC_RESERVED_5 = 0x5,
- OC_RESERVED_6 = 0x6,
- OC_RESERVED_7 = 0x7,
- OC_CLOSE = 0x8,
- OC_PING = 0x9,
- OC_PONG = 0xA,
- OC_RESERVED_B = 0xB,
- OC_RESERVED_V = 0xC,
- OC_RESERVED_D = 0xD,
- OC_RESERVED_E = 0xE,
- OC_RESERVED_F = 0xF
- };
-
-
- inline bool isOpCodeReserved(OpCode code)
- {
- return ((code > OC_BINARY) && (code < OC_CLOSE)) || (code > OC_PONG);
- }
- inline bool isCloseCodeValid(int closeCode)
- {
- return (closeCode > 999) && (closeCode < 5000) &&
- (closeCode != CC_RESERVED_1004) && //see RFC6455 7.4.1
- (closeCode != CC_MISSING_STATUS_CODE) &&
- (closeCode != CC_ABNORMAL_DISCONNECTION) &&
- ((closeCode >= 3000) || (closeCode < 1012));
- }
-
- void mask(QByteArray *payload, quint32 maskingKey);
- void mask(char *payload, quint64 size, quint32 maskingKey);
-
- inline Version currentVersion() { return V_LATEST; }
+enum Version
+{
+ V_Unknow = -1,
+ V_0 = 0,
+ //hybi-01, hybi-02 and hybi-03 not supported
+ V_4 = 4,
+ V_5 = 5,
+ V_6 = 6,
+ V_7 = 7,
+ V_8 = 8,
+ V_13 = 13,
+ V_LATEST = V_13
+};
+
+Version versionFromString(const QString &versionString);
+
+enum CloseCode
+{
+ CC_NORMAL = 1000,
+ CC_GOING_AWAY = 1001,
+ CC_PROTOCOL_ERROR = 1002,
+ CC_DATATYPE_NOT_SUPPORTED = 1003,
+ CC_RESERVED_1004 = 1004,
+ CC_MISSING_STATUS_CODE = 1005,
+ CC_ABNORMAL_DISCONNECTION = 1006,
+ CC_WRONG_DATATYPE = 1007,
+ CC_POLICY_VIOLATED = 1008,
+ CC_TOO_MUCH_DATA = 1009,
+ CC_MISSING_EXTENSION = 1010,
+ CC_BAD_OPERATION = 1011,
+ CC_TLS_HANDSHAKE_FAILED = 1015
+};
+
+enum OpCode
+{
+ OC_CONTINUE = 0x0,
+ OC_TEXT = 0x1,
+ OC_BINARY = 0x2,
+ OC_RESERVED_3 = 0x3,
+ OC_RESERVED_4 = 0x4,
+ OC_RESERVED_5 = 0x5,
+ OC_RESERVED_6 = 0x6,
+ OC_RESERVED_7 = 0x7,
+ OC_CLOSE = 0x8,
+ OC_PING = 0x9,
+ OC_PONG = 0xA,
+ OC_RESERVED_B = 0xB,
+ OC_RESERVED_V = 0xC,
+ OC_RESERVED_D = 0xD,
+ OC_RESERVED_E = 0xE,
+ OC_RESERVED_F = 0xF
+};
+
+
+inline bool isOpCodeReserved(OpCode code)
+{
+ return ((code > OC_BINARY) && (code < OC_CLOSE)) || (code > OC_PONG);
+}
+inline bool isCloseCodeValid(int closeCode)
+{
+ return (closeCode > 999) && (closeCode < 5000) &&
+ (closeCode != CC_RESERVED_1004) && //see RFC6455 7.4.1
+ (closeCode != CC_MISSING_STATUS_CODE) &&
+ (closeCode != CC_ABNORMAL_DISCONNECTION) &&
+ ((closeCode >= 3000) || (closeCode < 1012));
+}
+
+void mask(QByteArray *payload, quint32 maskingKey);
+void mask(char *payload, quint64 size, quint32 maskingKey);
+
+inline Version currentVersion() { return V_LATEST; }
} //end namespace QWebSocketProtocol
diff --git a/src/qwebsocketserver.cpp b/src/qwebsocketserver.cpp
index 97393f9..b1cfcb4 100644
--- a/src/qwebsocketserver.cpp
+++ b/src/qwebsocketserver.cpp
@@ -18,29 +18,29 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
- \class QWebSocketServer
+ \class QWebSocketServer
- \inmodule QWebSockets
+ \inmodule QWebSockets
- \brief Implements a websocket-based server.
+ \brief Implements a websocket-based server.
- It is modeled after QTcpServer, and behaves the same. So, if you know how to use QTcpServer, you know how to use QWebSocketServer.
- This class makes it possible to accept incoming websocket connections.
- You can specify the port or have QWebSocketServer pick one automatically.
- You can listen on a specific address or on all the machine's addresses.
- Call listen() to have the server listen for incoming connections.
+ It is modeled after QTcpServer, and behaves the same. So, if you know how to use QTcpServer, you know how to use QWebSocketServer.
+ This class makes it possible to accept incoming websocket connections.
+ You can specify the port or have QWebSocketServer pick one automatically.
+ You can listen on a specific address or on all the machine's addresses.
+ Call listen() to have the server listen for incoming connections.
- The newConnection() signal is then emitted each time a client connects to the server.
- Call nextPendingConnection() to accept the pending connection as a connected QWebSocket.
- The function returns a pointer to a QWebSocket in QAbstractSocket::ConnectedState that you can use for communicating with the client.
- If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human readable description of what happened.
- When listening for connections, the address and port on which the server is listening are available as serverAddress() and serverPort().
- Calling close() makes QWebSocketServer stop listening for incoming connections.
- Although QWebSocketServer is mostly designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForNewConnection(), which blocks until either a connection is available or a timeout expires.
+ The newConnection() signal is then emitted each time a client connects to the server.
+ Call nextPendingConnection() to accept the pending connection as a connected QWebSocket.
+ The function returns a pointer to a QWebSocket in QAbstractSocket::ConnectedState that you can use for communicating with the client.
+ If an error occurs, serverError() returns the type of error, and errorString() can be called to get a human readable description of what happened.
+ When listening for connections, the address and port on which the server is listening are available as serverAddress() and serverPort().
+ Calling close() makes QWebSocketServer stop listening for incoming connections.
+ Although QWebSocketServer is mostly designed for use with an event loop, it's possible to use it without one. In that case, you must use waitForNewConnection(), which blocks until either a connection is available or a timeout expires.
- \sa echoserver.html
+ \sa echoserver.html
- \sa QWebSocket
+ \sa QWebSocket
*/
/*!
@@ -73,18 +73,18 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/*!
- \fn void QWebSocketServer::acceptError(QAbstractSocket::SocketError socketError)
- This signal is emitted when accepting a new connection results in an error.
- The \a socketError parameter describes the type of error that occurred
+ \fn void QWebSocketServer::acceptError(QAbstractSocket::SocketError socketError)
+ This signal is emitted when accepting a new connection results in an error.
+ The \a socketError parameter describes the type of error that occurred
- \sa pauseAccepting(), resumeAccepting()
+ \sa pauseAccepting(), resumeAccepting()
*/
/*!
- \fn void QWebSocketServer::newConnection()
- This signal is emitted every time a new connection is available.
+ \fn void QWebSocketServer::newConnection()
+ This signal is emitted every time a new connection is available.
- \sa hasPendingConnections(), nextPendingConnection()
+ \sa hasPendingConnections(), nextPendingConnection()
*/
#include <QTcpServer>
@@ -98,26 +98,26 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
QT_BEGIN_NAMESPACE
/*!
- Constructs a new WebSocketServer with the given \a serverName.
- The \a serverName will be used in the http handshake phase to identify the server.
+ Constructs a new WebSocketServer with the given \a serverName.
+ The \a serverName will be used in the http handshake phase to identify the server.
- \a parent is passed to the QObject constructor.
+ \a parent is passed to the QObject constructor.
*/
QWebSocketServer::QWebSocketServer(const QString &serverName, QObject *parent) :
- QObject(parent),
- d_ptr(new QWebSocketServerPrivate(serverName, this, this))
+ QObject(parent),
+ d_ptr(new QWebSocketServerPrivate(serverName, this, this))
{
}
/*!
- Destroys the WebSocketServer object. If the server is listening for connections, the socket is automatically closed.
- Any client WebSockets that are still connected are closed and deleted.
+ Destroys the WebSocketServer object. If the server is listening for connections, the socket is automatically closed.
+ Any client WebSockets that are still connected are closed and deleted.
- \sa close()
+ \sa close()
*/
QWebSocketServer::~QWebSocketServer()
{
- delete d_ptr;
+ delete d_ptr;
}
/*!
@@ -125,203 +125,203 @@ QWebSocketServer::~QWebSocketServer()
*/
void QWebSocketServer::close()
{
- d_ptr->close();
+ d_ptr->close();
}
/*!
- Returns a human readable description of the last error that occurred.
+ Returns a human readable description of the last error that occurred.
- \sa serverError()
+ \sa serverError()
*/
QString QWebSocketServer::errorString() const
{
- return d_ptr->errorString();
+ return d_ptr->errorString();
}
/*!
- Returns true if the server has pending connections; otherwise returns false.
+ Returns true if the server has pending connections; otherwise returns false.
- \sa nextPendingConnection(), setMaxPendingConnections()
+ \sa nextPendingConnection(), setMaxPendingConnections()
*/
bool QWebSocketServer::hasPendingConnections() const
{
- return d_ptr->hasPendingConnections();
+ return d_ptr->hasPendingConnections();
}
/*!
- Returns true if the server is currently listening for incoming connections; otherwise returns false.
+ Returns true if the server is currently listening for incoming connections; otherwise returns false.
- \sa listen()
+ \sa listen()
*/
bool QWebSocketServer::isListening() const
{
- return d_ptr->isListening();
+ return d_ptr->isListening();
}
/*!
- Tells the server to listen for incoming connections on address \a address and port \a port.
- If \a port is 0, a port is chosen automatically.
- If \a address is QHostAddress::Any, the server will listen on all network interfaces.
+ Tells the server to listen for incoming connections on address \a address and port \a port.
+ If \a port is 0, a port is chosen automatically.
+ If \a address is QHostAddress::Any, the server will listen on all network interfaces.
- Returns true on success; otherwise returns false.
+ Returns true on success; otherwise returns false.
- \sa isListening()
+ \sa isListening()
*/
bool QWebSocketServer::listen(const QHostAddress &address, quint16 port)
{
- return d_ptr->listen(address, port);
+ return d_ptr->listen(address, port);
}
/*!
- Returns the maximum number of pending accepted connections. The default is 30.
+ Returns the maximum number of pending accepted connections. The default is 30.
- \sa setMaxPendingConnections(), hasPendingConnections()
+ \sa setMaxPendingConnections(), hasPendingConnections()
*/
int QWebSocketServer::maxPendingConnections() const
{
- return d_ptr->maxPendingConnections();
+ return d_ptr->maxPendingConnections();
}
/*!
- Returns the next pending connection as a connected WebSocket object.
- The socket is created as a child of the server, which means that it is automatically deleted when the WebSocketServer object is destroyed. It is still a good idea to delete the object explicitly when you are done with it, to avoid wasting memory.
- 0 is returned if this function is called when there are no pending connections.
+ Returns the next pending connection as a connected WebSocket object.
+ The socket is created as a child of the server, which means that it is automatically deleted when the WebSocketServer object is destroyed. It is still a good idea to delete the object explicitly when you are done with it, to avoid wasting memory.
+ 0 is returned if this function is called when there are no pending connections.
- Note: The returned WebSocket object cannot be used from another thread..
+ Note: The returned WebSocket object cannot be used from another thread..
- \sa hasPendingConnections()
+ \sa hasPendingConnections()
*/
QWebSocket *QWebSocketServer::nextPendingConnection()
{
- return d_ptr->nextPendingConnection();
+ return d_ptr->nextPendingConnection();
}
/*!
- Pauses incoming new connections. Queued connections will remain in queue.
- \sa resumeAccepting()
+ Pauses incoming new connections. Queued connections will remain in queue.
+ \sa resumeAccepting()
*/
void QWebSocketServer::pauseAccepting()
{
- d_ptr->pauseAccepting();
+ d_ptr->pauseAccepting();
}
#ifndef QT_NO_NETWORKPROXY
/*!
- Returns the network proxy for this socket. By default QNetworkProxy::DefaultProxy is used.
+ Returns the network proxy for this socket. By default QNetworkProxy::DefaultProxy is used.
- \sa setProxy()
+ \sa setProxy()
*/
QNetworkProxy QWebSocketServer::proxy() const
{
- return d_ptr->proxy();
+ return d_ptr->proxy();
}
/*!
- \brief Sets the explicit network proxy for this socket to \a networkProxy.
+ \brief Sets the explicit network proxy for this socket to \a networkProxy.
- To disable the use of a proxy for this socket, use the QNetworkProxy::NoProxy proxy type:
+ To disable the use of a proxy for this socket, use the QNetworkProxy::NoProxy proxy type:
- \code
- server->setProxy(QNetworkProxy::NoProxy);
- \endcode
+ \code
+ server->setProxy(QNetworkProxy::NoProxy);
+ \endcode
- \sa proxy()
+ \sa proxy()
*/
void QWebSocketServer::setProxy(const QNetworkProxy &networkProxy)
{
- d_ptr->setProxy(networkProxy);
+ d_ptr->setProxy(networkProxy);
}
#endif
/*!
- Resumes accepting new connections.
- \sa pauseAccepting()
+ Resumes accepting new connections.
+ \sa pauseAccepting()
*/
void QWebSocketServer::resumeAccepting()
{
- d_ptr->resumeAccepting();
+ d_ptr->resumeAccepting();
}
/*!
- Returns the server's address if the server is listening for connections; otherwise returns QHostAddress::Null.
+ Returns the server's address if the server is listening for connections; otherwise returns QHostAddress::Null.
- \sa serverPort(), listen()
+ \sa serverPort(), listen()
*/
QHostAddress QWebSocketServer::serverAddress() const
{
- return d_ptr->serverAddress();
+ return d_ptr->serverAddress();
}
/*!
- Returns an error code for the last error that occurred.
- \sa errorString()
+ Returns an error code for the last error that occurred.
+ \sa errorString()
*/
QAbstractSocket::SocketError QWebSocketServer::serverError() const
{
- return d_ptr->serverError();
+ return d_ptr->serverError();
}
/*!
- Returns the server's port if the server is listening for connections; otherwise returns 0.
- \sa serverAddress(), listen()
+ Returns the server's port if the server is listening for connections; otherwise returns 0.
+ \sa serverAddress(), listen()
*/
quint16 QWebSocketServer::serverPort() const
{
- return d_ptr->serverPort();
+ return d_ptr->serverPort();
}
/*!
- Sets the maximum number of pending accepted connections to \a numConnections.
- WebSocketServer will accept no more than \a numConnections incoming connections before nextPendingConnection() is called.
- By default, the limit is 30 pending connections.
+ Sets the maximum number of pending accepted connections to \a numConnections.
+ WebSocketServer will accept no more than \a numConnections incoming connections before nextPendingConnection() is called.
+ By default, the limit is 30 pending connections.
- Clients may still able to connect after the server has reached its maximum number of pending connections (i.e., WebSocket can still emit the connected() signal). WebSocketServer will stop accepting the new connections, but the operating system may still keep them in queue.
- \sa maxPendingConnections(), hasPendingConnections()
+ Clients may still able to connect after the server has reached its maximum number of pending connections (i.e., WebSocket can still emit the connected() signal). WebSocketServer will stop accepting the new connections, but the operating system may still keep them in queue.
+ \sa maxPendingConnections(), hasPendingConnections()
*/
void QWebSocketServer::setMaxPendingConnections(int numConnections)
{
- d_ptr->setMaxPendingConnections(numConnections);
+ d_ptr->setMaxPendingConnections(numConnections);
}
/*!
- Sets the socket descriptor this server should use when listening for incoming connections to \a socketDescriptor.
+ Sets the socket descriptor this server should use when listening for incoming connections to \a socketDescriptor.
- Returns true if the socket is set successfully; otherwise returns false.
- The socket is assumed to be in listening state.
+ Returns true if the socket is set successfully; otherwise returns false.
+ The socket is assumed to be in listening state.
- \sa socketDescriptor(), isListening()
+ \sa socketDescriptor(), isListening()
*/
bool QWebSocketServer::setSocketDescriptor(int socketDescriptor)
{
- return d_ptr->setSocketDescriptor(socketDescriptor);
+ return d_ptr->setSocketDescriptor(socketDescriptor);
}
/*!
- Returns the native socket descriptor the server uses to listen for incoming instructions, or -1 if the server is not listening.
- If the server is using QNetworkProxy, the returned descriptor may not be usable with native socket functions.
+ Returns the native socket descriptor the server uses to listen for incoming instructions, or -1 if the server is not listening.
+ If the server is using QNetworkProxy, the returned descriptor may not be usable with native socket functions.
- \sa setSocketDescriptor(), isListening()
+ \sa setSocketDescriptor(), isListening()
*/
int QWebSocketServer::socketDescriptor() const
{
- return d_ptr->socketDescriptor();
+ return d_ptr->socketDescriptor();
}
/*!
- Waits for at most \a msec milliseconds or until an incoming connection is available.
- Returns true if a connection is available; otherwise returns false.
- If the operation timed out and \a timedOut is not 0, \a timedOut will be set to true.
+ Waits for at most \a msec milliseconds or until an incoming connection is available.
+ Returns true if a connection is available; otherwise returns false.
+ If the operation timed out and \a timedOut is not 0, \a timedOut will be set to true.
- \note This is a blocking function call.
- \note Its use is disadvised in a single-threaded GUI application, since the whole application will stop responding until the function returns. waitForNewConnection() is mostly useful when there is no event loop available.
- \note The non-blocking alternative is to connect to the newConnection() signal.
+ \note This is a blocking function call.
+ \note Its use is disadvised in a single-threaded GUI application, since the whole application will stop responding until the function returns. waitForNewConnection() is mostly useful when there is no event loop available.
+ \note The non-blocking alternative is to connect to the newConnection() signal.
- If \a msec is -1, this function will not time out.
+ If \a msec is -1, this function will not time out.
- \sa hasPendingConnections(), nextPendingConnection()
+ \sa hasPendingConnections(), nextPendingConnection()
*/
bool QWebSocketServer::waitForNewConnection(int msec, bool *timedOut)
{
- return d_ptr->waitForNewConnection(msec, timedOut);
+ return d_ptr->waitForNewConnection(msec, timedOut);
}
/*!
@@ -329,7 +329,7 @@ bool QWebSocketServer::waitForNewConnection(int msec, bool *timedOut)
*/
QList<QWebSocketProtocol::Version> QWebSocketServer::supportedVersions() const
{
- return d_ptr->supportedVersions();
+ return d_ptr->supportedVersions();
}
/*!
@@ -337,7 +337,7 @@ QList<QWebSocketProtocol::Version> QWebSocketServer::supportedVersions() const
*/
QList<QString> QWebSocketServer::supportedProtocols() const
{
- return d_ptr->supportedProtocols();
+ return d_ptr->supportedProtocols();
}
/*!
@@ -345,23 +345,23 @@ QList<QString> QWebSocketServer::supportedProtocols() const
*/
QList<QString> QWebSocketServer::supportedExtensions() const
{
- return d_ptr->supportedExtensions();
+ return d_ptr->supportedExtensions();
}
/*!
- This method checks if the given \a origin is allowed; it returns true when the \a origin is allowed, otherwise false.
- It is supposed to be overriden by a subclass to filter out unwanted origins.
- By default, every origin is accepted.
+ This method checks if the given \a origin is allowed; it returns true when the \a origin is allowed, otherwise false.
+ It is supposed to be overriden by a subclass to filter out unwanted origins.
+ By default, every origin is accepted.
- \note Checking on the origin does not make much sense when the server is accessed
+ \note Checking on the origin does not make much sense when the server is accessed
via a non-browser client, as that client can set whatever origin header it likes
In case of a browser client, the server SHOULD check the validity of the origin.
\sa http://tools.ietf.org/html/rfc6455#section-10
*/
bool QWebSocketServer::isOriginAllowed(const QString &origin) const
{
- Q_UNUSED(origin)
- return true;
+ Q_UNUSED(origin)
+ return true;
}
QT_END_NAMESPACE
diff --git a/src/qwebsocketserver.h b/src/qwebsocketserver.h
index 05b3fff..2ad3d62 100644
--- a/src/qwebsocketserver.h
+++ b/src/qwebsocketserver.h
@@ -33,56 +33,56 @@ class QWebSocket;
class Q_WEBSOCKETS_EXPORT QWebSocketServer : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit QWebSocketServer(const QString &serverName, QObject *parent = 0);
- virtual ~QWebSocketServer();
+ explicit QWebSocketServer(const QString &serverName, QObject *parent = 0);
+ virtual ~QWebSocketServer();
- bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
- void close();
+ bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
+ void close();
- bool isListening() const;
+ bool isListening() const;
- void setMaxPendingConnections(int numConnections);
- int maxPendingConnections() const;
+ void setMaxPendingConnections(int numConnections);
+ int maxPendingConnections() const;
- quint16 serverPort() const;
- QHostAddress serverAddress() const;
+ quint16 serverPort() const;
+ QHostAddress serverAddress() const;
- bool setSocketDescriptor(int socketDescriptor);
- int socketDescriptor() const;
+ bool setSocketDescriptor(int socketDescriptor);
+ int socketDescriptor() const;
- bool waitForNewConnection(int msec = 0, bool *timedOut = 0);
- bool hasPendingConnections() const;
- virtual QWebSocket *nextPendingConnection();
+ bool waitForNewConnection(int msec = 0, bool *timedOut = 0);
+ bool hasPendingConnections() const;
+ virtual QWebSocket *nextPendingConnection();
- QAbstractSocket::SocketError serverError() const;
- QString errorString() const;
+ QAbstractSocket::SocketError serverError() const;
+ QString errorString() const;
- void pauseAccepting();
- void resumeAccepting();
+ void pauseAccepting();
+ void resumeAccepting();
#ifndef QT_NO_NETWORKPROXY
- void setProxy(const QNetworkProxy &networkProxy);
- QNetworkProxy proxy() const;
+ void setProxy(const QNetworkProxy &networkProxy);
+ QNetworkProxy proxy() const;
#endif
- QList<QWebSocketProtocol::Version> supportedVersions() const;
- QList<QString> supportedProtocols() const;
- QList<QString> supportedExtensions() const;
+ QList<QWebSocketProtocol::Version> supportedVersions() const;
+ QList<QString> supportedProtocols() const;
+ QList<QString> supportedExtensions() const;
protected:
- virtual bool isOriginAllowed(const QString &origin) const;
+ virtual bool isOriginAllowed(const QString &origin) const;
Q_SIGNALS:
- void acceptError(QAbstractSocket::SocketError socketError);
- void newConnection();
+ void acceptError(QAbstractSocket::SocketError socketError);
+ void newConnection();
private:
- Q_DISABLE_COPY(QWebSocketServer)
- QWebSocketServerPrivate * const d_ptr;
- friend class QWebSocketServerPrivate;
+ Q_DISABLE_COPY(QWebSocketServer)
+ QWebSocketServerPrivate * const d_ptr;
+ friend class QWebSocketServerPrivate;
};
QT_END_NAMESPACE
diff --git a/src/qwebsocketserver_p.cpp b/src/qwebsocketserver_p.cpp
index 4370cdb..d5e3dcb 100644
--- a/src/qwebsocketserver_p.cpp
+++ b/src/qwebsocketserver_p.cpp
@@ -31,307 +31,307 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
QT_BEGIN_NAMESPACE
/*!
- \internal
+ \internal
*/
QWebSocketServerPrivate::QWebSocketServerPrivate(const QString &serverName, QWebSocketServer * const pWebSocketServer, QObject *parent) :
- QObject(parent),
- q_ptr(pWebSocketServer),
- m_pTcpServer(0),
- m_serverName(serverName),
- m_pendingConnections()
+ QObject(parent),
+ q_ptr(pWebSocketServer),
+ m_pTcpServer(0),
+ m_serverName(serverName),
+ m_pendingConnections()
{
- Q_ASSERT(pWebSocketServer != 0);
- m_pTcpServer = new QTcpServer(this);
- connect(m_pTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), q_ptr, SIGNAL(acceptError(QAbstractSocket::SocketError)));
- connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
+ Q_ASSERT(pWebSocketServer != 0);
+ m_pTcpServer = new QTcpServer(this);
+ connect(m_pTcpServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), q_ptr, SIGNAL(acceptError(QAbstractSocket::SocketError)));
+ connect(m_pTcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
}
/*!
- \internal
+ \internal
*/
QWebSocketServerPrivate::~QWebSocketServerPrivate()
{
- while (!m_pendingConnections.isEmpty())
- {
- QWebSocket *pWebSocket = m_pendingConnections.dequeue();
- pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, "Server closed.");
- pWebSocket->deleteLater();
- }
- m_pTcpServer->deleteLater();
+ while (!m_pendingConnections.isEmpty())
+ {
+ QWebSocket *pWebSocket = m_pendingConnections.dequeue();
+ pWebSocket->close(QWebSocketProtocol::CC_GOING_AWAY, "Server closed.");
+ pWebSocket->deleteLater();
+ }
+ m_pTcpServer->deleteLater();
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::close()
{
- m_pTcpServer->close();
+ m_pTcpServer->close();
}
/*!
- \internal
+ \internal
*/
QString QWebSocketServerPrivate::errorString() const
{
- return m_pTcpServer->errorString();
+ return m_pTcpServer->errorString();
}
/*!
- \internal
+ \internal
*/
bool QWebSocketServerPrivate::hasPendingConnections() const
{
- return !m_pendingConnections.isEmpty();
+ return !m_pendingConnections.isEmpty();
}
/*!
- \internal
+ \internal
*/
bool QWebSocketServerPrivate::isListening() const
{
- return m_pTcpServer->isListening();
+ return m_pTcpServer->isListening();
}
/*!
- \internal
+ \internal
*/
bool QWebSocketServerPrivate::listen(const QHostAddress &address, quint16 port)
{
- return m_pTcpServer->listen(address, port);
+ return m_pTcpServer->listen(address, port);
}
/*!
- \internal
+ \internal
*/
int QWebSocketServerPrivate::maxPendingConnections() const
{
- return m_pTcpServer->maxPendingConnections();
+ return m_pTcpServer->maxPendingConnections();
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::addPendingConnection(QWebSocket *pWebSocket)
{
- if (m_pendingConnections.size() < maxPendingConnections())
- {
- m_pendingConnections.enqueue(pWebSocket);
- }
+ if (m_pendingConnections.size() < maxPendingConnections())
+ {
+ m_pendingConnections.enqueue(pWebSocket);
+ }
}
/*!
- \internal
+ \internal
*/
QWebSocket *QWebSocketServerPrivate::nextPendingConnection()
{
- QWebSocket *pWebSocket = 0;
- if (!m_pendingConnections.isEmpty())
- {
- pWebSocket = m_pendingConnections.dequeue();
- }
- return pWebSocket;
+ QWebSocket *pWebSocket = 0;
+ if (!m_pendingConnections.isEmpty())
+ {
+ pWebSocket = m_pendingConnections.dequeue();
+ }
+ return pWebSocket;
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::pauseAccepting()
{
- m_pTcpServer->pauseAccepting();
+ m_pTcpServer->pauseAccepting();
}
#ifndef QT_NO_NETWORKPROXY
/*!
- \internal
+ \internal
*/
QNetworkProxy QWebSocketServerPrivate::proxy() const
{
- return m_pTcpServer->proxy();
+ return m_pTcpServer->proxy();
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::setProxy(const QNetworkProxy &networkProxy)
{
- m_pTcpServer->setProxy(networkProxy);
+ m_pTcpServer->setProxy(networkProxy);
}
#endif
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::resumeAccepting()
{
- m_pTcpServer->resumeAccepting();
+ m_pTcpServer->resumeAccepting();
}
/*!
- \internal
+ \internal
*/
QHostAddress QWebSocketServerPrivate::serverAddress() const
{
- return m_pTcpServer->serverAddress();
+ return m_pTcpServer->serverAddress();
}
/*!
- \internal
+ \internal
*/
QAbstractSocket::SocketError QWebSocketServerPrivate::serverError() const
{
- return m_pTcpServer->serverError();
+ return m_pTcpServer->serverError();
}
/*!
- \internal
+ \internal
*/
quint16 QWebSocketServerPrivate::serverPort() const
{
- return m_pTcpServer->serverPort();
+ return m_pTcpServer->serverPort();
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::setMaxPendingConnections(int numConnections)
{
- m_pTcpServer->setMaxPendingConnections(numConnections);
+ m_pTcpServer->setMaxPendingConnections(numConnections);
}
/*!
- \internal
+ \internal
*/
bool QWebSocketServerPrivate::setSocketDescriptor(int socketDescriptor)
{
- return m_pTcpServer->setSocketDescriptor(socketDescriptor);
+ return m_pTcpServer->setSocketDescriptor(socketDescriptor);
}
/*!
- \internal
+ \internal
*/
int QWebSocketServerPrivate::socketDescriptor() const
{
- return m_pTcpServer->socketDescriptor();
+ return m_pTcpServer->socketDescriptor();
}
/*!
- \internal
+ \internal
*/
bool QWebSocketServerPrivate::waitForNewConnection(int msec, bool *timedOut)
{
- return m_pTcpServer->waitForNewConnection(msec, timedOut);
+ return m_pTcpServer->waitForNewConnection(msec, timedOut);
}
/*!
- \internal
+ \internal
*/
QList<QWebSocketProtocol::Version> QWebSocketServerPrivate::supportedVersions() const
{
- QList<QWebSocketProtocol::Version> supportedVersions;
- supportedVersions << QWebSocketProtocol::currentVersion(); //we only support V13
- return supportedVersions;
+ QList<QWebSocketProtocol::Version> supportedVersions;
+ supportedVersions << QWebSocketProtocol::currentVersion(); //we only support V13
+ return supportedVersions;
}
/*!
- \internal
+ \internal
*/
QList<QString> QWebSocketServerPrivate::supportedProtocols() const
{
- QList<QString> supportedProtocols;
- return supportedProtocols; //no protocols are currently supported
+ QList<QString> supportedProtocols;
+ return supportedProtocols; //no protocols are currently supported
}
/*!
- \internal
+ \internal
*/
QList<QString> QWebSocketServerPrivate::supportedExtensions() const
{
- QList<QString> supportedExtensions;
- return supportedExtensions; //no extensions are currently supported
+ QList<QString> supportedExtensions;
+ return supportedExtensions; //no extensions are currently supported
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::onNewConnection()
{
- QTcpSocket *pTcpSocket = m_pTcpServer->nextPendingConnection();
- connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
+ QTcpSocket *pTcpSocket = m_pTcpServer->nextPendingConnection();
+ connect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::onCloseConnection()
{
- QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
- if (pTcpSocket != 0)
- {
- pTcpSocket->close();
- }
+ QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
+ if (pTcpSocket != 0)
+ {
+ pTcpSocket->close();
+ }
}
/*!
- \internal
+ \internal
*/
void QWebSocketServerPrivate::handshakeReceived()
{
- QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
- if (pTcpSocket != 0)
- {
- bool success = false;
- bool isSecure = false;
- HandshakeRequest request(pTcpSocket->peerPort(), isSecure);
- QTextStream textStream(pTcpSocket);
- textStream >> request;
-
- HandshakeResponse response(request,
- m_serverName,
- q_ptr->isOriginAllowed(request.getOrigin()),
- supportedVersions(),
- supportedProtocols(),
- supportedExtensions());
- disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
-
- if (response.isValid())
- {
- QTextStream httpStream(pTcpSocket);
- httpStream << response;
- httpStream.flush();
-
- if (response.canUpgrade())
- {
- QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
- if (pWebSocket)
- {
- pWebSocket->setParent(this);
- addPendingConnection(pWebSocket);
- Q_EMIT q_ptr->newConnection();
- success = true;
- }
- else
- {
- qDebug() << "QWebSocketServerPrivate::handshakeReceived: Upgrading to WebSocket failed.";
- }
- }
- else
- {
- qDebug() << "QWebSocketServerPrivate::handshakeReceived: Cannot upgrade to websocket.";
- }
- }
- else
- {
- qDebug() << "QWebSocketServerPrivate::handshakeReceived: Invalid response. This should not happen!!!";
- }
- if (!success)
- {
- qDebug() << "QWebSocketServerPrivate::handshakeReceived: Closing socket because of invalid or unsupported request";
- pTcpSocket->close();
- }
- }
- else
- {
- qDebug() << "WebSocketServerPrivate::handshakeReceived: Sender socket is NULL. This should not happen!!!";
- }
+ QTcpSocket *pTcpSocket = qobject_cast<QTcpSocket*>(sender());
+ if (pTcpSocket != 0)
+ {
+ bool success = false;
+ bool isSecure = false;
+ HandshakeRequest request(pTcpSocket->peerPort(), isSecure);
+ QTextStream textStream(pTcpSocket);
+ textStream >> request;
+
+ HandshakeResponse response(request,
+ m_serverName,
+ q_ptr->isOriginAllowed(request.getOrigin()),
+ supportedVersions(),
+ supportedProtocols(),
+ supportedExtensions());
+ disconnect(pTcpSocket, SIGNAL(readyRead()), this, SLOT(handshakeReceived()));
+
+ if (response.isValid())
+ {
+ QTextStream httpStream(pTcpSocket);
+ httpStream << response;
+ httpStream.flush();
+
+ if (response.canUpgrade())
+ {
+ QWebSocket *pWebSocket = QWebSocketPrivate::upgradeFrom(pTcpSocket, request, response);
+ if (pWebSocket)
+ {
+ pWebSocket->setParent(this);
+ addPendingConnection(pWebSocket);
+ Q_EMIT q_ptr->newConnection();
+ success = true;
+ }
+ else
+ {
+ qDebug() << "QWebSocketServerPrivate::handshakeReceived: Upgrading to WebSocket failed.";
+ }
+ }
+ else
+ {
+ qDebug() << "QWebSocketServerPrivate::handshakeReceived: Cannot upgrade to websocket.";
+ }
+ }
+ else
+ {
+ qDebug() << "QWebSocketServerPrivate::handshakeReceived: Invalid response. This should not happen!!!";
+ }
+ if (!success)
+ {
+ qDebug() << "QWebSocketServerPrivate::handshakeReceived: Closing socket because of invalid or unsupported request";
+ pTcpSocket->close();
+ }
+ }
+ else
+ {
+ qDebug() << "WebSocketServerPrivate::handshakeReceived: Sender socket is NULL. This should not happen!!!";
+ }
}
QT_END_NAMESPACE
diff --git a/src/qwebsocketserver_p.h b/src/qwebsocketserver_p.h
index 6ab1d20..5ed3d8a 100644
--- a/src/qwebsocketserver_p.h
+++ b/src/qwebsocketserver_p.h
@@ -43,53 +43,53 @@ class QWebSocketServer;
class QWebSocketServerPrivate : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- explicit QWebSocketServerPrivate(const QString &serverName, QWebSocketServer * const pWebSocketServer, QObject *parent = 0);
- virtual ~QWebSocketServerPrivate();
-
- void close();
- QString errorString() const;
- bool hasPendingConnections() const;
- bool isListening() const;
- bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
- int maxPendingConnections() const;
- virtual QWebSocket *nextPendingConnection();
- void pauseAccepting();
+ explicit QWebSocketServerPrivate(const QString &serverName, QWebSocketServer * const pWebSocketServer, QObject *parent = 0);
+ virtual ~QWebSocketServerPrivate();
+
+ void close();
+ QString errorString() const;
+ bool hasPendingConnections() const;
+ bool isListening() const;
+ bool listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
+ int maxPendingConnections() const;
+ virtual QWebSocket *nextPendingConnection();
+ void pauseAccepting();
#ifndef QT_NO_NETWORKPROXY
- QNetworkProxy proxy() const;
- void setProxy(const QNetworkProxy &networkProxy);
+ QNetworkProxy proxy() const;
+ void setProxy(const QNetworkProxy &networkProxy);
#endif
- void resumeAccepting();
- QHostAddress serverAddress() const;
- QAbstractSocket::SocketError serverError() const;
- quint16 serverPort() const;
- void setMaxPendingConnections(int numConnections);
- bool setSocketDescriptor(int socketDescriptor);
- int socketDescriptor() const;
- bool waitForNewConnection(int msec = 0, bool *timedOut = 0);
-
- QList<QWebSocketProtocol::Version> supportedVersions() const;
- QList<QString> supportedProtocols() const;
- QList<QString> supportedExtensions() const;
+ void resumeAccepting();
+ QHostAddress serverAddress() const;
+ QAbstractSocket::SocketError serverError() const;
+ quint16 serverPort() const;
+ void setMaxPendingConnections(int numConnections);
+ bool setSocketDescriptor(int socketDescriptor);
+ int socketDescriptor() const;
+ bool waitForNewConnection(int msec = 0, bool *timedOut = 0);
+
+ QList<QWebSocketProtocol::Version> supportedVersions() const;
+ QList<QString> supportedProtocols() const;
+ QList<QString> supportedExtensions() const;
Q_SIGNALS:
- void newConnection();
+ void newConnection();
private Q_SLOTS:
- void onNewConnection();
- void onCloseConnection();
- void handshakeReceived();
+ void onNewConnection();
+ void onCloseConnection();
+ void handshakeReceived();
private:
- QWebSocketServer * const q_ptr;
+ QWebSocketServer * const q_ptr;
- QTcpServer *m_pTcpServer;
- QString m_serverName;
- QQueue<QWebSocket *> m_pendingConnections;
+ QTcpServer *m_pTcpServer;
+ QString m_serverName;
+ QQueue<QWebSocket *> m_pendingConnections;
- void addPendingConnection(QWebSocket *pWebSocket);
+ void addPendingConnection(QWebSocket *pWebSocket);
};
QT_END_NAMESPACE
diff --git a/tests/tst_compliance.cpp b/tests/tst_compliance.cpp
index d56fc1f..fb0936a 100644
--- a/tests/tst_compliance.cpp
+++ b/tests/tst_compliance.cpp
@@ -8,30 +8,30 @@
class ComplianceTest : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- ComplianceTest();
+ ComplianceTest();
private Q_SLOTS:
- void initTestCase();
- void cleanupTestCase();
- void init();
- void cleanup();
- /**
- * @brief Runs the autobahn tests against our implementation
- */
- void autobahnTest();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+ /**
+ * @brief Runs the autobahn tests against our implementation
+ */
+ void autobahnTest();
private:
- QUrl m_url;
+ QUrl m_url;
- void runTestCases(int startNbr, int stopNbr = -1);
- void runTestCase(int nbr, int total);
+ void runTestCases(int startNbr, int stopNbr = -1);
+ void runTestCase(int nbr, int total);
};
ComplianceTest::ComplianceTest() :
- m_url("ws://localhost:9001")
+ m_url("ws://localhost:9001")
{
}
@@ -53,71 +53,71 @@ void ComplianceTest::cleanup()
void ComplianceTest::runTestCase(int nbr, int total)
{
- if (nbr == total)
- {
- return;
- }
- QWebSocket *pWebSocket = new QWebSocket;
- QSignalSpy spy(pWebSocket, SIGNAL(disconnected()));
-
- //next for every case, connect to url
- //ws://ipaddress:port/runCase?case=<number>&agent=<agentname>
- //where agent name will be QWebSocket
- QObject::connect(pWebSocket, &QWebSocket::textMessageReceived, [=](QString message) {
- pWebSocket->write(message);
- });
- QObject::connect(pWebSocket, &QWebSocket::binaryMessageReceived, [=](QByteArray message) {
- pWebSocket->write(message);
- });
-
- qDebug() << "Executing test" << (nbr + 1) << "/" << total;
- QUrl url = m_url;
- url.setPath("/runCase?");
- QUrlQuery query;
- query.addQueryItem("case", QString::number(nbr + 1));
- query.addQueryItem("agent", "QWebSockets/0.9");
- url.setQuery(query);
- pWebSocket->open(url);
- spy.wait(60000);
- pWebSocket->close();
- delete pWebSocket;
- pWebSocket = 0;
- runTestCase(nbr + 1, total);
+ if (nbr == total)
+ {
+ return;
+ }
+ QWebSocket *pWebSocket = new QWebSocket;
+ QSignalSpy spy(pWebSocket, SIGNAL(disconnected()));
+
+ //next for every case, connect to url
+ //ws://ipaddress:port/runCase?case=<number>&agent=<agentname>
+ //where agent name will be QWebSocket
+ QObject::connect(pWebSocket, &QWebSocket::textMessageReceived, [=](QString message) {
+ pWebSocket->write(message);
+ });
+ QObject::connect(pWebSocket, &QWebSocket::binaryMessageReceived, [=](QByteArray message) {
+ pWebSocket->write(message);
+ });
+
+ qDebug() << "Executing test" << (nbr + 1) << "/" << total;
+ QUrl url = m_url;
+ url.setPath("/runCase?");
+ QUrlQuery query;
+ query.addQueryItem("case", QString::number(nbr + 1));
+ query.addQueryItem("agent", "QWebSockets/0.9");
+ url.setQuery(query);
+ pWebSocket->open(url);
+ spy.wait(60000);
+ pWebSocket->close();
+ delete pWebSocket;
+ pWebSocket = 0;
+ runTestCase(nbr + 1, total);
}
void ComplianceTest::runTestCases(int startNbr, int stopNbr)
{
- runTestCase(startNbr, stopNbr);
+ runTestCase(startNbr, stopNbr);
}
void ComplianceTest::autobahnTest()
{
- //connect to autobahn server at url ws://ipaddress:port/getCaseCount
- QWebSocket *pWebSocket = new QWebSocket;
- QUrl url = m_url;
- int numberOfTestCases = 0;
- QSignalSpy spy(pWebSocket, SIGNAL(disconnected()));
- QObject::connect(pWebSocket, &QWebSocket::textMessageReceived, [&](QString message) {
- numberOfTestCases = message.toInt();
- });
-
- url.setPath("/getCaseCount");
- pWebSocket->open(url);
- spy.wait(60000);
- QVERIFY(numberOfTestCases > 0);
-
- QObject::disconnect(pWebSocket, &QWebSocket::textMessageReceived, 0, 0);
-
- runTestCases(0, numberOfTestCases);
-
- url.setPath("/updateReports?");
- QUrlQuery query;
- query.addQueryItem("agent", "QWebSockets");
- url.setQuery(query);
- pWebSocket->open(url);
- spy.wait(60000);
- delete pWebSocket;
- pWebSocket = 0;
+ //connect to autobahn server at url ws://ipaddress:port/getCaseCount
+ QWebSocket *pWebSocket = new QWebSocket;
+ QUrl url = m_url;
+ int numberOfTestCases = 0;
+ QSignalSpy spy(pWebSocket, SIGNAL(disconnected()));
+ QObject::connect(pWebSocket, &QWebSocket::textMessageReceived, [&](QString message) {
+ numberOfTestCases = message.toInt();
+ });
+
+ url.setPath("/getCaseCount");
+ pWebSocket->open(url);
+ spy.wait(60000);
+ QVERIFY(numberOfTestCases > 0);
+
+ QObject::disconnect(pWebSocket, &QWebSocket::textMessageReceived, 0, 0);
+
+ runTestCases(0, numberOfTestCases);
+
+ url.setPath("/updateReports?");
+ QUrlQuery query;
+ query.addQueryItem("agent", "QWebSockets");
+ url.setQuery(query);
+ pWebSocket->open(url);
+ spy.wait(60000);
+ delete pWebSocket;
+ pWebSocket = 0;
}
DECLARE_TEST(ComplianceTest)
diff --git a/tests/tst_websockets.cpp b/tests/tst_websockets.cpp
index c404eef..ff4b6fd 100644
--- a/tests/tst_websockets.cpp
+++ b/tests/tst_websockets.cpp
@@ -8,71 +8,71 @@
class WebSocketsTest : public QObject
{
- Q_OBJECT
+ Q_OBJECT
public:
- WebSocketsTest();
+ WebSocketsTest();
private Q_SLOTS:
- void initTestCase();
- void cleanupTestCase();
- void init();
- void cleanup();
- /**
- * @brief testTextMessage Tests sending and receiving a text message
- */
- void testTextMessage();
-
- void testBinaryMessage();
-
- /**
- * @brief Tests the method localAddress and localPort
- */
- void testLocalAddress();
-
- /**
- * @brief Test the methods peerAddress, peerName and peerPort
- */
- void testPeerAddress();
-
- /**
- * @brief Test the methods proxy() and setProxy() and check if it can be correctly set
- */
- void testProxy();
-
- /**
- * @brief Runs the autobahn tests against our implementation
- */
- //void autobahnTest();
+ void initTestCase();
+ void cleanupTestCase();
+ void init();
+ void cleanup();
+ /**
+ * @brief testTextMessage Tests sending and receiving a text message
+ */
+ void testTextMessage();
+
+ void testBinaryMessage();
+
+ /**
+ * @brief Tests the method localAddress and localPort
+ */
+ void testLocalAddress();
+
+ /**
+ * @brief Test the methods peerAddress, peerName and peerPort
+ */
+ void testPeerAddress();
+
+ /**
+ * @brief Test the methods proxy() and setProxy() and check if it can be correctly set
+ */
+ void testProxy();
+
+ /**
+ * @brief Runs the autobahn tests against our implementation
+ */
+ //void autobahnTest();
private:
- QWebSocket *m_pWebSocket;
- QUrl m_url;
+ QWebSocket *m_pWebSocket;
+ QUrl m_url;
};
WebSocketsTest::WebSocketsTest() :
- m_pWebSocket(0),
- m_url("ws://localhost:9000")
+ m_pWebSocket(0),
+ m_url("ws://localhost:9000")
{
}
void WebSocketsTest::initTestCase()
{
- m_pWebSocket = new QWebSocket();
- m_pWebSocket->open(m_url, true);
- QTRY_VERIFY_WITH_TIMEOUT(m_pWebSocket->state() == QAbstractSocket::ConnectedState, 1000);
- QVERIFY(m_pWebSocket->isValid());
+ m_pWebSocket = new QWebSocket();
+ m_pWebSocket->open(m_url, true);
+ QTRY_VERIFY_WITH_TIMEOUT(m_pWebSocket->state() == QAbstractSocket::ConnectedState, 1000);
+ QVERIFY(m_pWebSocket->isValid());
}
void WebSocketsTest::cleanupTestCase()
{
- if (m_pWebSocket)
- {
- m_pWebSocket->close();
- //QVERIFY2(m_pWebSocket->waitForDisconnected(1000), "Disconnection failed.");
- delete m_pWebSocket;
- m_pWebSocket = 0;
- }
+ if (m_pWebSocket)
+ {
+ m_pWebSocket->close();
+ //QVERIFY2(m_pWebSocket->waitForDisconnected(1000), "Disconnection failed.");
+ delete m_pWebSocket;
+ m_pWebSocket = 0;
+ }
}
void WebSocketsTest::init()
@@ -85,79 +85,79 @@ void WebSocketsTest::cleanup()
void WebSocketsTest::testTextMessage()
{
- const char *message = "Hello world!";
+ const char *message = "Hello world!";
- QSignalSpy spy(m_pWebSocket, SIGNAL(textMessageReceived(QString)));
+ QSignalSpy spy(m_pWebSocket, SIGNAL(textMessageReceived(QString)));
- QCOMPARE(m_pWebSocket->write(message), (qint64)strlen(message));
+ QCOMPARE(m_pWebSocket->write(message), (qint64)strlen(message));
- QTRY_VERIFY_WITH_TIMEOUT(spy.count() != 0, 1000);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.at(0).count(), 1);
- QCOMPARE(spy.takeFirst().at(0).toString(), QString(message));
+ QTRY_VERIFY_WITH_TIMEOUT(spy.count() != 0, 1000);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).toString(), QString(message));
- spy.clear();
- QString qMessage(message);
- QCOMPARE(m_pWebSocket->write(qMessage), (qint64)qMessage.length());
- QTRY_VERIFY_WITH_TIMEOUT(spy.count() != 0, 1000);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.at(0).count(), 1);
- QCOMPARE(spy.takeFirst().at(0).toString(), qMessage);
+ spy.clear();
+ QString qMessage(message);
+ QCOMPARE(m_pWebSocket->write(qMessage), (qint64)qMessage.length());
+ QTRY_VERIFY_WITH_TIMEOUT(spy.count() != 0, 1000);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).toString(), qMessage);
}
void WebSocketsTest::testBinaryMessage()
{
- QSignalSpy spy(m_pWebSocket, SIGNAL(binaryMessageReceived(QByteArray)));
+ QSignalSpy spy(m_pWebSocket, SIGNAL(binaryMessageReceived(QByteArray)));
- QByteArray data("Hello world!");
+ QByteArray data("Hello world!");
- QCOMPARE(m_pWebSocket->write(data), (qint64)data.size());
+ QCOMPARE(m_pWebSocket->write(data), (qint64)data.size());
- QTRY_VERIFY_WITH_TIMEOUT(spy.count() != 0, 1000);
- QCOMPARE(spy.count(), 1);
- QCOMPARE(spy.at(0).count(), 1);
- QCOMPARE(spy.takeFirst().at(0).toByteArray(), data);
+ QTRY_VERIFY_WITH_TIMEOUT(spy.count() != 0, 1000);
+ QCOMPARE(spy.count(), 1);
+ QCOMPARE(spy.at(0).count(), 1);
+ QCOMPARE(spy.takeFirst().at(0).toByteArray(), data);
}
void WebSocketsTest::testLocalAddress()
{
- QCOMPARE(m_pWebSocket->localAddress().toString(), QString("127.0.0.1"));
- quint16 localPort = m_pWebSocket->localPort();
- QVERIFY2(localPort > 0, "Local port is invalid.");
+ QCOMPARE(m_pWebSocket->localAddress().toString(), QString("127.0.0.1"));
+ quint16 localPort = m_pWebSocket->localPort();
+ QVERIFY2(localPort > 0, "Local port is invalid.");
}
void WebSocketsTest::testPeerAddress()
{
- QHostInfo hostInfo = QHostInfo::fromName(m_url.host());
- QList<QHostAddress> addresses = hostInfo.addresses();
- QVERIFY(addresses.length() > 0);
- QHostAddress peer = m_pWebSocket->peerAddress();
- bool found = false;
- Q_FOREACH(QHostAddress a, addresses)
- {
- if (a == peer)
- {
- found = true;
- break;
- }
- }
-
- if (!found)
- {
- QFAIL("PeerAddress is not found as a result of a reverse lookup");
- }
- QCOMPARE(m_pWebSocket->peerName(), m_url.host());
- QCOMPARE(m_pWebSocket->peerPort(), (quint16)m_url.port(80));
+ QHostInfo hostInfo = QHostInfo::fromName(m_url.host());
+ QList<QHostAddress> addresses = hostInfo.addresses();
+ QVERIFY(addresses.length() > 0);
+ QHostAddress peer = m_pWebSocket->peerAddress();
+ bool found = false;
+ Q_FOREACH(QHostAddress a, addresses)
+ {
+ if (a == peer)
+ {
+ found = true;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ QFAIL("PeerAddress is not found as a result of a reverse lookup");
+ }
+ QCOMPARE(m_pWebSocket->peerName(), m_url.host());
+ QCOMPARE(m_pWebSocket->peerPort(), (quint16)m_url.port(80));
}
void WebSocketsTest::testProxy()
{
- QNetworkProxy oldProxy = m_pWebSocket->proxy();
- QNetworkProxy proxy(QNetworkProxy::HttpProxy, QString("proxy.network.com"), 80);
- m_pWebSocket->setProxy(proxy);
- QCOMPARE(proxy, m_pWebSocket->proxy());
- m_pWebSocket->setProxy(oldProxy);
- QCOMPARE(oldProxy, m_pWebSocket->proxy());
+ QNetworkProxy oldProxy = m_pWebSocket->proxy();
+ QNetworkProxy proxy(QNetworkProxy::HttpProxy, QString("proxy.network.com"), 80);
+ m_pWebSocket->setProxy(proxy);
+ QCOMPARE(proxy, m_pWebSocket->proxy());
+ m_pWebSocket->setProxy(oldProxy);
+ QCOMPARE(oldProxy, m_pWebSocket->proxy());
}
//DECLARE_TEST(WebSocketsTest)
diff --git a/tests/unittests.h b/tests/unittests.h
index a06fd24..923c218 100644
--- a/tests/unittests.h
+++ b/tests/unittests.h
@@ -15,46 +15,46 @@ typedef QList<QObject*> TestList;
inline TestList& testList()
{
- static TestList list;
- return list;
+ static TestList list;
+ return list;
}
inline bool findObject(QObject* object)
{
- TestList& list = testList();
- if (list.contains(object))
- {
- return true;
- }
- Q_FOREACH (QObject* test, list)
- {
- if (test->objectName() == object->objectName())
- {
- return true;
- }
- }
- return false;
+ TestList& list = testList();
+ if (list.contains(object))
+ {
+ return true;
+ }
+ Q_FOREACH (QObject* test, list)
+ {
+ if (test->objectName() == object->objectName())
+ {
+ return true;
+ }
+ }
+ return false;
}
inline void addTest(QObject* object)
{
- TestList& list = testList();
- if (!findObject(object))
- {
- list.append(object);
- }
+ TestList& list = testList();
+ if (!findObject(object))
+ {
+ list.append(object);
+ }
}
inline int run(int argc, char *argv[])
{
- int ret = 0;
+ int ret = 0;
- Q_FOREACH (QObject* test, testList())
- {
- ret += QTest::qExec(test, argc, argv);
- }
- testList().clear();
- return ret;
+ Q_FOREACH (QObject* test, testList())
+ {
+ ret += QTest::qExec(test, argc, argv);
+ }
+ testList().clear();
+ return ret;
}
} // end namespace
@@ -63,24 +63,24 @@ template <class T>
class Test
{
public:
- QSharedPointer<T> child;
+ QSharedPointer<T> child;
- Test(const QString& name) : child(new T)
- {
- child->setObjectName(name);
- AutoTest::addTest(child.data());
- }
+ Test(const QString& name) : child(new T)
+ {
+ child->setObjectName(name);
+ AutoTest::addTest(child.data());
+ }
};
#define DECLARE_TEST(className) static Test<className> t(#className);
#define TEST_MAIN \
-int main(int argc, char *argv[]) \
+ int main(int argc, char *argv[]) \
{ \
- QCoreApplication app(argc, argv); \
- int ret = AutoTest::run(argc, argv); \
- return ret; \
-}
+ QCoreApplication app(argc, argv); \
+ int ret = AutoTest::run(argc, argv); \
+ return ret; \
+ }
//return app.exec();
#endif