Add DriverWorker class.

This commit is contained in:
Nodir Temirkhodjaev 2017-09-04 16:39:15 +05:00
parent 1a6c63ba74
commit 187025b932
21 changed files with 397 additions and 59 deletions

View File

@ -3,9 +3,15 @@ include(../common/Test.pri)
SOURCES += \
$$UIPATH/activityLog/logbuffer.cpp \
$$UIPATH/activityLog/logentry.cpp \
$$UIPATH/fortcommon.cpp
$$UIPATH/fortcommon.cpp \
$$UIPATH/util/fileutil.cpp \
$$UIPATH/util/netutil.cpp \
$$UIPATH/util/processinfo.cpp
HEADERS += \
$$UIPATH/activityLog/logbuffer.h \
$$UIPATH/activityLog/logentry.h \
$$UIPATH/fortcommon.h
$$UIPATH/fortcommon.h \
$$UIPATH/util/fileutil.h \
$$UIPATH/util/netutil.h \
$$UIPATH/util/processinfo.h

View File

@ -25,13 +25,13 @@ void Test::logWriteRead()
// Write
for (int i = 0; i < testCount; ++i) {
QCOMPARE(buf.write(entry), entrySize);
QCOMPARE(buf.write(&entry), entrySize);
}
// Read
while (buf.read(entry)) {
while (buf.read(&entry)) {
QCOMPARE(entry.ip(), ip);
QCOMPARE(entry.pid(), pid);
QCOMPARE(entry.path(), path);
QCOMPARE(entry.dosPath(), path);
}
}

View File

