mirror of
https://github.com/hyperion-project/hyperion.ng.git
synced 2023-10-10 13:36:59 +02:00
The slot in the websocket client will now run through until there are no more data in the buffer
Signed-off-by: Paulchen-Panther <Paulchen-Panter@protonmail.com>
This commit is contained in:
parent
370e1b5f45
commit
96d79cdef6
@ -298,7 +298,7 @@ $(document).ready(function() {
|
|||||||
|
|
||||||
createCP('cp2', cpcolor, function(rgbT,hex){
|
createCP('cp2', cpcolor, function(rgbT,hex){
|
||||||
rgb = rgbT;
|
rgb = rgbT;
|
||||||
sendColor()
|
sendColor();
|
||||||
setStorage('rmcpcolor', hex);
|
setStorage('rmcpcolor', hex);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -180,8 +180,6 @@ void LinearColorSmoothing::componentStateChange(const hyperion::Components compo
|
|||||||
|
|
||||||
void LinearColorSmoothing::setEnable(bool enable)
|
void LinearColorSmoothing::setEnable(bool enable)
|
||||||
{
|
{
|
||||||
LedDevice::setEnable(enable);
|
|
||||||
|
|
||||||
if (!enable)
|
if (!enable)
|
||||||
{
|
{
|
||||||
_timer->stop();
|
_timer->stop();
|
||||||
|
@ -27,93 +27,131 @@ QtHttpClientWrapper::QtHttpClientWrapper (QTcpSocket * sock, const bool& localCo
|
|||||||
, m_websocketClient(nullptr)
|
, m_websocketClient(nullptr)
|
||||||
, m_webJsonRpc (nullptr)
|
, m_webJsonRpc (nullptr)
|
||||||
{
|
{
|
||||||
connect (m_sockClient, &QTcpSocket::readyRead, this, &QtHttpClientWrapper::onClientDataReceived);
|
connect (m_sockClient, &QTcpSocket::readyRead, this, &QtHttpClientWrapper::onClientDataReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtHttpClientWrapper::getGuid (void) {
|
QString QtHttpClientWrapper::getGuid (void)
|
||||||
if (m_guid.isEmpty ()) {
|
{
|
||||||
m_guid = QString::fromLocal8Bit (
|
if (m_guid.isEmpty ())
|
||||||
QCryptographicHash::hash (
|
{
|
||||||
QByteArray::number ((quint64) (this)),
|
m_guid = QString::fromLocal8Bit (
|
||||||
QCryptographicHash::Md5
|
QCryptographicHash::hash (
|
||||||
).toHex ()
|
QByteArray::number ((quint64) (this)),
|
||||||
);
|
QCryptographicHash::Md5
|
||||||
}
|
).toHex ()
|
||||||
return m_guid;
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return m_guid;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpClientWrapper::onClientDataReceived (void) {
|
void QtHttpClientWrapper::onClientDataReceived (void)
|
||||||
if (m_sockClient != Q_NULLPTR) {
|
{
|
||||||
while (m_sockClient->bytesAvailable ()) {
|
if (m_sockClient != Q_NULLPTR)
|
||||||
QByteArray line = m_sockClient->readLine ();
|
{
|
||||||
switch (m_parsingStatus) { // handle parsing steps
|
while (m_sockClient->bytesAvailable ())
|
||||||
case AwaitingRequest: { // "command url version" × 1
|
{
|
||||||
QString str = QString::fromUtf8 (line).trimmed ();
|
QByteArray line = m_sockClient->readLine ();
|
||||||
QStringList parts = str.split (SPACE, QString::SkipEmptyParts);
|
|
||||||
if (parts.size () == 3) {
|
switch (m_parsingStatus) // handle parsing steps
|
||||||
QString command = parts.at (0);
|
{
|
||||||
QString url = parts.at (1);
|
case AwaitingRequest: // "command url version" × 1
|
||||||
QString version = parts.at (2);
|
{
|
||||||
if (version == QtHttpServer::HTTP_VERSION) {
|
QString str = QString::fromUtf8 (line).trimmed ();
|
||||||
m_currentRequest = new QtHttpRequest (this, m_serverHandle);
|
QStringList parts = str.split (SPACE, QString::SkipEmptyParts);
|
||||||
m_currentRequest->setClientInfo(m_sockClient->localAddress(), m_sockClient->peerAddress());
|
|
||||||
m_currentRequest->setUrl (QUrl (url));
|
if (parts.size () == 3)
|
||||||
m_currentRequest->setCommand (command);
|
{
|
||||||
m_parsingStatus = AwaitingHeaders;
|
QString command = parts.at (0);
|
||||||
}
|
QString url = parts.at (1);
|
||||||
else {
|
QString version = parts.at (2);
|
||||||
m_parsingStatus = ParsingError;
|
|
||||||
//qWarning () << "Error : unhandled HTTP version :" << version;
|
if (version == QtHttpServer::HTTP_VERSION)
|
||||||
}
|
{
|
||||||
}
|
m_currentRequest = new QtHttpRequest (this, m_serverHandle);
|
||||||
else {
|
m_currentRequest->setClientInfo(m_sockClient->localAddress(), m_sockClient->peerAddress());
|
||||||
m_parsingStatus = ParsingError;
|
m_currentRequest->setUrl (QUrl (url));
|
||||||
//qWarning () << "Error : incorrect HTTP command line :" << line;
|
m_currentRequest->setCommand (command);
|
||||||
}
|
m_parsingStatus = AwaitingHeaders;
|
||||||
break;
|
}
|
||||||
}
|
else
|
||||||
case AwaitingHeaders: { // "header: value" × N (until empty line)
|
{
|
||||||
QByteArray raw = line.trimmed ();
|
m_parsingStatus = ParsingError;
|
||||||
if (!raw.isEmpty ()) { // parse headers
|
//qWarning () << "Error : unhandled HTTP version :" << version;
|
||||||
int pos = raw.indexOf (COLON);
|
}
|
||||||
if (pos > 0) {
|
}
|
||||||
QByteArray header = raw.left (pos).trimmed ();
|
else
|
||||||
QByteArray value = raw.mid (pos +1).trimmed ();
|
{
|
||||||
m_currentRequest->addHeader (header, value);
|
m_parsingStatus = ParsingError;
|
||||||
if (header == QtHttpHeader::ContentLength) {
|
//qWarning () << "Error : incorrect HTTP command line :" << line;
|
||||||
bool ok = false;
|
}
|
||||||
const int len = value.toInt (&ok, 10);
|
|
||||||
if (ok) {
|
break;
|
||||||
m_currentRequest->addHeader (QtHttpHeader::ContentLength, QByteArray::number (len));
|
}
|
||||||
}
|
case AwaitingHeaders: // "header: value" × N (until empty line)
|
||||||
}
|
{
|
||||||
}
|
QByteArray raw = line.trimmed ();
|
||||||
else {
|
|
||||||
m_parsingStatus = ParsingError;
|
if (!raw.isEmpty ()) // parse headers
|
||||||
qWarning () << "Error : incorrect HTTP headers line :" << line;
|
{
|
||||||
}
|
int pos = raw.indexOf (COLON);
|
||||||
}
|
|
||||||
else { // end of headers
|
if (pos > 0)
|
||||||
if (m_currentRequest->getHeader (QtHttpHeader::ContentLength).toInt () > 0) {
|
{
|
||||||
m_parsingStatus = AwaitingContent;
|
QByteArray header = raw.left (pos).trimmed ();
|
||||||
}
|
QByteArray value = raw.mid (pos +1).trimmed ();
|
||||||
else {
|
m_currentRequest->addHeader (header, value);
|
||||||
m_parsingStatus = RequestParsed;
|
if (header == QtHttpHeader::ContentLength)
|
||||||
}
|
{
|
||||||
}
|
bool ok = false;
|
||||||
break;
|
const int len = value.toInt (&ok, 10);
|
||||||
}
|
if (ok)
|
||||||
case AwaitingContent: { // raw data × N (until EOF ??)
|
{
|
||||||
m_currentRequest->appendRawData (line);
|
m_currentRequest->addHeader (QtHttpHeader::ContentLength, QByteArray::number (len));
|
||||||
if (m_currentRequest->getRawDataSize () == m_currentRequest->getHeader (QtHttpHeader::ContentLength).toInt ()) {
|
}
|
||||||
m_parsingStatus = RequestParsed;
|
}
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
}
|
{
|
||||||
default: { break; }
|
m_parsingStatus = ParsingError;
|
||||||
}
|
qWarning () << "Error : incorrect HTTP headers line :" << line;
|
||||||
switch (m_parsingStatus) { // handle parsing status end/error
|
}
|
||||||
case RequestParsed: { // a valid request has ben fully parsed
|
}
|
||||||
|
else // end of headers
|
||||||
|
{
|
||||||
|
if (m_currentRequest->getHeader (QtHttpHeader::ContentLength).toInt () > 0)
|
||||||
|
{
|
||||||
|
m_parsingStatus = AwaitingContent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_parsingStatus = RequestParsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case AwaitingContent: // raw data × N (until EOF ??)
|
||||||
|
{
|
||||||
|
m_currentRequest->appendRawData (line);
|
||||||
|
|
||||||
|
if (m_currentRequest->getRawDataSize () == m_currentRequest->getHeader (QtHttpHeader::ContentLength).toInt ())
|
||||||
|
{
|
||||||
|
m_parsingStatus = RequestParsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (m_parsingStatus) // handle parsing status end/error
|
||||||
|
{
|
||||||
|
case RequestParsed: // a valid request has ben fully parsed
|
||||||
|
{
|
||||||
// Catch websocket header "Upgrade"
|
// Catch websocket header "Upgrade"
|
||||||
if(m_currentRequest->getHeader(QtHttpHeader::Upgrade) == "websocket")
|
if(m_currentRequest->getHeader(QtHttpHeader::Upgrade) == "websocket")
|
||||||
{
|
{
|
||||||
@ -121,146 +159,184 @@ void QtHttpClientWrapper::onClientDataReceived (void) {
|
|||||||
{
|
{
|
||||||
// disconnect this slot from socket for further requests
|
// disconnect this slot from socket for further requests
|
||||||
disconnect(m_sockClient, &QTcpSocket::readyRead, this, &QtHttpClientWrapper::onClientDataReceived);
|
disconnect(m_sockClient, &QTcpSocket::readyRead, this, &QtHttpClientWrapper::onClientDataReceived);
|
||||||
|
// disabling packet bunching
|
||||||
|
m_sockClient->setSocketOption(QAbstractSocket::LowDelayOption, 1);
|
||||||
|
m_sockClient->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
|
||||||
m_websocketClient = new WebSocketClient(m_currentRequest, m_sockClient, m_localConnection, this);
|
m_websocketClient = new WebSocketClient(m_currentRequest, m_sockClient, m_localConnection, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add post data to request and catch /jsonrpc subroute url
|
// add post data to request and catch /jsonrpc subroute url
|
||||||
if ( m_currentRequest->getCommand() == "POST")
|
if ( m_currentRequest->getCommand() == "POST")
|
||||||
{
|
{
|
||||||
QtHttpPostData postData;
|
QtHttpPostData postData;
|
||||||
QByteArray data = m_currentRequest->getRawData();
|
QByteArray data = m_currentRequest->getRawData();
|
||||||
QList<QByteArray> parts = data.split('&');
|
QList<QByteArray> parts = data.split('&');
|
||||||
for (int i = 0; i < parts.size(); ++i)
|
|
||||||
{
|
for (int i = 0; i < parts.size(); ++i)
|
||||||
QList<QByteArray> keyValue = parts.at(i).split('=');
|
{
|
||||||
QByteArray value;
|
QList<QByteArray> keyValue = parts.at(i).split('=');
|
||||||
if (keyValue.size()>1)
|
QByteArray value;
|
||||||
{
|
|
||||||
value = QByteArray::fromPercentEncoding(keyValue.at(1));
|
if (keyValue.size()>1)
|
||||||
}
|
{
|
||||||
postData.insert(QString::fromUtf8(keyValue.at(0)),value);
|
value = QByteArray::fromPercentEncoding(keyValue.at(1));
|
||||||
}
|
}
|
||||||
m_currentRequest->setPostData(postData);
|
|
||||||
|
postData.insert(QString::fromUtf8(keyValue.at(0)),value);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentRequest->setPostData(postData);
|
||||||
|
|
||||||
// catch /jsonrpc in url, we need async callback, StaticFileServing is sync
|
// catch /jsonrpc in url, we need async callback, StaticFileServing is sync
|
||||||
QString path = m_currentRequest->getUrl ().path ();
|
QString path = m_currentRequest->getUrl ().path ();
|
||||||
QStringList uri_parts = path.split('/', QString::SkipEmptyParts);
|
QStringList uri_parts = path.split('/', QString::SkipEmptyParts);
|
||||||
|
|
||||||
if ( ! uri_parts.empty() && uri_parts.at(0) == "json-rpc" )
|
if ( ! uri_parts.empty() && uri_parts.at(0) == "json-rpc" )
|
||||||
{
|
{
|
||||||
if(m_webJsonRpc == Q_NULLPTR)
|
if(m_webJsonRpc == Q_NULLPTR)
|
||||||
{
|
{
|
||||||
m_webJsonRpc = new WebJsonRpc(m_currentRequest, m_serverHandle, m_localConnection, this);
|
m_webJsonRpc = new WebJsonRpc(m_currentRequest, m_serverHandle, m_localConnection, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_webJsonRpc->handleMessage(m_currentRequest);
|
m_webJsonRpc->handleMessage(m_currentRequest);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHttpReply reply (m_serverHandle);
|
QtHttpReply reply (m_serverHandle);
|
||||||
connect (&reply, &QtHttpReply::requestSendHeaders,
|
connect (&reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested);
|
||||||
this, &QtHttpClientWrapper::onReplySendHeadersRequested);
|
connect (&reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested);
|
||||||
connect (&reply, &QtHttpReply::requestSendData,
|
emit m_serverHandle->requestNeedsReply (m_currentRequest, &reply); // allow app to handle request
|
||||||
this, &QtHttpClientWrapper::onReplySendDataRequested);
|
|
||||||
emit m_serverHandle->requestNeedsReply (m_currentRequest, &reply); // allow app to handle request
|
|
||||||
m_parsingStatus = sendReplyToClient (&reply);
|
m_parsingStatus = sendReplyToClient (&reply);
|
||||||
break;
|
|
||||||
}
|
break;
|
||||||
case ParsingError: { // there was an error durin one of parsing steps
|
}
|
||||||
m_sockClient->readAll (); // clear remaining buffer to ignore content
|
case ParsingError: // there was an error durin one of parsing steps
|
||||||
QtHttpReply reply (m_serverHandle);
|
{
|
||||||
reply.setStatusCode (QtHttpReply::BadRequest);
|
m_sockClient->readAll (); // clear remaining buffer to ignore content
|
||||||
reply.appendRawData (QByteArrayLiteral ("<h1>Bad Request (HTTP parsing error) !</h1>"));
|
QtHttpReply reply (m_serverHandle);
|
||||||
reply.appendRawData (CRLF);
|
reply.setStatusCode (QtHttpReply::BadRequest);
|
||||||
m_parsingStatus = sendReplyToClient (&reply);
|
reply.appendRawData (QByteArrayLiteral ("<h1>Bad Request (HTTP parsing error) !</h1>"));
|
||||||
break;
|
reply.appendRawData (CRLF);
|
||||||
}
|
m_parsingStatus = sendReplyToClient (&reply);
|
||||||
default: { break; }
|
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
}
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpClientWrapper::onReplySendHeadersRequested (void) {
|
void QtHttpClientWrapper::onReplySendHeadersRequested (void)
|
||||||
QtHttpReply * reply = qobject_cast<QtHttpReply *> (sender ());
|
{
|
||||||
if (reply != Q_NULLPTR) {
|
QtHttpReply * reply = qobject_cast<QtHttpReply *> (sender ());
|
||||||
QByteArray data;
|
|
||||||
// HTTP Version + Status Code + Status Msg
|
if (reply != Q_NULLPTR)
|
||||||
data.append (QtHttpServer::HTTP_VERSION);
|
{
|
||||||
data.append (SPACE);
|
QByteArray data;
|
||||||
data.append (QByteArray::number (reply->getStatusCode ()));
|
// HTTP Version + Status Code + Status Msg
|
||||||
data.append (SPACE);
|
data.append (QtHttpServer::HTTP_VERSION);
|
||||||
data.append (QtHttpReply::getStatusTextForCode (reply->getStatusCode ()));
|
data.append (SPACE);
|
||||||
data.append (CRLF);
|
data.append (QByteArray::number (reply->getStatusCode ()));
|
||||||
// Header name: header value
|
data.append (SPACE);
|
||||||
if (reply->useChunked ()) {
|
data.append (QtHttpReply::getStatusTextForCode (reply->getStatusCode ()));
|
||||||
static const QByteArray & CHUNKED = QByteArrayLiteral ("chunked");
|
data.append (CRLF);
|
||||||
reply->addHeader (QtHttpHeader::TransferEncoding, CHUNKED);
|
|
||||||
}
|
if (reply->useChunked ()) // Header name: header value
|
||||||
else {
|
{
|
||||||
reply->addHeader (QtHttpHeader::ContentLength, QByteArray::number (reply->getRawDataSize ()));
|
static const QByteArray & CHUNKED = QByteArrayLiteral ("chunked");
|
||||||
}
|
reply->addHeader (QtHttpHeader::TransferEncoding, CHUNKED);
|
||||||
const QList<QByteArray> & headersList = reply->getHeadersList ();
|
}
|
||||||
foreach (const QByteArray & header, headersList) {
|
else
|
||||||
data.append (header);
|
{
|
||||||
data.append (COLON);
|
reply->addHeader (QtHttpHeader::ContentLength, QByteArray::number (reply->getRawDataSize ()));
|
||||||
data.append (SPACE);
|
}
|
||||||
data.append (reply->getHeader (header));
|
|
||||||
data.append (CRLF);
|
const QList<QByteArray> & headersList = reply->getHeadersList ();
|
||||||
}
|
|
||||||
// empty line
|
foreach (const QByteArray & header, headersList)
|
||||||
data.append (CRLF);
|
{
|
||||||
m_sockClient->write (data);
|
data.append (header);
|
||||||
m_sockClient->flush ();
|
data.append (COLON);
|
||||||
}
|
data.append (SPACE);
|
||||||
|
data.append (reply->getHeader (header));
|
||||||
|
data.append (CRLF);
|
||||||
|
}
|
||||||
|
|
||||||
|
// empty line
|
||||||
|
data.append (CRLF);
|
||||||
|
m_sockClient->write (data);
|
||||||
|
m_sockClient->flush ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpClientWrapper::onReplySendDataRequested (void) {
|
void QtHttpClientWrapper::onReplySendDataRequested (void)
|
||||||
QtHttpReply * reply = qobject_cast<QtHttpReply *> (sender ());
|
{
|
||||||
if (reply != Q_NULLPTR) {
|
QtHttpReply * reply = qobject_cast<QtHttpReply *> (sender ());
|
||||||
// content raw data
|
if (reply != Q_NULLPTR)
|
||||||
QByteArray data = reply->getRawData ();
|
{
|
||||||
if (reply->useChunked ()) {
|
// content raw data
|
||||||
data.prepend (QByteArray::number (data.size (), 16) % CRLF);
|
QByteArray data = reply->getRawData ();
|
||||||
data.append (CRLF);
|
|
||||||
reply->resetRawData ();
|
if (reply->useChunked ())
|
||||||
}
|
{
|
||||||
// write to socket
|
data.prepend (QByteArray::number (data.size (), 16) % CRLF);
|
||||||
m_sockClient->write (data);
|
data.append (CRLF);
|
||||||
m_sockClient->flush ();
|
reply->resetRawData ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write to socket
|
||||||
|
m_sockClient->write (data);
|
||||||
|
m_sockClient->flush ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpClientWrapper::sendToClientWithReply(QtHttpReply * reply) {
|
void QtHttpClientWrapper::sendToClientWithReply(QtHttpReply * reply)
|
||||||
connect (reply, &QtHttpReply::requestSendHeaders,
|
{
|
||||||
this, &QtHttpClientWrapper::onReplySendHeadersRequested);
|
connect (reply, &QtHttpReply::requestSendHeaders, this, &QtHttpClientWrapper::onReplySendHeadersRequested);
|
||||||
connect (reply, &QtHttpReply::requestSendData,
|
connect (reply, &QtHttpReply::requestSendData, this, &QtHttpClientWrapper::onReplySendDataRequested);
|
||||||
this, &QtHttpClientWrapper::onReplySendDataRequested);
|
|
||||||
m_parsingStatus = sendReplyToClient (reply);
|
m_parsingStatus = sendReplyToClient (reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHttpClientWrapper::ParsingStatus QtHttpClientWrapper::sendReplyToClient (QtHttpReply * reply) {
|
QtHttpClientWrapper::ParsingStatus QtHttpClientWrapper::sendReplyToClient (QtHttpReply * reply)
|
||||||
if (reply != Q_NULLPTR) {
|
{
|
||||||
if (!reply->useChunked ()) {
|
if (reply != Q_NULLPTR)
|
||||||
//reply->appendRawData (CRLF);
|
{
|
||||||
// send all headers and all data in one shot
|
if (!reply->useChunked ())
|
||||||
reply->requestSendHeaders ();
|
{
|
||||||
reply->requestSendData ();
|
//reply->appendRawData (CRLF);
|
||||||
}
|
// send all headers and all data in one shot
|
||||||
else {
|
reply->requestSendHeaders ();
|
||||||
// last chunk
|
reply->requestSendData ();
|
||||||
m_sockClient->write ("0" % CRLF % CRLF);
|
}
|
||||||
m_sockClient->flush ();
|
else
|
||||||
}
|
{
|
||||||
if (m_currentRequest != Q_NULLPTR) {
|
// last chunk
|
||||||
static const QByteArray & CLOSE = QByteArrayLiteral ("close");
|
m_sockClient->write ("0" % CRLF % CRLF);
|
||||||
if (m_currentRequest->getHeader (QtHttpHeader::Connection).toLower () == CLOSE) {
|
m_sockClient->flush ();
|
||||||
// must close connection after this request
|
}
|
||||||
m_sockClient->close ();
|
|
||||||
}
|
if (m_currentRequest != Q_NULLPTR)
|
||||||
m_currentRequest->deleteLater ();
|
{
|
||||||
m_currentRequest = Q_NULLPTR;
|
static const QByteArray & CLOSE = QByteArrayLiteral ("close");
|
||||||
}
|
|
||||||
}
|
if (m_currentRequest->getHeader (QtHttpHeader::Connection).toLower () == CLOSE)
|
||||||
return AwaitingRequest;
|
{
|
||||||
|
// must close connection after this request
|
||||||
|
m_sockClient->close ();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_currentRequest->deleteLater ();
|
||||||
|
m_currentRequest = Q_NULLPTR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return AwaitingRequest;
|
||||||
}
|
}
|
||||||
|
@ -3,35 +3,36 @@
|
|||||||
|
|
||||||
class QByteArray;
|
class QByteArray;
|
||||||
|
|
||||||
class QtHttpHeader {
|
class QtHttpHeader
|
||||||
|
{
|
||||||
public:
|
public:
|
||||||
static const QByteArray & Server;
|
static const QByteArray & Server;
|
||||||
static const QByteArray & Date;
|
static const QByteArray & Date;
|
||||||
static const QByteArray & Host;
|
static const QByteArray & Host;
|
||||||
static const QByteArray & Accept;
|
static const QByteArray & Accept;
|
||||||
static const QByteArray & ContentType;
|
static const QByteArray & ContentType;
|
||||||
static const QByteArray & ContentLength;
|
static const QByteArray & ContentLength;
|
||||||
static const QByteArray & Connection;
|
static const QByteArray & Connection;
|
||||||
static const QByteArray & Cookie;
|
static const QByteArray & Cookie;
|
||||||
static const QByteArray & UserAgent;
|
static const QByteArray & UserAgent;
|
||||||
static const QByteArray & AcceptCharset;
|
static const QByteArray & AcceptCharset;
|
||||||
static const QByteArray & AcceptEncoding;
|
static const QByteArray & AcceptEncoding;
|
||||||
static const QByteArray & AcceptLanguage;
|
static const QByteArray & AcceptLanguage;
|
||||||
static const QByteArray & Authorization;
|
static const QByteArray & Authorization;
|
||||||
static const QByteArray & CacheControl;
|
static const QByteArray & CacheControl;
|
||||||
static const QByteArray & ContentMD5;
|
static const QByteArray & ContentMD5;
|
||||||
static const QByteArray & ProxyAuthorization;
|
static const QByteArray & ProxyAuthorization;
|
||||||
static const QByteArray & Range;
|
static const QByteArray & Range;
|
||||||
static const QByteArray & ContentEncoding;
|
static const QByteArray & ContentEncoding;
|
||||||
static const QByteArray & ContentLanguage;
|
static const QByteArray & ContentLanguage;
|
||||||
static const QByteArray & ContentLocation;
|
static const QByteArray & ContentLocation;
|
||||||
static const QByteArray & ContentRange;
|
static const QByteArray & ContentRange;
|
||||||
static const QByteArray & Expires;
|
static const QByteArray & Expires;
|
||||||
static const QByteArray & LastModified;
|
static const QByteArray & LastModified;
|
||||||
static const QByteArray & Location;
|
static const QByteArray & Location;
|
||||||
static const QByteArray & SetCookie;
|
static const QByteArray & SetCookie;
|
||||||
static const QByteArray & TransferEncoding;
|
static const QByteArray & TransferEncoding;
|
||||||
static const QByteArray & ContentDisposition;
|
static const QByteArray & ContentDisposition;
|
||||||
static const QByteArray & AccessControlAllow;
|
static const QByteArray & AccessControlAllow;
|
||||||
// Websocket specific headers
|
// Websocket specific headers
|
||||||
static const QByteArray & Upgrade;
|
static const QByteArray & Upgrade;
|
||||||
|
@ -6,70 +6,35 @@
|
|||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
QtHttpReply::QtHttpReply (QtHttpServer * parent)
|
QtHttpReply::QtHttpReply (QtHttpServer * parent)
|
||||||
: QObject (parent)
|
: QObject (parent)
|
||||||
, m_useChunked (false)
|
, m_useChunked (false)
|
||||||
, m_statusCode (Ok)
|
, m_statusCode (Ok)
|
||||||
, m_data (QByteArray ())
|
, m_data (QByteArray ())
|
||||||
, m_serverHandle (parent)
|
, m_serverHandle (parent)
|
||||||
{
|
{
|
||||||
// set some additional headers
|
// set some additional headers
|
||||||
addHeader (QtHttpHeader::Date, QDateTime::currentDateTimeUtc ().toString ("ddd, dd MMM yyyy hh:mm:ss t").toUtf8 ());
|
addHeader (QtHttpHeader::Date, QDateTime::currentDateTimeUtc ().toString ("ddd, dd MMM yyyy hh:mm:ss t").toUtf8 ());
|
||||||
addHeader (QtHttpHeader::Server, m_serverHandle->getServerName ().toUtf8 ());
|
addHeader (QtHttpHeader::Server, m_serverHandle->getServerName ().toUtf8 ());
|
||||||
}
|
}
|
||||||
|
|
||||||
int QtHttpReply::getRawDataSize (void) const {
|
const QByteArray QtHttpReply::getStatusTextForCode (QtHttpReply::StatusCode statusCode)
|
||||||
return m_data.size ();
|
{
|
||||||
|
switch (statusCode)
|
||||||
|
{
|
||||||
|
case Ok: return QByteArrayLiteral ("OK.");
|
||||||
|
case BadRequest: return QByteArrayLiteral ("Bad request !");
|
||||||
|
case Forbidden: return QByteArrayLiteral ("Forbidden !");
|
||||||
|
case NotFound: return QByteArrayLiteral ("Not found !");
|
||||||
|
default: return QByteArrayLiteral ("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QtHttpReply::useChunked (void) const {
|
void QtHttpReply::addHeader (const QByteArray & header, const QByteArray & value)
|
||||||
return m_useChunked;
|
{
|
||||||
}
|
QByteArray key = header.trimmed ();
|
||||||
|
|
||||||
QtHttpReply::StatusCode QtHttpReply::getStatusCode (void) const {
|
if (!key.isEmpty ())
|
||||||
return m_statusCode;
|
{
|
||||||
}
|
m_headersHash.insert (key, value);
|
||||||
|
}
|
||||||
QByteArray QtHttpReply::getRawData (void) const {
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QByteArray> QtHttpReply::getHeadersList (void) const {
|
|
||||||
return m_headersHash.keys ();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray QtHttpReply::getHeader (const QByteArray & header) const {
|
|
||||||
return m_headersHash.value (header, QByteArray ());
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArray QtHttpReply::getStatusTextForCode (QtHttpReply::StatusCode statusCode) {
|
|
||||||
switch (statusCode) {
|
|
||||||
case Ok: return QByteArrayLiteral ("OK.");
|
|
||||||
case BadRequest: return QByteArrayLiteral ("Bad request !");
|
|
||||||
case Forbidden: return QByteArrayLiteral ("Forbidden !");
|
|
||||||
case NotFound: return QByteArrayLiteral ("Not found !");
|
|
||||||
default: return QByteArrayLiteral ("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpReply::setUseChunked (bool chunked){
|
|
||||||
m_useChunked = chunked;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpReply::setStatusCode (QtHttpReply::StatusCode statusCode) {
|
|
||||||
m_statusCode = statusCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpReply::appendRawData (const QByteArray & data) {
|
|
||||||
m_data.append (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpReply::addHeader (const QByteArray & header, const QByteArray & value) {
|
|
||||||
QByteArray key = header.trimmed ();
|
|
||||||
if (!key.isEmpty ()) {
|
|
||||||
m_headersHash.insert (key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpReply::resetRawData (void) {
|
|
||||||
m_data.clear ();
|
|
||||||
}
|
}
|
||||||
|
@ -8,53 +8,58 @@
|
|||||||
|
|
||||||
class QtHttpServer;
|
class QtHttpServer;
|
||||||
|
|
||||||
class QtHttpReply : public QObject {
|
class QtHttpReply : public QObject
|
||||||
Q_OBJECT
|
{
|
||||||
Q_ENUMS (StatusCode)
|
Q_OBJECT
|
||||||
|
Q_ENUMS (StatusCode)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QtHttpReply (QtHttpServer * parent);
|
explicit QtHttpReply (QtHttpServer * parent);
|
||||||
|
|
||||||
enum StatusCode {
|
enum StatusCode
|
||||||
Ok = 200,
|
{
|
||||||
SeeOther = 303,
|
Ok = 200,
|
||||||
BadRequest = 400,
|
SeeOther = 303,
|
||||||
Forbidden = 403,
|
BadRequest = 400,
|
||||||
NotFound = 404,
|
Forbidden = 403,
|
||||||
MethodNotAllowed = 405,
|
NotFound = 404,
|
||||||
InternalError = 500,
|
MethodNotAllowed = 405,
|
||||||
NotImplemented = 501,
|
InternalError = 500,
|
||||||
BadGateway = 502,
|
NotImplemented = 501,
|
||||||
ServiceUnavailable = 503,
|
BadGateway = 502,
|
||||||
};
|
ServiceUnavailable = 503,
|
||||||
|
};
|
||||||
|
|
||||||
int getRawDataSize (void) const;
|
int getRawDataSize (void) const { return m_data.size(); };
|
||||||
bool useChunked (void) const;
|
bool useChunked (void) const { return m_useChunked; };
|
||||||
StatusCode getStatusCode (void) const;
|
StatusCode getStatusCode (void) const { return m_statusCode; };
|
||||||
QByteArray getRawData (void) const;
|
QByteArray getRawData (void) const { return m_data; };
|
||||||
QList<QByteArray> getHeadersList (void) const;
|
QList<QByteArray> getHeadersList (void) const { return m_headersHash.keys (); };
|
||||||
|
|
||||||
QByteArray getHeader (const QByteArray & header) const;
|
QByteArray getHeader (const QByteArray & header) const
|
||||||
|
{
|
||||||
|
return m_headersHash.value (header, QByteArray ());
|
||||||
|
};
|
||||||
|
|
||||||
static const QByteArray getStatusTextForCode (StatusCode statusCode);
|
static const QByteArray getStatusTextForCode (StatusCode statusCode);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setUseChunked (bool chunked = false);
|
void setUseChunked (bool chunked = false) { m_useChunked = chunked; };
|
||||||
void setStatusCode (StatusCode statusCode);
|
void setStatusCode (StatusCode statusCode) { m_statusCode = statusCode; };
|
||||||
void appendRawData (const QByteArray & data);
|
void appendRawData (const QByteArray & data) { m_data.append(data); };
|
||||||
void addHeader (const QByteArray & header, const QByteArray & value);
|
void addHeader (const QByteArray & header, const QByteArray & value);
|
||||||
void resetRawData (void);
|
void resetRawData (void) { m_data.clear (); };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void requestSendHeaders (void);
|
void requestSendHeaders (void);
|
||||||
void requestSendData (void);
|
void requestSendData (void);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_useChunked;
|
bool m_useChunked;
|
||||||
StatusCode m_statusCode;
|
StatusCode m_statusCode;
|
||||||
QByteArray m_data;
|
QByteArray m_data;
|
||||||
QtHttpServer * m_serverHandle;
|
QtHttpServer * m_serverHandle;
|
||||||
QHash<QByteArray, QByteArray> m_headersHash;
|
QHash<QByteArray, QByteArray> m_headersHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QTHTTPREPLY_H
|
#endif // QTHTTPREPLY_H
|
||||||
|
@ -4,80 +4,31 @@
|
|||||||
#include "QtHttpServer.h"
|
#include "QtHttpServer.h"
|
||||||
|
|
||||||
QtHttpRequest::QtHttpRequest (QtHttpClientWrapper * client, QtHttpServer * parent)
|
QtHttpRequest::QtHttpRequest (QtHttpClientWrapper * client, QtHttpServer * parent)
|
||||||
: QObject (parent)
|
: QObject (parent)
|
||||||
, m_url (QUrl ())
|
, m_url (QUrl ())
|
||||||
, m_command (QString ())
|
, m_command (QString ())
|
||||||
, m_data (QByteArray ())
|
, m_data (QByteArray ())
|
||||||
, m_serverHandle (parent)
|
, m_serverHandle (parent)
|
||||||
, m_clientHandle (client)
|
, m_clientHandle (client)
|
||||||
, m_postData (QtHttpPostData())
|
, m_postData (QtHttpPostData())
|
||||||
{
|
{
|
||||||
// set some additional headers
|
// set some additional headers
|
||||||
addHeader (QtHttpHeader::ContentLength, QByteArrayLiteral ("0"));
|
addHeader (QtHttpHeader::ContentLength, QByteArrayLiteral ("0"));
|
||||||
addHeader (QtHttpHeader::Connection, QByteArrayLiteral ("Keep-Alive"));
|
addHeader (QtHttpHeader::Connection, QByteArrayLiteral ("Keep-Alive"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QUrl QtHttpRequest::getUrl (void) const {
|
void QtHttpRequest::setClientInfo (const QHostAddress & server, const QHostAddress & client)
|
||||||
return m_url;
|
{
|
||||||
|
m_clientInfo.serverAddress = server;
|
||||||
|
m_clientInfo.clientAddress = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString QtHttpRequest::getCommand (void) const {
|
void QtHttpRequest::addHeader (const QByteArray & header, const QByteArray & value)
|
||||||
return m_command;
|
{
|
||||||
}
|
QByteArray key = header.trimmed ();
|
||||||
|
|
||||||
QtHttpRequest::ClientInfo QtHttpRequest::getClientInfo (void) const {
|
if (!key.isEmpty ())
|
||||||
return m_clientInfo;
|
{
|
||||||
}
|
m_headersHash.insert (key, value);
|
||||||
|
}
|
||||||
int QtHttpRequest::getRawDataSize (void) const {
|
|
||||||
return m_data.size ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QByteArray QtHttpRequest::getRawData (void) const {
|
|
||||||
return m_data;
|
|
||||||
}
|
|
||||||
|
|
||||||
QtHttpPostData QtHttpRequest::getPostData (void) const {
|
|
||||||
return m_postData;
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QByteArray> QtHttpRequest::getHeadersList (void) const {
|
|
||||||
return m_headersHash.keys ();
|
|
||||||
}
|
|
||||||
|
|
||||||
QtHttpClientWrapper * QtHttpRequest::getClient (void) const {
|
|
||||||
return m_clientHandle;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray QtHttpRequest::getHeader (const QByteArray & header) const {
|
|
||||||
return m_headersHash.value (header, QByteArray ());
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpRequest::setUrl (const QUrl & url) {
|
|
||||||
m_url = url;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpRequest::setCommand (const QString & command) {
|
|
||||||
m_command = command;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpRequest::setClientInfo (const QHostAddress & server, const QHostAddress & client) {
|
|
||||||
m_clientInfo.serverAddress = server;
|
|
||||||
m_clientInfo.clientAddress = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpRequest::addHeader (const QByteArray & header, const QByteArray & value) {
|
|
||||||
QByteArray key = header.trimmed ();
|
|
||||||
if (!key.isEmpty ()) {
|
|
||||||
m_headersHash.insert (key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpRequest::appendRawData (const QByteArray & data) {
|
|
||||||
m_data.append (data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpRequest::setPostData (const QtHttpPostData & data) {
|
|
||||||
m_postData = data;
|
|
||||||
}
|
}
|
||||||
|
@ -14,45 +14,50 @@ class QtHttpClientWrapper;
|
|||||||
|
|
||||||
using QtHttpPostData = QMap<QString,QByteArray>;
|
using QtHttpPostData = QMap<QString,QByteArray>;
|
||||||
|
|
||||||
class QtHttpRequest : public QObject {
|
class QtHttpRequest : public QObject
|
||||||
Q_OBJECT
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QtHttpRequest (QtHttpClientWrapper * client, QtHttpServer * parent);
|
explicit QtHttpRequest (QtHttpClientWrapper * client, QtHttpServer * parent);
|
||||||
|
|
||||||
struct ClientInfo {
|
struct ClientInfo
|
||||||
QHostAddress serverAddress;
|
{
|
||||||
QHostAddress clientAddress;
|
QHostAddress serverAddress;
|
||||||
};
|
QHostAddress clientAddress;
|
||||||
|
};
|
||||||
|
|
||||||
int getRawDataSize (void) const;
|
int getRawDataSize (void) const { return m_data.size (); };
|
||||||
QUrl getUrl (void) const;
|
QUrl getUrl (void) const { return m_url; };
|
||||||
QString getCommand (void) const;
|
QString getCommand (void) const { return m_command; };
|
||||||
QByteArray getRawData (void) const;
|
QByteArray getRawData (void) const { return m_data; };
|
||||||
QList<QByteArray> getHeadersList (void) const;
|
QList<QByteArray> getHeadersList (void) const { return m_headersHash.keys (); };
|
||||||
QtHttpClientWrapper * getClient (void) const;
|
QtHttpClientWrapper * getClient (void) const { return m_clientHandle; };
|
||||||
|
QtHttpPostData getPostData (void) const { return m_postData; };
|
||||||
|
ClientInfo getClientInfo (void) const { return m_clientInfo; };
|
||||||
|
|
||||||
QByteArray getHeader (const QByteArray & header) const;
|
QByteArray getHeader (const QByteArray & header) const
|
||||||
QtHttpPostData getPostData (void) const;
|
{
|
||||||
|
return m_headersHash.value (header, QByteArray ());
|
||||||
ClientInfo getClientInfo (void) const;
|
};
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setUrl (const QUrl & url);
|
void setUrl (const QUrl & url) { m_url = url; };
|
||||||
void setCommand (const QString & command);
|
void setCommand (const QString & command) { m_command = command; };
|
||||||
void setClientInfo (const QHostAddress & server, const QHostAddress & client);
|
void appendRawData (const QByteArray & data) { m_data.append (data); };
|
||||||
void addHeader (const QByteArray & header, const QByteArray & value);
|
void setPostData (const QtHttpPostData & data) { m_postData = data; };
|
||||||
void appendRawData (const QByteArray & data);
|
|
||||||
void setPostData (const QtHttpPostData & data);
|
void setClientInfo (const QHostAddress & server, const QHostAddress & client);
|
||||||
|
void addHeader (const QByteArray & header, const QByteArray & value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QUrl m_url;
|
QUrl m_url;
|
||||||
QString m_command;
|
QString m_command;
|
||||||
QByteArray m_data;
|
QByteArray m_data;
|
||||||
QtHttpServer * m_serverHandle;
|
QtHttpServer * m_serverHandle;
|
||||||
QtHttpClientWrapper * m_clientHandle;
|
QtHttpClientWrapper * m_clientHandle;
|
||||||
QHash<QByteArray, QByteArray> m_headersHash;
|
QHash<QByteArray, QByteArray> m_headersHash;
|
||||||
ClientInfo m_clientInfo;
|
ClientInfo m_clientInfo;
|
||||||
QtHttpPostData m_postData;
|
QtHttpPostData m_postData;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -11,142 +11,116 @@
|
|||||||
const QString & QtHttpServer::HTTP_VERSION = QStringLiteral ("HTTP/1.1");
|
const QString & QtHttpServer::HTTP_VERSION = QStringLiteral ("HTTP/1.1");
|
||||||
|
|
||||||
QtHttpServerWrapper::QtHttpServerWrapper (QObject * parent)
|
QtHttpServerWrapper::QtHttpServerWrapper (QObject * parent)
|
||||||
: QTcpServer (parent)
|
: QTcpServer (parent)
|
||||||
, m_useSsl (false)
|
, m_useSsl (false)
|
||||||
{ }
|
{
|
||||||
|
|
||||||
QtHttpServerWrapper::~QtHttpServerWrapper (void) { }
|
|
||||||
|
|
||||||
void QtHttpServerWrapper::setUseSecure (const bool ssl) {
|
|
||||||
m_useSsl = ssl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpServerWrapper::incomingConnection (qintptr handle) {
|
QtHttpServerWrapper::~QtHttpServerWrapper (void)
|
||||||
QTcpSocket * sock = (m_useSsl
|
{
|
||||||
? new QSslSocket (this)
|
|
||||||
: new QTcpSocket (this));
|
}
|
||||||
if (sock->setSocketDescriptor (handle)) {
|
|
||||||
addPendingConnection (sock);
|
void QtHttpServerWrapper::setUseSecure (const bool ssl)
|
||||||
}
|
{
|
||||||
else {
|
m_useSsl = ssl;
|
||||||
delete sock;
|
}
|
||||||
}
|
|
||||||
|
void QtHttpServerWrapper::incomingConnection (qintptr handle)
|
||||||
|
{
|
||||||
|
QTcpSocket * sock = (m_useSsl ? new QSslSocket (this) : new QTcpSocket (this));
|
||||||
|
sock->setSocketDescriptor(handle) ? addPendingConnection (sock) : delete sock;
|
||||||
}
|
}
|
||||||
|
|
||||||
QtHttpServer::QtHttpServer (QObject * parent)
|
QtHttpServer::QtHttpServer (QObject * parent)
|
||||||
: QObject (parent)
|
: QObject (parent)
|
||||||
, m_useSsl (false)
|
, m_useSsl (false)
|
||||||
, m_serverName (QStringLiteral ("The Qt5 HTTP Server"))
|
, m_serverName (QStringLiteral ("The Qt5 HTTP Server"))
|
||||||
, m_netOrigin (NetOrigin::getInstance())
|
, m_netOrigin (NetOrigin::getInstance())
|
||||||
{
|
{
|
||||||
m_sockServer = new QtHttpServerWrapper (this);
|
m_sockServer = new QtHttpServerWrapper (this);
|
||||||
connect (m_sockServer, &QtHttpServerWrapper::newConnection, this, &QtHttpServer::onClientConnected);
|
connect (m_sockServer, &QtHttpServerWrapper::newConnection, this, &QtHttpServer::onClientConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
const QString & QtHttpServer::getServerName (void) const {
|
void QtHttpServer::start (quint16 port)
|
||||||
return m_serverName;
|
{
|
||||||
}
|
|
||||||
|
|
||||||
quint16 QtHttpServer::getServerPort (void) const {
|
|
||||||
return m_sockServer->serverPort ();
|
|
||||||
}
|
|
||||||
|
|
||||||
QString QtHttpServer::getErrorString (void) const {
|
|
||||||
return m_sockServer->errorString ();
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpServer::start (quint16 port) {
|
|
||||||
if(!m_sockServer->isListening())
|
if(!m_sockServer->isListening())
|
||||||
{
|
{
|
||||||
if (m_sockServer->listen (QHostAddress::Any, port)) {
|
m_sockServer->listen (QHostAddress::Any, port)
|
||||||
emit started (m_sockServer->serverPort ());
|
? emit started (m_sockServer->serverPort ())
|
||||||
}
|
: emit error (m_sockServer->errorString ());
|
||||||
else {
|
|
||||||
emit error (m_sockServer->errorString ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpServer::stop (void) {
|
void QtHttpServer::stop (void)
|
||||||
if (m_sockServer->isListening ()) {
|
{
|
||||||
m_sockServer->close ();
|
if (m_sockServer->isListening ())
|
||||||
|
{
|
||||||
|
m_sockServer->close ();
|
||||||
// disconnect clients
|
// disconnect clients
|
||||||
const QList<QTcpSocket*> socks = m_socksClientsHash.keys();
|
const QList<QTcpSocket*> socks = m_socksClientsHash.keys();
|
||||||
for(auto sock : socks)
|
for(auto sock : socks)
|
||||||
{
|
{
|
||||||
sock->close();
|
sock->close();
|
||||||
}
|
}
|
||||||
emit stopped ();
|
|
||||||
}
|
emit stopped ();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpServer::setServerName (const QString & serverName) {
|
void QtHttpServer::setUseSecure (const bool ssl)
|
||||||
m_serverName = serverName;
|
{
|
||||||
|
m_useSsl = ssl;
|
||||||
|
m_sockServer->setUseSecure (m_useSsl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpServer::setUseSecure (const bool ssl) {
|
void QtHttpServer::onClientConnected (void)
|
||||||
m_useSsl = ssl;
|
{
|
||||||
m_sockServer->setUseSecure (m_useSsl);
|
while (m_sockServer->hasPendingConnections ())
|
||||||
}
|
{
|
||||||
|
if (QTcpSocket * sock = m_sockServer->nextPendingConnection ())
|
||||||
void QtHttpServer::setPrivateKey (const QSslKey & key) {
|
{
|
||||||
m_sslKey = key;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpServer::setCertificates (const QList<QSslCertificate> & certs) {
|
|
||||||
m_sslCerts = certs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpServer::onClientConnected (void) {
|
|
||||||
while (m_sockServer->hasPendingConnections ()) {
|
|
||||||
if (QTcpSocket * sock = m_sockServer->nextPendingConnection ()) {
|
|
||||||
if(m_netOrigin->accessAllowed(sock->peerAddress(), sock->localAddress()))
|
if(m_netOrigin->accessAllowed(sock->peerAddress(), sock->localAddress()))
|
||||||
{
|
{
|
||||||
connect (sock, &QTcpSocket::disconnected, this, &QtHttpServer::onClientDisconnected);
|
connect (sock, &QTcpSocket::disconnected, this, &QtHttpServer::onClientDisconnected);
|
||||||
if (m_useSsl) {
|
|
||||||
if (QSslSocket * ssl = qobject_cast<QSslSocket *> (sock)) {
|
if (m_useSsl)
|
||||||
connect (ssl, SslErrorSignal (&QSslSocket::sslErrors), this, &QtHttpServer::onClientSslErrors);
|
{
|
||||||
connect (ssl, &QSslSocket::encrypted, this, &QtHttpServer::onClientSslEncrypted);
|
if (QSslSocket * ssl = qobject_cast<QSslSocket *> (sock))
|
||||||
connect (ssl, &QSslSocket::peerVerifyError, this, &QtHttpServer::onClientSslPeerVerifyError);
|
{
|
||||||
connect (ssl, &QSslSocket::modeChanged, this, &QtHttpServer::onClientSslModeChanged);
|
connect (ssl, SslErrorSignal (&QSslSocket::sslErrors), this, &QtHttpServer::onClientSslErrors);
|
||||||
ssl->setLocalCertificateChain (m_sslCerts);
|
connect (ssl, &QSslSocket::encrypted, this, &QtHttpServer::onClientSslEncrypted);
|
||||||
ssl->setPrivateKey (m_sslKey);
|
connect (ssl, &QSslSocket::peerVerifyError, this, &QtHttpServer::onClientSslPeerVerifyError);
|
||||||
ssl->setPeerVerifyMode (QSslSocket::AutoVerifyPeer);
|
connect (ssl, &QSslSocket::modeChanged, this, &QtHttpServer::onClientSslModeChanged);
|
||||||
ssl->startServerEncryption ();
|
ssl->setLocalCertificateChain (m_sslCerts);
|
||||||
}
|
ssl->setPrivateKey (m_sslKey);
|
||||||
}
|
ssl->setPeerVerifyMode (QSslSocket::AutoVerifyPeer);
|
||||||
QtHttpClientWrapper * wrapper = new QtHttpClientWrapper (sock, m_netOrigin->isLocalAddress(sock->peerAddress(), sock->localAddress()), this);
|
ssl->startServerEncryption ();
|
||||||
m_socksClientsHash.insert (sock, wrapper);
|
}
|
||||||
emit clientConnected (wrapper->getGuid ());
|
}
|
||||||
|
|
||||||
|
QtHttpClientWrapper * wrapper = new QtHttpClientWrapper (sock, m_netOrigin->isLocalAddress(sock->peerAddress(), sock->localAddress()), this);
|
||||||
|
m_socksClientsHash.insert (sock, wrapper);
|
||||||
|
emit clientConnected (wrapper->getGuid ());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sock->close();
|
sock->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QtHttpServer::onClientSslEncrypted (void) { }
|
void QtHttpServer::onClientDisconnected (void)
|
||||||
|
{
|
||||||
void QtHttpServer::onClientSslPeerVerifyError (const QSslError & err) {
|
if (QTcpSocket * sockClient = qobject_cast<QTcpSocket *> (sender ()))
|
||||||
Q_UNUSED (err)
|
{
|
||||||
}
|
if (QtHttpClientWrapper * wrapper = m_socksClientsHash.value (sockClient, Q_NULLPTR))
|
||||||
|
{
|
||||||
void QtHttpServer::onClientSslErrors (const QList<QSslError> & errors) {
|
emit clientDisconnected (wrapper->getGuid ());
|
||||||
Q_UNUSED (errors)
|
wrapper->deleteLater ();
|
||||||
}
|
m_socksClientsHash.remove (sockClient);
|
||||||
|
}
|
||||||
void QtHttpServer::onClientSslModeChanged (QSslSocket::SslMode mode) {
|
}
|
||||||
Q_UNUSED (mode)
|
|
||||||
}
|
|
||||||
|
|
||||||
void QtHttpServer::onClientDisconnected (void) {
|
|
||||||
if (QTcpSocket * sockClient = qobject_cast<QTcpSocket *> (sender ())) {
|
|
||||||
if (QtHttpClientWrapper * wrapper = m_socksClientsHash.value (sockClient, Q_NULLPTR)) {
|
|
||||||
emit clientDisconnected (wrapper->getGuid ());
|
|
||||||
wrapper->deleteLater ();
|
|
||||||
m_socksClientsHash.remove (sockClient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -13,76 +13,77 @@
|
|||||||
|
|
||||||
class QTcpSocket;
|
class QTcpSocket;
|
||||||
class QTcpServer;
|
class QTcpServer;
|
||||||
|
|
||||||
class QtHttpRequest;
|
class QtHttpRequest;
|
||||||
class QtHttpReply;
|
class QtHttpReply;
|
||||||
class QtHttpClientWrapper;
|
class QtHttpClientWrapper;
|
||||||
class NetOrigin;
|
class NetOrigin;
|
||||||
|
|
||||||
class QtHttpServerWrapper : public QTcpServer {
|
class QtHttpServerWrapper : public QTcpServer
|
||||||
Q_OBJECT
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR);
|
explicit QtHttpServerWrapper (QObject * parent = Q_NULLPTR);
|
||||||
virtual ~QtHttpServerWrapper (void);
|
virtual ~QtHttpServerWrapper (void);
|
||||||
|
|
||||||
void setUseSecure (const bool ssl = true);
|
void setUseSecure (const bool ssl = true);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void incomingConnection (qintptr handle) Q_DECL_OVERRIDE;
|
void incomingConnection (qintptr handle) Q_DECL_OVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_useSsl;
|
bool m_useSsl;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QtHttpServer : public QObject {
|
class QtHttpServer : public QObject
|
||||||
Q_OBJECT
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QtHttpServer (QObject * parent = Q_NULLPTR);
|
explicit QtHttpServer (QObject * parent = Q_NULLPTR);
|
||||||
|
|
||||||
static const QString & HTTP_VERSION;
|
static const QString & HTTP_VERSION;
|
||||||
|
|
||||||
typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &);
|
typedef void (QSslSocket::* SslErrorSignal) (const QList<QSslError> &);
|
||||||
|
|
||||||
const QString & getServerName (void) const;
|
const QString & getServerName (void) const { return m_serverName; };
|
||||||
|
|
||||||
quint16 getServerPort (void) const;
|
quint16 getServerPort (void) const { return m_sockServer->serverPort(); };
|
||||||
QString getErrorString (void) const;
|
QString getErrorString (void) const { return m_sockServer->errorString(); };
|
||||||
bool isListening() { return m_sockServer->isListening(); };
|
bool isListening() { return m_sockServer->isListening(); };
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void start (quint16 port = 0);
|
void start (quint16 port = 0);
|
||||||
void stop (void);
|
void stop (void);
|
||||||
void setServerName (const QString & serverName);
|
void setUseSecure (const bool ssl = true);
|
||||||
void setUseSecure (const bool ssl = true);
|
void setServerName (const QString & serverName) { m_serverName = serverName; };
|
||||||
void setPrivateKey (const QSslKey & key);
|
void setPrivateKey (const QSslKey & key) { m_sslKey = key; };
|
||||||
void setCertificates (const QList<QSslCertificate> & certs);
|
void setCertificates (const QList<QSslCertificate> & certs) { m_sslCerts = certs; };
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void started (quint16 port);
|
void started (quint16 port);
|
||||||
void stopped (void);
|
void stopped (void);
|
||||||
void error (const QString & msg);
|
void error (const QString & msg);
|
||||||
void clientConnected (const QString & guid);
|
void clientConnected (const QString & guid);
|
||||||
void clientDisconnected (const QString & guid);
|
void clientDisconnected (const QString & guid);
|
||||||
void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
|
void requestNeedsReply (QtHttpRequest * request, QtHttpReply * reply);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onClientConnected (void);
|
void onClientConnected (void);
|
||||||
void onClientDisconnected (void);
|
void onClientDisconnected (void);
|
||||||
void onClientSslEncrypted (void);
|
void onClientSslEncrypted (void) { };
|
||||||
void onClientSslPeerVerifyError (const QSslError & err);
|
void onClientSslPeerVerifyError (const QSslError & err) { Q_UNUSED (err) };
|
||||||
void onClientSslErrors (const QList<QSslError> & errors);
|
void onClientSslErrors (const QList<QSslError> & errors) { Q_UNUSED (errors) };
|
||||||
void onClientSslModeChanged (QSslSocket::SslMode mode);
|
void onClientSslModeChanged (QSslSocket::SslMode mode) { Q_UNUSED (mode) };
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool m_useSsl;
|
bool m_useSsl;
|
||||||
QSslKey m_sslKey;
|
QSslKey m_sslKey;
|
||||||
QList<QSslCertificate> m_sslCerts;
|
QList<QSslCertificate> m_sslCerts;
|
||||||
QString m_serverName;
|
QString m_serverName;
|
||||||
NetOrigin* m_netOrigin;
|
NetOrigin* m_netOrigin;
|
||||||
QtHttpServerWrapper * m_sockServer;
|
QtHttpServerWrapper * m_sockServer;
|
||||||
QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash;
|
QHash<QTcpSocket *, QtHttpClientWrapper *> m_socksClientsHash;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QTHTTPSERVER_H
|
#endif // QTHTTPSERVER_H
|
||||||
|
@ -63,7 +63,8 @@ void WebServer::onServerStarted (quint16 port)
|
|||||||
emit stateChange(true);
|
emit stateChange(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebServer::onServerStopped () {
|
void WebServer::onServerStopped ()
|
||||||
|
{
|
||||||
Info(_log, "Stopped %s", _server->getServerName().toStdString().c_str());
|
Info(_log, "Stopped %s", _server->getServerName().toStdString().c_str());
|
||||||
emit stateChange(false);
|
emit stateChange(false);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, const
|
|||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
, _socket(sock)
|
, _socket(sock)
|
||||||
, _log(Logger::getInstance("WEBSOCKET"))
|
, _log(Logger::getInstance("WEBSOCKET"))
|
||||||
// , _hyperion(Hyperion::getInstance())
|
|
||||||
{
|
{
|
||||||
// connect socket; disconnect handled from QtHttpServer
|
// connect socket; disconnect handled from QtHttpServer
|
||||||
connect(_socket, &QTcpSocket::readyRead , this, &WebSocketClient::handleWebSocketFrame);
|
connect(_socket, &QTcpSocket::readyRead , this, &WebSocketClient::handleWebSocketFrame);
|
||||||
@ -45,107 +44,113 @@ WebSocketClient::WebSocketClient(QtHttpRequest* request, QTcpSocket* sock, const
|
|||||||
|
|
||||||
void WebSocketClient::handleWebSocketFrame(void)
|
void WebSocketClient::handleWebSocketFrame(void)
|
||||||
{
|
{
|
||||||
// we are on no continious reading from socket from call before
|
while (_socket->bytesAvailable())
|
||||||
if (!_notEnoughData)
|
|
||||||
{
|
{
|
||||||
getWsFrameHeader(&_wsh);
|
// we are on no continious reading from socket from call before
|
||||||
}
|
if (!_notEnoughData)
|
||||||
|
|
||||||
if(_socket->bytesAvailable() < (qint64)_wsh.payloadLength)
|
|
||||||
{
|
|
||||||
//printf("not enough data %llu %llu\n", _socket->bytesAvailable(), _wsh.payloadLength);
|
|
||||||
_notEnoughData=true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_notEnoughData = false;
|
|
||||||
|
|
||||||
QByteArray buf = _socket->read(_wsh.payloadLength);
|
|
||||||
//printf("opcode %x payload bytes %llu avail: %llu\n", _wsh.opCode, _wsh.payloadLength, _socket->bytesAvailable());
|
|
||||||
|
|
||||||
if (OPCODE::invalid((OPCODE::value)_wsh.opCode))
|
|
||||||
{
|
|
||||||
sendClose(CLOSECODE::INV_TYPE, "invalid opcode");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check the type of data frame
|
|
||||||
bool isContinuation=false;
|
|
||||||
switch (_wsh.opCode)
|
|
||||||
{
|
|
||||||
case OPCODE::CONTINUATION:
|
|
||||||
isContinuation = true;
|
|
||||||
// no break here, just jump over to opcode text
|
|
||||||
|
|
||||||
case OPCODE::BINARY:
|
|
||||||
case OPCODE::TEXT:
|
|
||||||
{
|
{
|
||||||
// check for protocal violations
|
getWsFrameHeader(&_wsh);
|
||||||
if (_onContinuation && !isContinuation)
|
}
|
||||||
{
|
|
||||||
sendClose(CLOSECODE::VIOLATION, "protocol violation, somebody sends frames in between continued frames");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_wsh.masked && _wsh.opCode == OPCODE::TEXT)
|
if(_socket->bytesAvailable() < (qint64)_wsh.payloadLength)
|
||||||
{
|
{
|
||||||
sendClose(CLOSECODE::VIOLATION, "protocol violation, unmasked text frames not allowed");
|
//printf("not enough data %llu %llu\n", _socket->bytesAvailable(), _wsh.payloadLength);
|
||||||
return;
|
_notEnoughData=true;
|
||||||
}
|
return;
|
||||||
|
}
|
||||||
|
_notEnoughData = false;
|
||||||
|
|
||||||
// unmask data
|
QByteArray buf = _socket->read(_wsh.payloadLength);
|
||||||
for (int i=0; i < buf.size(); i++)
|
//printf("opcode %x payload bytes %llu avail: %llu\n", _wsh.opCode, _wsh.payloadLength, _socket->bytesAvailable());
|
||||||
{
|
|
||||||
buf[i] = buf[i] ^ _wsh.key[i % 4];
|
|
||||||
}
|
|
||||||
|
|
||||||
_onContinuation = !_wsh.fin || isContinuation;
|
if (OPCODE::invalid((OPCODE::value)_wsh.opCode))
|
||||||
|
{
|
||||||
|
sendClose(CLOSECODE::INV_TYPE, "invalid opcode");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// frame contains text, extract it, append data if this is a continuation
|
// check the type of data frame
|
||||||
if (_wsh.fin && ! isContinuation) // one frame
|
bool isContinuation=false;
|
||||||
{
|
|
||||||
_wsReceiveBuffer.clear();
|
|
||||||
}
|
|
||||||
_wsReceiveBuffer.append(buf);
|
|
||||||
|
|
||||||
// this is the final frame, decode and handle data
|
switch (_wsh.opCode)
|
||||||
if (_wsh.fin)
|
{
|
||||||
|
case OPCODE::CONTINUATION:
|
||||||
|
isContinuation = true;
|
||||||
|
// no break here, just jump over to opcode text
|
||||||
|
|
||||||
|
case OPCODE::BINARY:
|
||||||
|
case OPCODE::TEXT:
|
||||||
{
|
{
|
||||||
_onContinuation = false;
|
// check for protocol violations
|
||||||
|
if (_onContinuation && !isContinuation)
|
||||||
|
{
|
||||||
|
sendClose(CLOSECODE::VIOLATION, "protocol violation, somebody sends frames in between continued frames");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_wsh.masked && _wsh.opCode == OPCODE::TEXT)
|
||||||
|
{
|
||||||
|
sendClose(CLOSECODE::VIOLATION, "protocol violation, unmasked text frames not allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// unmask data
|
||||||
|
for (int i=0; i < buf.size(); i++)
|
||||||
|
{
|
||||||
|
buf[i] = buf[i] ^ _wsh.key[i % 4];
|
||||||
|
}
|
||||||
|
|
||||||
|
_onContinuation = !_wsh.fin || isContinuation;
|
||||||
|
|
||||||
|
// frame contains text, extract it, append data if this is a continuation
|
||||||
|
if (_wsh.fin && ! isContinuation) // one frame
|
||||||
|
{
|
||||||
|
_wsReceiveBuffer.clear();
|
||||||
|
}
|
||||||
|
_wsReceiveBuffer.append(buf);
|
||||||
|
|
||||||
|
// this is the final frame, decode and handle data
|
||||||
|
if (_wsh.fin)
|
||||||
|
{
|
||||||
|
_onContinuation = false;
|
||||||
if (_wsh.opCode == OPCODE::TEXT)
|
if (_wsh.opCode == OPCODE::TEXT)
|
||||||
{
|
{
|
||||||
_jsonAPI->handleMessage(QString(_wsReceiveBuffer));
|
|
||||||
|
_jsonAPI->handleMessage(QString(_wsReceiveBuffer));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
handleBinaryMessage(_wsReceiveBuffer);
|
handleBinaryMessage(_wsReceiveBuffer);
|
||||||
}
|
}
|
||||||
_wsReceiveBuffer.clear();
|
_wsReceiveBuffer.clear();
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE::CLOSE:
|
||||||
|
{
|
||||||
|
sendClose(CLOSECODE::NORMAL);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE::PING:
|
||||||
|
{
|
||||||
|
// ping received, send pong
|
||||||
|
quint8 pong[] = {OPCODE::PONG, 0};
|
||||||
|
_socket->write((const char*)pong, 2);
|
||||||
|
_socket->flush();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPCODE::PONG:
|
||||||
|
{
|
||||||
|
Error(_log, "pong received, protocol violation!");
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
Warning(_log, "strange %d\n%s\n", _wsh.opCode, QSTRING_CSTR(QString(buf)));
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE::CLOSE:
|
|
||||||
{
|
|
||||||
sendClose(CLOSECODE::NORMAL);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE::PING:
|
|
||||||
{
|
|
||||||
// ping received, send pong
|
|
||||||
quint8 pong[] = {OPCODE::PONG, 0};
|
|
||||||
_socket->write((const char*)pong, 2);
|
|
||||||
_socket->flush();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OPCODE::PONG:
|
|
||||||
{
|
|
||||||
Error(_log, "pong received, protocol violation!");
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
Warning(_log, "strange %d\n%s\n", _wsh.opCode, QSTRING_CSTR(QString(buf)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,6 +226,7 @@ void WebSocketClient::sendClose(int status, QString reason)
|
|||||||
_socket->close();
|
_socket->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WebSocketClient::handleBinaryMessage(QByteArray &data)
|
void WebSocketClient::handleBinaryMessage(QByteArray &data)
|
||||||
{
|
{
|
||||||
//uint8_t priority = data.at(0);
|
//uint8_t priority = data.at(0);
|
||||||
@ -243,6 +249,7 @@ void WebSocketClient::handleBinaryMessage(QByteArray &data)
|
|||||||
//_hyperion->setInputImage(priority, image, duration_s*1000);
|
//_hyperion->setInputImage(priority, image, duration_s*1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
qint64 WebSocketClient::sendMessage(QJsonObject obj)
|
qint64 WebSocketClient::sendMessage(QJsonObject obj)
|
||||||
{
|
{
|
||||||
QJsonDocument writer(obj);
|
QJsonDocument writer(obj);
|
||||||
|
@ -17,7 +17,7 @@ public:
|
|||||||
struct WebSocketHeader
|
struct WebSocketHeader
|
||||||
{
|
{
|
||||||
bool fin;
|
bool fin;
|
||||||
quint8 opCode;
|
quint8 opCode;
|
||||||
bool masked;
|
bool masked;
|
||||||
quint64 payloadLength;
|
quint64 payloadLength;
|
||||||
char key[4];
|
char key[4];
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
/**
|
/**
|
||||||
* WebSocket Opcodes are 4 bits. See RFC6455 section 5.2.
|
* WebSocket Opcodes are 4 bits. See RFC6455 section 5.2.
|
||||||
*/
|
*/
|
||||||
namespace OPCODE {
|
namespace OPCODE
|
||||||
enum value {
|
{
|
||||||
|
enum value
|
||||||
|
{
|
||||||
CONTINUATION = 0x0,
|
CONTINUATION = 0x0,
|
||||||
TEXT = 0x1,
|
TEXT = 0x1,
|
||||||
BINARY = 0x2,
|
BINARY = 0x2,
|
||||||
@ -29,7 +31,8 @@ namespace OPCODE {
|
|||||||
* @param v The opcode to test.
|
* @param v The opcode to test.
|
||||||
* @return Whether or not the opcode is reserved.
|
* @return Whether or not the opcode is reserved.
|
||||||
*/
|
*/
|
||||||
inline bool reserved(value v) {
|
inline bool reserved(value v)
|
||||||
|
{
|
||||||
return (v >= RSV3 && v <= RSV7) || (v >= CONTROL_RSVB && v <= CONTROL_RSVF);
|
return (v >= RSV3 && v <= RSV7) || (v >= CONTROL_RSVB && v <= CONTROL_RSVF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +43,8 @@ namespace OPCODE {
|
|||||||
* @param v The opcode to test.
|
* @param v The opcode to test.
|
||||||
* @return Whether or not the opcode is invalid.
|
* @return Whether or not the opcode is invalid.
|
||||||
*/
|
*/
|
||||||
inline bool invalid(value v) {
|
inline bool invalid(value v)
|
||||||
|
{
|
||||||
return (v > 0xF || v < 0);
|
return (v > 0xF || v < 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -49,13 +53,16 @@ namespace OPCODE {
|
|||||||
* @param v The opcode to test.
|
* @param v The opcode to test.
|
||||||
* @return Whether or not the opcode is a control opcode.
|
* @return Whether or not the opcode is a control opcode.
|
||||||
*/
|
*/
|
||||||
inline bool is_control(value v) {
|
inline bool is_control(value v)
|
||||||
|
{
|
||||||
return v >= 0x8;
|
return v >= 0x8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace CLOSECODE {
|
namespace CLOSECODE
|
||||||
enum value {
|
{
|
||||||
|
enum value
|
||||||
|
{
|
||||||
NORMAL = 1000,
|
NORMAL = 1000,
|
||||||
AWAY = 1001,
|
AWAY = 1001,
|
||||||
TERM = 1002,
|
TERM = 1002,
|
||||||
|
Loading…
Reference in New Issue
Block a user