fixed namespace and added documentation for servers

This commit is contained in:
Simon Stürz 2015-08-05 00:43:35 +02:00 committed by Michael Zanetti
parent b67de54325
commit b35f5f69bf
19 changed files with 303 additions and 62 deletions

View File

@ -7,6 +7,7 @@ SUBDIRS += libguh server plugins
!disabletesting { !disabletesting {
message("Building guh tests enabled") message("Building guh tests enabled")
SUBDIRS += tests SUBDIRS += tests
DEFINES += TESTING_ENABLED
} else { } else {
message("Building guh tests disabled") message("Building guh tests disabled")
} }

View File

@ -96,6 +96,7 @@ public:
LogEngine* logEngine() const; LogEngine* logEngine() const;
JsonRPCServer *jsonRPCServer() const; JsonRPCServer *jsonRPCServer() const;
RestServer *restServer() const; RestServer *restServer() const;
DeviceManager *deviceManager() const;
signals: signals:
void eventTriggered(const Event &event); void eventTriggered(const Event &event);
@ -118,7 +119,6 @@ signals:
private: private:
RuleEngine *ruleEngine() const; RuleEngine *ruleEngine() const;
DeviceManager *deviceManager() const;
explicit GuhCore(QObject *parent = 0); explicit GuhCore(QObject *parent = 0);
static GuhCore *s_instance; static GuhCore *s_instance;

View File