@ -68,9 +68,9 @@ void Test::printLogs(LogBuffer &buf)
{
LogEntry entry;
while (buf.read(entry)) {
while (buf.read(&entry)) {
const quint32 pid = entry.pid();
QString dosPath = entry.path();
QString dosPath = entry.dosPath();
if (dosPath.isEmpty()) {
ProcessInfo pi(pid);

View File

@ -12,7 +12,8 @@ SOURCES += \
conf/addressgroup.cpp \
conf/appgroup.cpp \
conf/firewallconf.cpp \
drivermanager.cpp \
driver/drivermanager.cpp \
driver/driverworker.cpp \
fortcommon.cpp \
fortmanager.cpp \
fortsettings.cpp \
@ -29,7 +30,8 @@ HEADERS += \
conf/addressgroup.h \
conf/appgroup.h \
conf/firewallconf.h \
drivermanager.h \
driver/drivermanager.h \
driver/driverworker.h \
fortcommon.h \
fortmanager.h \
fortsettings.h \

View File

@ -7,7 +7,8 @@ LogBuffer::LogBuffer(int bufferSize, QObject *parent) :
QObject(parent),
m_top(0),
m_offset(0),
m_array(bufferSize, Qt::Uninitialized)
m_array(bufferSize ? bufferSize : FortCommon::bufferSize(),
Qt::Uninitialized)
{
}
@ -20,9 +21,9 @@ void LogBuffer::prepareFor(int len)
}
}
int LogBuffer::write(const LogEntry &logEntry)
int LogBuffer::write(const LogEntry *logEntry)
{
const QString path = logEntry.path();
const QString path = logEntry->dosPath();
const int pathLen = path.size() * sizeof(wchar_t);
const int entrySize = FortCommon::logSize(pathLen);
@ -30,7 +31,8 @@ int LogBuffer::write(const LogEntry &logEntry)
char *output = m_array.data() + m_top;
FortCommon::logHeaderWrite(output, logEntry.ip(), logEntry.pid(), pathLen);
FortCommon::logHeaderWrite(output, logEntry->ip(),
logEntry->pid(), pathLen);
output += FortCommon::logHeaderSize();
if (pathLen) {
@ -42,7 +44,7 @@ int LogBuffer::write(const LogEntry &logEntry)
return entrySize;
}
int LogBuffer::read(LogEntry &logEntry)
int LogBuffer::read(LogEntry *logEntry)
{
if (m_offset >= m_top)
return 0;
@ -59,9 +61,9 @@ int LogBuffer::read(LogEntry &logEntry)
pathLen / sizeof(wchar_t));
}
logEntry.setIp(ip);
logEntry.setPid(pid);
logEntry.setPath(path);
logEntry->setIp(ip);
logEntry->setPid(pid);
logEntry->setDosPath(path);
const int entrySize = FortCommon::logSize(pathLen);
m_offset += entrySize;

View File

@ -27,8 +27,8 @@ public slots:
m_offset = 0;
}
int write(const LogEntry &logEntry);
int read(LogEntry &logEntry);
int write(const LogEntry *logEntry);
int read(LogEntry *logEntry);
private:
void prepareFor(int len);

View File

@ -1,12 +1,16 @@
#include "logentry.h"
#include "../util/fileutil.h"
#include "../util/netutil.h"
#include "../util/processinfo.h"
LogEntry::LogEntry(quint32 ip, quint32 pid,
const QString &path,
const QString &dosPath,
QObject *parent) :
QObject(parent),
m_ip(ip),
m_pid(pid),
m_path(path)
m_dosPath(dosPath)
{
}
@ -26,10 +30,26 @@ void LogEntry::setPid(quint32 pid)
}
}
void LogEntry::setPath(const QString &path)
void LogEntry::setDosPath(const QString &dosPath)
{
if (m_path != path) {
m_path = path;
emit pathChanged();
if (m_dosPath != dosPath) {
m_dosPath = dosPath;
emit dosPathChanged();
}
}
QString LogEntry::ipText() const
{
return NetUtil::ip4ToText(m_ip);
}
QString LogEntry::path() const
{
QString dosPath = m_dosPath;
if (dosPath.isEmpty()) {
const ProcessInfo pi(m_pid);
dosPath = pi.dosPath();
}
return FileUtil::dosPathToPath(dosPath);
}

View File

@ -8,11 +8,13 @@ class LogEntry : public QObject
Q_OBJECT
Q_PROPERTY(quint32 ip READ ip WRITE setIp NOTIFY ipChanged)
Q_PROPERTY(quint32 pid READ pid WRITE setPid NOTIFY pidChanged)
Q_PROPERTY(QString path READ path WRITE setPath NOTIFY pathChanged)
Q_PROPERTY(QString dosPath READ dosPath WRITE setDosPath NOTIFY dosPathChanged)
Q_PROPERTY(QString ipText READ ipText NOTIFY ipChanged)
Q_PROPERTY(QString path READ path NOTIFY dosPathChanged)
public:
explicit LogEntry(quint32 ip = 0, quint32 pid = 0,
const QString &path = QString(),
const QString &dosPath = QString(),
QObject *parent = nullptr);
quint32 ip() const { return m_ip; }
@ -21,23 +23,23 @@ public:
quint32 pid() const { return m_pid; }
void setPid(quint32 pid);
QString path() const { return m_path; }
void setPath(const QString &path);
QString dosPath() const { return m_dosPath; }
void setDosPath(const QString &dosPath);
QString ipText() const;
QString path() const;
signals:
void ipChanged();
void pidChanged();
void pathChanged();
void dosPathChanged();
public slots:
private:
friend class LogBuffer;
private:
quint32 m_ip;
quint32 m_pid;
QString m_path;
QString m_dosPath;
};
#endif // LOGENTRY_H

View File

