diff --git a/src/tests/logbuffer/test.cpp b/src/tests/logbuffer/test.cpp index 73cc79b2..d6586727 100644 --- a/src/tests/logbuffer/test.cpp +++ b/src/tests/logbuffer/test.cpp @@ -25,14 +25,20 @@ void Test::logWriteRead() // Write for (int i = 0; i < testCount; ++i) { - QCOMPARE(buf.write(&entry), entrySize); + buf.writeEntryBlocked(&entry); } // Read - while (buf.read(&entry)) { + int readCount = 0; + while (buf.peekEntryType() == LogEntry::AppBlocked) { + buf.readEntryBlocked(&entry); + QCOMPARE(entry.type(), LogEntry::AppBlocked); QCOMPARE(entry.ip(), ip); QCOMPARE(entry.pid(), pid); QCOMPARE(entry.kernelPath(), path); + + ++readCount; } + QCOMPARE(readCount, testCount); } diff --git a/src/tests/logreader/test.cpp b/src/tests/logreader/test.cpp index 775e874a..8cc18f47 100644 --- a/src/tests/logreader/test.cpp +++ b/src/tests/logreader/test.cpp @@ -71,7 +71,7 @@ void Test::setConf(Device &device) void Test::printLogs(LogBuffer &buf) { forever { - const LogEntry::LogType logType = buf.readType(); + const LogEntry::LogType logType = buf.peekEntryType(); if (logType == LogEntry::TypeNone) break; @@ -79,8 +79,7 @@ void Test::printLogs(LogBuffer &buf) LogEntryBlocked entry; - if (!buf.read(&entry)) - break; + buf.readEntryBlocked(&entry); const quint32 pid = entry.pid(); QString kernelPath = entry.kernelPath(); diff --git a/src/ui/FortFirewall.pro b/src/ui/FortFirewall.pro index 0b1802eb..4d2b59bf 100644 --- a/src/ui/FortFirewall.pro +++ b/src/ui/FortFirewall.pro @@ -7,10 +7,6 @@ TEMPLATE = app SOURCES += \ main.cpp \ - log/logbuffer.cpp \ - log/logentry.cpp \ - log/logentryblocked.cpp \ - log/logmanager.cpp \ conf/addressgroup.cpp \ conf/appgroup.cpp \ conf/firewallconf.cpp \ @@ -19,6 +15,12 @@ SOURCES += \ fortcommon.cpp \ fortmanager.cpp \ fortsettings.cpp \ + log/logbuffer.cpp \ + log/logentry.cpp \ + log/logentryblocked.cpp \ + log/logmanager.cpp \ + log/model/appblockedmodel.cpp \ + log/model/stringlistmodel.cpp \ mainwindow.cpp \ task/taskinfo.cpp \ task/taskmanager.cpp \ @@ -40,10 +42,6 @@ SOURCES += \ util/stringutil.cpp HEADERS += \ - log/logbuffer.h \ - log/logentry.h \ - log/logentryblocked.h \ - log/logmanager.h \ conf/addressgroup.h \ conf/appgroup.h \ conf/firewallconf.h \ @@ -52,6 +50,12 @@ HEADERS += \ fortcommon.h \ fortmanager.h \ fortsettings.h \ + log/logbuffer.h \ + log/logentry.h \ + log/logentryblocked.h \ + log/logmanager.h \ + log/model/appblockedmodel.h \ + log/model/stringlistmodel.h \ mainwindow.h \ task/taskinfo.h \ task/taskmanager.h \ diff --git a/src/ui/fortmanager.cpp b/src/ui/fortmanager.cpp index 8baf4fa4..45fb02b7 100644 --- a/src/ui/fortmanager.cpp +++ b/src/ui/fortmanager.cpp @@ -34,7 +34,7 @@ FortManager::FortManager(FortSettings *fortSettings, m_firewallConf(new FirewallConf(this)), m_firewallConfToEdit(nullConf()), m_driverManager(new DriverManager(this)), - m_logManager(new LogManager(m_driverManager->driverWorker(), m_driverManager)), + m_logManager(new LogManager(m_driverManager->driverWorker(), this)), m_taskManager(new TaskManager(this, this)) { setupDriver(); diff --git a/src/ui/log/logbuffer.cpp b/src/ui/log/logbuffer.cpp index 001aa6fd..26705ffc 100644 --- a/src/ui/log/logbuffer.cpp +++ b/src/ui/log/logbuffer.cpp @@ -31,7 +31,7 @@ void LogBuffer::prepareFor(int len) } } -LogEntry::LogType LogBuffer::readType() +LogEntry::LogType LogBuffer::peekEntryType() { if (m_offset >= m_top) return LogEntry::TypeNone; @@ -43,7 +43,7 @@ LogEntry::LogType LogBuffer::readType() return static_cast(type); } -int LogBuffer::write(const LogEntryBlocked *logEntry) +void LogBuffer::writeEntryBlocked(const LogEntryBlocked *logEntry) { const QString path = logEntry->kernelPath(); const int pathLen = path.size() * sizeof(wchar_t); @@ -62,14 +62,11 @@ int LogBuffer::write(const LogEntryBlocked *logEntry) } m_top += entrySize; - - return entrySize; } -int LogBuffer::read(LogEntryBlocked *logEntry) +void LogBuffer::readEntryBlocked(LogEntryBlocked *logEntry) { - if (m_offset >= m_top) - return 0; + Q_ASSERT(m_offset < m_top); const char *input = this->input(); @@ -89,6 +86,4 @@ int LogBuffer::read(LogEntryBlocked *logEntry) const int entrySize = FortCommon::logBlockedSize(pathLen); m_offset += entrySize; - - return entrySize; } diff --git a/src/ui/log/logbuffer.h b/src/ui/log/logbuffer.h index 927f063f..40f963b0 100644 --- a/src/ui/log/logbuffer.h +++ b/src/ui/log/logbuffer.h @@ -21,7 +21,10 @@ public: QByteArray &array() { return m_array; } - LogEntry::LogType readType(); + LogEntry::LogType peekEntryType(); + + void writeEntryBlocked(const LogEntryBlocked *logEntry); + void readEntryBlocked(LogEntryBlocked *logEntry); signals: @@ -31,9 +34,6 @@ public slots: m_offset = 0; } - int write(const LogEntryBlocked *logEntry); - int read(LogEntryBlocked *logEntry); - private: char *output(); const char *input() const; diff --git a/src/ui/log/logentry.cpp b/src/ui/log/logentry.cpp index f2bf7e94..3b5124b8 100644 --- a/src/ui/log/logentry.cpp +++ b/src/ui/log/logentry.cpp @@ -1,6 +1,9 @@ #include "logentry.h" -LogEntry::LogEntry(QObject *parent) : - QObject(parent) +LogEntry::LogEntry() +{ +} + +LogEntry::~LogEntry() { } diff --git a/src/ui/log/logentry.h b/src/ui/log/logentry.h index fe66615e..b6af2401 100644 --- a/src/ui/log/logentry.h +++ b/src/ui/log/logentry.h @@ -3,11 +3,8 @@ #include -class LogEntry : public QObject +class LogEntry { - Q_OBJECT - Q_PROPERTY(LogType type READ type CONSTANT) - public: enum LogType { TypeNone = -1, @@ -15,9 +12,9 @@ public: AppBlocked = 0x01000000, UsageStat = 0x02000000 }; - Q_ENUM(LogType) - explicit LogEntry(QObject *parent = nullptr); + explicit LogEntry(); + virtual ~LogEntry(); virtual LogEntry::LogType type() const = 0; }; diff --git a/src/ui/log/logentryblocked.cpp b/src/ui/log/logentryblocked.cpp index 2ac94338..a3ccac80 100644 --- a/src/ui/log/logentryblocked.cpp +++ b/src/ui/log/logentryblocked.cpp @@ -1,9 +1,8 @@ #include "logentryblocked.h" LogEntryBlocked::LogEntryBlocked(quint32 ip, quint32 pid, - const QString &kernelPath, - QObject *parent) : - LogEntry(parent), + const QString &kernelPath) : + LogEntry(), m_ip(ip), m_pid(pid), m_kernelPath(kernelPath) @@ -12,24 +11,15 @@ LogEntryBlocked::LogEntryBlocked(quint32 ip, quint32 pid, void LogEntryBlocked::setIp(quint32 ip) { - if (m_ip != ip) { - m_ip = ip; - emit ipChanged(); - } + m_ip = ip; } void LogEntryBlocked::setPid(quint32 pid) { - if (m_pid != pid) { - m_pid = pid; - emit pidChanged(); - } + m_pid = pid; } void LogEntryBlocked::setKernelPath(const QString &kernelPath) { - if (m_kernelPath != kernelPath) { - m_kernelPath = kernelPath; - emit kernelPathChanged(); - } + m_kernelPath = kernelPath; } diff --git a/src/ui/log/logentryblocked.h b/src/ui/log/logentryblocked.h index e9c3faca..cda22672 100644 --- a/src/ui/log/logentryblocked.h +++ b/src/ui/log/logentryblocked.h @@ -5,15 +5,9 @@ class LogEntryBlocked : public LogEntry { - 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 kernelPath READ kernelPath WRITE setKernelPath NOTIFY kernelPathChanged) - public: explicit LogEntryBlocked(quint32 ip = 0, quint32 pid = 0, - const QString &kernelPath = QString(), - QObject *parent = nullptr); + const QString &kernelPath = QString()); virtual LogEntry::LogType type() const { return AppBlocked; } @@ -26,13 +20,6 @@ public: QString kernelPath() const { return m_kernelPath; } void setKernelPath(const QString &kernelPath); -signals: - void ipChanged(); - void pidChanged(); - void kernelPathChanged(); - -public slots: - private: quint32 m_ip; quint32 m_pid; diff --git a/src/ui/log/logmanager.cpp b/src/ui/log/logmanager.cpp index ff67d2b0..bd2c6ff5 100644 --- a/src/ui/log/logmanager.cpp +++ b/src/ui/log/logmanager.cpp @@ -3,17 +3,24 @@ #include "../driver/driverworker.h" #include "../fortcommon.h" #include "logbuffer.h" +#include "logentryblocked.h" +#include "model/appblockedmodel.h" LogManager::LogManager(DriverWorker *driverWorker, QObject *parent) : QObject(parent), m_logReadingEnabled(false), m_driverWorker(driverWorker), - m_logBuffer(new LogBuffer(FortCommon::bufferSize(), this)) + m_appBlockedModel(new AppBlockedModel(this)) { setupDriverWorker(); } +QAbstractItemModel *LogManager::appBlockedModel() const +{ + return m_appBlockedModel; +} + void LogManager::setErrorMessage(const QString &errorMessage) { if (m_errorMessage != errorMessage) { @@ -28,7 +35,7 @@ void LogManager::setLogReadingEnabled(bool enabled) m_logReadingEnabled = enabled; if (m_logReadingEnabled) { - readLogAsync(m_logBuffer); + readLogAsync(getFreeBuffer()); } else { cancelAsyncIo(); readLogAsync(nullptr); @@ -52,17 +59,48 @@ void LogManager::cancelAsyncIo() m_driverWorker->cancelAsyncIo(); } +LogBuffer *LogManager::getFreeBuffer() +{ + if (m_freeBuffers.isEmpty()) { + return new LogBuffer(FortCommon::bufferSize(), this); + } else { + return m_freeBuffers.takeLast(); + } +} + void LogManager::processLogBuffer(LogBuffer *logBuffer, bool success, const QString &errorMessage) { - Q_ASSERT(logBuffer == m_logBuffer); + if (m_logReadingEnabled) { + readLogAsync(getFreeBuffer()); + } if (success) { + readLogEntries(logBuffer); + logBuffer->reset(); } else { setErrorMessage(errorMessage); } - if (m_logReadingEnabled) { - readLogAsync(m_logBuffer); + m_freeBuffers.append(logBuffer); +} + +void LogManager::readLogEntries(LogBuffer *logBuffer) +{ + LogEntryBlocked entryBlocked; + + forever { + switch (logBuffer->peekEntryType()) { + case LogEntry::AppBlocked: { + logBuffer->readEntryBlocked(&entryBlocked); + m_appBlockedModel->addLogEntry(entryBlocked); + break; + } + case LogEntry::UsageStat: { + //break; + } + default: + return; + } } } diff --git a/src/ui/log/logmanager.h b/src/ui/log/logmanager.h index fa793235..05b59349 100644 --- a/src/ui/log/logmanager.h +++ b/src/ui/log/logmanager.h @@ -1,10 +1,13 @@ #ifndef LOGMANAGER_H #define LOGMANAGER_H +#include #include +class AppBlockedModel; class DriverWorker; class LogBuffer; +class LogEntry; class LogManager : public QObject { @@ -21,6 +24,8 @@ signals: void errorMessageChanged(); public slots: + QAbstractItemModel *appBlockedModel() const; + void setLogReadingEnabled(bool enabled); private slots: @@ -35,11 +40,17 @@ private: void readLogAsync(LogBuffer *logBuffer); void cancelAsyncIo(); + LogBuffer *getFreeBuffer(); + + void readLogEntries(LogBuffer *logBuffer); + private: bool m_logReadingEnabled; DriverWorker *m_driverWorker; - LogBuffer *m_logBuffer; + QList m_freeBuffers; + + AppBlockedModel *m_appBlockedModel; QString m_errorMessage; }; diff --git a/src/ui/log/model/appblockedmodel.cpp b/src/ui/log/model/appblockedmodel.cpp new file mode 100644 index 00000000..293c7fa9 --- /dev/null +++ b/src/ui/log/model/appblockedmodel.cpp @@ -0,0 +1,51 @@ +#include "appblockedmodel.h" + +#include "../../util/fileutil.h" +#include "../../util/net/netutil.h" +#include "../../util/osutil.h" +#include "../logentryblocked.h" + +#define IP_LIST_COUNT_MAX 64 + +AppBlockedModel::AppBlockedModel(QObject *parent) : + StringListModel(parent) +{ +} + +void AppBlockedModel::addLogEntry(const LogEntryBlocked &logEntry) +{ + const QString appPath = getEntryPath(logEntry); + const QString ipText = NetUtil::ip4ToText(logEntry.ip()); + bool isNewApp = false; + + if (!m_appIpList.contains(appPath)) { + m_appIpList.insert(appPath, QStringList()); + m_appIpSet.insert(appPath, QSet()); + isNewApp = true; + } + + QSet &ipSet = m_appIpSet[appPath]; + if (ipSet.contains(ipText)) + return; + + ipSet.insert(ipText); + + QStringList &ipList = m_appIpList[appPath]; + ipList.prepend(ipText); + + if (isNewApp) { + insert(appPath); + } else if (ipList.size() > IP_LIST_COUNT_MAX) { + const QString oldIpText = ipList.takeLast(); + ipSet.remove(oldIpText); + } +} + +QString AppBlockedModel::getEntryPath(const LogEntryBlocked &logEntry) +{ + const QString kernelPath = logEntry.kernelPath(); + + return kernelPath.isEmpty() + ? OsUtil::pidToPath(logEntry.pid()) + : FileUtil::kernelPathToPath(kernelPath); +} diff --git a/src/ui/log/model/appblockedmodel.h b/src/ui/log/model/appblockedmodel.h new file mode 100644 index 00000000..39c27303 --- /dev/null +++ b/src/ui/log/model/appblockedmodel.h @@ -0,0 +1,32 @@ +#ifndef APPBLOCKEDMODEL_H +#define APPBLOCKEDMODEL_H + +#include +#include + +#include "stringlistmodel.h" + +class LogEntryBlocked; + +class AppBlockedModel : public StringListModel +{ + Q_OBJECT + +public: + explicit AppBlockedModel(QObject *parent = nullptr); + + void addLogEntry(const LogEntryBlocked &logEntry); + +signals: + +public slots: + +private: + static QString getEntryPath(const LogEntryBlocked &logEntry); + +private: + QHash m_appIpList; + QHash> m_appIpSet; +}; + +#endif // APPBLOCKEDMODEL_H diff --git a/src/ui/log/model/stringlistmodel.cpp b/src/ui/log/model/stringlistmodel.cpp new file mode 100644 index 00000000..0992a572 --- /dev/null +++ b/src/ui/log/model/stringlistmodel.cpp @@ -0,0 +1,55 @@ +#include "stringlistmodel.h" + +StringListModel::StringListModel(QObject *parent) : + QAbstractListModel(parent) +{ +} + +int StringListModel::rowCount(const QModelIndex &parent) const +{ + Q_UNUSED(parent) + + return m_list.size(); +} + +QVariant StringListModel::data(const QModelIndex &index, int role) const +{ + if (role == Qt::DisplayRole && index.isValid()) { + return m_list.at(index.row()); + } + return QVariant(); +} + +void StringListModel::insert(const QString &text, int row) +{ + row = adjustRow(row); + + beginInsertRows(QModelIndex(), row, row); + m_list.insert(row, text); + endInsertRows(); +} + +void StringListModel::remove(int row) +{ + row = adjustRow(row); + + beginRemoveRows(QModelIndex(), row, row); + m_list.removeAt(row); + endRemoveRows(); +} + +void StringListModel::replace(const QString &text, int row) +{ + row = adjustRow(row); + + m_list.replace(row, text); + + const QModelIndex modelIndex = index(row); + + dataChanged(modelIndex, modelIndex); +} + +int StringListModel::adjustRow(int row) const +{ + return (row < 0) ? (m_list.size() + 1 + row) : row; +} diff --git a/src/ui/log/model/stringlistmodel.h b/src/ui/log/model/stringlistmodel.h new file mode 100644 index 00000000..3daa9f14 --- /dev/null +++ b/src/ui/log/model/stringlistmodel.h @@ -0,0 +1,33 @@ +#ifndef STRINGLISTMODEL_H +#define STRINGLISTMODEL_H + +#include +#include + +class StringListModel : public QAbstractListModel +{ + Q_OBJECT + +public: + explicit StringListModel(QObject *parent = nullptr); + + int rowCount(const QModelIndex &parent = QModelIndex()) const override; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + +protected: + void insert(const QString &text, int row = -1); + void remove(int row = -1); + void replace(const QString &text, int row = -1); + +signals: + +public slots: + +private: + int adjustRow(int row) const; + +private: + QStringList m_list; +}; + +#endif // STRINGLISTMODEL_H