@ -18,12 +18,27 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::GuhService
\brief The daemon service reprenetation of the guh server.
\ingroup core
\inmodule server
The \l{GuhService} represents the forked guhd.
\sa QtService
*/
#include <unistd.h> #include <unistd.h>
#include "guhservice.h" #include "guhservice.h"
#include "loggingcategories.h" #include "loggingcategories.h"
namespace guhserver { namespace guhserver {
/*! Constructs the forked guhd application with the given argument count \a argc and argument vector \a argv. */
GuhService::GuhService(int argc, char **argv): GuhService::GuhService(int argc, char **argv):
QtService<QCoreApplication>(argc, argv, "guh daemon") QtService<QCoreApplication>(argc, argv, "guh daemon")
{ {
@ -38,10 +53,12 @@ GuhService::GuhService(int argc, char **argv):
setServiceFlags(QtServiceBase::CanBeSuspended); setServiceFlags(QtServiceBase::CanBeSuspended);
} }
/*! Destroyes the forked guhd application. */
GuhService::~GuhService() GuhService::~GuhService()
{ {
} }
/*! Starts the forked guhd application. */
void GuhService::start() void GuhService::start()
{ {
GuhCore::instance()->setRunningMode(GuhCore::RunningModeService); GuhCore::instance()->setRunningMode(GuhCore::RunningModeService);

View File

@ -19,17 +19,16 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*! /*!
\class guhserver::HttpReply \class guhserver::HttpReply
\brief Represents a reply of the guh webserver. \brief Represents a reply of the guh webserver to a \l{HttpRequest}.
\ingroup core \ingroup core
\inmodule server \inmodule server
This class holds the header and the payload data of a network reply and represents a response This class holds the header and the payload data of a network reply and represents a response
from the guh webserver. from the guh webserver to a \l{HttpRequest}.
\note RFC 7231 HTTP/1.1 Semantics and Content -> \l{http://tools.ietf.org/html/rfc7231}{http://tools.ietf.org/html/rfc7231}
\note RFC 7231 HTTP/1.1 Semantics and Content -> \l{http://tools.ietf.org/html/rfc7231}{http://tools.ietf.org/html/rfc7231}
*/ */
/*! \enum guhserver::HttpReply::HttpStatusCode /*! \enum guhserver::HttpReply::HttpStatusCode
@ -75,9 +74,7 @@
*/ */
/*! \enum guhserver::HttpReply::HttpHeaderType /*! \enum guhserver::HttpReply::HttpHeaderType
This enum type specifies the known type of a header in a HTTP webserver reply. This enum type specifies the known type of a header in a HTTP webserver reply.
You can find more information here: \l{http://tools.ietf.org/html/rfc7231#section-5} You can find more information here: \l{http://tools.ietf.org/html/rfc7231#section-5}
\value ContentTypeHeader \value ContentTypeHeader
@ -162,7 +159,7 @@ HttpReply::HttpReply(const HttpReply::HttpStatusCode &statusCode, const HttpRepl
packReply(); packReply();
} }
/*! Set the \a statusCode for this \l{HttpReply}.*/ /*! Set the \l{HttpStatusCode} \a statusCode for this \l{HttpReply}. */
void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode) void HttpReply::setHttpStatusCode(const HttpReply::HttpStatusCode &statusCode)
{ {
m_statusCode = statusCode; m_statusCode = statusCode;
@ -363,6 +360,10 @@ QByteArray HttpReply::getHeaderType(const HttpReply::HttpHeaderType &headerType)
} }
} }
/*! Starts the timer for an async \l{HttpReply}.
*
* \sa finished()
*/
void HttpReply::startWait() void HttpReply::startWait()
{ {
m_timer->start(5000); m_timer->start(5000);

View File

@ -148,9 +148,10 @@ bool HttpRequest::hasPayload() const
return !m_payload.isEmpty(); return !m_payload.isEmpty();
} }
/*! Appends data to the current raw data of this \l{HttpRequest}. This method will be used if a \l{HttpRequest} is not complete yet. /*! Appends the given \a data to the current raw data of this \l{HttpRequest}.
* This method will be used if a \l{HttpRequest} is not complete yet.
\sa isComplete() *
* \sa isComplete()
*/ */
void HttpRequest::appendData(const QByteArray &data) void HttpRequest::appendData(const QByteArray &data)
{ {

View File

@ -21,14 +21,7 @@
#include "jsonrpcserver.h" #include "jsonrpcserver.h"
#include "jsontypes.h" #include "jsontypes.h"
#ifdef TESTING_ENABLED
#include "mocktcpserver.h"
#else
#include "tcpserver.h"
#endif
#include "jsonhandler.h" #include "jsonhandler.h"
#include "guhcore.h" #include "guhcore.h"
#include "devicemanager.h" #include "devicemanager.h"
#include "plugin/deviceplugin.h" #include "plugin/deviceplugin.h"
@ -45,6 +38,12 @@
#include "logginghandler.h" #include "logginghandler.h"
#include "statehandler.h" #include "statehandler.h"
#ifndef TESTING_ENABLED
#include "tcpserver.h"
#else
#include "mocktcpserver.h"
#endif
#ifdef WEBSOCKET #ifdef WEBSOCKET
#include "websocketserver.h" #include "websocketserver.h"
#endif #endif

View File

@ -36,14 +36,18 @@
class Device; class Device;
class QSslConfiguration; class QSslConfiguration;
#ifdef TESTING_ENABLED
class MockTcpServer;
#endif
namespace guhserver { namespace guhserver {
#ifdef WEBSOCKET #ifdef WEBSOCKET
class WebSocketServer; class WebSocketServer;
#endif #endif
#ifdef TESTING_ENABLED #ifndef TESTING_ENABLED
class MockTcpServer;
#else
class TcpServer; class TcpServer;
#endif #endif
@ -76,11 +80,6 @@ private slots:
void asyncReplyFinished(); void asyncReplyFinished();
private:
void registerHandler(JsonHandler *handler);
QString formatAssertion(const QString &targetNamespace, const QString &method, JsonHandler *handler, const QVariantMap &data) const;
private: private:
#ifdef TESTING_ENABLED #ifdef TESTING_ENABLED
MockTcpServer *m_tcpServer; MockTcpServer *m_tcpServer;
@ -100,6 +99,9 @@ private:
QHash<QUuid, bool> m_clients; QHash<QUuid, bool> m_clients;
int m_notificationId; int m_notificationId;
void registerHandler(JsonHandler *handler);
QString formatAssertion(const QString &targetNamespace, const QString &method, JsonHandler *handler, const QVariantMap &data) const;
}; };
} }

View File

@ -45,7 +45,6 @@ class RestServer : public QObject
public: public:
explicit RestServer(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = 0); explicit RestServer(const QSslConfiguration &sslConfiguration = QSslConfiguration(), QObject *parent = 0);
private: private:
WebServer *m_webserver; WebServer *m_webserver;
QList<QUuid> m_clientList; QList<QUuid> m_clientList;

View File

@ -72,6 +72,7 @@
*/ */
/*! \enum guhserver::RuleEngine::RemovePolicy /*! \enum guhserver::RuleEngine::RemovePolicy
\value RemovePolicyCascade \value RemovePolicyCascade
Remove the whole \l{Rule}. Remove the whole \l{Rule}.
\value RemovePolicyUpdate \value RemovePolicyUpdate
@ -99,7 +100,7 @@ namespace guhserver {
/*! Constructs the RuleEngine with the given \a parent. Although it wouldn't harm to have multiple RuleEngines, there is one /*! Constructs the RuleEngine with the given \a parent. Although it wouldn't harm to have multiple RuleEngines, there is one
instance available from \l{GuhCore}. This one should be used instead of creating multiple ones. instance available from \l{GuhCore}. This one should be used instead of creating multiple ones.
*/ */
RuleEngine::RuleEngine(QObject *parent) : RuleEngine::RuleEngine(QObject *parent) :
QObject(parent) QObject(parent)
{ {
@ -204,7 +205,8 @@ RuleEngine::RuleEngine(QObject *parent) :
This will search all the \l{Rule}{Rules} triggered by the given \a event This will search all the \l{Rule}{Rules} triggered by the given \a event
and evaluate their states in the system. It will return a and evaluate their states in the system. It will return a
list of all \l{Rule}{Rules} that are triggered or change its active state list of all \l{Rule}{Rules} that are triggered or change its active state
because of this \a event. */ because of this \a event.
*/
QList<Rule> RuleEngine::evaluateEvent(const Event &event) QList<Rule> RuleEngine::evaluateEvent(const Event &event)
{ {
Device *device = GuhCore::instance()->findConfiguredDevice(event.deviceId()); Device *device = GuhCore::instance()->findConfiguredDevice(event.deviceId());
@ -254,7 +256,8 @@ QList<Rule> RuleEngine::evaluateEvent(const Event &event)
} }
/*! Add a new \l{Rule} with the given \a ruleId , \a name, \a eventDescriptorList, \a actions and \a enabled value to the engine. /*! Add a new \l{Rule} with the given \a ruleId , \a name, \a eventDescriptorList, \a actions and \a enabled value to the engine.
For convenience, this creates a Rule without any \l{State} comparison. */ For convenience, this creates a Rule without any \l{State} comparison.
*/
RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const QList<RuleAction> &actions, bool enabled) RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const QList<RuleAction> &actions, bool enabled)
{ {
return addRule(ruleId, name, eventDescriptorList, StateEvaluator(), actions, QList<RuleAction>(), enabled); return addRule(ruleId, name, eventDescriptorList, StateEvaluator(), actions, QList<RuleAction>(), enabled);
@ -349,7 +352,9 @@ RuleEngine::RuleError RuleEngine::addRule(const RuleId &ruleId, const QString &n
return RuleErrorNoError; return RuleErrorNoError;
} }
/*! Edit a \l{Rule} with the given \a ruleId, \a name, \a eventDescriptorList, \a stateEvaluator, the list of \a actions the list of \a exitActions and the \a enabled in the engine. */ /*! Edit a \l{Rule} with the given \a ruleId, \a name, \a eventDescriptorList, \a stateEvaluator,
the list of \a actions the list of \a exitActions and the \a enabled in the engine.
*/
RuleEngine::RuleError RuleEngine::editRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled) RuleEngine::RuleError RuleEngine::editRule(const RuleId &ruleId, const QString &name, const QList<EventDescriptor> &eventDescriptorList, const StateEvaluator &stateEvaluator, const QList<RuleAction> &actions, const QList<RuleAction> &exitActions, bool enabled)
{ {
if (ruleId.isNull()) { if (ruleId.isNull()) {
@ -427,7 +432,9 @@ RuleEngine::RuleError RuleEngine::removeRule(const RuleId &ruleId, bool fromEdit
} }
/*! Enables the rule with the given \a ruleId that has been previously disabled. /*! Enables the rule with the given \a ruleId that has been previously disabled.
\sa disableRule(), */
\sa disableRule()
*/
RuleEngine::RuleError RuleEngine::enableRule(const RuleId &ruleId) RuleEngine::RuleError RuleEngine::enableRule(const RuleId &ruleId)
{ {
if (!m_rules.contains(ruleId)) { if (!m_rules.contains(ruleId)) {
@ -445,7 +452,9 @@ RuleEngine::RuleError RuleEngine::enableRule(const RuleId &ruleId)
} }
/*! Disables the rule with the given \a ruleId. Disabled rules won't be triggered. /*! Disables the rule with the given \a ruleId. Disabled rules won't be triggered.
\sa enableRule(), */
\sa enableRule()
*/
RuleEngine::RuleError RuleEngine::disableRule(const RuleId &ruleId) RuleEngine::RuleError RuleEngine::disableRule(const RuleId &ruleId)
{ {
if (!m_rules.contains(ruleId)) { if (!m_rules.contains(ruleId)) {

View File

@ -18,6 +18,20 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::ServerManager
\brief This class represents the manager of all server interfaces of the guh server.
\ingroup core
\inmodule server
The \l{ServerManager} starts the \l{JsonRPCServer} and the \l{RestServer}. He also loads
and provides the SSL configurations for the secure \l{WebServer} and \l{WebSocketServer}
connection.
\sa JsonRPCServer, RestServer
*/
#include "servermanager.h" #include "servermanager.h"
#include "guhsettings.h" #include "guhsettings.h"
@ -27,6 +41,7 @@
namespace guhserver { namespace guhserver {
/*! Constructs a \l{ServerManager} with the given \a parent. */
ServerManager::ServerManager(QObject *parent) : ServerManager::ServerManager(QObject *parent) :
QObject(parent), QObject(parent),
m_sslConfiguration(QSslConfiguration()) m_sslConfiguration(QSslConfiguration())
@ -62,11 +77,13 @@ ServerManager::ServerManager(QObject *parent) :
m_restServer = new RestServer(m_sslConfiguration, this); m_restServer = new RestServer(m_sslConfiguration, this);
} }
/*! Returns the pointer to the created \l{JsonRPCServer} in this \l{ServerManager}. */
JsonRPCServer *ServerManager::jsonServer() const JsonRPCServer *ServerManager::jsonServer() const
{ {
return m_jsonServer; return m_jsonServer;
} }
/*! Returns the pointer to the created \l{RestServer} in this \l{ServerManager}. */
RestServer *ServerManager::restServer() const RestServer *ServerManager::restServer() const
{ {
return m_restServer; return m_restServer;

View File

@ -19,6 +19,20 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::TcpServer
\brief This class represents the tcp server for guhd.
\ingroup core
\inmodule server
\inherits TransportInterface
The TCP server allowes clients to connect to the JSON-RPC API.
\sa WebSocketServer, TransportInterface
*/
#include "tcpserver.h" #include "tcpserver.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "guhsettings.h" #include "guhsettings.h"
@ -30,6 +44,10 @@
namespace guhserver { namespace guhserver {
/*! Constructs a \l{TcpServer} with the given \a parent.
*
* \sa ServerManager
*/
TcpServer::TcpServer(QObject *parent) : TcpServer::TcpServer(QObject *parent) :
TransportInterface(parent) TransportInterface(parent)
{ {
@ -66,10 +84,12 @@ TcpServer::TcpServer(QObject *parent) :
settings.endGroup(); settings.endGroup();
} }
/*! Destructor of this \l{TcpServer}. */
TcpServer::~TcpServer() TcpServer::~TcpServer()
{ {
} }
/*! Sending \a data to a list of \a clients.*/
void TcpServer::sendData(const QList<QUuid> &clients, const QVariantMap &data) void TcpServer::sendData(const QList<QUuid> &clients, const QVariantMap &data)
{ {
foreach (const QUuid &client, clients) { foreach (const QUuid &client, clients) {
@ -77,6 +97,16 @@ void TcpServer::sendData(const QList<QUuid> &clients, const QVariantMap &data)
} }
} }
/*! Sending \a data to the client with the given \a clientId.*/
void TcpServer::sendData(const QUuid &clientId, const QVariantMap &data)
{
QTcpSocket *client = 0;
client = m_clientList.value(clientId);
if (client) {
client->write(QJsonDocument::fromVariant(data).toJson());
}
}
void TcpServer::reloadNetworkInterfaces() void TcpServer::reloadNetworkInterfaces()
{ {
GuhSettings settings(GuhSettings::SettingsRoleGlobal); GuhSettings settings(GuhSettings::SettingsRoleGlobal);
@ -98,15 +128,6 @@ void TcpServer::reloadNetworkInterfaces()
settings.endGroup(); settings.endGroup();
} }
void TcpServer::sendData(const QUuid &clientId, const QVariantMap &data)
{
QTcpSocket *client = 0;
client = m_clientList.value(clientId);
if (client) {
client->write(QJsonDocument::fromVariant(data).toJson());
}
}
void TcpServer::onClientConnected() void TcpServer::onClientConnected()
{ {
// got a new client connected // got a new client connected
@ -233,6 +254,10 @@ void TcpServer::onTimeout()
} }
} }
/*! Returns true if this \l{TcpServer} started successfully.
*
* \sa TransportInterface::startServer()
*/
bool TcpServer::startServer() bool TcpServer::startServer()
{ {
bool ipV4 = m_ipVersions.contains("IPv4"); bool ipV4 = m_ipVersions.contains("IPv4");
@ -276,6 +301,10 @@ bool TcpServer::startServer()
return true; return true;
} }
/*! Returns true if this \l{TcpServer} stopped successfully.
*
* \sa TransportInterface::startServer()
*/
bool TcpServer::stopServer() bool TcpServer::stopServer()
{ {
// Listen on all Networkinterfaces // Listen on all Networkinterfaces

View File

@ -18,6 +18,58 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::TransportInterface
\brief This class provides an interface for the JSON servers.
\ingroup core
\inmodule server
\sa WebSocketServer, TcpServer
*/
/*! \fn void guhserver::TransportInterface::clientConnected(const QUuid &clientId);
This signal is emitted when a new client with the given \a clientId has been connected.
\sa WebSocketServer, TcpServer
*/
/*! \fn void guhserver::TransportInterface::clientDisconnected(const QUuid &clientId);
This signal is emitted when a new client with the given \a clientId has been connected.
\sa WebSocketServer, TcpServer
*/
/*! \fn bool guhserver::TransportInterface::startServer();
Pure virtual public slot for starting the corresponding \l{TransportInterface}. Returns true
if started successfully.
\sa WebSocketServer::startServer(), TcpServer::startServer()
*/
/*! \fn bool guhserver::TransportInterface::stopServer();
Pure virtual public slot for stopping the corresponding \l{TransportInterface}. Returns true
if stopped successfully.
\sa WebSocketServer::stopServer(), TcpServer::stopServer()
*/
/*! \fn void guhserver::TransportInterface::sendData(const QUuid &clientId, const QVariantMap &data);
Pure virtual method for sending \a data to the client with the id \a clientId over the corresponding \l{TransportInterface}.
*/
/*! \fn void guhserver::TransportInterface::sendData(const QList<QUuid> &clients, const QVariantMap &data);
Pure virtual method for sending \a data to \a clients over the corresponding \l{TransportInterface}.
*/
/*! \fn void guhserver::TransportInterface::dataAvailable(const QUuid &clientId, const QString &targetNamespace, const QString &method, const QVariantMap &message);
This signal is emitted when valid data from the client with the given \a clientId are available.
Data are valid if the corresponding \l{TransportInterface} has parsed successfully the given
\a targetNamespace, \a method and \a message.
\sa WebSocketServer, TcpServer
*/
#include "transportinterface.h" #include "transportinterface.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "jsonhandler.h" #include "jsonhandler.h"
@ -27,15 +79,20 @@
namespace guhserver { namespace guhserver {
/*! Constructs a \l{TransportInterface} with the given \a parent. */
TransportInterface::TransportInterface(QObject *parent) : TransportInterface::TransportInterface(QObject *parent) :
QObject(parent) QObject(parent)
{ {
} }
/*! Pure virtual destructor for \l{TransportInterface}. */
TransportInterface::~TransportInterface() TransportInterface::~TransportInterface()
{ {
} }
/*! Send a JSON success response to the client with the given \a clientId,
* \a commandId and \a params to the inerted \l{TransportInterface}.
*/
void TransportInterface::sendResponse(const QUuid &clientId, int commandId, const QVariantMap &params) void TransportInterface::sendResponse(const QUuid &clientId, int commandId, const QVariantMap &params)
{ {
QVariantMap response; QVariantMap response;
@ -46,6 +103,10 @@ void TransportInterface::sendResponse(const QUuid &clientId, int commandId, cons
sendData(clientId, response); sendData(clientId, response);
} }
/*! Send a JSON error response to the client with the given \a clientId,
* \a commandId and \a error to the inerted \l{TransportInterface}.
*/
void TransportInterface::sendErrorResponse(const QUuid &clientId, int commandId, const QString &error) void TransportInterface::sendErrorResponse(const QUuid &clientId, int commandId, const QString &error)
{ {
QVariantMap errorResponse; QVariantMap errorResponse;
@ -56,7 +117,12 @@ void TransportInterface::sendErrorResponse(const QUuid &clientId, int commandId,
sendData(clientId, errorResponse); sendData(clientId, errorResponse);
} }
/*! Validates the given \a data from the client with the id \a clientId. If the validation was
* successfull, the signal \l{dataAvailable()} will be emitted, otherwise an error response
* will be sent to the client.
*
* \sa dataAvailable()
*/
void TransportInterface::validateMessage(const QUuid &clientId, const QByteArray &data) void TransportInterface::validateMessage(const QUuid &clientId, const QByteArray &data)
{ {
QJsonParseError error; QJsonParseError error;

View File

@ -18,6 +18,58 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::WebServer
\brief This class represents the web server for guhd.
\ingroup core
\inmodule server
The \l{WebServer} class provides a HTTP/1.1 web server. The web server
provides access to the guh-webinterface and the path can be specified
in the \tt /etc/guh/guhd.conf file and to the guh \l{https://github.com/guh/guh/wiki/REST-Api-documentation}{REST API}.
The default port for the web server is 3333, which is according to this
\l{https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers}{list}
officially free.
The URL for the insecure guh-webinterface access:
\code http://localhost:3333\endcode
The URL for the secure HTTPS (TLS 1.2) guh-webinterface access:
\code https://localhost:3333\endcode
The URL for the insecure REST API access to a \l{RestResource}:
\code http://localhost:3333/api/v1/{resource}\endcode
The URL for the secure HTTPS (TLS 1.2) REST API access to a \l{RestResource}:
\code https://localhost:3333/api/v1/{RestResource}\endcode
You can turn on the HTTPS server in the \tt WebServer section of the \tt /etc/guh/guhd.conf file.
\note For \tt HTTPS you need to have a certificate and configure it in the \tt SSL-configuration
section of the \tt /etc/guh/guhd.conf file.
\sa WebSocketServer, TcpServer
*/
/*! \fn void guhserver::WebServer::httpRequestReady(const QUuid &clientId, const HttpRequest &httpRequest);
This signal is emitted when a \a httpRequest from a client with the given \a clientId is ready.
\sa RestServer, HttpRequest
*/
/*! \fn void guhserver::WebServer::clientConnected(const QUuid &clientId);
This signal is emitted when a new client with the given \a clientId has been connected.
*/
/*! \fn void guhserver::WebServer::clientDisconnected(const QUuid &clientId);
This signal is emitted when a client with the given \a clientId has been disconnected.
*/
/*! \fn void guhserver::WebServer::incomingConnection(qintptr socketDescriptor);
Overwritten virtual method from \l{http://doc.qt.io/qt-5/qtcpserver.html#incomingConnection}{QTcpServer::incomingConnection( \a socketDescriptor)}.
*/
#include "webserver.h" #include "webserver.h"
#include "loggingcategories.h" #include "loggingcategories.h"
#include "guhsettings.h" #include "guhsettings.h"
@ -35,6 +87,10 @@
namespace guhserver { namespace guhserver {
/*! Constructs a \l{WebServer} with the given \a sslConfiguration and \a parent.
*
* \sa ServerManager
*/
WebServer::WebServer(const QSslConfiguration &sslConfiguration, QObject *parent) : WebServer::WebServer(const QSslConfiguration &sslConfiguration, QObject *parent) :
QTcpServer(parent), QTcpServer(parent),
m_sslConfiguration(sslConfiguration), m_sslConfiguration(sslConfiguration),
@ -63,11 +119,16 @@ WebServer::WebServer(const QSslConfiguration &sslConfiguration, QObject *parent)
m_useSsl = false; m_useSsl = false;
} }
/*! Destructor of this \l{WebServer}. */
WebServer::~WebServer() WebServer::~WebServer()
{ {
this->close(); this->close();
} }
/*! Send the given \a reply map to the corresponding client.
*
* \sa HttpReply
*/
void WebServer::sendHttpReply(HttpReply *reply) void WebServer::sendHttpReply(HttpReply *reply)
{ {
QSslSocket *socket = 0; QSslSocket *socket = 0;
@ -297,6 +358,7 @@ void WebServer::onError(QAbstractSocket::SocketError error)
qCWarning(dcConnection) << "Client socket error" << socket->peerAddress() << error << socket->errorString(); qCWarning(dcConnection) << "Client socket error" << socket->peerAddress() << error << socket->errorString();
} }
/*! Returns true if this \l{WebServer} started successfully. */
bool WebServer::startServer() bool WebServer::startServer()
{ {
if (!listen(QHostAddress::Any, m_port)) { if (!listen(QHostAddress::Any, m_port)) {
@ -313,6 +375,7 @@ bool WebServer::startServer()
return true; return true;
} }
/*! Returns true if this \l{WebServer} stopped successfully. */
bool WebServer::stopServer() bool WebServer::stopServer()
{ {
close(); close();

View File

@ -72,7 +72,6 @@ signals:
void httpRequestReady(const QUuid &clientId, const HttpRequest &httpRequest); void httpRequestReady(const QUuid &clientId, const HttpRequest &httpRequest);
void clientConnected(const QUuid &clientId); void clientConnected(const QUuid &clientId);
void clientDisconnected(const QUuid &clientId); void clientDisconnected(const QUuid &clientId);
void dataAvailable(const QUuid &clientId, const QString &targetNamespace, const QString &method, const QVariantMap &message);
private slots: private slots:
void readClient(); void readClient();

View File

@ -18,6 +18,33 @@
* * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*!
\class guhserver::WebSocketServer
\brief This class represents the websocket server for guhd.
\ingroup core
\inmodule server
The websocket server provides a server for websocket clients based on
\l{http://tools.ietf.org/html/rfc6455}{Protocol Version 13}. The default
port for the websocket server is 4444, which is according to this
\l{https://en.wikipedia.org/wiki/List_of_TCP_and_UDP_port_numbers}{list}
officially free.
The URL for the insecure websocket:
\code ws://localhost:4444\endcode
The URL for the secure websocket (TLS 1.2):
\code wss://localhost:4444\endcode
You can turn on the \tt wss server in the \tt WebServerServer section of the \tt /etc/guh/guhd.conf file.
\note For \tt wss you need to have a certificate and configure it in the \tt SSL-configuration
section of the \tt /etc/guh/guhd.conf file.
\sa WebServer, TcpServer, TransportInterface
*/
#include "websocketserver.h" #include "websocketserver.h"
#include "guhsettings.h" #include "guhsettings.h"
#include "loggingcategories.h" #include "loggingcategories.h"
@ -27,6 +54,10 @@
namespace guhserver { namespace guhserver {
/*! Constructs a \l{WebSocketServer} with the given \a sslConfiguration and \a parent.
*
* \sa ServerManager
*/
WebSocketServer::WebSocketServer(const QSslConfiguration &sslConfiguration, QObject *parent) : WebSocketServer::WebSocketServer(const QSslConfiguration &sslConfiguration, QObject *parent) :
TransportInterface(parent), TransportInterface(parent),
m_server(0), m_server(0),
@ -49,10 +80,15 @@ WebSocketServer::WebSocketServer(const QSslConfiguration &sslConfiguration, QObj
m_useSsl = false; m_useSsl = false;
} }
/*! Destructor of this \l{WebSocketServer}. */
WebSocketServer::~WebSocketServer() WebSocketServer::~WebSocketServer()
{ {
} }
/*! Send the given \a data map to the client with the given \a clientId.
*
* \sa TransportInterface::sendData()
*/
void WebSocketServer::sendData(const QUuid &clientId, const QVariantMap &data) void WebSocketServer::sendData(const QUuid &clientId, const QVariantMap &data)
{ {
QWebSocket *client = 0; QWebSocket *client = 0;
@ -62,6 +98,10 @@ void WebSocketServer::sendData(const QUuid &clientId, const QVariantMap &data)
} }
} }
/*! Send the given \a data map to the given list of \a clients.
*
* \sa TransportInterface::sendData()
*/
void WebSocketServer::sendData(const QList<QUuid> &clients, const QVariantMap &data) void WebSocketServer::sendData(const QList<QUuid> &clients, const QVariantMap &data)
{ {
foreach (const QUuid &client, clients) { foreach (const QUuid &client, clients) {
@ -135,6 +175,10 @@ void WebSocketServer::onPing(quint64 elapsedTime, const QByteArray &payload)
qCDebug(dcWebSocketServer) << "ping response" << client->peerAddress() << elapsedTime << payload; qCDebug(dcWebSocketServer) << "ping response" << client->peerAddress() << elapsedTime << payload;
} }
/*! Returns true if this \l{WebSocketServer} started successfully.
*
* \sa TransportInterface::startServer()
*/
bool WebSocketServer::startServer() bool WebSocketServer::startServer()
{ {
if (m_server) { if (m_server) {
@ -164,6 +208,10 @@ bool WebSocketServer::startServer()
return true; return true;
} }
/*! Returns true if this \l{WebSocketServer} stopped successfully.
*
* \sa TransportInterface::stopServer()
*/
bool WebSocketServer::stopServer() bool WebSocketServer::stopServer()
{ {
qCDebug(dcConnection) << "Stopping websocket server"; qCDebug(dcConnection) << "Stopping websocket server";

View File

@ -34,7 +34,7 @@
#include <QMetaType> #include <QMetaType>
#include <QNetworkReply> #include <QNetworkReply>
namespace guhserver { using namespace guhserver;
PluginId mockPluginId = PluginId("727a4a9a-c187-446f-aadf-f1b2220607d1"); PluginId mockPluginId = PluginId("727a4a9a-c187-446f-aadf-f1b2220607d1");
VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6"); VendorId guhVendorId = VendorId("2062d64d-3232-433c-88bc-0d33c0ba2ba6");
@ -67,7 +67,6 @@ GuhTestBase::GuhTestBase(QObject *parent) :
void GuhTestBase::initTestCase() void GuhTestBase::initTestCase()
{ {
// If testcase asserts cleanup won't do. Lets clear any previous test run settings leftovers // If testcase asserts cleanup won't do. Lets clear any previous test run settings leftovers
GuhSettings rulesSettings(GuhSettings::SettingsRoleRules); GuhSettings rulesSettings(GuhSettings::SettingsRoleRules);
rulesSettings.clear(); rulesSettings.clear();
@ -198,4 +197,3 @@ void GuhTestBase::restartServer()
m_mockTcpServer = MockTcpServer::servers().first(); m_mockTcpServer = MockTcpServer::servers().first();
} }
}

View File

@ -34,8 +34,6 @@
#include <QSignalSpy> #include <QSignalSpy>
#include <QtTest> #include <QtTest>
namespace guhserver {
extern DeviceClassId mockDeviceClassId; extern DeviceClassId mockDeviceClassId;
extern DeviceClassId mockDeviceAutoClassId; extern DeviceClassId mockDeviceAutoClassId;
extern DeviceClassId mockDeviceDiscoveryClassId; extern DeviceClassId mockDeviceDiscoveryClassId;
@ -52,6 +50,7 @@ extern EventTypeId mockEvent2Id;
extern StateTypeId mockIntStateId; extern StateTypeId mockIntStateId;
extern StateTypeId mockBoolStateId; extern StateTypeId mockBoolStateId;
using namespace guhserver;
class MockTcpServer; class MockTcpServer;
@ -137,6 +136,4 @@ protected:
}; };
}
#endif // GUHTESTBASE_H #endif // GUHTESTBASE_H

View File

@ -27,8 +27,7 @@
#include <QHash> #include <QHash>
#include <QJsonDocument> #include <QJsonDocument>
using namespace guhserver;
namespace guhserver {
QList<MockTcpServer*> MockTcpServer::s_allServers; QList<MockTcpServer*> MockTcpServer::s_allServers;
@ -134,5 +133,3 @@ bool MockTcpServer::stopServer()
{ {
return true; return true;
} }
}

View File

@ -27,7 +27,7 @@
#include "transportinterface.h" #include "transportinterface.h"
namespace guhserver { using namespace guhserver;
class JsonRPCServer; class JsonRPCServer;
@ -60,7 +60,5 @@ private:
static QList<MockTcpServer*> s_allServers; static QList<MockTcpServer*> s_allServers;
}; };
}
#endif // TCPSERVER_H #endif // TCPSERVER_H