@ -119,6 +119,11 @@ void FirewallConf::copyFlags(const FirewallConf &o)
setAppGroupBits(o.appGroupBits());
}
void FirewallConf::copyTempFlags(const FirewallConf &o)
{
setAppLogBlocked(o.appLogBlocked());
}
QVariant FirewallConf::toVariant() const
{
QVariantMap map;

View File

@ -45,6 +45,7 @@ public:
QQmlListProperty<AppGroup> appGroups();
void copyFlags(const FirewallConf &o);
void copyTempFlags(const FirewallConf &o);
QVariant toVariant() const;
void fromVariant(const QVariant &v);

View File

@ -1,14 +1,30 @@
#include "drivermanager.h"
#include "fortcommon.h"
#include "conf/firewallconf.h"
#include "util/confutil.h"
#include "util/device.h"
#include <QThread>
#include "../activityLog/logbuffer.h"
#include "../activityLog/logentry.h"
#include "../fortcommon.h"
#include "../conf/firewallconf.h"
#include "../util/confutil.h"
#include "../util/device.h"
#include "driverworker.h"
DriverManager::DriverManager(QObject *parent) :
QObject(parent),
m_device(new Device(this))
m_device(new Device(this)),
m_driverWorker(new DriverWorker(m_device)), // no parent, delete later
m_workerThread(new QThread(this))
{
setupWorker();
}
DriverManager::~DriverManager()
{
cancelDeviceIo();
m_workerThread->quit();
m_workerThread->wait();
}
void DriverManager::setErrorMessage(const QString &errorMessage)
@ -19,16 +35,39 @@ void DriverManager::setErrorMessage(const QString &errorMessage)
}
}
void DriverManager::setupWorker()
{
m_driverWorker->moveToThread(m_workerThread);
connect(m_workerThread, &QThread::finished,
m_driverWorker, &QObject::deleteLater);
connect(m_driverWorker, &DriverWorker::readLogResult,
this, &DriverManager::readLogResult);
m_workerThread->start();
}
bool DriverManager::openDevice()
{
if (!m_device->open(FortCommon::deviceName())) {
setErrorMessage(m_device->getLastErrorMessage());
setErrorMessage(m_device->lastErrorMessage());
return false;
}
return true;
}
void DriverManager::enableDeviceIo()
{
m_driverWorker->enableIo();
}
bool DriverManager::cancelDeviceIo()
{
return m_driverWorker->cancelIo();
}
bool DriverManager::writeConf(const FirewallConf &conf)
{
ConfUtil confUtil;
@ -61,10 +100,20 @@ bool DriverManager::writeConfFlags(const FirewallConf &conf)
bool DriverManager::writeData(int code, QByteArray &buf, int size)
{
cancelDeviceIo();
if (!m_device->ioctl(code, buf.data(), size)) {
setErrorMessage(m_device->getLastErrorMessage());
setErrorMessage(m_device->lastErrorMessage());
return false;
}
return true;
}
void DriverManager::readLogAsync(LogBuffer *logBuffer)
{
cancelDeviceIo();
enableDeviceIo();
emit m_driverWorker->readLogAsync(logBuffer);
}

View File

@ -3,8 +3,12 @@
#include <QObject>
class QThread;
class Device;
class DriverWorker;
class FirewallConf;
class LogBuffer;
class DriverManager : public QObject
{
@ -13,25 +17,37 @@ class DriverManager : public QObject
public:
explicit DriverManager(QObject *parent = nullptr);
virtual ~DriverManager();
QString errorMessage() const { return m_errorMessage; }
signals:
void errorMessageChanged();
void readLogResult(bool success, const QString &errorMessage);
public slots:
bool openDevice();
void enableDeviceIo();
bool cancelDeviceIo();
bool writeConf(const FirewallConf &conf);
bool writeConfFlags(const FirewallConf &conf);
void readLogAsync(LogBuffer *logBuffer);
private:
void setErrorMessage(const QString &errorMessage);
void setupWorker();
bool writeData(int code, QByteArray &buf, int size);
private:
Device *m_device;
DriverWorker *m_driverWorker;
QThread *m_workerThread;
QString m_errorMessage;
};

View File

@ -0,0 +1,69 @@
#include "driverworker.h"
#include "../activityLog/logbuffer.h"
#include "../fortcommon.h"
#include "../util/device.h"
DriverWorker::DriverWorker(Device *device, QObject *parent) :
QObject(parent),
m_isWorking(false),
m_cancelled(false),
m_device(device)
{
connect(this, &DriverWorker::readLogAsync,
this, &DriverWorker::readLog, Qt::QueuedConnection);
}
void DriverWorker::enableIo()
{
m_mutex.lock();
m_cancelled = false;
m_mutex.unlock();
}
bool DriverWorker::cancelIo()
{
m_cancelled = true;
const bool res = m_isWorking ? m_device->cancelIo() : false;
m_mutex.lock();
while (m_isWorking) {
m_waitCondition.wait(&m_mutex);
}
m_mutex.unlock();
return res;
}
void DriverWorker::readLog(LogBuffer *logBuffer)
{
QByteArray &array = logBuffer->array();
int nr;
bool success;
QString errorMessage;
m_mutex.lock();
if (!m_cancelled) {
m_isWorking = true;
success = m_device->ioctl(
FortCommon::ioctlGetLog(), nullptr, 0,
array.data(), array.size(), &nr);
m_isWorking = false;
errorMessage = m_cancelled
? QString() : m_device->lastErrorMessage();
if (m_cancelled) {
m_waitCondition.wakeOne();
}
}
m_mutex.unlock();
if (success) {
logBuffer->reset(nr);
}
emit readLogResult(success, errorMessage);
}

View File

@ -0,0 +1,39 @@
#ifndef DRIVERWORKER_H
#define DRIVERWORKER_H
#include <QMutex>
#include <QObject>
#include <QWaitCondition>
class Device;
class LogBuffer;
class DriverWorker : public QObject
{
Q_OBJECT
public:
explicit DriverWorker(Device *device, QObject *parent = nullptr);
signals:
void readLogAsync(LogBuffer *logBuffer);
void readLogResult(bool success, const QString &errorMessage);
public slots:
void enableIo();
bool cancelIo();
private slots:
void readLog(LogBuffer *logBuffer);
private:
volatile bool m_isWorking;
volatile bool m_cancelled;
Device *m_device;
QMutex m_mutex;
QWaitCondition m_waitCondition;
};
#endif // DRIVERWORKER_H

View File

@ -8,10 +8,12 @@
#include <QSystemTrayIcon>
#include <QWindow>
#include "activityLog/logbuffer.h"
#include "activityLog/logentry.h"
#include "conf/addressgroup.h"
#include "conf/appgroup.h"
#include "conf/firewallconf.h"
#include "drivermanager.h"
#include "driver/drivermanager.h"
#include "fortsettings.h"
FortManager::FortManager(QObject *parent) :
@ -33,14 +35,19 @@ FortManager::FortManager(QObject *parent) :
void FortManager::registerQmlTypes()
{
qmlRegisterUncreatableType<FortManager>("com.fortfirewall", 1, 0, "FortManager",
"Singleton");
qmlRegisterUncreatableType<DriverManager>("com.fortfirewall", 1, 0, "DriverManager",
"Singleton");
qmlRegisterUncreatableType<FortSettings>("com.fortfirewall", 1, 0, "FortSettings",
"Singleton");
qmlRegisterUncreatableType<FortSettings>("com.fortfirewall", 1, 0, "FortSettings",
"Singleton");
qmlRegisterType<AddressGroup>("com.fortfirewall", 1, 0, "AddressGroup");
qmlRegisterType<AppGroup>("com.fortfirewall", 1, 0, "AppGroup");
qmlRegisterType<FirewallConf>("com.fortfirewall", 1, 0, "FirewallConf");
qmlRegisterType<LogBuffer>("com.fortfirewall", 1, 0, "LogBuffer");
qmlRegisterType<LogEntry>("com.fortfirewall", 1, 0, "LogEntry");
}
void FortManager::setupTrayIcon()
@ -114,7 +121,12 @@ bool FortManager::saveConf()
bool FortManager::applyConf()
{
Q_ASSERT(m_firewallConfToEdit != nullConf());
return saveSettings(cloneConf(*m_firewallConfToEdit));
FirewallConf *newConf = cloneConf(*m_firewallConfToEdit);
newConf->copyTempFlags(*m_firewallConf);
return saveSettings(newConf);
}
void FortManager::setFirewallConfToEdit(FirewallConf *conf)
@ -149,6 +161,24 @@ bool FortManager::saveSettings(FirewallConf *newConf)
return true;
}
bool FortManager::updateDriverFlags(FirewallConf *conf)
{
// Update driver
if (!m_driverManager->writeConfFlags(*conf)) {
showErrorBox(m_driverManager->errorMessage());
return false;
}
return true;
}
void FortManager::setAppLogBlocked(bool enable)
{
m_firewallConf->setAppLogBlocked(enable);
updateDriverFlags(m_firewallConf);
}
void FortManager::saveTrayFlags()
{
m_firewallConf->setFilterEnabled(m_filterEnabledAction->isChecked());
@ -167,10 +197,7 @@ void FortManager::saveTrayFlags()
m_fortSettings->writeConfFlags(*m_firewallConf);
// Update driver
if (!m_driverManager->writeConfFlags(*m_firewallConf)) {
showErrorBox(m_driverManager->errorMessage());
}
updateDriverFlags(m_firewallConf);
}
FirewallConf *FortManager::cloneConf(const FirewallConf &conf)

