WIP: main
This commit is contained in:
parent
f25f34565a
commit
15730b470e
52 changed files with 2438 additions and 208 deletions
168
service/server/localserver.cpp
Normal file
168
service/server/localserver.cpp
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
#include <QCoreApplication>
|
||||
#include <QFileInfo>
|
||||
#include <QLocalServer>
|
||||
#include <QLocalSocket>
|
||||
|
||||
#include "localserver.h"
|
||||
#include "utils.h"
|
||||
|
||||
LocalServer::LocalServer(const QString& name, QObject *parent) : QObject(parent),
|
||||
m_clientConnected(false),
|
||||
m_clientConnection(nullptr)
|
||||
{
|
||||
m_server = new QLocalServer(this);
|
||||
m_server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||
|
||||
if (!m_server->listen(name)) {
|
||||
qDebug() << QString("Unable to start the server: %1.").arg(m_server->errorString());
|
||||
return;
|
||||
}
|
||||
|
||||
connect(m_server, &QLocalServer::newConnection, this, &LocalServer::onNewConnection);
|
||||
|
||||
qDebug() << "Local server started";
|
||||
}
|
||||
|
||||
LocalServer::~LocalServer()
|
||||
{
|
||||
m_clientConnected = false;
|
||||
m_server->disconnect();
|
||||
|
||||
qDebug() << "Local server stopped";
|
||||
}
|
||||
|
||||
bool LocalServer::isRunning() const
|
||||
{
|
||||
return m_server->isListening();
|
||||
}
|
||||
|
||||
void LocalServer::onNewConnection()
|
||||
{
|
||||
if (m_clientConnection) {
|
||||
m_clientConnection->deleteLater();
|
||||
}
|
||||
|
||||
m_clientConnection = m_server->nextPendingConnection();
|
||||
connect(m_clientConnection, &QLocalSocket::disconnected, this, &LocalServer::onDisconnected);
|
||||
m_clientConnected = true;
|
||||
|
||||
qDebug() << "On new connection";
|
||||
|
||||
for(;;) {
|
||||
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
if (!m_clientConnected || !m_clientConnection) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_clientConnection->waitForReadyRead() && m_clientConnection->canReadLine()) {
|
||||
char buf[1024];
|
||||
qint64 lineLength = m_clientConnection->readLine(buf, sizeof(buf));
|
||||
if (lineLength != -1) {
|
||||
QString line = buf;
|
||||
line = line.simplified();
|
||||
qDebug().noquote() << QString("Readed line: '%1'").arg(line);
|
||||
Message icomingMessage(line);
|
||||
if (!icomingMessage.isValid()) {
|
||||
qWarning().noquote() << "Message is not valid!";
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (icomingMessage.state()) {
|
||||
case Message::State::Initialize:
|
||||
sendMessage(Message(Message::State::Initialize, QStringList({"Pong"})));
|
||||
break;
|
||||
case Message::State::StartRequest:
|
||||
startProcess(icomingMessage.args());
|
||||
break;
|
||||
case Message::State::FinishRequest:
|
||||
finishProcess(icomingMessage.args());
|
||||
break;
|
||||
default:
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
qDebug() << "Released";
|
||||
}
|
||||
|
||||
void LocalServer::finishProcess(const QStringList& args)
|
||||
{
|
||||
Q_UNUSED(args)
|
||||
}
|
||||
|
||||
void LocalServer::startProcess(const QStringList& messageArgs)
|
||||
{
|
||||
if (messageArgs.size() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
QProcess* process = new QProcess();
|
||||
connect(process, SIGNAL(started()), this, SLOT(onStarted()));
|
||||
connect(process, SIGNAL(finished(int, QProcess::ExitStatus)), this, SLOT(onFinished(int, QProcess::ExitStatus)));
|
||||
|
||||
const QString program = messageArgs.at(0);
|
||||
QStringList args;
|
||||
for (int i = 1; i < messageArgs.size(); i++) {
|
||||
args.append(messageArgs.at(i));
|
||||
}
|
||||
|
||||
QFileInfo fi(program);
|
||||
const QString baseName = fi.baseName();
|
||||
if (!fi.exists()) {
|
||||
qWarning() << "This program does not exist";
|
||||
sendMessage(Message(Message::State::Started, QStringList({baseName})));
|
||||
sendMessage(Message(Message::State::Finished, QStringList({baseName, QString::number(-1)})));
|
||||
return;
|
||||
}
|
||||
|
||||
process->setObjectName(baseName);
|
||||
|
||||
qDebug().noquote() << QString("Start process '%1' - '%2' with args '%3'")
|
||||
.arg(baseName).arg(program).arg(args.join(","));
|
||||
|
||||
process->start(program, args);
|
||||
m_processList.append(process);
|
||||
}
|
||||
|
||||
void LocalServer::onFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
Q_UNUSED(exitStatus)
|
||||
|
||||
QProcess* process = (QProcess*)sender();
|
||||
sendMessage(Message(Message::State::Finished, QStringList({process->objectName(), QString::number(exitCode)})));
|
||||
}
|
||||
|
||||
void LocalServer::onStarted()
|
||||
{
|
||||
QProcess* process = (QProcess*)sender();
|
||||
sendMessage(Message(Message::State::Started, QStringList({process->objectName()})));
|
||||
}
|
||||
|
||||
void LocalServer::onDisconnected()
|
||||
{
|
||||
if (!m_clientConnected) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_clientConnected = false;
|
||||
QLocalSocket* clientConnection = (QLocalSocket*)sender();
|
||||
clientConnection->deleteLater();
|
||||
|
||||
qDebug() << "Diconnected";
|
||||
}
|
||||
|
||||
void LocalServer::sendMessage(const Message& message)
|
||||
{
|
||||
if (!m_clientConnection || !m_clientConnected) {
|
||||
qDebug()<< "Cannot send data, remote peer is not connected";
|
||||
return;
|
||||
}
|
||||
|
||||
const QString data = message.toString();
|
||||
bool status = m_clientConnection->write(QString(data + "\n").toLocal8Bit());
|
||||
|
||||
qDebug().noquote() << QString("Send message '%1', status '%2'").arg(data).arg(Utils::toString(status));
|
||||
}
|
||||
|
||||
43
service/server/localserver.h
Normal file
43
service/server/localserver.h
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef LOCALSERVER_H
|
||||
#define LOCALSERVER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QProcess>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
#include "message.h"
|
||||
|
||||
class QLocalServer;
|
||||
class QLocalSocket;
|
||||
class QProcess;
|
||||
|
||||
class LocalServer : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LocalServer(const QString& name, QObject* parent = nullptr);
|
||||
~LocalServer();
|
||||
|
||||
bool isRunning() const;
|
||||
|
||||
protected slots:
|
||||
void onDisconnected();
|
||||
void onNewConnection();
|
||||
|
||||
void onFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
void onStarted();
|
||||
|
||||
private:
|
||||
void finishProcess(const QStringList& messageArgs);
|
||||
void sendMessage(const Message& message);
|
||||
void startProcess(const QStringList& messageArgs);
|
||||
|
||||
QLocalServer* m_server;
|
||||
QLocalSocket* m_clientConnection;
|
||||
QVector<QProcess*> m_processList;
|
||||
bool m_clientConnected;
|
||||
};
|
||||
|
||||
#endif // LOCALSERVER_H
|
||||
53
service/server/log.cpp
Normal file
53
service/server/log.cpp
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
#include <QDir>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "log.h"
|
||||
#include "defines.h"
|
||||
#include "utils.h"
|
||||
|
||||
QFile Log::m_file;
|
||||
QTextStream Log::m_textStream;
|
||||
QString Log::m_logFileName;
|
||||
|
||||
void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg)
|
||||
{
|
||||
if (msg.simplified().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Log::m_textStream << qFormatLogMessage(type, context, msg) << endl << flush;
|
||||
|
||||
std::cout << qFormatLogMessage(type, context, msg).toStdString() << std::endl << std::flush;
|
||||
}
|
||||
|
||||
bool Log::initialize()
|
||||
{
|
||||
QString path = Utils::systemLogPath();
|
||||
QDir appDir(path);
|
||||
if (!appDir.mkpath(path)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
m_logFileName = QString("%1.log").arg(SERVICE_NAME);
|
||||
|
||||
qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{type} %{message}");
|
||||
|
||||
m_file.setFileName(appDir.filePath(m_logFileName));
|
||||
if (!m_file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||
qWarning() << "Cannot open log file:" << m_logFileName;
|
||||
return false;
|
||||
}
|
||||
m_file.setTextModeEnabled(true);
|
||||
m_textStream.setDevice(&m_file);
|
||||
qInstallMessageHandler(debugMessageHandler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
QString Log::serviceLogFileNamePath()
|
||||
{
|
||||
return m_file.fileName();
|
||||
}
|
||||
|
||||
23
service/server/log.h
Normal file
23
service/server/log.h
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <QDebug>
|
||||
#include <QFile>
|
||||
#include <QString>
|
||||
#include <QTextStream>
|
||||
|
||||
class Log
|
||||
{
|
||||
public:
|
||||
static bool initialize();
|
||||
static QString serviceLogFileNamePath();
|
||||
|
||||
private:
|
||||
friend void debugMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg);
|
||||
|
||||
static QFile m_file;
|
||||
static QString m_logFileName;
|
||||
static QTextStream m_textStream;
|
||||
};
|
||||
|
||||
#endif // LOG_H
|
||||
|
|
@ -1,7 +1,10 @@
|
|||
#include <QSettings>
|
||||
#include <QDir>
|
||||
|
||||
#include "server.h"
|
||||
#include "systemservice.h"
|
||||
#include "log.h"
|
||||
#include "defines.h"
|
||||
#include "localserver.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
|
@ -11,6 +14,20 @@ int main(int argc, char **argv)
|
|||
QSettings::setPath(QSettings::NativeFormat, QSettings::SystemScope, QDir::tempPath());
|
||||
qWarning("(Example uses dummy settings file: %s/QtSoftware.conf)", QDir::tempPath().toLatin1().constData());
|
||||
#endif
|
||||
HttpService service(argc, argv);
|
||||
return service.exec();
|
||||
|
||||
Log::initialize();
|
||||
|
||||
if (argc == 2) {
|
||||
qInfo() << "Started as console application";
|
||||
QCoreApplication app(argc,argv);
|
||||
LocalServer localServer(SERVICE_NAME);
|
||||
if (!localServer.isRunning()) {
|
||||
return -1;
|
||||
}
|
||||
return app.exec();
|
||||
} else {
|
||||
qInfo() << "Started as system service";
|
||||
SystemService systemService(argc, argv);
|
||||
return systemService.exec();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,112 +0,0 @@
|
|||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
#include <QTcpSocket>
|
||||
|
||||
#include "server.h"
|
||||
|
||||
HttpDaemon::HttpDaemon(quint16 port, QObject* parent)
|
||||
: QTcpServer(parent), disabled(false)
|
||||
{
|
||||
listen(QHostAddress::Any, port);
|
||||
qDebug() << "Listen on port: " << port;
|
||||
|
||||
connect(this, &QTcpServer::newConnection, this, &HttpDaemon::sendFortune);
|
||||
}
|
||||
|
||||
void HttpDaemon::sendFortune()
|
||||
{
|
||||
qDebug() << "New connection: ";
|
||||
|
||||
QTcpSocket *clientConnection = this->nextPendingConnection();
|
||||
connect(clientConnection, &QAbstractSocket::disconnected,
|
||||
clientConnection, &QObject::deleteLater);
|
||||
|
||||
|
||||
connect(clientConnection, SIGNAL(readyRead()), this, SLOT(readClient()));
|
||||
connect(clientConnection, SIGNAL(disconnected()), this, SLOT(discardClient()));
|
||||
//->setSocketDescriptor(socket);
|
||||
}
|
||||
|
||||
void HttpDaemon::pause()
|
||||
{
|
||||
disabled = true;
|
||||
}
|
||||
|
||||
void HttpDaemon::resume()
|
||||
{
|
||||
disabled = false;
|
||||
}
|
||||
|
||||
void HttpDaemon::readClient()
|
||||
{
|
||||
qDebug() << "readClient";
|
||||
|
||||
// if (disabled)
|
||||
// return;
|
||||
//
|
||||
// This slot is called when the client sent data to the server. The
|
||||
// server looks if it was a get request and sends a very simple HTML
|
||||
// document back.
|
||||
QTcpSocket* socket = (QTcpSocket*)sender();
|
||||
if (socket->canReadLine()) {
|
||||
QStringList tokens = QString(socket->readLine()).split(QRegExp("[ \r\n][ \r\n]*"));
|
||||
if (tokens[0] == "GET") {
|
||||
QTextStream os(socket);
|
||||
os.setAutoDetectUnicode(true);
|
||||
os << "HTTP/1.0 200 Ok\r\n"
|
||||
"Content-Type: text/html; charset=\"utf-8\"\r\n"
|
||||
"\r\n"
|
||||
"<h1>Nothing to see here</h1>\n"
|
||||
<< QDateTime::currentDateTime().toString() << "\n";
|
||||
socket->close();
|
||||
|
||||
QtServiceBase::instance()->logMessage("Wrote to client");
|
||||
|
||||
if (socket->state() == QTcpSocket::UnconnectedState) {
|
||||
delete socket;
|
||||
QtServiceBase::instance()->logMessage("Connection closed");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HttpDaemon::discardClient()
|
||||
{
|
||||
QTcpSocket* socket = (QTcpSocket*)sender();
|
||||
socket->deleteLater();
|
||||
|
||||
QtServiceBase::instance()->logMessage("Connection closed");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
HttpService::HttpService(int argc, char **argv)
|
||||
: QtService<QCoreApplication>(argc, argv, "Qt HTTP Daemon")
|
||||
{
|
||||
setServiceDescription("A dummy HTTP service implemented with Qt");
|
||||
setServiceFlags(QtServiceBase::CanBeSuspended);
|
||||
}
|
||||
|
||||
void HttpService::start()
|
||||
{
|
||||
QCoreApplication *app = application();
|
||||
daemon = new HttpDaemon(8989, app);
|
||||
|
||||
if (!daemon->isListening()) {
|
||||
logMessage(QString("Failed to bind to port %1").arg(daemon->serverPort()), QtServiceBase::Error);
|
||||
app->quit();
|
||||
}
|
||||
}
|
||||
|
||||
void HttpService::pause()
|
||||
{
|
||||
daemon->pause();
|
||||
}
|
||||
|
||||
void HttpService::resume()
|
||||
{
|
||||
daemon->resume();
|
||||
}
|
||||
|
|
@ -1,43 +0,0 @@
|
|||
#ifndef SERVER_H
|
||||
#define SERVER_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
#include <QTcpServer>
|
||||
|
||||
#include "qtservice.h"
|
||||
|
||||
|
||||
class HttpDaemon : public QTcpServer
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
HttpDaemon(quint16 port, QObject* parent = 0);
|
||||
void sendFortune();
|
||||
|
||||
void pause();
|
||||
void resume();
|
||||
|
||||
private slots:
|
||||
void readClient();
|
||||
void discardClient();
|
||||
private:
|
||||
bool disabled;
|
||||
};
|
||||
|
||||
|
||||
class HttpService : public QtService<QCoreApplication>
|
||||
{
|
||||
public:
|
||||
HttpService(int argc, char **argv);
|
||||
|
||||
protected:
|
||||
void pause();
|
||||
void resume();
|
||||
void start();
|
||||
|
||||
private:
|
||||
HttpDaemon *daemon;
|
||||
};
|
||||
|
||||
|
||||
#endif // SERVER_H
|
||||
|
|
@ -1,13 +1,22 @@
|
|||
TARGET = AmneziaVPN-service
|
||||
TEMPLATE = app
|
||||
CONFIG += console qt
|
||||
QT = core network
|
||||
CONFIG += console qt no_batch
|
||||
QT += core network
|
||||
|
||||
HEADERS = \
|
||||
server.h
|
||||
../../client/message.h \
|
||||
../../client/utils.h \
|
||||
localserver.h \
|
||||
log.h \
|
||||
systemservice.h
|
||||
|
||||
SOURCES = \
|
||||
server.cpp \
|
||||
main.cpp
|
||||
../../client/message.cpp \
|
||||
../../client/utils.cpp \
|
||||
localserver.cpp \
|
||||
log.cpp \
|
||||
main.cpp \
|
||||
systemservice.cpp
|
||||
|
||||
include(../src/qtservice.pri)
|
||||
|
||||
|
|
@ -17,3 +26,5 @@ CONFIG(release, debug|release) {
|
|||
OBJECTS_DIR = $$DESTDIR
|
||||
RCC_DIR = $$DESTDIR
|
||||
}
|
||||
|
||||
INCLUDEPATH += "$$PWD/../../client"
|
||||
|
|
|
|||
24
service/server/systemservice.cpp
Normal file
24
service/server/systemservice.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include "defines.h"
|
||||
#include "localserver.h"
|
||||
#include "systemservice.h"
|
||||
|
||||
SystemService::SystemService(int argc, char **argv)
|
||||
: QtService<QCoreApplication>(argc, argv, SERVICE_NAME)
|
||||
{
|
||||
setServiceDescription("Service for AmneziaVPN");
|
||||
}
|
||||
|
||||
void SystemService::start()
|
||||
{
|
||||
QCoreApplication* app = application();
|
||||
m_localServer = new LocalServer(SERVICE_NAME);
|
||||
|
||||
if (!m_localServer->isRunning()) {
|
||||
app->quit();
|
||||
}
|
||||
}
|
||||
|
||||
void SystemService::stop()
|
||||
{
|
||||
delete m_localServer;
|
||||
}
|
||||
24
service/server/systemservice.h
Normal file
24
service/server/systemservice.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef SYSTEMSERVICE_H
|
||||
#define SYSTEMSERVICE_H
|
||||
|
||||
#include <QCoreApplication>
|
||||
|
||||
#include "qtservice.h"
|
||||
|
||||
class LocalServer;
|
||||
|
||||
class SystemService : public QtService<QCoreApplication>
|
||||
{
|
||||
|
||||
public:
|
||||
SystemService(int argc, char** argv);
|
||||
|
||||
protected:
|
||||
void start() override;
|
||||
void stop() override;
|
||||
|
||||
private:
|
||||
LocalServer* m_localServer;
|
||||
};
|
||||
|
||||
#endif // SYSTEMSERVICE_H
|
||||
Loading…
Add table
Add a link
Reference in a new issue