View File

@ -10,12 +10,14 @@ class QSystemTrayIcon;
class DriverManager;
class FortSettings;
class FirewallConf;
class LogBuffer;
class FortManager : public QObject
{
Q_OBJECT
Q_PROPERTY(FortSettings *fortSettings READ fortSettings CONSTANT)
Q_PROPERTY(FirewallConf *firewallConfToEdit READ firewallConfToEdit NOTIFY firewallConfToEditChanged)
Q_PROPERTY(DriverManager *driverManager READ driverManager CONSTANT)
public:
explicit FortManager(QObject *parent = nullptr);
@ -26,6 +28,8 @@ public:
return m_firewallConfToEdit ? m_firewallConfToEdit : m_firewallConf;
}
DriverManager *driverManager() const { return m_driverManager; }
signals:
void firewallConfToEditChanged();
@ -42,6 +46,8 @@ public slots:
bool saveConf();
bool applyConf();
void setAppLogBlocked(bool enable);
private slots:
void saveTrayFlags();
@ -56,6 +62,7 @@ private:
void setupEngine();
bool saveSettings(FirewallConf *newConf);
bool updateDriverFlags(FirewallConf *conf);
FirewallConf *cloneConf(const FirewallConf &conf);

View File

@ -26,7 +26,9 @@ ApplicationWindow {
onVisibleChanged: {
if (visible) {
mainPage.initialize();
mainPage.opened();
} else {
mainPage.closed();
}
}

View File

@ -5,17 +5,99 @@ import com.fortfirewall 1.0
BasePage {
readonly property DriverManager driverManager: fortManager.driverManager
property bool enableLogReading: false
property var appPaths: []
property var appPathsMap: ({})
function readLogAsync() {
driverManager.readLogAsync(logBuffer);
}
function cancelDeviceIo() {
driverManager.cancelDeviceIo();
}
function switchLogReading(enable) {
enableLogReading = enable;
fortManager.setAppLogBlocked(enable);
if (enable) {
readLogAsync();
} else {
cancelDeviceIo();
}
}
function clearAppPaths() {
appPaths = ([]);
appPathsMap = ({});
}
function processLogBuffer() {
while (logBuffer.read(logEntry)) {
var path = logEntry.path;
var ipText = logEntry.ipText;
console.log(">", path, ipText);
var ipTextsMap = appPathsMap[path];
if (!ipTextsMap) {
ipTextsMap = ({});
appPathsMap[path] = ipTextsMap;
}
ipTextsMap[ipText] = (ipTextsMap[ipText] || 0) + 1;
}
}
Connections {
target: mainPage
onClosed: switchLogReading(false)
}
Connections {
target: driverManager
onReadLogResult: {
if (success) {
processLogBuffer();
}
if (enableLogReading) {
readLogAsync();
}
}
}
LogBuffer {
id: logBuffer
}
LogEntry {
id: logEntry
}
ColumnLayout {
anchors.fill: parent
Switch {
anchors.right: parent.right
onToggled: {
firewallConf.appLogBlocked = checked;
RowLayout {
Button {
text: QT_TRANSLATE_NOOP("qml", "Clear")
onClicked: clearAppPaths()
}
Item {
Layout.fillWidth: true
}
Switch {
text: QT_TRANSLATE_NOOP("qml", "Show Blocked Applications and Addresses")
onToggled: switchLogReading(checked)
}
}
GridView {
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
}

View File

@ -6,9 +6,11 @@ import com.fortfirewall 1.0
Page {
id: mainPage
signal opened()
signal closed()
signal saved()
function initialize() {
onOpened: {
tabBar.currentItem.forceActiveFocus();
}

View File

@ -40,6 +40,11 @@ bool Device::close()
return res;
}
bool Device::cancelIo()
{
return CancelIoEx(m_handle, NULL);
}
bool Device::ioctl(int code, char *in, int inSize,
char *out, int outSize,
int *retSize)
@ -57,10 +62,10 @@ bool Device::ioctl(int code, char *in, int inSize,
return res;
}
QString Device::getLastErrorMessage()
QString Device::lastErrorMessage()
{
const DWORD err = GetLastError();
LPWSTR buf = nullptr;
LPWSTR buf = NULL;
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM

View File

@ -11,7 +11,7 @@ public:
explicit Device(QObject *parent = nullptr);
virtual ~Device();
static QString getLastErrorMessage();
static QString lastErrorMessage();
signals:
@ -19,6 +19,8 @@ public slots:
bool open(const QString &filePath);
bool close();
bool cancelIo();
bool ioctl(int code, char *in = nullptr, int inSize = 0,
char *out = nullptr, int outSize = 0,
int *retSize = nullptr);