Compare commits
175 Commits
find-repla
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
318fe124bf | ||
|
b3ac5f8d5d | ||
|
f185ceb206 | ||
|
cf84060277 | ||
|
469e0b054e | ||
|
23ee0e6f00 | ||
|
f3dccb9484 | ||
|
8f89c577ef | ||
|
71435869cf | ||
|
f779b0138b | ||
|
8c58d8610f | ||
|
c285e91d4a | ||
|
f5350663cd | ||
|
483f7fb4c5 | ||
|
d067019959 | ||
|
eb9d5eaf1a | ||
|
e677dc7d16 | ||
|
ebe6aef62d | ||
|
1e8486991d | ||
|
fff61d7773 | ||
|
eb3331f74d | ||
|
f3f553d149 | ||
|
49cb7c40e0 | ||
|
5581118e2f | ||
|
3bcd31a1ea | ||
|
268fad0690 | ||
|
28b308ce6c | ||
|
bfda96a888 | ||
|
a2734647b6 | ||
|
5eb2ad1979 | ||
|
1fa84ec644 | ||
|
c044880f1a | ||
|
2941c7ec22 | ||
|
ee45aaf0eb | ||
|
5ec7010c51 | ||
|
bef0f1d162 | ||
|
598e6bf243 | ||
|
63ed64a9d2 | ||
|
8ef9da062d | ||
|
7fee90313e | ||
|
bafdd948f8 | ||
|
e138fa0d3d | ||
|
8583299a1c | ||
|
4ba98cc520 | ||
|
649fa03575 | ||
|
650c098370 | ||
|
d375736a39 | ||
|
976fc72de8 | ||
|
4426a51d0f | ||
|
3c6632b6a2 | ||
|
d3be505a0c | ||
|
70f1b6c6e6 | ||
|
d65fea00d5 | ||
|
0afc150264 | ||
|
6ba942d00f | ||
|
4ee91c1bc2 | ||
|
aebb609e37 | ||
|
7160f724cb | ||
|
a48a11fe02 | ||
|
91a6efdeb7 | ||
|
bfdcee2baa | ||
|
c2967b663d | ||
|
70b5e60440 | ||
|
5540253e61 | ||
|
8ecbe78ddd | ||
|
3e3b5144aa | ||
|
596df69519 | ||
|
680f6eb89f | ||
|
1b18149aaa | ||
|
bf749847e0 | ||
|
ab713ce043 | ||
|
fc2d8408fa | ||
|
39c8d6f5f3 | ||
|
219ad576ad | ||
|
3060701386 | ||
|
47325c38b0 | ||
|
21ce331c43 | ||
|
fd2fae711b | ||
|
2d998b3708 | ||
|
f65aed7bb0 | ||
|
fdf8c77350 | ||
|
429eff123d | ||
|
3c98900092 | ||
|
159cd7c0da | ||
|
46b148b62b | ||
|
f29d31d38a | ||
|
1056b8d170 | ||
|
4a4de23d8a | ||
|
425e4ef261 | ||
|
d950432bc9 | ||
|
9849973562 | ||
|
4f6749f16d | ||
|
8dbd01622c | ||
|
2f3add63d8 | ||
|
7b7ede351b | ||
|
c70811eaa4 | ||
|
e2369c02bc | ||
|
c07d9e8691 | ||
|
d44fdf4ae7 | ||
|
f07cba39d5 | ||
|
1e50f9b095 | ||
|
3cea0244d4 | ||
|
8d3f0c807f | ||
|
449a489986 | ||
|
b645e02963 | ||
|
32ddf223b6 | ||
|
42091e5221 | ||
|
82db82d85b | ||
|
e9fa8a0c5b | ||
|
027b0562de | ||
|
c82cccc5eb | ||
|
94a6423a96 | ||
|
cda08d9afb | ||
|
97068b97e3 | ||
|
06ad12777f | ||
|
2970a292c6 | ||
|
701a058c7d | ||
|
2103f2c5a6 | ||
|
4be8a2969d | ||
|
46a54fd56b | ||
|
d32f89d30b | ||
|
1b647ade1b | ||
|
789338c8e1 | ||
|
898b56fc76 | ||
|
9d42ed12cc | ||
|
c949dc6682 | ||
|
eb2ca12f32 | ||
|
e79b61b189 | ||
|
741202ca76 | ||
|
843733567a | ||
|
6f4ef70dbc | ||
|
b296c5fddd | ||
|
d9cd90a13d | ||
|
fb879d2c72 | ||
|
5e7bf77b0c | ||
|
a1d985e44b | ||
|
b8d5d9421f | ||
|
2868806f3f | ||
|
ccf5b5ca47 | ||
|
c03038167c | ||
|
de9018166d | ||
|
c0d860b92d | ||
|
81c975d6d1 | ||
|
1854f1ab9e | ||
|
5a91dc4561 | ||
|
3d6f39e84d | ||
|
60f61ed947 | ||
|
26d0c8ab9c | ||
|
25a91e52f6 | ||
|
c8cc7a021f | ||
|
564687ffe3 | ||
|
9d4aaa4f7b | ||
|
329469dd6e | ||
|
7374c74b95 | ||
|
6f433bb7a1 | ||
|
2ee19da15c | ||
|
22b8c405f7 | ||
|
2ce7f0c7a0 | ||
|
041f500e65 | ||
|
7dd070fd98 | ||
|
ac52844b3f | ||
|
2bf2973a23 | ||
|
341d0c3be8 | ||
|
6534312968 | ||
|
a089cc1751 | ||
|
b0a81fb231 | ||
|
735e960dcb | ||
|
226705f015 | ||
|
45d5e15f23 | ||
|
d09d83000e | ||
|
0f322fb2d8 | ||
|
0587e22de9 | ||
|
5045b7f273 | ||
|
a89400a4e5 | ||
|
73dd198069 |
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
github: pstavirs
|
@ -13,11 +13,11 @@ I have been developing and maintaining Ostinato [single-handedly](https://github
|
|||||||
|
|
||||||
I sell binary licenses on [ostinato.org](https://ostinato.org/downloads) to try and cover the costs of development. Please consider buying those - they are priced low enough that you can afford it or you could just as easily expense them to your organisation.
|
I sell binary licenses on [ostinato.org](https://ostinato.org/downloads) to try and cover the costs of development. Please consider buying those - they are priced low enough that you can afford it or you could just as easily expense them to your organisation.
|
||||||
|
|
||||||
If you build Ostinato from source and find it useful, please donate to keep the lights on and sustain the project.
|
If you build Ostinato from source and find it useful, please sponsor to keep the lights on and sustain the project.
|
||||||
|
|
||||||
|
[](https://github.com/sponsors/pstavirs)
|
||||||
|
|
||||||
Read the Ostinato [origin story](https://ostinato.org/about).
|
Read the Ostinato [origin story](https://ostinato.org/about).
|
||||||
|
|
||||||
[](https://gum.co/ostdonate)
|
|
||||||
|
|
||||||
Srivats P<br/>
|
Srivats P<br/>
|
||||||
Author, Ostinato
|
Author, Ostinato
|
||||||
|
@ -94,7 +94,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="CopyrightLabel" >
|
<widget class="QLabel" name="CopyrightLabel" >
|
||||||
<property name="text" >
|
<property name="text" >
|
||||||
<string>Copyright (c) 2007-2020 Srivats P.</string>
|
<string>Copyright (c) 2007-2023 Srivats P.</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment" >
|
<property name="alignment" >
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignCenter</set>
|
||||||
|
@ -209,7 +209,7 @@ void DeviceGroupDialog::updateTotalDeviceCount()
|
|||||||
|
|
||||||
void DeviceGroupDialog::updateIp4Gateway()
|
void DeviceGroupDialog::updateIp4Gateway()
|
||||||
{
|
{
|
||||||
quint32 net = ip4Address->value() & (~0 << (32 - ip4PrefixLength->value()));
|
quint32 net = ip4Address->value() & (~0UL << (32 - ip4PrefixLength->value()));
|
||||||
ip4Gateway->setValue(net | 0x01);
|
ip4Gateway->setValue(net | 0x01);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,8 +262,10 @@ void DumpView::paintEvent(QPaintEvent* /*event*/)
|
|||||||
// FIXME(LOW): unable to set the self widget's font in constructor
|
// FIXME(LOW): unable to set the self widget's font in constructor
|
||||||
painter.setFont(QFont("Courier"));
|
painter.setFont(QFont("Courier"));
|
||||||
|
|
||||||
// set a white background
|
// Qt automatically clears the background before we are called
|
||||||
painter.fillRect(rect(), QBrush(QColor(Qt::white)));
|
// QWidget::paintEvent doc:
|
||||||
|
// When the paint event occurs, the update region has normally
|
||||||
|
// been erased, so you are painting on the widget's background.
|
||||||
|
|
||||||
if (model())
|
if (model())
|
||||||
{
|
{
|
||||||
|
@ -31,9 +31,13 @@ class IconOnlyDelegate : public QStyledItemDelegate
|
|||||||
{
|
{
|
||||||
QStyleOptionViewItem opt = option;
|
QStyleOptionViewItem opt = option;
|
||||||
opt.decorationPosition = QStyleOptionViewItem::Top;
|
opt.decorationPosition = QStyleOptionViewItem::Top;
|
||||||
opt.features &= ~QStyleOptionViewItem::HasDisplay;
|
|
||||||
QStyledItemDelegate::paint(painter, opt, index);
|
QStyledItemDelegate::paint(painter, opt, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString displayText(const QVariant&, const QLocale&) const
|
||||||
|
{
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -182,6 +182,8 @@ void LogsWindow::alert(State state)
|
|||||||
// start - center of main window
|
// start - center of main window
|
||||||
QRect start;
|
QRect start;
|
||||||
QWidget *view = mainWindow;
|
QWidget *view = mainWindow;
|
||||||
|
if (!view)
|
||||||
|
return;
|
||||||
alert_->setParent(view);
|
alert_->setParent(view);
|
||||||
alert_->raise();
|
alert_->raise();
|
||||||
start.setSize(QSize(256, 256).scaled(view->size()/2, Qt::KeepAspectRatio));
|
start.setSize(QSize(256, 256).scaled(view->size()/2, Qt::KeepAspectRatio));
|
||||||
|
@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "params.h"
|
#include "params.h"
|
||||||
#include "preferences.h"
|
#include "preferences.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "thememanager.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@ -84,6 +85,8 @@ int main(int argc, char* argv[])
|
|||||||
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
|
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
|
||||||
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
|
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
|
||||||
|
|
||||||
|
ThemeManager::instance()->setTheme(appSettings->value(kThemeKey).toString());
|
||||||
|
|
||||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||||
|
|
||||||
mainWindow = new MainWindow;
|
mainWindow = new MainWindow;
|
||||||
|
@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "clipboardhelper.h"
|
#include "clipboardhelper.h"
|
||||||
|
#include "fileformatoptions.h"
|
||||||
#include "jumpurl.h"
|
#include "jumpurl.h"
|
||||||
#include "logsmodel.h"
|
#include "logsmodel.h"
|
||||||
#include "logswindow.h"
|
#include "logswindow.h"
|
||||||
@ -85,8 +86,14 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
localServer_ = new QProcess(this);
|
localServer_ = new QProcess(this);
|
||||||
connect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
|
connect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
|
SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
|
||||||
|
|
||||||
|
#if QT_VERSION >= 0x050600
|
||||||
|
connect(localServer_, SIGNAL(errorOccurred(QProcess::ProcessError)),
|
||||||
|
SLOT(onLocalServerError(QProcess::ProcessError)));
|
||||||
|
#else
|
||||||
connect(localServer_, SIGNAL(error(QProcess::ProcessError)),
|
connect(localServer_, SIGNAL(error(QProcess::ProcessError)),
|
||||||
SLOT(onLocalServerError(QProcess::ProcessError)));
|
SLOT(onLocalServerError(QProcess::ProcessError)));
|
||||||
|
#endif
|
||||||
localServer_->setProcessChannelMode(QProcess::ForwardedChannels);
|
localServer_->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||||
localServer_->start(serverApp, QStringList());
|
localServer_->start(serverApp, QStringList());
|
||||||
QTimer::singleShot(5000, this, SLOT(stopLocalServerMonitor()));
|
QTimer::singleShot(5000, this, SLOT(stopLocalServerMonitor()));
|
||||||
@ -119,8 +126,11 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
|
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
menuFile->insertActions(menuFile->actions().at(3), portsWindow->actions());
|
menuFile->insertActions(menuFile->actions().at(3),
|
||||||
|
portsWindow->portActions());
|
||||||
menuEdit->addActions(clipboardHelper->actions());
|
menuEdit->addActions(clipboardHelper->actions());
|
||||||
|
menuStreams->addActions(portsWindow->streamActions());
|
||||||
|
menuDevices->addActions(portsWindow->deviceActions());
|
||||||
|
|
||||||
statsDock->setWidget(statsWindow);
|
statsDock->setWidget(statsWindow);
|
||||||
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
|
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
|
||||||
@ -165,6 +175,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||||||
this, SLOT(onNewVersion(QString)));
|
this, SLOT(onNewVersion(QString)));
|
||||||
updater->checkForNewVersion();
|
updater->checkForNewVersion();
|
||||||
|
|
||||||
|
// TODO: If session file specified (and valid?), don't add local drone PG
|
||||||
// Add the "Local" Port Group
|
// Add the "Local" Port Group
|
||||||
if (appParams.optLocalDrone()) {
|
if (appParams.optLocalDrone()) {
|
||||||
PortGroup *pg = new PortGroup;
|
PortGroup *pg = new PortGroup;
|
||||||
@ -409,8 +420,13 @@ void MainWindow::on_actionHelpAbout_triggered()
|
|||||||
void MainWindow::stopLocalServerMonitor()
|
void MainWindow::stopLocalServerMonitor()
|
||||||
{
|
{
|
||||||
// We are only interested in startup errors
|
// We are only interested in startup errors
|
||||||
|
#if QT_VERSION >= 0x050600
|
||||||
|
disconnect(localServer_, SIGNAL(errorOccurred(QProcess::ProcessError)),
|
||||||
|
this, SLOT(onLocalServerError(QProcess::ProcessError)));
|
||||||
|
#else
|
||||||
disconnect(localServer_, SIGNAL(error(QProcess::ProcessError)),
|
disconnect(localServer_, SIGNAL(error(QProcess::ProcessError)),
|
||||||
this, SLOT(onLocalServerError(QProcess::ProcessError)));
|
this, SLOT(onLocalServerError(QProcess::ProcessError)));
|
||||||
|
#endif
|
||||||
disconnect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
|
disconnect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
|
||||||
this, SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
|
this, SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
|
||||||
}
|
}
|
||||||
@ -451,8 +467,8 @@ void MainWindow::reportLocalServerError()
|
|||||||
if (localServer_->exitCode() == STATUS_DLL_NOT_FOUND)
|
if (localServer_->exitCode() == STATUS_DLL_NOT_FOUND)
|
||||||
errorStr.append(tr("<p>This is most likely because Packet.dll "
|
errorStr.append(tr("<p>This is most likely because Packet.dll "
|
||||||
"was not found - make sure you have "
|
"was not found - make sure you have "
|
||||||
"<a href='%1'>WinPcap"
|
"<a href='%1'>npcap installed and accessible</a>."
|
||||||
"</a> installed.</p>")
|
"</p>")
|
||||||
.arg(jumpUrl("winpcap")));
|
.arg(jumpUrl("winpcap")));
|
||||||
#endif
|
#endif
|
||||||
msgBox.setText(errorStr);
|
msgBox.setText(errorStr);
|
||||||
@ -532,7 +548,7 @@ bool MainWindow::openSession(QString fileName, QString &error)
|
|||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((optDialog = fmt->openOptionsDialog()))
|
if ((optDialog = FileFormatOptions::openOptionsDialog(fmt)))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
optDialog->setParent(this, Qt::Dialog);
|
optDialog->setParent(this, Qt::Dialog);
|
||||||
|
@ -25,21 +25,10 @@
|
|||||||
<addaction name="actionOpenSession" />
|
<addaction name="actionOpenSession" />
|
||||||
<addaction name="actionSaveSession" />
|
<addaction name="actionSaveSession" />
|
||||||
<addaction name="separator" />
|
<addaction name="separator" />
|
||||||
|
<addaction name="separator" />
|
||||||
<addaction name="actionPreferences" />
|
<addaction name="actionPreferences" />
|
||||||
<addaction name="actionFileExit" />
|
<addaction name="actionFileExit" />
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuHelp" >
|
|
||||||
<property name="title" >
|
|
||||||
<string>&Help</string>
|
|
||||||
</property>
|
|
||||||
<addaction name="actionHelpOnline" />
|
|
||||||
<addaction name="separator" />
|
|
||||||
<addaction name="actionDonate" />
|
|
||||||
<addaction name="actionCheckForUpdates" />
|
|
||||||
<addaction name="separator" />
|
|
||||||
<addaction name="actionHelpAbout" />
|
|
||||||
<addaction name="actionAboutQt" />
|
|
||||||
</widget>
|
|
||||||
<widget class="QMenu" name="menuEdit" >
|
<widget class="QMenu" name="menuEdit" >
|
||||||
<property name="title" >
|
<property name="title" >
|
||||||
<string>&Edit</string>
|
<string>&Edit</string>
|
||||||
@ -52,9 +41,34 @@
|
|||||||
<addaction name="actionViewShowMyReservedPortsOnly" />
|
<addaction name="actionViewShowMyReservedPortsOnly" />
|
||||||
<addaction name="actionViewRestoreDefaults" />
|
<addaction name="actionViewRestoreDefaults" />
|
||||||
</widget>
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuStreams" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>&Streams</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionTest" />
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuDevices" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>&Devices</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
<widget class="QMenu" name="menuHelp" >
|
||||||
|
<property name="title" >
|
||||||
|
<string>&Help</string>
|
||||||
|
</property>
|
||||||
|
<addaction name="actionHelpOnline" />
|
||||||
|
<addaction name="separator" />
|
||||||
|
<addaction name="actionDonate" />
|
||||||
|
<addaction name="actionCheckForUpdates" />
|
||||||
|
<addaction name="separator" />
|
||||||
|
<addaction name="actionHelpAbout" />
|
||||||
|
<addaction name="actionAboutQt" />
|
||||||
|
</widget>
|
||||||
<addaction name="menuFile" />
|
<addaction name="menuFile" />
|
||||||
<addaction name="menuEdit" />
|
<addaction name="menuEdit" />
|
||||||
<addaction name="menuView" />
|
<addaction name="menuView" />
|
||||||
|
<addaction name="menuStreams" />
|
||||||
|
<addaction name="menuDevices" />
|
||||||
<addaction name="menuHelp" />
|
<addaction name="menuHelp" />
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QStatusBar" name="statusbar" />
|
<widget class="QStatusBar" name="statusbar" />
|
||||||
|
@ -5,31 +5,26 @@ win32:RC_FILE = ostinato.rc
|
|||||||
macx:ICON = icons/logo.icns
|
macx:ICON = icons/logo.icns
|
||||||
QT += widgets network script xml svg
|
QT += widgets network script xml svg
|
||||||
INCLUDEPATH += "../rpc/" "../common/"
|
INCLUDEPATH += "../rpc/" "../common/"
|
||||||
|
|
||||||
|
OBJDIR = .
|
||||||
win32 {
|
win32 {
|
||||||
QMAKE_LFLAGS += -static
|
QMAKE_LFLAGS += -static
|
||||||
CONFIG(debug, debug|release) {
|
CONFIG(debug, debug|release) {
|
||||||
LIBS += -L"../common/debug" -lostprotogui -lostproto
|
OBJDIR = debug
|
||||||
LIBS += -L"../rpc/debug" -lpbrpc
|
|
||||||
POST_TARGETDEPS += \
|
|
||||||
"../common/debug/libostprotogui.a" \
|
|
||||||
"../common/debug/libostproto.a" \
|
|
||||||
"../rpc/debug/libpbrpc.a"
|
|
||||||
} else {
|
} else {
|
||||||
LIBS += -L"../common/release" -lostprotogui -lostproto
|
OBJDIR = release
|
||||||
LIBS += -L"../rpc/release" -lpbrpc
|
|
||||||
POST_TARGETDEPS += \
|
|
||||||
"../common/release/libostprotogui.a" \
|
|
||||||
"../common/release/libostproto.a" \
|
|
||||||
"../rpc/release/libpbrpc.a"
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
LIBS += -L"../common" -lostprotogui -lostproto
|
|
||||||
LIBS += -L"../rpc" -lpbrpc
|
|
||||||
POST_TARGETDEPS += \
|
|
||||||
"../common/libostprotogui.a" \
|
|
||||||
"../common/libostproto.a" \
|
|
||||||
"../rpc/libpbrpc.a"
|
|
||||||
}
|
}
|
||||||
|
LIBS += -L"../common/$$OBJDIR" -lostfile -lostfilegui
|
||||||
|
LIBS += -L"../common/$$OBJDIR" -lostprotogui -lostproto
|
||||||
|
LIBS += -L"../rpc/$$OBJDIR" -lpbrpc
|
||||||
|
POST_TARGETDEPS += \
|
||||||
|
"../common/$$OBJDIR/libostfilegui.a" \
|
||||||
|
"../common/$$OBJDIR/libostfile.a" \
|
||||||
|
"../common/$$OBJDIR/libostprotogui.a" \
|
||||||
|
"../common/$$OBJDIR/libostproto.a" \
|
||||||
|
"../rpc/$$OBJDIR/libpbrpc.a"
|
||||||
|
|
||||||
LIBS += -lprotobuf
|
LIBS += -lprotobuf
|
||||||
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
LIBS += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
|
||||||
RESOURCES += ostinato.qrc
|
RESOURCES += ostinato.qrc
|
||||||
@ -128,12 +123,23 @@ SOURCES += \
|
|||||||
streamstatsmodel.cpp \
|
streamstatsmodel.cpp \
|
||||||
streamstatswindow.cpp \
|
streamstatswindow.cpp \
|
||||||
streamswidget.cpp \
|
streamswidget.cpp \
|
||||||
|
thememanager.cpp \
|
||||||
variablefieldswidget.cpp
|
variablefieldswidget.cpp
|
||||||
|
|
||||||
|
THEMES += \
|
||||||
|
themes/material-dark.qss \
|
||||||
|
themes/material-dark.rcc \
|
||||||
|
themes/material-light.qss \
|
||||||
|
themes/material-light.rcc \
|
||||||
|
themes/qds-dark.qss \
|
||||||
|
themes/qds-dark.rcc \
|
||||||
|
themes/qds-light.qss \
|
||||||
|
themes/qds-light.rcc \
|
||||||
|
|
||||||
QMAKE_DISTCLEAN += object_script.*
|
QMAKE_DISTCLEAN += object_script.*
|
||||||
|
|
||||||
include(../install.pri)
|
include(../install.pri)
|
||||||
|
include(../shared.pri)
|
||||||
include(../version.pri)
|
include(../version.pri)
|
||||||
include(../options.pri)
|
include(../options.pri)
|
||||||
|
|
||||||
|
@ -45,11 +45,11 @@ int Params::parseCommandLine(int argc, char* argv[])
|
|||||||
logsDisabled_ = false;
|
logsDisabled_ = false;
|
||||||
break;
|
break;
|
||||||
case 'v':
|
case 'v':
|
||||||
qDebug("Ostinato %s rev %s\n", version, revision);
|
printf("Ostinato %s rev %s\n", version, revision);
|
||||||
exit(0);
|
exit(0);
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
qDebug("usage: %s [-cdhv]\n", argv[0]);
|
printf("usage: %s [-cdhv]\n", argv[0]);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
n++;
|
n++;
|
||||||
|
@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "port.h"
|
#include "port.h"
|
||||||
|
|
||||||
#include "emulation.h"
|
#include "emulation.h"
|
||||||
|
#include "fileformatoptions.h"
|
||||||
#include "streamfileformat.h"
|
#include "streamfileformat.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@ -604,7 +605,7 @@ bool Port::openStreams(QString fileName, bool append, QString &error)
|
|||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((optDialog = fmt->openOptionsDialog()))
|
if ((optDialog = FileFormatOptions::openOptionsDialog(fmt)))
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
optDialog->setParent(mainWindow, Qt::Dialog);
|
optDialog->setParent(mainWindow, Qt::Dialog);
|
||||||
|
@ -88,8 +88,15 @@ public:
|
|||||||
{ return d.port_id().id(); }
|
{ return d.port_id().id(); }
|
||||||
const QString name() const
|
const QString name() const
|
||||||
{ return QString().fromStdString(d.name()); }
|
{ return QString().fromStdString(d.name()); }
|
||||||
const QString description() const
|
const QString systemDescription() const
|
||||||
{ return QString().fromStdString(d.description()); }
|
{ return QString().fromStdString(d.description()); }
|
||||||
|
const QString userDescription() const
|
||||||
|
{ return QString().fromStdString(d.user_description()); }
|
||||||
|
const QString description() const
|
||||||
|
{
|
||||||
|
return userDescription().isEmpty() ?
|
||||||
|
systemDescription() : userDescription();
|
||||||
|
}
|
||||||
const QString notes() const
|
const QString notes() const
|
||||||
{ return QString().fromStdString(d.notes()); }
|
{ return QString().fromStdString(d.notes()); }
|
||||||
const QString userName() const
|
const QString userName() const
|
||||||
|
@ -32,6 +32,8 @@ PortConfigDialog::PortConfigDialog(
|
|||||||
|
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
|
description->setPlaceholderText(portConfig_.description().c_str());
|
||||||
|
description->setText(portConfig_.user_description().c_str());
|
||||||
switch(portConfig_.transmit_mode())
|
switch(portConfig_.transmit_mode())
|
||||||
{
|
{
|
||||||
case OstProto::kSequentialTransmit:
|
case OstProto::kSequentialTransmit:
|
||||||
@ -80,6 +82,8 @@ void PortConfigDialog::accept()
|
|||||||
{
|
{
|
||||||
OstProto::Port pc;
|
OstProto::Port pc;
|
||||||
|
|
||||||
|
pc.set_user_description(description->text().toStdString());
|
||||||
|
|
||||||
if (sequentialStreamsButton->isChecked())
|
if (sequentialStreamsButton->isChecked())
|
||||||
pc.set_transmit_mode(OstProto::kSequentialTransmit);
|
pc.set_transmit_mode(OstProto::kSequentialTransmit);
|
||||||
else if (interleavedStreamsButton->isChecked())
|
else if (interleavedStreamsButton->isChecked())
|
||||||
@ -109,6 +113,11 @@ void PortConfigDialog::accept()
|
|||||||
pc.set_is_tracking_stream_stats(streamStatsButton->isChecked());
|
pc.set_is_tracking_stream_stats(streamStatsButton->isChecked());
|
||||||
|
|
||||||
// Update fields that have changed, clear the rest
|
// Update fields that have changed, clear the rest
|
||||||
|
if (pc.user_description() != portConfig_.user_description())
|
||||||
|
portConfig_.set_user_description(pc.user_description());
|
||||||
|
else
|
||||||
|
portConfig_.clear_user_description();
|
||||||
|
|
||||||
if (pc.transmit_mode() != portConfig_.transmit_mode())
|
if (pc.transmit_mode() != portConfig_.transmit_mode())
|
||||||
portConfig_.set_transmit_mode(pc.transmit_mode());
|
portConfig_.set_transmit_mode(pc.transmit_mode());
|
||||||
else
|
else
|
||||||
|
@ -1,37 +1,51 @@
|
|||||||
<ui version="4.0" >
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
<class>PortConfigDialog</class>
|
<class>PortConfigDialog</class>
|
||||||
<widget class="QDialog" name="PortConfigDialog" >
|
<widget class="QDialog" name="PortConfigDialog">
|
||||||
<property name="geometry" >
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>244</width>
|
<width>248</width>
|
||||||
<height>257</height>
|
<height>292</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle" >
|
<property name="windowTitle">
|
||||||
<string>Port Config</string>
|
<string>Port Config</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" >
|
<layout class="QVBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="transmitModeBox" >
|
<widget class="QLabel" name="label">
|
||||||
<property name="title" >
|
<property name="text">
|
||||||
|
<string>Description</string>
|
||||||
|
</property>
|
||||||
|
<property name="buddy">
|
||||||
|
<cstring>description</cstring>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="description"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QGroupBox" name="transmitModeBox">
|
||||||
|
<property name="title">
|
||||||
<string>Transmit Mode</string>
|
<string>Transmit Mode</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" >
|
<layout class="QVBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="sequentialStreamsButton" >
|
<widget class="QRadioButton" name="sequentialStreamsButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>Sequential Streams</string>
|
<string>Sequential Streams</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="checked" >
|
<property name="checked">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="interleavedStreamsButton" >
|
<widget class="QRadioButton" name="interleavedStreamsButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>Interleaved Streams</string>
|
<string>Interleaved Streams</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -40,21 +54,21 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QGroupBox" name="groupBox" >
|
<widget class="QGroupBox" name="groupBox">
|
||||||
<property name="title" >
|
<property name="title">
|
||||||
<string>Reservation</string>
|
<string>Reservation</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" >
|
<layout class="QVBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="reservedBy" >
|
<widget class="QLabel" name="reservedBy">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>Reserved by: </string>
|
<string>Reserved by: </string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="reserveButton" >
|
<widget class="QCheckBox" name="reserveButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>Reserve</string>
|
<string>Reserve</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
@ -63,25 +77,25 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="exclusiveControlButton" >
|
<widget class="QCheckBox" name="exclusiveControlButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>Exclusive Control</string>
|
<string>Exclusive Control</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="streamStatsButton" >
|
<widget class="QCheckBox" name="streamStatsButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>Stream Statistics</string>
|
<string>Stream Statistics</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation" >
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" >
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>226</width>
|
<width>226</width>
|
||||||
<height>71</height>
|
<height>71</height>
|
||||||
@ -90,17 +104,25 @@
|
|||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
<property name="orientation" >
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons" >
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>description</tabstop>
|
||||||
|
<tabstop>sequentialStreamsButton</tabstop>
|
||||||
|
<tabstop>interleavedStreamsButton</tabstop>
|
||||||
|
<tabstop>reserveButton</tabstop>
|
||||||
|
<tabstop>exclusiveControlButton</tabstop>
|
||||||
|
<tabstop>streamStatsButton</tabstop>
|
||||||
|
</tabstops>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
@ -109,11 +131,11 @@
|
|||||||
<receiver>PortConfigDialog</receiver>
|
<receiver>PortConfigDialog</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel" >
|
<hint type="sourcelabel">
|
||||||
<x>234</x>
|
<x>234</x>
|
||||||
<y>205</y>
|
<y>205</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel" >
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
<y>214</y>
|
<y>214</y>
|
||||||
</hint>
|
</hint>
|
||||||
@ -125,11 +147,11 @@
|
|||||||
<receiver>PortConfigDialog</receiver>
|
<receiver>PortConfigDialog</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel" >
|
<hint type="sourcelabel">
|
||||||
<x>234</x>
|
<x>234</x>
|
||||||
<y>205</y>
|
<y>205</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel" >
|
<hint type="destinationlabel">
|
||||||
<x>243</x>
|
<x>243</x>
|
||||||
<y>214</y>
|
<y>214</y>
|
||||||
</hint>
|
</hint>
|
||||||
|
@ -1111,8 +1111,11 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
|
|||||||
// * modify (new) deviceGroups
|
// * modify (new) deviceGroups
|
||||||
// * add (new) stream ids
|
// * add (new) stream ids
|
||||||
// * modify (new) streams
|
// * modify (new) streams
|
||||||
|
// * resolve neighbors
|
||||||
|
// * build packets
|
||||||
// XXX: This assumes getDeviceGroupIdList() was invoked before
|
// XXX: This assumes getDeviceGroupIdList() was invoked before
|
||||||
// getStreamIdList() - if the order changes this code will break!
|
// getStreamIdList() - if the order changes this code will break!
|
||||||
|
// XXX: See resolve/build notes below
|
||||||
|
|
||||||
// XXX: same name as input param, but shouldn't cause any problem
|
// XXX: same name as input param, but shouldn't cause any problem
|
||||||
PbRpcController *controller;
|
PbRpcController *controller;
|
||||||
@ -1153,6 +1156,7 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add/modify deviceGroups
|
// add/modify deviceGroups
|
||||||
|
bool resolve = false;
|
||||||
if (newPortContent->device_groups_size())
|
if (newPortContent->device_groups_size())
|
||||||
{
|
{
|
||||||
OstProto::DeviceGroupIdList *deviceGroupIdList
|
OstProto::DeviceGroupIdList *deviceGroupIdList
|
||||||
@ -1184,6 +1188,7 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
|
|||||||
deviceGroupConfigList, ack,
|
deviceGroupConfigList, ack,
|
||||||
NewCallback(this, &PortGroup::processModifyDeviceGroupAck,
|
NewCallback(this, &PortGroup::processModifyDeviceGroupAck,
|
||||||
portIndex, controller));
|
portIndex, controller));
|
||||||
|
resolve = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add/modify streams
|
// add/modify streams
|
||||||
@ -1214,6 +1219,26 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
|
|||||||
serviceStub->modifyStream(controller, streamConfigList, ack,
|
serviceStub->modifyStream(controller, streamConfigList, ack,
|
||||||
NewCallback(this, &PortGroup::processModifyStreamAck,
|
NewCallback(this, &PortGroup::processModifyStreamAck,
|
||||||
portIndex, controller));
|
portIndex, controller));
|
||||||
|
resolve = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: Ideally resolve and build should be called after **all**
|
||||||
|
// ports and portgroups are configured. As of now, any resolve
|
||||||
|
// replied to by ports/portgroups configured later in the open
|
||||||
|
// session sequence will fail.
|
||||||
|
// However, to do that, we may need to rethink the open session
|
||||||
|
// implementation - so going with this for now
|
||||||
|
if (resolve)
|
||||||
|
{
|
||||||
|
OstProto::PortIdList *portIdList = new OstProto::PortIdList;
|
||||||
|
portIdList->add_port_id()->set_id(portId);
|
||||||
|
OstProto::Ack *ack = new OstProto::Ack;
|
||||||
|
controller = new PbRpcController(portIdList, ack);
|
||||||
|
serviceStub->resolveDeviceNeighbors(controller, portIdList, ack,
|
||||||
|
NewCallback(this,
|
||||||
|
&PortGroup::processResolveDeviceNeighborsAck,
|
||||||
|
controller));
|
||||||
|
resolve = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// build packets using the new config
|
// build packets using the new config
|
||||||
|
@ -68,6 +68,7 @@ bool PortGroupList::isPort(const QModelIndex& index)
|
|||||||
|
|
||||||
PortGroup& PortGroupList::portGroup(const QModelIndex& index)
|
PortGroup& PortGroupList::portGroup(const QModelIndex& index)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(index.isValid());
|
||||||
Q_ASSERT(mPortGroupListModel.isPortGroup(index));
|
Q_ASSERT(mPortGroupListModel.isPortGroup(index));
|
||||||
|
|
||||||
return *(mPortGroups[index.row()]);
|
return *(mPortGroups[index.row()]);
|
||||||
@ -75,6 +76,8 @@ PortGroup& PortGroupList::portGroup(const QModelIndex& index)
|
|||||||
|
|
||||||
Port& PortGroupList::port(const QModelIndex& index)
|
Port& PortGroupList::port(const QModelIndex& index)
|
||||||
{
|
{
|
||||||
|
Q_ASSERT(index.isValid());
|
||||||
|
Q_ASSERT(index.parent().isValid());
|
||||||
Q_ASSERT(mPortGroupListModel.isPort(index));
|
Q_ASSERT(mPortGroupListModel.isPort(index));
|
||||||
return (*mPortGroups.at(index.parent().row())->mPorts[index.row()]);
|
return (*mPortGroups.at(index.parent().row())->mPorts[index.row()]);
|
||||||
}
|
}
|
||||||
@ -97,6 +100,9 @@ void PortGroupList::addPortGroup(PortGroup &portGroup)
|
|||||||
connect(&portGroup, SIGNAL(portListChanged(quint32)),
|
connect(&portGroup, SIGNAL(portListChanged(quint32)),
|
||||||
&mPortStatsModel, SLOT(when_portListChanged()));
|
&mPortStatsModel, SLOT(when_portListChanged()));
|
||||||
|
|
||||||
|
connect(&portGroup, SIGNAL(portGroupDataChanged(int, int)),
|
||||||
|
&mPortStatsModel, SLOT(when_portGroupDataChanged(int, int)));
|
||||||
|
|
||||||
connect(&portGroup, SIGNAL(statsChanged(quint32)),
|
connect(&portGroup, SIGNAL(statsChanged(quint32)),
|
||||||
&mPortStatsModel, SLOT(when_portGroup_stats_update(quint32)));
|
&mPortStatsModel, SLOT(when_portGroup_stats_update(quint32)));
|
||||||
|
|
||||||
@ -110,8 +116,10 @@ void PortGroupList::addPortGroup(PortGroup &portGroup)
|
|||||||
|
|
||||||
void PortGroupList::removePortGroup(PortGroup &portGroup)
|
void PortGroupList::removePortGroup(PortGroup &portGroup)
|
||||||
{
|
{
|
||||||
mPortGroupListModel.portGroupAboutToBeRemoved(&portGroup);
|
// Disconnect before removing from list
|
||||||
|
portGroup.disconnectFromHost();
|
||||||
|
|
||||||
|
mPortGroupListModel.portGroupAboutToBeRemoved(&portGroup);
|
||||||
PortGroup* pg = mPortGroups.takeAt(mPortGroups.indexOf(&portGroup));
|
PortGroup* pg = mPortGroups.takeAt(mPortGroups.indexOf(&portGroup));
|
||||||
qDebug("after takeAt()");
|
qDebug("after takeAt()");
|
||||||
mPortGroupListModel.portGroupRemoved();
|
mPortGroupListModel.portGroupRemoved();
|
||||||
@ -128,11 +136,12 @@ void PortGroupList::removeAllPortGroups()
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
PortGroup *pg = mPortGroups.at(0);
|
PortGroup *pg = mPortGroups.at(0);
|
||||||
|
pg->disconnectFromHost();
|
||||||
mPortGroupListModel.portGroupAboutToBeRemoved(pg);
|
mPortGroupListModel.portGroupAboutToBeRemoved(pg);
|
||||||
mPortGroups.removeFirst();
|
mPortGroups.removeFirst();
|
||||||
delete pg;
|
delete pg;
|
||||||
|
mPortGroupListModel.portGroupRemoved();
|
||||||
} while (!mPortGroups.isEmpty());
|
} while (!mPortGroups.isEmpty());
|
||||||
mPortGroupListModel.portGroupRemoved();
|
|
||||||
|
|
||||||
mPortGroupListModel.when_portListChanged();
|
mPortGroupListModel.when_portListChanged();
|
||||||
mPortStatsModel.when_portListChanged();
|
mPortStatsModel.when_portListChanged();
|
||||||
|
@ -49,7 +49,8 @@ QList<uint> PortStatsFilterDialog::getItemList(bool* ok,
|
|||||||
{
|
{
|
||||||
QStandardItem *item;
|
QStandardItem *item;
|
||||||
|
|
||||||
item = new QStandardItem(model->headerData(i, orientation).toString());
|
item = new QStandardItem(model->headerData(i, orientation)
|
||||||
|
.toString().replace('\n', ' '));
|
||||||
item->setData(i, kLogicalIndex);
|
item->setData(i, kLogicalIndex);
|
||||||
item->setData(initial.indexOf(i), kVisualIndex);
|
item->setData(initial.indexOf(i), kVisualIndex);
|
||||||
item->setFlags(Qt::ItemIsSelectable
|
item->setFlags(Qt::ItemIsSelectable
|
||||||
|
@ -20,7 +20,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "portstatsmodel.h"
|
#include "portstatsmodel.h"
|
||||||
#include "portgrouplist.h"
|
#include "portgrouplist.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include <QPalette>
|
||||||
#include <QPixmapCache>
|
#include <QPixmapCache>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
@ -135,7 +137,10 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
|
|
||||||
// States
|
// States
|
||||||
case e_COMBO_STATE:
|
case e_COMBO_STATE:
|
||||||
return QVariant();
|
return QString("Link %1%2%3")
|
||||||
|
.arg(LinkStateName.at(stats.state().link_state()))
|
||||||
|
.arg(stats.state().is_transmit_on() ? ";Tx On" : "")
|
||||||
|
.arg(stats.state().is_capture_on() ? ";Cap On" : "");
|
||||||
|
|
||||||
// Statistics
|
// Statistics
|
||||||
case e_STAT_FRAMES_RCVD:
|
case e_STAT_FRAMES_RCVD:
|
||||||
@ -156,11 +161,13 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
case e_STAT_BYTES_SENT:
|
case e_STAT_BYTES_SENT:
|
||||||
return QString("%L1").arg(quint64(stats.tx_bytes()));
|
return QString("%L1").arg(quint64(stats.tx_bytes()));
|
||||||
|
|
||||||
|
#if 0
|
||||||
case e_STAT_BYTE_SEND_RATE:
|
case e_STAT_BYTE_SEND_RATE:
|
||||||
return QString("%L1").arg(quint64(stats.tx_bps()));
|
return QString("%L1").arg(quint64(stats.tx_bps()));
|
||||||
|
|
||||||
case e_STAT_BYTE_RECV_RATE:
|
case e_STAT_BYTE_RECV_RATE:
|
||||||
return QString("%L1").arg(quint64(stats.rx_bps()));
|
return QString("%L1").arg(quint64(stats.rx_bps()));
|
||||||
|
#endif
|
||||||
|
|
||||||
case e_STAT_BIT_SEND_RATE:
|
case e_STAT_BIT_SEND_RATE:
|
||||||
return QString("%L1").arg(quint64(
|
return QString("%L1").arg(quint64(
|
||||||
@ -270,6 +277,14 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((role == Qt::BackgroundRole) && (orientation == Qt::Vertical)
|
||||||
|
&& qApp->styleSheet().isEmpty())
|
||||||
|
{
|
||||||
|
QPalette palette = QApplication::palette();
|
||||||
|
return section & 0x1 ?
|
||||||
|
palette.alternateBase() : palette.base();
|
||||||
|
}
|
||||||
|
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
@ -280,16 +295,23 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
|
|||||||
|
|
||||||
if (numPorts.isEmpty() || section >= numPorts.last())
|
if (numPorts.isEmpty() || section >= numPorts.last())
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
|
||||||
getDomainIndexes(index(0, section), portGroupIdx, portIdx);
|
getDomainIndexes(index(0, section), portGroupIdx, portIdx);
|
||||||
|
|
||||||
|
PortGroup *portGroup = pgl->mPortGroups.at(portGroupIdx);
|
||||||
|
Port *port = portGroup->mPorts.at(portIdx);
|
||||||
|
|
||||||
portName = QString("Port %1-%2")
|
portName = QString("Port %1-%2")
|
||||||
.arg(pgl->mPortGroups.at(portGroupIdx)->id())
|
.arg(portGroup->id())
|
||||||
.arg(pgl->mPortGroups.at(portGroupIdx)->mPorts.at(portIdx)->id());
|
.arg(port->id());
|
||||||
if (portGroupIdx < (uint) pgl->mPortGroups.size()
|
if (portGroupIdx < (uint) pgl->mPortGroups.size()
|
||||||
&& portIdx < (uint) pgl->mPortGroups.at(portGroupIdx)->mPorts.size())
|
&& portIdx < (uint) portGroup->mPorts.size())
|
||||||
{
|
{
|
||||||
if (!pgl->mPortGroups.at(portGroupIdx)->mPorts[portIdx]->notes()
|
if (!port->notes().isEmpty())
|
||||||
.isEmpty())
|
|
||||||
portName += " *";
|
portName += " *";
|
||||||
|
portName += "\n";
|
||||||
|
portName += port->userDescription().isEmpty() ?
|
||||||
|
port->userAlias() : port->userDescription();
|
||||||
}
|
}
|
||||||
return portName;
|
return portName;
|
||||||
}
|
}
|
||||||
@ -363,6 +385,16 @@ void PortStatsModel::when_portListChanged()
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PortStatsModel::when_portGroupDataChanged(int /*portGroupId*/, int /*portId*/)
|
||||||
|
{
|
||||||
|
if (!columnCount())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Port (user) description may have changed - update column headers
|
||||||
|
// TODO: update only the changed ports, not all
|
||||||
|
emit headerDataChanged(Qt::Horizontal, 0, columnCount()-1);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: unused? if used, the index calculation row/column needs to be swapped
|
// FIXME: unused? if used, the index calculation row/column needs to be swapped
|
||||||
#if 0
|
#if 0
|
||||||
void PortStatsModel::on_portStatsUpdate(int port, void* /*stats*/)
|
void PortStatsModel::on_portStatsUpdate(int port, void* /*stats*/)
|
||||||
|
@ -26,15 +26,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
class QTimer;
|
class QTimer;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
// Info
|
|
||||||
e_INFO_START = 0,
|
|
||||||
|
|
||||||
e_INFO_USER = e_INFO_START,
|
|
||||||
|
|
||||||
e_INFO_END = e_INFO_USER,
|
|
||||||
|
|
||||||
// State
|
// State
|
||||||
e_STATE_START,
|
e_STATE_START = 0,
|
||||||
|
|
||||||
e_COMBO_STATE = e_STATE_START,
|
e_COMBO_STATE = e_STATE_START,
|
||||||
|
|
||||||
@ -43,14 +36,16 @@ typedef enum {
|
|||||||
// Statistics
|
// Statistics
|
||||||
e_STATISTICS_START,
|
e_STATISTICS_START,
|
||||||
|
|
||||||
e_STAT_FRAMES_RCVD = e_STATISTICS_START,
|
e_STAT_FRAMES_SENT = e_STATISTICS_START,
|
||||||
e_STAT_FRAMES_SENT,
|
e_STAT_FRAMES_RCVD,
|
||||||
|
e_STAT_BYTES_SENT,
|
||||||
|
e_STAT_BYTES_RCVD,
|
||||||
e_STAT_FRAME_SEND_RATE,
|
e_STAT_FRAME_SEND_RATE,
|
||||||
e_STAT_FRAME_RECV_RATE,
|
e_STAT_FRAME_RECV_RATE,
|
||||||
e_STAT_BYTES_RCVD,
|
#if 0
|
||||||
e_STAT_BYTES_SENT,
|
|
||||||
e_STAT_BYTE_SEND_RATE,
|
e_STAT_BYTE_SEND_RATE,
|
||||||
e_STAT_BYTE_RECV_RATE,
|
e_STAT_BYTE_RECV_RATE,
|
||||||
|
#endif
|
||||||
e_STAT_BIT_SEND_RATE,
|
e_STAT_BIT_SEND_RATE,
|
||||||
e_STAT_BIT_RECV_RATE,
|
e_STAT_BIT_RECV_RATE,
|
||||||
#if 0
|
#if 0
|
||||||
@ -69,24 +64,34 @@ typedef enum {
|
|||||||
|
|
||||||
e_STATISTICS_END = e_STAT_RX_FRAME_ERRORS,
|
e_STATISTICS_END = e_STAT_RX_FRAME_ERRORS,
|
||||||
|
|
||||||
|
// Info
|
||||||
|
e_INFO_START,
|
||||||
|
|
||||||
|
// XXX: keep hidden rows at end to avoid having to recalculate rows
|
||||||
|
e_INFO_USER = e_INFO_START,
|
||||||
|
|
||||||
|
e_INFO_END = e_INFO_USER,
|
||||||
|
|
||||||
|
|
||||||
e_STAT_MAX
|
e_STAT_MAX
|
||||||
} PortStat;
|
} PortStat;
|
||||||
|
|
||||||
static QStringList PortStatName = (QStringList()
|
static const QStringList PortStatName = (QStringList()
|
||||||
<< "User"
|
|
||||||
|
|
||||||
<< "Status"
|
<< "Status"
|
||||||
|
|
||||||
<< "Frames Received"
|
<< "Sent Frames"
|
||||||
<< "Frames Sent"
|
<< "Received Frames"
|
||||||
<< "Frame Send Rate (fps)"
|
<< "Sent Bytes"
|
||||||
<< "Frame Receive Rate (fps)"
|
<< "Received Bytes"
|
||||||
<< "Bytes Received"
|
|
||||||
<< "Bytes Sent"
|
<< "Send Frame Rate (fps)"
|
||||||
<< "Byte Send Rate (Bps)"
|
<< "Receive Frame Rate (fps)"
|
||||||
<< "Byte Receive Rate (Bps)"
|
#if 0
|
||||||
<< "Bit Send Rate (bps)"
|
<< "Send Byte Rate (Bps)"
|
||||||
<< "Bit Receive Rate (bps)"
|
<< "Receive Byte Rate (Bps)"
|
||||||
|
#endif
|
||||||
|
<< "Send Bit Rate (bps)"
|
||||||
|
<< "Receive Bit Rate (bps)"
|
||||||
#if 0
|
#if 0
|
||||||
<< "Frames Received (NIC)"
|
<< "Frames Received (NIC)"
|
||||||
<< "Frames Sent (NIC)"
|
<< "Frames Sent (NIC)"
|
||||||
@ -98,6 +103,8 @@ static QStringList PortStatName = (QStringList()
|
|||||||
<< "Receive Errors"
|
<< "Receive Errors"
|
||||||
<< "Receive Fifo Errors"
|
<< "Receive Fifo Errors"
|
||||||
<< "Receive Frame Errors"
|
<< "Receive Frame Errors"
|
||||||
|
|
||||||
|
<< "User"
|
||||||
);
|
);
|
||||||
|
|
||||||
static QStringList LinkStateName = (QStringList()
|
static QStringList LinkStateName = (QStringList()
|
||||||
@ -136,6 +143,7 @@ class PortStatsModel : public QAbstractTableModel
|
|||||||
public slots:
|
public slots:
|
||||||
void when_portListChanged();
|
void when_portListChanged();
|
||||||
//void on_portStatsUpdate(int port, void*stats);
|
//void on_portStatsUpdate(int port, void*stats);
|
||||||
|
void when_portGroupDataChanged(int portGroupId, int portId);
|
||||||
void when_portGroup_stats_update(quint32 portGroupId);
|
void when_portGroup_stats_update(quint32 portGroupId);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
@ -26,8 +26,8 @@ class PortStatsProxyModel : public QSortFilterProxyModel
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
PortStatsProxyModel(QObject *parent = 0)
|
PortStatsProxyModel(int userRow, QObject *parent = 0)
|
||||||
: QSortFilterProxyModel(parent)
|
: QSortFilterProxyModel(parent), userRow_(userRow)
|
||||||
{
|
{
|
||||||
setFilterRegExp(QRegExp(".*"));
|
setFilterRegExp(QRegExp(".*"));
|
||||||
}
|
}
|
||||||
@ -36,7 +36,7 @@ protected:
|
|||||||
bool filterAcceptsColumn(int sourceColumn,
|
bool filterAcceptsColumn(int sourceColumn,
|
||||||
const QModelIndex &sourceParent) const
|
const QModelIndex &sourceParent) const
|
||||||
{
|
{
|
||||||
QModelIndex index = sourceModel()->index(0, sourceColumn, sourceParent);
|
QModelIndex index = sourceModel()->index(userRow_, sourceColumn,sourceParent);
|
||||||
QString user = sourceModel()->data(index).toString();
|
QString user = sourceModel()->data(index).toString();
|
||||||
|
|
||||||
return filterRegExp().exactMatch(user) ? true : false;
|
return filterRegExp().exactMatch(user) ? true : false;
|
||||||
@ -44,9 +44,10 @@ protected:
|
|||||||
bool filterAcceptsRow(int sourceRow,
|
bool filterAcceptsRow(int sourceRow,
|
||||||
const QModelIndex &/*sourceParent*/) const
|
const QModelIndex &/*sourceParent*/) const
|
||||||
{
|
{
|
||||||
// Hide row 0 - username (needed only by this filter class)
|
return sourceRow == userRow_ ? false : true;
|
||||||
return (sourceRow > 0) ? true : false;
|
|
||||||
}
|
}
|
||||||
|
private:
|
||||||
|
int userRow_;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -24,6 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "portstatsfilterdialog.h"
|
#include "portstatsfilterdialog.h"
|
||||||
#include "portstatsmodel.h"
|
#include "portstatsmodel.h"
|
||||||
#include "portstatsproxymodel.h"
|
#include "portstatsproxymodel.h"
|
||||||
|
#include "rowborderdelegate.h"
|
||||||
#include "streamstatsmodel.h"
|
#include "streamstatsmodel.h"
|
||||||
#include "streamstatswindow.h"
|
#include "streamstatswindow.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
@ -42,7 +43,8 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
this->pgl = pgl;
|
this->pgl = pgl;
|
||||||
model = pgl->getPortStatsModel();
|
model = pgl->getPortStatsModel();
|
||||||
|
|
||||||
proxyStatsModel = new PortStatsProxyModel(this);
|
// Hide 'user' row
|
||||||
|
proxyStatsModel = new PortStatsProxyModel(e_INFO_USER, this);
|
||||||
if (proxyStatsModel) {
|
if (proxyStatsModel) {
|
||||||
proxyStatsModel->setSourceModel(model);
|
proxyStatsModel->setSourceModel(model);
|
||||||
tvPortStats->setModel(proxyStatsModel);
|
tvPortStats->setModel(proxyStatsModel);
|
||||||
@ -55,6 +57,17 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
tvPortStats->verticalHeader()->setDefaultSectionSize(
|
tvPortStats->verticalHeader()->setDefaultSectionSize(
|
||||||
tvPortStats->verticalHeader()->minimumSectionSize());
|
tvPortStats->verticalHeader()->minimumSectionSize());
|
||||||
|
|
||||||
|
// XXX: Set Delegates for port stats view
|
||||||
|
// RowBorderDelegate: Group related stats using a horizontal line
|
||||||
|
// IconOnlyDelegate : For status, show only icons not icons+text
|
||||||
|
tvPortStats->setItemDelegate(
|
||||||
|
new RowBorderDelegate(
|
||||||
|
QSet<int>({
|
||||||
|
e_STAT_FRAMES_SENT,
|
||||||
|
e_STAT_FRAME_SEND_RATE,
|
||||||
|
e_STAT_RX_DROPS}),
|
||||||
|
this));
|
||||||
|
|
||||||
statusDelegate = new IconOnlyDelegate(this);
|
statusDelegate = new IconOnlyDelegate(this);
|
||||||
#if 0
|
#if 0
|
||||||
// XXX: Ideally we should use this, but it doesn't work because in
|
// XXX: Ideally we should use this, but it doesn't work because in
|
||||||
@ -68,9 +81,7 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
statusDelegate);
|
statusDelegate);
|
||||||
#else
|
#else
|
||||||
// ... so we use this hard-coded hack
|
// ... so we use this hard-coded hack
|
||||||
tvPortStats->setItemDelegateForRow(
|
tvPortStats->setItemDelegateForRow(e_COMBO_STATE, statusDelegate);
|
||||||
proxyStatsModel ? e_COMBO_STATE-1 : e_COMBO_STATE,
|
|
||||||
statusDelegate);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(tvPortStats->selectionModel(),
|
connect(tvPortStats->selectionModel(),
|
||||||
|
@ -165,7 +165,7 @@
|
|||||||
<string>Stop Capture</string>
|
<string>Stop Capture</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="statusTip">
|
<property name="statusTip">
|
||||||
<string>End capture on selecteed port(s)</string>
|
<string>End capture on selected port(s)</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Stop</string>
|
<string>Stop</string>
|
||||||
|
@ -97,14 +97,19 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
|||||||
connect(plm->getPortModel(), SIGNAL(modelReset()),
|
connect(plm->getPortModel(), SIGNAL(modelReset()),
|
||||||
SLOT(when_portModel_reset()));
|
SLOT(when_portModel_reset()));
|
||||||
|
|
||||||
connect( tvPortList->selectionModel(),
|
connect(actionPort_Configuration, SIGNAL(triggered()),
|
||||||
|
SLOT(when_actionPort_Configuration_triggered()));
|
||||||
|
connect(tvPortList, SIGNAL(activated(const QModelIndex&)),
|
||||||
|
SLOT(when_actionPort_Configuration_triggered(const QModelIndex&)));
|
||||||
|
connect(tvPortList->selectionModel(),
|
||||||
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
|
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
|
||||||
this, SLOT(when_portView_currentChanged(const QModelIndex&,
|
this, SLOT(when_portView_currentChanged(const QModelIndex&,
|
||||||
const QModelIndex&)));
|
const QModelIndex&)));
|
||||||
|
|
||||||
connect(this,
|
connect(this,
|
||||||
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
|
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
|
||||||
portWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
|
portWidget,
|
||||||
|
SLOT(setCurrentPortIndex(const QModelIndex&, const QModelIndex&)));
|
||||||
connect(this,
|
connect(this,
|
||||||
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
|
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
|
||||||
streamsWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
|
streamsWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
|
||||||
@ -233,6 +238,21 @@ bool PortsWindow::saveSession(
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QList<QAction*> PortsWindow::portActions()
|
||||||
|
{
|
||||||
|
return tvPortList->actions();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QAction*> PortsWindow::streamActions()
|
||||||
|
{
|
||||||
|
return streamsWidget->actions();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QAction*> PortsWindow::deviceActions()
|
||||||
|
{
|
||||||
|
return devicesWidget->actions();
|
||||||
|
}
|
||||||
|
|
||||||
void PortsWindow::clearCurrentSelection()
|
void PortsWindow::clearCurrentSelection()
|
||||||
{
|
{
|
||||||
tvPortList->selectionModel()->clearCurrentIndex();
|
tvPortList->selectionModel()->clearCurrentIndex();
|
||||||
@ -582,9 +602,11 @@ void PortsWindow::on_actionExclusive_Control_triggered(bool checked)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortsWindow::on_actionPort_Configuration_triggered()
|
void PortsWindow::when_actionPort_Configuration_triggered(
|
||||||
|
const QModelIndex &portIndex)
|
||||||
{
|
{
|
||||||
QModelIndex current = tvPortList->selectionModel()->currentIndex();
|
QModelIndex current = portIndex.isValid() ?
|
||||||
|
portIndex : tvPortList->selectionModel()->currentIndex();
|
||||||
|
|
||||||
if (proxyPortModel)
|
if (proxyPortModel)
|
||||||
current = proxyPortModel->mapToSource(current);
|
current = proxyPortModel->mapToSource(current);
|
||||||
@ -599,6 +621,8 @@ void PortsWindow::on_actionPort_Configuration_triggered()
|
|||||||
// TODO: extend Port::protoDataCopyInto() to accept an optional param
|
// TODO: extend Port::protoDataCopyInto() to accept an optional param
|
||||||
// which says copy only modifiable fields
|
// which says copy only modifiable fields
|
||||||
//plm->port(current).protoDataCopyInto(&config);
|
//plm->port(current).protoDataCopyInto(&config);
|
||||||
|
config.set_description(port.systemDescription().toStdString());
|
||||||
|
config.set_user_description(port.userDescription().toStdString());
|
||||||
config.set_transmit_mode(port.transmitMode());
|
config.set_transmit_mode(port.transmitMode());
|
||||||
config.set_is_tracking_stream_stats(port.trackStreamStats());
|
config.set_is_tracking_stream_stats(port.trackStreamStats());
|
||||||
config.set_is_exclusive_control(port.hasExclusiveControl());
|
config.set_is_exclusive_control(port.hasExclusiveControl());
|
||||||
|
@ -50,6 +50,10 @@ public:
|
|||||||
QString &error,
|
QString &error,
|
||||||
QProgressDialog *progress = NULL);
|
QProgressDialog *progress = NULL);
|
||||||
|
|
||||||
|
QList<QAction*> portActions();
|
||||||
|
QList<QAction*> streamActions();
|
||||||
|
QList<QAction*> deviceActions();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void currentPortChanged(const QModelIndex ¤t,
|
void currentPortChanged(const QModelIndex ¤t,
|
||||||
const QModelIndex &previous);
|
const QModelIndex &previous);
|
||||||
@ -76,7 +80,8 @@ private slots:
|
|||||||
void on_actionDisconnect_Port_Group_triggered();
|
void on_actionDisconnect_Port_Group_triggered();
|
||||||
|
|
||||||
void on_actionExclusive_Control_triggered(bool checked);
|
void on_actionExclusive_Control_triggered(bool checked);
|
||||||
void on_actionPort_Configuration_triggered();
|
void when_actionPort_Configuration_triggered(
|
||||||
|
const QModelIndex &portIndex = QModelIndex());
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PortGroupList *plm;
|
PortGroupList *plm;
|
||||||
|
@ -39,7 +39,7 @@
|
|||||||
<widget class="QStackedWidget" name="swDetail">
|
<widget class="QStackedWidget" name="swDetail">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||||
<horstretch>2</horstretch>
|
<horstretch>1</horstretch>
|
||||||
<verstretch>0</verstretch>
|
<verstretch>0</verstretch>
|
||||||
</sizepolicy>
|
</sizepolicy>
|
||||||
</property>
|
</property>
|
||||||
|
@ -48,30 +48,34 @@ PortWidget::~PortWidget()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void PortWidget::setCurrentPortIndex(const QModelIndex &portIndex)
|
void PortWidget::setCurrentPortIndex(const QModelIndex ¤tIndex,
|
||||||
|
const QModelIndex &previousIndex)
|
||||||
{
|
{
|
||||||
if (!plm)
|
if (!plm)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel
|
qDebug("In %s", __PRETTY_FUNCTION__);
|
||||||
if (!plm->isPort(portIndex))
|
|
||||||
return;
|
|
||||||
|
|
||||||
qDebug("In %s", __FUNCTION__);
|
// XXX: We assume indices corresponds to sourceModel, not proxyModel
|
||||||
|
// - caller/sender should ensure this
|
||||||
|
|
||||||
// Disconnect previous port
|
// Disconnect previous port
|
||||||
if (plm->isPort(currentPortIndex_))
|
if (plm->isPort(previousIndex))
|
||||||
disconnect(&(plm->port(currentPortIndex_)),
|
disconnect(&(plm->port(previousIndex)),
|
||||||
SIGNAL(portRateChanged(int, int)),
|
SIGNAL(portRateChanged(int, int)),
|
||||||
this, SLOT(updatePortRates()));
|
this, SLOT(updatePortRates()));
|
||||||
|
|
||||||
currentPortIndex_ = portIndex;
|
if (!plm->isPort(currentIndex)) {
|
||||||
|
currentPortIndex_ = QModelIndex(); // set to invalid
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentPortIndex_ = currentIndex;
|
||||||
|
|
||||||
// Connect current port
|
// Connect current port
|
||||||
if (plm->isPort(currentPortIndex_))
|
connect(&(plm->port(currentPortIndex_)),
|
||||||
connect(&(plm->port(currentPortIndex_)),
|
SIGNAL(portRateChanged(int, int)),
|
||||||
SIGNAL(portRateChanged(int, int)),
|
this, SLOT(updatePortRates()));
|
||||||
this, SLOT(updatePortRates()));
|
|
||||||
|
|
||||||
double speed = plm->port(currentPortIndex_).speed();
|
double speed = plm->port(currentPortIndex_).speed();
|
||||||
portSpeed->setText(QString("Max %L1 Mbps").arg(speed));
|
portSpeed->setText(QString("Max %L1 Mbps").arg(speed));
|
||||||
|
@ -37,7 +37,8 @@ public:
|
|||||||
void setPortGroupList(PortGroupList *portGroups);
|
void setPortGroupList(PortGroupList *portGroups);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void setCurrentPortIndex(const QModelIndex &portIndex);
|
void setCurrentPortIndex(const QModelIndex ¤tIndex,
|
||||||
|
const QModelIndex &previousIndex);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "../common/ostprotolib.h"
|
#include "../common/ostprotolib.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
|
#include "thememanager.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QtGlobal>
|
#include <QtGlobal>
|
||||||
@ -40,6 +41,7 @@ Preferences::Preferences()
|
|||||||
|
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
|
|
||||||
|
// Program paths
|
||||||
wiresharkPathEdit->setText(appSettings->value(kWiresharkPathKey,
|
wiresharkPathEdit->setText(appSettings->value(kWiresharkPathKey,
|
||||||
kWiresharkPathDefaultValue).toString());
|
kWiresharkPathDefaultValue).toString());
|
||||||
tsharkPathEdit->setText(appSettings->value(kTsharkPathKey,
|
tsharkPathEdit->setText(appSettings->value(kTsharkPathKey,
|
||||||
@ -51,6 +53,10 @@ Preferences::Preferences()
|
|||||||
awkPathEdit->setText(appSettings->value(kAwkPathKey,
|
awkPathEdit->setText(appSettings->value(kAwkPathKey,
|
||||||
kAwkPathDefaultValue).toString());
|
kAwkPathDefaultValue).toString());
|
||||||
|
|
||||||
|
// Theme
|
||||||
|
theme->addItems(ThemeManager::instance()->themeList());
|
||||||
|
theme->setCurrentText(appSettings->value(kThemeKey).toString());
|
||||||
|
|
||||||
// TODO(only if required): kUserKey
|
// TODO(only if required): kUserKey
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -78,6 +84,7 @@ void Preferences::initDefaults()
|
|||||||
|
|
||||||
void Preferences::accept()
|
void Preferences::accept()
|
||||||
{
|
{
|
||||||
|
// Program paths
|
||||||
appSettings->setValue(kWiresharkPathKey, wiresharkPathEdit->text());
|
appSettings->setValue(kWiresharkPathKey, wiresharkPathEdit->text());
|
||||||
appSettings->setValue(kTsharkPathKey, tsharkPathEdit->text());
|
appSettings->setValue(kTsharkPathKey, tsharkPathEdit->text());
|
||||||
appSettings->setValue(kGzipPathKey, gzipPathEdit->text());
|
appSettings->setValue(kGzipPathKey, gzipPathEdit->text());
|
||||||
@ -90,6 +97,9 @@ void Preferences::accept()
|
|||||||
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
|
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
|
||||||
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
|
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
|
||||||
|
|
||||||
|
// Theme
|
||||||
|
ThemeManager::instance()->setTheme(theme->currentText());
|
||||||
|
|
||||||
QDialog::accept();
|
QDialog::accept();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
<ui version="4.0" >
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
<class>Preferences</class>
|
<class>Preferences</class>
|
||||||
<widget class="QDialog" name="Preferences" >
|
<widget class="QDialog" name="Preferences">
|
||||||
<property name="geometry" >
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
@ -9,148 +10,149 @@
|
|||||||
<height>220</height>
|
<height>220</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle" >
|
<property name="windowTitle">
|
||||||
<string>Preferences</string>
|
<string>Preferences</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowIcon" >
|
<property name="windowIcon">
|
||||||
<iconset resource="ostinato.qrc" >:/icons/preferences.png</iconset>
|
<iconset resource="ostinato.qrc">
|
||||||
|
<normaloff>:/icons/preferences.png</normaloff>:/icons/preferences.png</iconset>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" >
|
<layout class="QVBoxLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QFrame" name="frame" >
|
<widget class="QFrame" name="frame">
|
||||||
<property name="frameShape" >
|
<property name="frameShape">
|
||||||
<enum>QFrame::Box</enum>
|
<enum>QFrame::Box</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="frameShadow" >
|
<property name="frameShadow">
|
||||||
<enum>QFrame::Sunken</enum>
|
<enum>QFrame::Sunken</enum>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" >
|
<layout class="QGridLayout">
|
||||||
<item row="0" column="0" >
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="label" >
|
<widget class="QLabel" name="label">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>'wireshark' Path</string>
|
<string>'wireshark' Path</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy" >
|
<property name="buddy">
|
||||||
<cstring>wiresharkPathEdit</cstring>
|
<cstring>wiresharkPathEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="1" >
|
<item row="0" column="1">
|
||||||
<widget class="QLineEdit" name="wiresharkPathEdit" >
|
<widget class="QLineEdit" name="wiresharkPathEdit">
|
||||||
<property name="enabled" >
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="0" column="2" >
|
<item row="0" column="2">
|
||||||
<widget class="QToolButton" name="wiresharkPathButton" >
|
<widget class="QToolButton" name="wiresharkPathButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="0" >
|
<item row="1" column="0">
|
||||||
<widget class="QLabel" name="label_2" >
|
<widget class="QLabel" name="label_2">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>'tshark' Path</string>
|
<string>'tshark' Path</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy" >
|
<property name="buddy">
|
||||||
<cstring>tsharkPathEdit</cstring>
|
<cstring>tsharkPathEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" >
|
<item row="1" column="1">
|
||||||
<widget class="QLineEdit" name="tsharkPathEdit" >
|
<widget class="QLineEdit" name="tsharkPathEdit">
|
||||||
<property name="enabled" >
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="1" column="2" >
|
<item row="1" column="2">
|
||||||
<widget class="QToolButton" name="tsharkPathButton" >
|
<widget class="QToolButton" name="tsharkPathButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" >
|
<item row="2" column="0">
|
||||||
<widget class="QLabel" name="label_5" >
|
<widget class="QLabel" name="label_5">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>'gzip' Path</string>
|
<string>'gzip' Path</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy" >
|
<property name="buddy">
|
||||||
<cstring>diffPathEdit</cstring>
|
<cstring>diffPathEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" >
|
<item row="2" column="1">
|
||||||
<widget class="QLineEdit" name="gzipPathEdit" >
|
<widget class="QLineEdit" name="gzipPathEdit">
|
||||||
<property name="enabled" >
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="2" >
|
<item row="2" column="2">
|
||||||
<widget class="QToolButton" name="gzipPathButton" >
|
<widget class="QToolButton" name="gzipPathButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" >
|
<item row="3" column="0">
|
||||||
<widget class="QLabel" name="label_3" >
|
<widget class="QLabel" name="label_3">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>'diff' Path</string>
|
<string>'diff' Path</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy" >
|
<property name="buddy">
|
||||||
<cstring>diffPathEdit</cstring>
|
<cstring>diffPathEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="1" >
|
<item row="3" column="1">
|
||||||
<widget class="QLineEdit" name="diffPathEdit" >
|
<widget class="QLineEdit" name="diffPathEdit">
|
||||||
<property name="enabled" >
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="2" >
|
<item row="3" column="2">
|
||||||
<widget class="QToolButton" name="diffPathButton" >
|
<widget class="QToolButton" name="diffPathButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="0" >
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="label_4" >
|
<widget class="QLabel" name="label_4">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>'awk' Path</string>
|
<string>'awk' Path</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="buddy" >
|
<property name="buddy">
|
||||||
<cstring>awkPathEdit</cstring>
|
<cstring>awkPathEdit</cstring>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1" >
|
<item row="4" column="1">
|
||||||
<widget class="QLineEdit" name="awkPathEdit" >
|
<widget class="QLineEdit" name="awkPathEdit">
|
||||||
<property name="enabled" >
|
<property name="enabled">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="2" >
|
<item row="4" column="2">
|
||||||
<widget class="QToolButton" name="awkPathButton" >
|
<widget class="QToolButton" name="awkPathButton">
|
||||||
<property name="text" >
|
<property name="text">
|
||||||
<string>...</string>
|
<string>...</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1" >
|
<item row="5" column="1">
|
||||||
<spacer>
|
<spacer>
|
||||||
<property name="orientation" >
|
<property name="orientation">
|
||||||
<enum>Qt::Vertical</enum>
|
<enum>Qt::Vertical</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="sizeHint" >
|
<property name="sizeHint" stdset="0">
|
||||||
<size>
|
<size>
|
||||||
<width>21</width>
|
<width>21</width>
|
||||||
<height>61</height>
|
<height>61</height>
|
||||||
@ -162,12 +164,26 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QDialogButtonBox" name="buttonBox" >
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="orientation" >
|
<item>
|
||||||
|
<widget class="QLabel" name="label_6">
|
||||||
|
<property name="text">
|
||||||
|
<string>Theme (Experimental)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QComboBox" name="theme"/>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QDialogButtonBox" name="buttonBox">
|
||||||
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="standardButtons" >
|
<property name="standardButtons">
|
||||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
|
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -187,7 +203,7 @@
|
|||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
</tabstops>
|
</tabstops>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="ostinato.qrc" />
|
<include location="ostinato.qrc"/>
|
||||||
</resources>
|
</resources>
|
||||||
<connections>
|
<connections>
|
||||||
<connection>
|
<connection>
|
||||||
@ -196,11 +212,11 @@
|
|||||||
<receiver>Preferences</receiver>
|
<receiver>Preferences</receiver>
|
||||||
<slot>accept()</slot>
|
<slot>accept()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel" >
|
<hint type="sourcelabel">
|
||||||
<x>248</x>
|
<x>248</x>
|
||||||
<y>254</y>
|
<y>254</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel" >
|
<hint type="destinationlabel">
|
||||||
<x>157</x>
|
<x>157</x>
|
||||||
<y>274</y>
|
<y>274</y>
|
||||||
</hint>
|
</hint>
|
||||||
@ -212,11 +228,11 @@
|
|||||||
<receiver>Preferences</receiver>
|
<receiver>Preferences</receiver>
|
||||||
<slot>reject()</slot>
|
<slot>reject()</slot>
|
||||||
<hints>
|
<hints>
|
||||||
<hint type="sourcelabel" >
|
<hint type="sourcelabel">
|
||||||
<x>316</x>
|
<x>316</x>
|
||||||
<y>260</y>
|
<y>260</y>
|
||||||
</hint>
|
</hint>
|
||||||
<hint type="destinationlabel" >
|
<hint type="destinationlabel">
|
||||||
<x>286</x>
|
<x>286</x>
|
||||||
<y>274</y>
|
<y>274</y>
|
||||||
</hint>
|
</hint>
|
||||||
|
50
client/rowborderdelegate.h
Normal file
50
client/rowborderdelegate.h
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2023 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _ROW_BORDER_DELEGATE
|
||||||
|
#define _ROW_BORDER_DELEGATE
|
||||||
|
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
|
|
||||||
|
class RowBorderDelegate : public QStyledItemDelegate
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
RowBorderDelegate(QSet<int> rows, QObject *parent = nullptr)
|
||||||
|
: QStyledItemDelegate(parent), rows_(rows)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void paint(QPainter *painter, const QStyleOptionViewItem &option,
|
||||||
|
const QModelIndex &index) const
|
||||||
|
{
|
||||||
|
QStyledItemDelegate::paint(painter, option, index);
|
||||||
|
if (rows_.contains(index.row())) {
|
||||||
|
const QRect rect(option.rect);
|
||||||
|
painter->drawLine(rect.topLeft(), rect.topRight());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QSet<int> rows_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -74,6 +74,8 @@ const QString kAwkPathDefaultValue("/usr/bin/awk");
|
|||||||
const QString kAwkPathDefaultValue("/usr/bin/awk");
|
const QString kAwkPathDefaultValue("/usr/bin/awk");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const QString kThemeKey("Theme");
|
||||||
|
|
||||||
const QString kUserKey("User");
|
const QString kUserKey("User");
|
||||||
extern QString kUserDefaultValue;
|
extern QString kUserDefaultValue;
|
||||||
|
|
||||||
|
@ -675,6 +675,19 @@ QLineEdit:enabled[inputMask = "HH HH HH HH HH HH; "] { background-colo
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="page_2">
|
<widget class="QWidget" name="page_2">
|
||||||
|
@ -361,15 +361,13 @@ void StreamModel::setCurrentPortIndex(const QModelIndex ¤t)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug("change to valid port");
|
qDebug("change to valid port");
|
||||||
// Disconnect any existing connection to avoid duplication
|
|
||||||
// Qt 4.6 has Qt::UniqueConnection, but we want to remain compatible
|
|
||||||
// with earlier Qt versions
|
|
||||||
if (mCurrentPort)
|
if (mCurrentPort)
|
||||||
{
|
{
|
||||||
disconnect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
|
disconnect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
|
||||||
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));
|
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));
|
||||||
}
|
}
|
||||||
quint16 pg = current.internalId() >> 16;
|
quint16 pg = current.internalId() >> 16;
|
||||||
|
// TODO: make mCurrentPort a smart weak pointer
|
||||||
mCurrentPort = pgl->mPortGroups[pgl->indexOfPortGroup(pg)]->mPorts[current.row()];
|
mCurrentPort = pgl->mPortGroups[pgl->indexOfPortGroup(pg)]->mPorts[current.row()];
|
||||||
connect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
|
connect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
|
||||||
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));
|
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));
|
||||||
|
@ -20,8 +20,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "streamstatsmodel.h"
|
#include "streamstatsmodel.h"
|
||||||
|
|
||||||
#include "protocol.pb.h"
|
#include "protocol.pb.h"
|
||||||
|
#include "xqlocale.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
#include <QBrush>
|
#include <QBrush>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QPalette>
|
||||||
|
|
||||||
// XXX: Keep the enum in sync with it's string
|
// XXX: Keep the enum in sync with it's string
|
||||||
enum {
|
enum {
|
||||||
@ -42,12 +46,26 @@ enum {
|
|||||||
kAggrTxPkts,
|
kAggrTxPkts,
|
||||||
kAggrRxPkts,
|
kAggrRxPkts,
|
||||||
kAggrPktLoss,
|
kAggrPktLoss,
|
||||||
|
kTxDuration,
|
||||||
|
kAvgTxFrameRate,
|
||||||
|
kAvgRxFrameRate,
|
||||||
|
kAvgTxBitRate,
|
||||||
|
kAvgRxBitRate,
|
||||||
|
kAvgLatency,
|
||||||
|
kAvgJitter,
|
||||||
kMaxAggrStreamStats
|
kMaxAggrStreamStats
|
||||||
};
|
};
|
||||||
static QStringList aggrStatTitles = QStringList()
|
static QStringList aggrStatTitles = QStringList()
|
||||||
<< "Total\nTx Pkts"
|
<< "Total\nTx Pkts"
|
||||||
<< "Total\nRx Pkts"
|
<< "Total\nRx Pkts"
|
||||||
<< "Total\nPkt Loss";
|
<< "Total\nPkt Loss"
|
||||||
|
<< "Duration\n(secs)"
|
||||||
|
<< "Avg\nTx PktRate"
|
||||||
|
<< "Avg\nRx PktRate"
|
||||||
|
<< "Avg\nTx BitRate"
|
||||||
|
<< "Avg\nRx BitRate"
|
||||||
|
<< "Avg\nLatency"
|
||||||
|
<< "Avg\nJitter";
|
||||||
|
|
||||||
static const uint kAggrGuid = 0xffffffff;
|
static const uint kAggrGuid = 0xffffffff;
|
||||||
|
|
||||||
@ -103,20 +121,35 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
return Qt::AlignRight;
|
return Qt::AlignRight;
|
||||||
|
|
||||||
int portColumn = index.column() - kMaxAggrStreamStats;
|
int portColumn = index.column() - kMaxAggrStreamStats;
|
||||||
if (role == Qt::BackgroundRole) {
|
|
||||||
if (portColumn < 0)
|
// Stylesheets typically don't use or set palette colors, so if
|
||||||
return QBrush(QColor("lavender")); // Aggregate Column
|
// using one, don't use palette colors
|
||||||
if (index.row() == (guidList_.size() - 1))
|
if ((role == Qt::BackgroundRole) && qApp->styleSheet().isEmpty()) {
|
||||||
return QBrush(QColor("burlywood")); // Aggregate Row
|
QPalette palette = QApplication::palette();
|
||||||
else if ((portColumn/kMaxStreamStats) & 1)
|
if (index.row() == (guidList_.size() - 1)) // Aggregate Row
|
||||||
return QBrush(QColor("beige")); // Color alternate Ports
|
return palette.dark();
|
||||||
|
if (portColumn < 0) // Aggregate Column
|
||||||
|
return palette.alternateBase();
|
||||||
|
if ((portColumn/kMaxStreamStats) & 1) // Color alternate Ports
|
||||||
|
return palette.alternateBase();
|
||||||
}
|
}
|
||||||
|
|
||||||
Guid guid = guidList_.at(index.row());
|
Guid guid = guidList_.at(index.row());
|
||||||
if (role == Qt::ForegroundRole) {
|
if ((role == Qt::ForegroundRole && qApp->styleSheet().isEmpty())) {
|
||||||
|
QPalette palette = QApplication::palette();
|
||||||
if ((index.column() == kAggrPktLoss)
|
if ((index.column() == kAggrPktLoss)
|
||||||
&& aggrGuidStats_.value(guid).pktLoss)
|
&& aggrGuidStats_.value(guid).pktLoss)
|
||||||
return QBrush(QColor("firebrick"));
|
return palette.link();
|
||||||
|
if (index.row() == (guidList_.size() - 1)) // Aggregate Row
|
||||||
|
return palette.brightText();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == Qt::FontRole ) {
|
||||||
|
if (index.row() == (guidList_.size() - 1)) { // Aggregate Row
|
||||||
|
QFont font;
|
||||||
|
font.setBold(true);
|
||||||
|
return font;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (role != Qt::DisplayRole)
|
if (role != Qt::DisplayRole)
|
||||||
@ -131,6 +164,42 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
|
|||||||
return QString("%L1").arg(aggrGuidStats_.value(guid).txPkts);
|
return QString("%L1").arg(aggrGuidStats_.value(guid).txPkts);
|
||||||
case kAggrPktLoss:
|
case kAggrPktLoss:
|
||||||
return QString("%L1").arg(aggrGuidStats_.value(guid).pktLoss);
|
return QString("%L1").arg(aggrGuidStats_.value(guid).pktLoss);
|
||||||
|
case kTxDuration:
|
||||||
|
return QString("%L1").arg(aggrGuidStats_.value(guid).txDuration);
|
||||||
|
case kAvgTxFrameRate:
|
||||||
|
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
||||||
|
XLocale().toPktRateString(
|
||||||
|
aggrGuidStats_.value(guid).txPkts
|
||||||
|
/ aggrGuidStats_.value(guid).txDuration);
|
||||||
|
case kAvgRxFrameRate:
|
||||||
|
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
||||||
|
XLocale().toPktRateString(
|
||||||
|
aggrGuidStats_.value(guid).rxPkts
|
||||||
|
/ aggrGuidStats_.value(guid).txDuration);
|
||||||
|
case kAvgTxBitRate:
|
||||||
|
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
||||||
|
XLocale().toBitRateString(
|
||||||
|
(aggrGuidStats_.value(guid).txBytes
|
||||||
|
+ 24 * aggrGuidStats_.value(guid).txPkts) * 8
|
||||||
|
/ aggrGuidStats_.value(guid).txDuration);
|
||||||
|
case kAvgRxBitRate:
|
||||||
|
return aggrGuidStats_.value(guid).txDuration <= 0 ? QString("-") :
|
||||||
|
XLocale().toBitRateString(
|
||||||
|
(aggrGuidStats_.value(guid).rxBytes
|
||||||
|
+ 24 * aggrGuidStats_.value(guid).rxPkts) * 8
|
||||||
|
/ aggrGuidStats_.value(guid).txDuration);
|
||||||
|
case kAvgLatency:
|
||||||
|
return aggrGuidStats_.value(guid).latencyCount <= 0
|
||||||
|
|| aggrGuidStats_.value(guid).latencySum <= 0 ? QString("-") :
|
||||||
|
XLocale().toTimeIntervalString(
|
||||||
|
aggrGuidStats_.value(guid).latencySum
|
||||||
|
/ aggrGuidStats_.value(guid).latencyCount);
|
||||||
|
case kAvgJitter:
|
||||||
|
return aggrGuidStats_.value(guid).latencyCount <= 0
|
||||||
|
|| aggrGuidStats_.value(guid).latencySum <= 0 ? QString("-") :
|
||||||
|
XLocale().toTimeIntervalString(
|
||||||
|
aggrGuidStats_.value(guid).jitterSum
|
||||||
|
/ aggrGuidStats_.value(guid).latencyCount);
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
@ -205,6 +274,8 @@ void StreamStatsModel::appendStreamStatsList(
|
|||||||
ss.txPkts = s.tx_pkts();
|
ss.txPkts = s.tx_pkts();
|
||||||
ss.rxBytes = s.rx_bytes();
|
ss.rxBytes = s.rx_bytes();
|
||||||
ss.txBytes = s.tx_bytes();
|
ss.txBytes = s.tx_bytes();
|
||||||
|
ss.rxLatency = s.latency();
|
||||||
|
ss.rxJitter = s.jitter();
|
||||||
|
|
||||||
aggrPort.rxPkts += ss.rxPkts;
|
aggrPort.rxPkts += ss.rxPkts;
|
||||||
aggrPort.txPkts += ss.txPkts;
|
aggrPort.txPkts += ss.txPkts;
|
||||||
@ -214,10 +285,28 @@ void StreamStatsModel::appendStreamStatsList(
|
|||||||
aggrGuid.rxPkts += ss.rxPkts;
|
aggrGuid.rxPkts += ss.rxPkts;
|
||||||
aggrGuid.txPkts += ss.txPkts;
|
aggrGuid.txPkts += ss.txPkts;
|
||||||
aggrGuid.pktLoss += ss.txPkts - ss.rxPkts;
|
aggrGuid.pktLoss += ss.txPkts - ss.rxPkts;
|
||||||
|
aggrGuid.rxBytes += ss.rxBytes;
|
||||||
|
aggrGuid.txBytes += ss.txBytes;
|
||||||
|
if (s.tx_duration() > aggrGuid.txDuration)
|
||||||
|
aggrGuid.txDuration = s.tx_duration(); // XXX: use largest or avg?
|
||||||
|
if (ss.rxLatency) {
|
||||||
|
aggrGuid.latencySum += ss.rxLatency;
|
||||||
|
aggrGuid.jitterSum += ss.rxJitter;
|
||||||
|
aggrGuid.latencyCount++;
|
||||||
|
}
|
||||||
|
|
||||||
aggrAggr.rxPkts += ss.rxPkts;
|
aggrAggr.rxPkts += ss.rxPkts;
|
||||||
aggrAggr.txPkts += ss.txPkts;
|
aggrAggr.txPkts += ss.txPkts;
|
||||||
aggrAggr.pktLoss += ss.txPkts - ss.rxPkts;
|
aggrAggr.pktLoss += ss.txPkts - ss.rxPkts;
|
||||||
|
aggrAggr.rxBytes += ss.rxBytes;
|
||||||
|
aggrAggr.txBytes += ss.txBytes;
|
||||||
|
if (aggrGuid.txDuration > aggrAggr.txDuration)
|
||||||
|
aggrAggr.txDuration = aggrGuid.txDuration;
|
||||||
|
if (ss.rxLatency) {
|
||||||
|
aggrAggr.latencySum += ss.rxLatency;
|
||||||
|
aggrAggr.jitterSum += ss.rxJitter;
|
||||||
|
aggrAggr.latencyCount++;
|
||||||
|
}
|
||||||
|
|
||||||
if (!portList_.contains(pgp))
|
if (!portList_.contains(pgp))
|
||||||
portList_.append(pgp);
|
portList_.append(pgp);
|
||||||
@ -228,6 +317,8 @@ void StreamStatsModel::appendStreamStatsList(
|
|||||||
if (guidList_.size() && !guidList_.contains(kAggrGuid))
|
if (guidList_.size() && !guidList_.contains(kAggrGuid))
|
||||||
guidList_.append(kAggrGuid);
|
guidList_.append(kAggrGuid);
|
||||||
|
|
||||||
|
std::sort(guidList_.begin(), guidList_.end());
|
||||||
|
|
||||||
#if QT_VERSION >= 0x040600
|
#if QT_VERSION >= 0x040600
|
||||||
endResetModel();
|
endResetModel();
|
||||||
#else
|
#else
|
||||||
|
@ -57,11 +57,19 @@ private:
|
|||||||
quint64 txPkts;
|
quint64 txPkts;
|
||||||
quint64 rxBytes;
|
quint64 rxBytes;
|
||||||
quint64 txBytes;
|
quint64 txBytes;
|
||||||
|
quint64 rxLatency;
|
||||||
|
quint64 rxJitter;
|
||||||
};
|
};
|
||||||
struct AggrGuidStats {
|
struct AggrGuidStats {
|
||||||
quint64 rxPkts;
|
quint64 rxPkts;
|
||||||
quint64 txPkts;
|
quint64 txPkts;
|
||||||
|
quint64 rxBytes;
|
||||||
|
quint64 txBytes;
|
||||||
qint64 pktLoss;
|
qint64 pktLoss;
|
||||||
|
double txDuration;
|
||||||
|
quint64 latencySum;
|
||||||
|
quint64 jitterSum;
|
||||||
|
uint latencyCount;
|
||||||
};
|
};
|
||||||
QList<Guid> guidList_;
|
QList<Guid> guidList_;
|
||||||
QList<PortGroupPort> portList_;
|
QList<PortGroupPort> portList_;
|
||||||
|
@ -31,7 +31,7 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
setupUi(this);
|
setupUi(this);
|
||||||
streamStats->addAction(actionShowByteCounters);
|
streamStats->addAction(actionShowDetails);
|
||||||
|
|
||||||
if (id)
|
if (id)
|
||||||
setWindowTitle(windowTitle() + QString("(%1)").arg(id));
|
setWindowTitle(windowTitle() + QString("(%1)").arg(id));
|
||||||
@ -39,13 +39,17 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
|
|||||||
count++;
|
count++;
|
||||||
|
|
||||||
filterModel_ = new StreamStatsFilterModel(this);
|
filterModel_ = new StreamStatsFilterModel(this);
|
||||||
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*"));
|
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
|
||||||
filterModel_->setSourceModel(model);
|
filterModel_->setSourceModel(model);
|
||||||
streamStats->setModel(filterModel_);
|
streamStats->setModel(filterModel_);
|
||||||
|
|
||||||
streamStats->verticalHeader()->setHighlightSections(false);
|
streamStats->verticalHeader()->setHighlightSections(false);
|
||||||
streamStats->verticalHeader()->setDefaultSectionSize(
|
streamStats->verticalHeader()->setDefaultSectionSize(
|
||||||
streamStats->verticalHeader()->minimumSectionSize());
|
streamStats->verticalHeader()->minimumSectionSize());
|
||||||
|
|
||||||
|
// Fit all columns in window whenever data changes
|
||||||
|
connect(model, &QAbstractItemModel::modelReset,
|
||||||
|
[=]() { streamStats->resizeColumnsToContents(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
StreamStatsWindow::~StreamStatsWindow()
|
StreamStatsWindow::~StreamStatsWindow()
|
||||||
@ -56,10 +60,12 @@ StreamStatsWindow::~StreamStatsWindow()
|
|||||||
id = 0;
|
id = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamStatsWindow::on_actionShowByteCounters_triggered(bool checked)
|
void StreamStatsWindow::on_actionShowDetails_triggered(bool checked)
|
||||||
{
|
{
|
||||||
if (checked)
|
if (checked)
|
||||||
filterModel_->setFilterRegExp(QRegExp(".*"));
|
filterModel_->setFilterRegExp(QRegExp(".*"));
|
||||||
else
|
else
|
||||||
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*"));
|
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
|
||||||
|
|
||||||
|
streamStats->resizeColumnsToContents();
|
||||||
}
|
}
|
||||||
|
@ -33,9 +33,10 @@ public:
|
|||||||
~StreamStatsWindow();
|
~StreamStatsWindow();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_actionShowByteCounters_triggered(bool checked);
|
void on_actionShowDetails_triggered(bool checked);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QString kDefaultFilter_{"^(?!Port).*"};
|
||||||
QSortFilterProxyModel *filterModel_;
|
QSortFilterProxyModel *filterModel_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
<property name="contextMenuPolicy">
|
<property name="contextMenuPolicy">
|
||||||
<enum>Qt::ActionsContextMenu</enum>
|
<enum>Qt::ActionsContextMenu</enum>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="selectionBehavior">
|
||||||
|
<enum>QAbstractItemView::SelectRows</enum>
|
||||||
|
</property>
|
||||||
<property name="whatsThis">
|
<property name="whatsThis">
|
||||||
<string>Oops! We don't seem to have any stream statistics for the requested port(s)
|
<string>Oops! We don't seem to have any stream statistics for the requested port(s)
|
||||||
|
|
||||||
@ -27,12 +30,12 @@ Wait a little bit to see if they appear, otherwise verify your stream stats conf
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
<action name="actionShowByteCounters">
|
<action name="actionShowDetails">
|
||||||
<property name="checkable">
|
<property name="checkable">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Show Byte Counters</string>
|
<string>Show Details</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
|
@ -126,6 +126,8 @@ void StreamsWidget::on_tvStreamList_activated(const QModelIndex & index)
|
|||||||
|
|
||||||
qDebug("stream list activated\n");
|
qDebug("stream list activated\n");
|
||||||
|
|
||||||
|
Q_ASSERT(plm->isPort(currentPortIndex_));
|
||||||
|
|
||||||
Port &curPort = plm->port(currentPortIndex_);
|
Port &curPort = plm->port(currentPortIndex_);
|
||||||
|
|
||||||
QList<Stream*> streams;
|
QList<Stream*> streams;
|
||||||
@ -143,11 +145,10 @@ void StreamsWidget::setCurrentPortIndex(const QModelIndex &portIndex)
|
|||||||
if (!plm)
|
if (!plm)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel
|
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel;
|
||||||
if (!plm->isPort(portIndex))
|
// caller should ensure this
|
||||||
return;
|
|
||||||
|
|
||||||
qDebug("In %s", __FUNCTION__);
|
qDebug("In %s", __PRETTY_FUNCTION__);
|
||||||
|
|
||||||
currentPortIndex_ = portIndex;
|
currentPortIndex_ = portIndex;
|
||||||
plm->getStreamModel()->setCurrentPortIndex(portIndex);
|
plm->getStreamModel()->setCurrentPortIndex(portIndex);
|
||||||
@ -223,6 +224,8 @@ void StreamsWidget::on_actionNew_Stream_triggered()
|
|||||||
count = selectionModel->selection().at(0).height();
|
count = selectionModel->selection().at(0).height();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_ASSERT(plm->isPort(currentPortIndex_));
|
||||||
|
|
||||||
Port &curPort = plm->port(currentPortIndex_);
|
Port &curPort = plm->port(currentPortIndex_);
|
||||||
|
|
||||||
QList<Stream*> streams;
|
QList<Stream*> streams;
|
||||||
@ -243,6 +246,8 @@ void StreamsWidget::on_actionEdit_Stream_triggered()
|
|||||||
if (!streamModel->hasSelection())
|
if (!streamModel->hasSelection())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
Q_ASSERT(plm->isPort(currentPortIndex_));
|
||||||
|
|
||||||
Port &curPort = plm->port(currentPortIndex_);
|
Port &curPort = plm->port(currentPortIndex_);
|
||||||
|
|
||||||
QList<Stream*> streams;
|
QList<Stream*> streams;
|
||||||
@ -262,6 +267,8 @@ void StreamsWidget::on_actionDuplicate_Stream_triggered()
|
|||||||
|
|
||||||
qDebug("Duplicate Stream Action");
|
qDebug("Duplicate Stream Action");
|
||||||
|
|
||||||
|
Q_ASSERT(plm->isPort(currentPortIndex_));
|
||||||
|
|
||||||
if (model->hasSelection())
|
if (model->hasSelection())
|
||||||
{
|
{
|
||||||
bool isOk;
|
bool isOk;
|
||||||
@ -304,6 +311,8 @@ void StreamsWidget::on_actionFind_Replace_triggered()
|
|||||||
{
|
{
|
||||||
qDebug("Find & Replace Action");
|
qDebug("Find & Replace Action");
|
||||||
|
|
||||||
|
Q_ASSERT(plm->isPort(currentPortIndex_));
|
||||||
|
|
||||||
QItemSelectionModel* selectionModel = tvStreamList->selectionModel();
|
QItemSelectionModel* selectionModel = tvStreamList->selectionModel();
|
||||||
FindReplaceDialog::Action action;
|
FindReplaceDialog::Action action;
|
||||||
|
|
||||||
|
130
client/thememanager.cpp
Normal file
130
client/thememanager.cpp
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "thememanager.h"
|
||||||
|
|
||||||
|
#include "settings.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QDir>
|
||||||
|
#include <QDirIterator>
|
||||||
|
#include <QRegularExpression>
|
||||||
|
#include <QResource>
|
||||||
|
|
||||||
|
ThemeManager *ThemeManager::instance_{nullptr};
|
||||||
|
|
||||||
|
ThemeManager::ThemeManager()
|
||||||
|
{
|
||||||
|
themeDir_ = QCoreApplication::applicationDirPath() + "/themes/";
|
||||||
|
#if defined(Q_OS_MAC)
|
||||||
|
/*
|
||||||
|
* Executable and Theme directory location inside app bundle -
|
||||||
|
* Ostinato.app/Contents/MacOS/
|
||||||
|
* Ostinato.app/Contents/SharedSupport/themes/
|
||||||
|
*/
|
||||||
|
themeDir_.replace("/MacOS/", "/SharedSupport/");
|
||||||
|
#elif defined(Q_OS_UNIX)
|
||||||
|
/*
|
||||||
|
* Possible (but not comprehensive) locations for Ostinato executable
|
||||||
|
* and theme directory locations
|
||||||
|
*
|
||||||
|
* non-install-dir/
|
||||||
|
* non-install-dir/themes/
|
||||||
|
*
|
||||||
|
* /usr/[local]/bin/
|
||||||
|
* /usr/[local]/share/ostinato-controller/themes/
|
||||||
|
*
|
||||||
|
* /opt/ostinato/bin/
|
||||||
|
* /opt/ostinato/share/themes/
|
||||||
|
*/
|
||||||
|
if (themeDir_.contains(QRegularExpression("^/usr/.*/bin/")))
|
||||||
|
themeDir_.replace("/bin/", "/share/ostinato-controller/");
|
||||||
|
else if (themeDir_.contains(QRegularExpression("^/opt/.*/bin/")))
|
||||||
|
themeDir_.replace("/bin/", "/share/");
|
||||||
|
#endif
|
||||||
|
qDebug("Themes directory: %s", qPrintable(themeDir_));
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList ThemeManager::themeList()
|
||||||
|
{
|
||||||
|
QDir themeDir(themeDir_);
|
||||||
|
|
||||||
|
themeDir.setFilter(QDir::Files);
|
||||||
|
themeDir.setNameFilters(QStringList() << "*.qss");
|
||||||
|
themeDir.setSorting(QDir::Name);
|
||||||
|
|
||||||
|
QStringList themes = themeDir.entryList();
|
||||||
|
for (QString& theme : themes)
|
||||||
|
theme.remove(".qss");
|
||||||
|
themes.prepend("default");
|
||||||
|
|
||||||
|
return themes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThemeManager::setTheme(QString theme)
|
||||||
|
{
|
||||||
|
// Remove current theme, if we have one
|
||||||
|
QString oldTheme = appSettings->value(kThemeKey).toString();
|
||||||
|
if (!oldTheme.isEmpty()) {
|
||||||
|
// Remove stylesheet first so that there are
|
||||||
|
// no references to resources when unregistering 'em
|
||||||
|
qApp->setStyleSheet("");
|
||||||
|
QString rccFile = themeDir_ + oldTheme + ".rcc";
|
||||||
|
if (QResource::unregisterResource(rccFile)) {
|
||||||
|
qDebug("Unable to unregister theme rccFile %s",
|
||||||
|
qPrintable(rccFile));
|
||||||
|
}
|
||||||
|
appSettings->setValue(kThemeKey, QVariant());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theme.isEmpty() || (theme == "default"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Apply new theme
|
||||||
|
QFile qssFile(themeDir_ + theme + ".qss");
|
||||||
|
if (!qssFile.open(QFile::ReadOnly)) {
|
||||||
|
qDebug("Unable to open theme qssFile %s",
|
||||||
|
qPrintable(qssFile.fileName()));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register theme resource before applying theme style sheet
|
||||||
|
QString rccFile = themeDir_ + theme + ".rcc";
|
||||||
|
if (!QResource::registerResource(rccFile))
|
||||||
|
qDebug("Unable to register theme rccFile %s", qPrintable(rccFile));
|
||||||
|
|
||||||
|
#if 0 // FIXME: debug only
|
||||||
|
QDirIterator it(":", QDirIterator::Subdirectories);
|
||||||
|
while (it.hasNext()) {
|
||||||
|
qDebug() << it.next();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QString styleSheet { qssFile.readAll() };
|
||||||
|
qApp->setStyleSheet(styleSheet);
|
||||||
|
appSettings->setValue(kThemeKey, theme);
|
||||||
|
}
|
||||||
|
|
||||||
|
ThemeManager* ThemeManager::instance()
|
||||||
|
{
|
||||||
|
if (!instance_)
|
||||||
|
instance_ = new ThemeManager();
|
||||||
|
return instance_;
|
||||||
|
}
|
42
client/thememanager.h
Normal file
42
client/thememanager.h
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _THEME_MANAGER_H
|
||||||
|
#define _THEME_MANAGER_H
|
||||||
|
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
class ThemeManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ThemeManager();
|
||||||
|
|
||||||
|
QStringList themeList();
|
||||||
|
void setTheme(QString theme);
|
||||||
|
|
||||||
|
static ThemeManager* instance();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString themeDir_;
|
||||||
|
|
||||||
|
static ThemeManager *instance_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
1307
client/themes/material-dark.qss
Normal file
1307
client/themes/material-dark.qss
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/themes/material-dark.rcc
Normal file
BIN
client/themes/material-dark.rcc
Normal file
Binary file not shown.
1307
client/themes/material-light.qss
Normal file
1307
client/themes/material-light.qss
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/themes/material-light.rcc
Normal file
BIN
client/themes/material-light.rcc
Normal file
Binary file not shown.
2213
client/themes/qds-dark.qss
Normal file
2213
client/themes/qds-dark.qss
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/themes/qds-dark.rcc
Normal file
BIN
client/themes/qds-dark.rcc
Normal file
Binary file not shown.
2213
client/themes/qds-light.qss
Normal file
2213
client/themes/qds-light.qss
Normal file
File diff suppressed because it is too large
Load Diff
BIN
client/themes/qds-light.rcc
Normal file
BIN
client/themes/qds-light.rcc
Normal file
Binary file not shown.
@ -376,6 +376,9 @@ void VariableFieldsWidget::loadProtocolFields(
|
|||||||
int byteOfs = bitOfs >> 3;
|
int byteOfs = bitOfs >> 3;
|
||||||
uint bitSize = protocol->fieldData(i, AbstractProtocol::FieldBitSize)
|
uint bitSize = protocol->fieldData(i, AbstractProtocol::FieldBitSize)
|
||||||
.toInt();
|
.toInt();
|
||||||
|
if (bitSize == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
vm["offset"] = byteOfs;
|
vm["offset"] = byteOfs;
|
||||||
if (bitSize <= 8) {
|
if (bitSize <= 8) {
|
||||||
vm["type"] = int(OstProto::VariableField::kCounter8);
|
vm["type"] = int(OstProto::VariableField::kCounter8);
|
||||||
|
@ -85,20 +85,49 @@ public:
|
|||||||
return toDouble(text, ok) * multiplier;
|
return toDouble(text, ok) * multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString toPktRateString(double pps) const
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
|
||||||
|
if (pps >= 1e6)
|
||||||
|
return QObject::tr("%L1 Mpps").arg(pps/1e6, 0, 'f', 3);
|
||||||
|
|
||||||
|
if (pps >= 1e3)
|
||||||
|
return QObject::tr("%L1 Kpps").arg(pps/1e3, 0, 'f', 3);
|
||||||
|
|
||||||
|
return QObject::tr("%L1").arg(pps, 0, 'f', 3);
|
||||||
|
}
|
||||||
|
|
||||||
QString toBitRateString(double bps) const
|
QString toBitRateString(double bps) const
|
||||||
{
|
{
|
||||||
QString text;
|
QString text;
|
||||||
|
|
||||||
if (bps >= 1e9)
|
if (bps >= 1e9)
|
||||||
return QObject::tr("%L1 Gbps").arg(bps/1e9, 0, 'f', 4);
|
return QObject::tr("%L1 Gbps").arg(bps/1e9, 0, 'f', 3);
|
||||||
|
|
||||||
if (bps >= 1e6)
|
if (bps >= 1e6)
|
||||||
return QObject::tr("%L1 Mbps").arg(bps/1e6, 0, 'f', 4);
|
return QObject::tr("%L1 Mbps").arg(bps/1e6, 0, 'f', 3);
|
||||||
|
|
||||||
if (bps >= 1e3)
|
if (bps >= 1e3)
|
||||||
return QObject::tr("%L1 Kbps").arg(bps/1e3, 0, 'f', 4);
|
return QObject::tr("%L1 Kbps").arg(bps/1e3, 0, 'f', 3);
|
||||||
|
|
||||||
return QObject::tr("%L1 bps").arg(bps, 0, 'f', 4);
|
return QObject::tr("%L1 bps").arg(bps, 0, 'f', 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString toTimeIntervalString(qint64 nanosecs) const
|
||||||
|
{
|
||||||
|
QString text;
|
||||||
|
|
||||||
|
if (nanosecs >= 1e9)
|
||||||
|
return QObject::tr("%L1 s").arg(nanosecs/1e9, 0, 'f', 2);
|
||||||
|
|
||||||
|
if (nanosecs >= 1e6)
|
||||||
|
return QObject::tr("%L1 ms").arg(nanosecs/1e6, 0, 'f', 2);
|
||||||
|
|
||||||
|
if (nanosecs >= 1e3)
|
||||||
|
return QObject::tr("%L1 us").arg(nanosecs/1e3, 0, 'f', 2);
|
||||||
|
|
||||||
|
return QObject::tr("%L1 ns").arg(nanosecs);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -169,7 +169,8 @@ private:
|
|||||||
for (int i = start; i < end; i++)
|
for (int i = start; i < end; i++)
|
||||||
if (indexes.contains(model()->index(indexes.first().row(), i)))
|
if (indexes.contains(model()->index(indexes.first().row(), i)))
|
||||||
text.append(model()->headerData(i, Qt::Horizontal)
|
text.append(model()->headerData(i, Qt::Horizontal)
|
||||||
.toString()+"\t");;
|
.toString().replace('\n', ' ')
|
||||||
|
+"\t");;
|
||||||
text.append("\n");
|
text.append("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,12 +62,14 @@ void ArpProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
|
|||||||
|
|
||||||
QString ArpProtocol::name() const
|
QString ArpProtocol::name() const
|
||||||
{
|
{
|
||||||
return QString("Address Resolution Protocol");
|
return isRarp() ?
|
||||||
|
QString("Reverse Address Resolution Protocol") :
|
||||||
|
QString("Address Resolution Protocol");
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ArpProtocol::shortName() const
|
QString ArpProtocol::shortName() const
|
||||||
{
|
{
|
||||||
return QString("ARP");
|
return isRarp() ? QString("RARP") : QString("ARP");
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -96,7 +98,7 @@ quint32 ArpProtocol::protocolId(ProtocolIdType type) const
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case ProtocolIdEth: return 0x0806;
|
case ProtocolIdEth: return isRarp() ? 0x8035 : 0x0806;
|
||||||
default:break;
|
default:break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -808,3 +810,11 @@ int ArpProtocol::protocolFrameVariableCount() const
|
|||||||
|
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ArpProtocol::isRarp() const
|
||||||
|
{
|
||||||
|
if ((data.op_code() == 3)
|
||||||
|
|| (data.op_code() ==4))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
@ -96,6 +96,8 @@ public:
|
|||||||
virtual int protocolFrameVariableCount() const;
|
virtual int protocolFrameVariableCount() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool isRarp() const;
|
||||||
|
|
||||||
OstProto::Arp data;
|
OstProto::Arp data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -30,6 +30,8 @@ ArpConfigForm::ArpConfigForm(QWidget *parent)
|
|||||||
opCodeCombo->setValidator(new QIntValidator(0, 0xFFFF, this));
|
opCodeCombo->setValidator(new QIntValidator(0, 0xFFFF, this));
|
||||||
opCodeCombo->addItem(1, "ARP Request");
|
opCodeCombo->addItem(1, "ARP Request");
|
||||||
opCodeCombo->addItem(2, "ARP Reply");
|
opCodeCombo->addItem(2, "ARP Reply");
|
||||||
|
opCodeCombo->addItem(3, "Reverse ARP Request");
|
||||||
|
opCodeCombo->addItem(4, "Reverse ARP Reply");
|
||||||
|
|
||||||
connect(senderHwAddrMode, SIGNAL(currentIndexChanged(int)),
|
connect(senderHwAddrMode, SIGNAL(currentIndexChanged(int)),
|
||||||
SLOT(on_senderHwAddrMode_currentIndexChanged(int)));
|
SLOT(on_senderHwAddrMode_currentIndexChanged(int)));
|
||||||
|
@ -25,10 +25,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
template <int protoNumber, class ProtoA, class ProtoB>
|
template <int protoNumber, class ProtoA, class ProtoB>
|
||||||
class ComboProtocol : public AbstractProtocol
|
class ComboProtocol : public AbstractProtocol
|
||||||
{
|
{
|
||||||
protected:
|
|
||||||
ProtoA *protoA;
|
|
||||||
ProtoB *protoB;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ComboProtocol(StreamBase *stream, AbstractProtocol *parent = 0)
|
ComboProtocol(StreamBase *stream, AbstractProtocol *parent = 0)
|
||||||
: AbstractProtocol(stream, parent)
|
: AbstractProtocol(stream, parent)
|
||||||
@ -40,6 +36,12 @@ public:
|
|||||||
|
|
||||||
qDebug("%s: protoNumber = %d, %p <--> %p", __FUNCTION__,
|
qDebug("%s: protoNumber = %d, %p <--> %p", __FUNCTION__,
|
||||||
protoNumber, protoA, protoB);
|
protoNumber, protoA, protoB);
|
||||||
|
|
||||||
|
if (protoA->protocolNumber() == protoB->protocolNumber())
|
||||||
|
fieldPrefix = OuterInnerPrefix;
|
||||||
|
else if (similarProto())
|
||||||
|
fieldPrefix = ProtoNamePrefix;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ComboProtocol()
|
virtual ~ComboProtocol()
|
||||||
@ -125,11 +127,29 @@ public:
|
|||||||
int streamIndex = 0) const
|
int streamIndex = 0) const
|
||||||
{
|
{
|
||||||
int cnt = protoA->fieldCount();
|
int cnt = protoA->fieldCount();
|
||||||
|
QVariant value = index < cnt ?
|
||||||
|
protoA->fieldData(index, attrib, streamIndex) :
|
||||||
|
protoB->fieldData(index - cnt, attrib, streamIndex);
|
||||||
|
|
||||||
if (index < cnt)
|
if (attrib == FieldName) {
|
||||||
return protoA->fieldData(index, attrib, streamIndex);
|
switch (fieldPrefix) {
|
||||||
else
|
case OuterInnerPrefix:
|
||||||
return protoB->fieldData(index - cnt, attrib, streamIndex);
|
value = QString("%1 %2")
|
||||||
|
.arg(index < cnt ? QString("Outer") : QString("Inner"))
|
||||||
|
.arg(value.toString());
|
||||||
|
break;
|
||||||
|
case ProtoNamePrefix:
|
||||||
|
value = QString("%1 %2")
|
||||||
|
.arg(index < cnt ? protoA->shortName() : protoB->shortName())
|
||||||
|
.arg(value.toString());
|
||||||
|
break;
|
||||||
|
case NoPrefix:
|
||||||
|
// Fall-through
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return value;
|
||||||
}
|
}
|
||||||
virtual bool setFieldData(int index, const QVariant &value,
|
virtual bool setFieldData(int index, const QVariant &value,
|
||||||
FieldAttrib attrib = FieldValue)
|
FieldAttrib attrib = FieldValue)
|
||||||
@ -186,6 +206,32 @@ public:
|
|||||||
CksumType cksumType = CksumIp) const;
|
CksumType cksumType = CksumIp) const;
|
||||||
#endif
|
#endif
|
||||||
template <int protocolNumber, class FormA, class FormB, class ProtocolA, class ProtocolB> friend class ComboProtocolConfigForm;
|
template <int protocolNumber, class FormA, class FormB, class ProtocolA, class ProtocolB> friend class ComboProtocolConfigForm;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ProtoA *protoA;
|
||||||
|
ProtoB *protoB;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool similarProto()
|
||||||
|
{
|
||||||
|
// TODO: Use Levenshtein distance or something similar with > 70% match
|
||||||
|
// For now we use an ugly hack!
|
||||||
|
if (protoA->shortName().contains("IPv")
|
||||||
|
&& protoB->shortName().contains("IPv"))
|
||||||
|
return true;
|
||||||
|
if (protoA->shortName().contains("Vlan")
|
||||||
|
&& protoB->shortName().contains("Vlan"))
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FieldNamePrefix {
|
||||||
|
NoPrefix,
|
||||||
|
ProtoNamePrefix,
|
||||||
|
OuterInnerPrefix
|
||||||
|
};
|
||||||
|
|
||||||
|
FieldNamePrefix fieldPrefix{NoPrefix};
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
29
common/debugdefs.h
Normal file
29
common/debugdefs.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2023 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _DEBUG_DEFS_H
|
||||||
|
#define _DEBUG_DEFS_H
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
#define timingDebug(fmt, ...) qDebug("TIMING:" fmt, __VA_ARGS__)
|
||||||
|
#else
|
||||||
|
#define timingDebug(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
47
common/fileformatoptions.cpp
Normal file
47
common/fileformatoptions.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2022 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "fileformatoptions.h"
|
||||||
|
|
||||||
|
#include "pcapfileformat.h"
|
||||||
|
#include "pcapoptionsdialog.h"
|
||||||
|
#include "streamfileformat.h"
|
||||||
|
|
||||||
|
QDialog* FileFormatOptions::openOptionsDialog(StreamFileFormat *fileFormat)
|
||||||
|
{
|
||||||
|
if (dynamic_cast<PcapFileFormat*>(fileFormat))
|
||||||
|
return new PcapImportOptionsDialog(fileFormat->options());
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog* FileFormatOptions::saveOptionsDialog(StreamFileFormat* /*fileFormat*/)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog* FileFormatOptions::openOptionsDialog(SessionFileFormat* /*fileFormat*/)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDialog* FileFormatOptions::saveOptionsDialog(SessionFileFormat* /*fileFormat*/)
|
||||||
|
{
|
||||||
|
return NULL;
|
||||||
|
}
|
41
common/fileformatoptions.h
Normal file
41
common/fileformatoptions.h
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2022 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FILE_FORMAT_OPTIONS_H
|
||||||
|
#define _FILE_FORMAT_OPTIONS_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class SessionFileFormat;
|
||||||
|
class StreamFileFormat;
|
||||||
|
class QDialog;
|
||||||
|
|
||||||
|
class FileFormatOptions : QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static QDialog* openOptionsDialog(StreamFileFormat *fileFormat);
|
||||||
|
static QDialog* saveOptionsDialog(StreamFileFormat *fileFormat);
|
||||||
|
|
||||||
|
static QDialog* openOptionsDialog(SessionFileFormat *fileFormat);
|
||||||
|
static QDialog* saveOptionsDialog(SessionFileFormat *fileFormat);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -27,6 +27,7 @@ struct FrameValueAttrib
|
|||||||
enum ErrorFlag {
|
enum ErrorFlag {
|
||||||
UnresolvedSrcMacError = 0x1,
|
UnresolvedSrcMacError = 0x1,
|
||||||
UnresolvedDstMacError = 0x2,
|
UnresolvedDstMacError = 0x2,
|
||||||
|
OutOfMemoryError = 0x4,
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(ErrorFlags, ErrorFlag);
|
Q_DECLARE_FLAGS(ErrorFlags, ErrorFlag);
|
||||||
ErrorFlags errorFlags{0};
|
ErrorFlags errorFlags{0};
|
||||||
|
471
common/gre.cpp
Normal file
471
common/gre.cpp
Normal file
@ -0,0 +1,471 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "gre.h"
|
||||||
|
|
||||||
|
GreProtocol::GreProtocol(StreamBase *stream, AbstractProtocol *parent)
|
||||||
|
: AbstractProtocol(stream, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GreProtocol::~GreProtocol()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractProtocol* GreProtocol::createInstance(StreamBase *stream,
|
||||||
|
AbstractProtocol *parent)
|
||||||
|
{
|
||||||
|
return new GreProtocol(stream, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 GreProtocol::protocolNumber() const
|
||||||
|
{
|
||||||
|
return OstProto::Protocol::kGreFieldNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GreProtocol::protoDataCopyInto(OstProto::Protocol &protocol) const
|
||||||
|
{
|
||||||
|
protocol.MutableExtension(OstProto::gre)->CopyFrom(data);
|
||||||
|
protocol.mutable_protocol_id()->set_id(protocolNumber());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GreProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
|
||||||
|
{
|
||||||
|
if (protocol.protocol_id().id() == protocolNumber() &&
|
||||||
|
protocol.HasExtension(OstProto::gre))
|
||||||
|
data.MergeFrom(protocol.GetExtension(OstProto::gre));
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GreProtocol::name() const
|
||||||
|
{
|
||||||
|
return QString("General Routing Encapsulation Protocol");
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GreProtocol::shortName() const
|
||||||
|
{
|
||||||
|
return QString("GRE");
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractProtocol::ProtocolIdType GreProtocol::protocolIdType() const
|
||||||
|
{
|
||||||
|
return ProtocolIdEth;
|
||||||
|
}
|
||||||
|
|
||||||
|
quint32 GreProtocol::protocolId(ProtocolIdType type) const
|
||||||
|
{
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case ProtocolIdIp: return 47;
|
||||||
|
default:break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AbstractProtocol::protocolId(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GreProtocol::fieldCount() const
|
||||||
|
{
|
||||||
|
return gre_fieldCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
AbstractProtocol::FieldFlags GreProtocol::fieldFlags(int index) const
|
||||||
|
{
|
||||||
|
AbstractProtocol::FieldFlags flags;
|
||||||
|
|
||||||
|
flags = AbstractProtocol::fieldFlags(index);
|
||||||
|
|
||||||
|
switch (index) {
|
||||||
|
case gre_checksum:
|
||||||
|
flags |= CksumField;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case gre_isOverrideChecksum:
|
||||||
|
flags &= ~FrameField;
|
||||||
|
flags |= MetaField;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant GreProtocol::fieldData(int index, FieldAttrib attrib,
|
||||||
|
int streamIndex) const
|
||||||
|
{
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case gre_flags:
|
||||||
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("Flags");
|
||||||
|
case FieldValue:
|
||||||
|
return data.flags();
|
||||||
|
case FieldTextValue:
|
||||||
|
{
|
||||||
|
QString fstr;
|
||||||
|
fstr.append("Cksum:");
|
||||||
|
fstr.append(data.flags() & GRE_FLAG_CKSUM ? "Y" : "N");
|
||||||
|
fstr.append(" Key:");
|
||||||
|
fstr.append(data.flags() & GRE_FLAG_KEY ? "Y" : "N");
|
||||||
|
fstr.append(" Seq:");
|
||||||
|
fstr.append(data.flags() & GRE_FLAG_SEQ ? "Y" : "N");
|
||||||
|
return fstr;
|
||||||
|
}
|
||||||
|
case FieldFrameValue:
|
||||||
|
return QByteArray(1, char(data.flags()));
|
||||||
|
case FieldBitSize:
|
||||||
|
return 4;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_rsvd0:
|
||||||
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("Reserved0");
|
||||||
|
case FieldValue:
|
||||||
|
return data.rsvd0();
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("%1").arg(data.rsvd0());
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(2);
|
||||||
|
qToBigEndian(quint16(data.rsvd0()), (uchar*)fv.data());
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
case FieldBitSize:
|
||||||
|
return 9;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case gre_version:
|
||||||
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("Version");
|
||||||
|
case FieldValue:
|
||||||
|
return data.version();
|
||||||
|
case FieldFrameValue:
|
||||||
|
return QByteArray(1, char(data.version()));
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("%1").arg(data.version());
|
||||||
|
case FieldBitSize:
|
||||||
|
return 3;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_protocol:
|
||||||
|
{
|
||||||
|
quint16 protocol = payloadProtocolId(ProtocolIdEth);
|
||||||
|
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("Protocol");
|
||||||
|
case FieldValue:
|
||||||
|
return protocol;
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(2);
|
||||||
|
qToBigEndian(protocol, (uchar*) fv.data());
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("0x%1").arg(
|
||||||
|
protocol, 4, BASE_HEX, QChar('0'));;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_checksum:
|
||||||
|
{
|
||||||
|
if (attrib == FieldName)
|
||||||
|
return QString("Checksum");
|
||||||
|
|
||||||
|
if ((data.flags() & GRE_FLAG_CKSUM) == 0)
|
||||||
|
{
|
||||||
|
if (attrib == FieldTextValue)
|
||||||
|
return QObject::tr("<not-included>");
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (attrib == FieldBitSize)
|
||||||
|
return 16;
|
||||||
|
|
||||||
|
quint16 cksum;
|
||||||
|
if (data.is_override_checksum()) {
|
||||||
|
cksum = data.checksum();
|
||||||
|
} else {
|
||||||
|
quint32 sum = 0;
|
||||||
|
cksum = protocolFrameCksum(streamIndex, CksumIp);
|
||||||
|
sum += (quint16) ~cksum;
|
||||||
|
cksum = protocolFramePayloadCksum(streamIndex, CksumIp);
|
||||||
|
sum += (quint16) ~cksum;
|
||||||
|
|
||||||
|
while (sum >> 16)
|
||||||
|
sum = (sum & 0xFFFF) + (sum >> 16);
|
||||||
|
|
||||||
|
cksum = (~sum) & 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldValue:
|
||||||
|
return cksum;
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(2);
|
||||||
|
qToBigEndian(cksum, (uchar*) fv.data());
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("0x%1").arg(
|
||||||
|
cksum, 4, BASE_HEX, QChar('0'));;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case gre_rsvd1:
|
||||||
|
{
|
||||||
|
if (attrib == FieldName)
|
||||||
|
return QString("Reserved1");
|
||||||
|
|
||||||
|
if ((data.flags() & GRE_FLAG_CKSUM) == 0)
|
||||||
|
{
|
||||||
|
if (attrib == FieldTextValue)
|
||||||
|
return QObject::tr("<not-included>");
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldValue:
|
||||||
|
return data.rsvd1();
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("%1").arg(data.rsvd1());
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(2);
|
||||||
|
qToBigEndian((quint16) data.rsvd1(), (uchar*) fv.data());
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case gre_key:
|
||||||
|
{
|
||||||
|
if (attrib == FieldName)
|
||||||
|
return QString("Key");
|
||||||
|
|
||||||
|
if ((data.flags() & GRE_FLAG_KEY) == 0)
|
||||||
|
{
|
||||||
|
if (attrib == FieldTextValue)
|
||||||
|
return QObject::tr("<not-included>");
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldValue:
|
||||||
|
return data.key();
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("0x%1").arg(data.key(), 8, BASE_HEX, QChar('0'));
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(4);
|
||||||
|
qToBigEndian((quint32) data.key(), (uchar*) fv.data());
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case gre_sequence:
|
||||||
|
{
|
||||||
|
if (attrib == FieldName)
|
||||||
|
return QString("Sequence Number");
|
||||||
|
|
||||||
|
if ((data.flags() & GRE_FLAG_SEQ) == 0)
|
||||||
|
{
|
||||||
|
if (attrib == FieldTextValue)
|
||||||
|
return QObject::tr("<not-included>");
|
||||||
|
else
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldValue:
|
||||||
|
return data.sequence_num();
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("%1").arg(data.sequence_num());
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(4);
|
||||||
|
qToBigEndian((quint32) data.sequence_num(), (uchar*) fv.data());
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Meta fields
|
||||||
|
case gre_isOverrideChecksum:
|
||||||
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldValue:
|
||||||
|
return data.is_override_checksum();
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
|
||||||
|
index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return AbstractProtocol::fieldData(index, attrib, streamIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GreProtocol::setFieldData(int index, const QVariant &value,
|
||||||
|
FieldAttrib attrib)
|
||||||
|
{
|
||||||
|
bool isOk = false;
|
||||||
|
|
||||||
|
if (attrib != FieldValue)
|
||||||
|
goto _exit;
|
||||||
|
|
||||||
|
switch (index)
|
||||||
|
{
|
||||||
|
case gre_flags:
|
||||||
|
{
|
||||||
|
uint flags = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_flags(flags);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_rsvd0:
|
||||||
|
{
|
||||||
|
uint rsvd0 = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_rsvd0(rsvd0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_version:
|
||||||
|
{
|
||||||
|
uint ver = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_version(ver);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_protocol:
|
||||||
|
{
|
||||||
|
uint proto = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_protocol_type(proto);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_checksum:
|
||||||
|
{
|
||||||
|
uint csum = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_checksum(csum);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_isOverrideChecksum:
|
||||||
|
{
|
||||||
|
data.set_is_override_checksum(value.toBool());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_rsvd1:
|
||||||
|
{
|
||||||
|
uint rsvd1 = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_rsvd1(rsvd1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_key:
|
||||||
|
{
|
||||||
|
uint key = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_key(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case gre_sequence:
|
||||||
|
{
|
||||||
|
uint seq = value.toUInt(&isOk);
|
||||||
|
if (isOk)
|
||||||
|
data.set_sequence_num(seq);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
|
||||||
|
index);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
_exit:
|
||||||
|
return isOk;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GreProtocol::protocolFrameSize(int /*streamIndex*/) const
|
||||||
|
{
|
||||||
|
int size = 4; // mandatory fields - flags, rsvd0, version, protocol
|
||||||
|
|
||||||
|
if (data.flags() & GRE_FLAG_CKSUM)
|
||||||
|
size += 4;
|
||||||
|
if (data.flags() & GRE_FLAG_KEY)
|
||||||
|
size += 4;
|
||||||
|
if (data.flags() & GRE_FLAG_SEQ)
|
||||||
|
size += 4;
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
97
common/gre.h
Normal file
97
common/gre.h
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GRE_H
|
||||||
|
#define _GRE_H
|
||||||
|
|
||||||
|
#include "abstractprotocol.h"
|
||||||
|
#include "gre.pb.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
GRE Protocol Frame Format (RFC2890)-
|
||||||
|
0 1 2 3
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
|C| |K|S| Reserved0 | Ver | Protocol Type |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Checksum (optional) | Reserved1 (Optional) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Key (optional) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
| Sequence Number (Optional) |
|
||||||
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
|
Figures in brackets represent field width in bits
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define GRE_FLAG_CKSUM 0x8
|
||||||
|
#define GRE_FLAG_KEY 0x2
|
||||||
|
#define GRE_FLAG_SEQ 0x1
|
||||||
|
|
||||||
|
class GreProtocol : public AbstractProtocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum grefield
|
||||||
|
{
|
||||||
|
// Frame Fields
|
||||||
|
gre_flags = 0,
|
||||||
|
gre_rsvd0,
|
||||||
|
gre_version,
|
||||||
|
gre_protocol,
|
||||||
|
gre_checksum,
|
||||||
|
gre_rsvd1,
|
||||||
|
gre_key,
|
||||||
|
gre_sequence,
|
||||||
|
|
||||||
|
// Meta Fields
|
||||||
|
gre_isOverrideChecksum,
|
||||||
|
|
||||||
|
gre_fieldCount
|
||||||
|
};
|
||||||
|
|
||||||
|
GreProtocol(StreamBase *stream, AbstractProtocol *parent = 0);
|
||||||
|
virtual ~GreProtocol();
|
||||||
|
|
||||||
|
static AbstractProtocol* createInstance(StreamBase *stream,
|
||||||
|
AbstractProtocol *parent = 0);
|
||||||
|
virtual quint32 protocolNumber() const;
|
||||||
|
|
||||||
|
virtual void protoDataCopyInto(OstProto::Protocol &protocol) const;
|
||||||
|
virtual void protoDataCopyFrom(const OstProto::Protocol &protocol);
|
||||||
|
|
||||||
|
virtual ProtocolIdType protocolIdType() const;
|
||||||
|
virtual quint32 protocolId(ProtocolIdType type) const;
|
||||||
|
|
||||||
|
virtual QString name() const;
|
||||||
|
virtual QString shortName() const;
|
||||||
|
|
||||||
|
virtual int fieldCount() const;
|
||||||
|
|
||||||
|
virtual AbstractProtocol::FieldFlags fieldFlags(int index) const;
|
||||||
|
virtual QVariant fieldData(int index, FieldAttrib attrib,
|
||||||
|
int streamIndex = 0) const;
|
||||||
|
virtual bool setFieldData(int index, const QVariant &value,
|
||||||
|
FieldAttrib attrib = FieldValue);
|
||||||
|
|
||||||
|
virtual int protocolFrameSize(int streamIndex = 0) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
OstProto::Gre data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
39
common/gre.proto
Normal file
39
common/gre.proto
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
import "protocol.proto";
|
||||||
|
|
||||||
|
package OstProto;
|
||||||
|
|
||||||
|
// GRE Protocol
|
||||||
|
message Gre {
|
||||||
|
optional uint32 flags = 1 [default = 0xa];
|
||||||
|
optional uint32 rsvd0 = 2;
|
||||||
|
optional uint32 version = 3;
|
||||||
|
optional uint32 protocol_type = 4;
|
||||||
|
optional uint32 checksum = 5;
|
||||||
|
optional bool is_override_checksum = 6;
|
||||||
|
optional uint32 rsvd1 = 7;
|
||||||
|
optional uint32 key = 8 [default = 0x2020bad7];
|
||||||
|
optional uint32 sequence_num = 9;
|
||||||
|
}
|
||||||
|
|
||||||
|
extend Protocol {
|
||||||
|
optional Gre gre = 405;
|
||||||
|
}
|
193
common/gre.ui
Normal file
193
common/gre.ui
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>Gre</class>
|
||||||
|
<widget class="QWidget" name="Gre">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>264</width>
|
||||||
|
<height>140</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Gre</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="label">
|
||||||
|
<property name="text">
|
||||||
|
<string>Version</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QSpinBox" name="version">
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string>0 (RFC2784)</string>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>7</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="2">
|
||||||
|
<spacer>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QCheckBox" name="hasChecksum">
|
||||||
|
<property name="text">
|
||||||
|
<string>Checksum</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="IntEdit" name="checksum">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
<property name="specialValueText">
|
||||||
|
<string><auto></string>
|
||||||
|
</property>
|
||||||
|
<property name="prefix">
|
||||||
|
<string>0x</string>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>65535</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>-1</number>
|
||||||
|
</property>
|
||||||
|
<property name="displayIntegerBase">
|
||||||
|
<number>16</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QCheckBox" name="hasKey">
|
||||||
|
<property name="text">
|
||||||
|
<string>Key</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="UIntEdit" name="key">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QCheckBox" name="hasSequence">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sequence No</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="UIntEdit" name="sequence">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<spacer>
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>20</width>
|
||||||
|
<height>40</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>IntEdit</class>
|
||||||
|
<extends>QSpinBox</extends>
|
||||||
|
<header>intedit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>UIntEdit</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header>uintedit.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>hasChecksum</tabstop>
|
||||||
|
<tabstop>checksum</tabstop>
|
||||||
|
<tabstop>hasKey</tabstop>
|
||||||
|
<tabstop>key</tabstop>
|
||||||
|
<tabstop>hasSequence</tabstop>
|
||||||
|
<tabstop>sequence</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections>
|
||||||
|
<connection>
|
||||||
|
<sender>hasKey</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>key</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>32</x>
|
||||||
|
<y>69</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>107</x>
|
||||||
|
<y>71</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>hasSequence</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>sequence</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>75</x>
|
||||||
|
<y>99</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>125</x>
|
||||||
|
<y>97</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
<connection>
|
||||||
|
<sender>hasChecksum</sender>
|
||||||
|
<signal>toggled(bool)</signal>
|
||||||
|
<receiver>checksum</receiver>
|
||||||
|
<slot>setEnabled(bool)</slot>
|
||||||
|
<hints>
|
||||||
|
<hint type="sourcelabel">
|
||||||
|
<x>87</x>
|
||||||
|
<y>43</y>
|
||||||
|
</hint>
|
||||||
|
<hint type="destinationlabel">
|
||||||
|
<x>109</x>
|
||||||
|
<y>45</y>
|
||||||
|
</hint>
|
||||||
|
</hints>
|
||||||
|
</connection>
|
||||||
|
</connections>
|
||||||
|
</ui>
|
118
common/greconfig.cpp
Normal file
118
common/greconfig.cpp
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "greconfig.h"
|
||||||
|
#include "gre.h"
|
||||||
|
|
||||||
|
GreConfigForm::GreConfigForm(QWidget *parent)
|
||||||
|
: AbstractProtocolConfigForm(parent)
|
||||||
|
{
|
||||||
|
setupUi(this);
|
||||||
|
|
||||||
|
connect(hasChecksum, SIGNAL(clicked(bool)),
|
||||||
|
this, SLOT(setAutoChecksum(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
GreConfigForm::~GreConfigForm()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
GreConfigForm* GreConfigForm::createInstance()
|
||||||
|
{
|
||||||
|
return new GreConfigForm;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load widget contents from proto
|
||||||
|
void GreConfigForm::loadWidget(AbstractProtocol *proto)
|
||||||
|
{
|
||||||
|
uint flags = proto->fieldData(GreProtocol::gre_flags,
|
||||||
|
AbstractProtocol::FieldValue)
|
||||||
|
.toUInt();
|
||||||
|
|
||||||
|
version->setValue(
|
||||||
|
proto->fieldData(
|
||||||
|
GreProtocol::gre_version,
|
||||||
|
AbstractProtocol::FieldValue
|
||||||
|
).toUInt());
|
||||||
|
|
||||||
|
hasChecksum->setChecked(flags & GRE_FLAG_CKSUM);
|
||||||
|
checksum->setValue(
|
||||||
|
proto->fieldData(
|
||||||
|
GreProtocol::gre_isOverrideChecksum,
|
||||||
|
AbstractProtocol::FieldValue).toBool() ?
|
||||||
|
proto->fieldData(
|
||||||
|
GreProtocol::gre_checksum,
|
||||||
|
AbstractProtocol::FieldValue).toUInt() : -1);
|
||||||
|
|
||||||
|
hasKey->setChecked(flags & GRE_FLAG_KEY);
|
||||||
|
key->setValue(
|
||||||
|
proto->fieldData(
|
||||||
|
GreProtocol::gre_key,
|
||||||
|
AbstractProtocol::FieldValue
|
||||||
|
).toUInt());
|
||||||
|
|
||||||
|
hasSequence->setChecked(flags & GRE_FLAG_SEQ);
|
||||||
|
sequence->setValue(
|
||||||
|
proto->fieldData(
|
||||||
|
GreProtocol::gre_sequence,
|
||||||
|
AbstractProtocol::FieldValue
|
||||||
|
).toUInt());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store widget contents into proto
|
||||||
|
void GreConfigForm::storeWidget(AbstractProtocol *proto)
|
||||||
|
{
|
||||||
|
uint flags = 0;
|
||||||
|
|
||||||
|
if (hasChecksum->isChecked())
|
||||||
|
flags |= GRE_FLAG_CKSUM;
|
||||||
|
if (hasKey->isChecked())
|
||||||
|
flags |= GRE_FLAG_KEY;
|
||||||
|
if (hasSequence->isChecked())
|
||||||
|
flags |= GRE_FLAG_SEQ;
|
||||||
|
|
||||||
|
proto->setFieldData(
|
||||||
|
GreProtocol::gre_flags,
|
||||||
|
flags);
|
||||||
|
|
||||||
|
proto->setFieldData(
|
||||||
|
GreProtocol::gre_version,
|
||||||
|
version->value());
|
||||||
|
|
||||||
|
proto->setFieldData(
|
||||||
|
GreProtocol::gre_checksum,
|
||||||
|
checksum->value());
|
||||||
|
proto->setFieldData(
|
||||||
|
GreProtocol::gre_isOverrideChecksum,
|
||||||
|
checksum->value() > -1 ? true: false);
|
||||||
|
|
||||||
|
proto->setFieldData(
|
||||||
|
GreProtocol::gre_key,
|
||||||
|
key->value());
|
||||||
|
|
||||||
|
proto->setFieldData(
|
||||||
|
GreProtocol::gre_sequence,
|
||||||
|
sequence->value());
|
||||||
|
}
|
||||||
|
|
||||||
|
void GreConfigForm::setAutoChecksum(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled)
|
||||||
|
checksum->setValue(-1); // auto
|
||||||
|
}
|
44
common/greconfig.h
Normal file
44
common/greconfig.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2010, 2014 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GRE_CONFIG_H
|
||||||
|
#define _GRE_CONFIG_H
|
||||||
|
|
||||||
|
#include "abstractprotocolconfig.h"
|
||||||
|
#include "ui_gre.h"
|
||||||
|
|
||||||
|
class GreConfigForm :
|
||||||
|
public AbstractProtocolConfigForm,
|
||||||
|
private Ui::Gre
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GreConfigForm(QWidget *parent = 0);
|
||||||
|
virtual ~GreConfigForm();
|
||||||
|
|
||||||
|
static GreConfigForm* createInstance();
|
||||||
|
|
||||||
|
virtual void loadWidget(AbstractProtocol *proto);
|
||||||
|
virtual void storeWidget(AbstractProtocol *proto);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void setAutoChecksum(bool enabled);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
69
common/grepdml.cpp
Normal file
69
common/grepdml.cpp
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "grepdml.h"
|
||||||
|
|
||||||
|
#include "gre.pb.h"
|
||||||
|
|
||||||
|
PdmlGreProtocol::PdmlGreProtocol()
|
||||||
|
{
|
||||||
|
ostProtoId_ = OstProto::Protocol::kGreFieldNumber;
|
||||||
|
|
||||||
|
fieldMap_.insert("gre.proto", OstProto::Gre::kProtocolTypeFieldNumber);
|
||||||
|
fieldMap_.insert("gre.checksum", OstProto::Gre::kChecksumFieldNumber);
|
||||||
|
fieldMap_.insert("gre.offset", OstProto::Gre::kRsvd1FieldNumber);
|
||||||
|
fieldMap_.insert("gre.key", OstProto::Gre::kKeyFieldNumber);
|
||||||
|
fieldMap_.insert("gre.sequence_number", OstProto::Gre::kSequenceNumFieldNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
PdmlGreProtocol::~PdmlGreProtocol()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
PdmlProtocol* PdmlGreProtocol::createInstance()
|
||||||
|
{
|
||||||
|
return new PdmlGreProtocol();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdmlGreProtocol::postProtocolHandler(OstProto::Protocol* pbProto,
|
||||||
|
OstProto::Stream* /*stream*/)
|
||||||
|
{
|
||||||
|
OstProto::Gre *gre = pbProto->MutableExtension(OstProto::gre);
|
||||||
|
|
||||||
|
qDebug("GRE: post");
|
||||||
|
|
||||||
|
gre->set_is_override_checksum(overrideCksum_);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PdmlGreProtocol::unknownFieldHandler(QString name,
|
||||||
|
int /*pos*/, int /*size*/, const QXmlStreamAttributes& attributes,
|
||||||
|
OstProto::Protocol* proto, OstProto::Stream* /*stream*/)
|
||||||
|
{
|
||||||
|
if (name == "gre.flags_and_version") {
|
||||||
|
bool isOk;
|
||||||
|
OstProto::Gre *gre = proto->MutableExtension(OstProto::gre);
|
||||||
|
quint16 flagsAndVersion = attributes.value("value")
|
||||||
|
.toUInt(&isOk, kBaseHex);
|
||||||
|
|
||||||
|
gre->set_flags(flagsAndVersion >> 12);
|
||||||
|
gre->set_rsvd0((flagsAndVersion & 0x0FFF) >> 3);
|
||||||
|
gre->set_version(flagsAndVersion & 0x0007);
|
||||||
|
}
|
||||||
|
}
|
45
common/grepdml.h
Normal file
45
common/grepdml.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2021 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _GRE_PDML_H
|
||||||
|
#define _GRE_PDML_H
|
||||||
|
|
||||||
|
#include "pdmlprotocol.h"
|
||||||
|
|
||||||
|
class PdmlGreProtocol : public PdmlProtocol
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~PdmlGreProtocol();
|
||||||
|
|
||||||
|
static PdmlProtocol* createInstance();
|
||||||
|
|
||||||
|
virtual void postProtocolHandler(OstProto::Protocol *pbProto,
|
||||||
|
OstProto::Stream *stream);
|
||||||
|
|
||||||
|
void fieldHandler(QString name, const QXmlStreamAttributes &attributes,
|
||||||
|
OstProto::Protocol *pbProto, OstProto::Stream *stream);
|
||||||
|
virtual void unknownFieldHandler(QString name, int pos, int size,
|
||||||
|
const QXmlStreamAttributes &attributes,
|
||||||
|
OstProto::Protocol *pbProto, OstProto::Stream *stream);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
PdmlGreProtocol();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -214,12 +214,6 @@ Length (x4)</string>
|
|||||||
</item>
|
</item>
|
||||||
<item row="1" column="1" >
|
<item row="1" column="1" >
|
||||||
<widget class="QLineEdit" name="leIpSrcAddr" >
|
<widget class="QLineEdit" name="leIpSrcAddr" >
|
||||||
<property name="inputMask" >
|
|
||||||
<string>009.009.009.009; </string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment" >
|
<property name="alignment" >
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
@ -264,12 +258,6 @@ Length (x4)</string>
|
|||||||
<property name="enabled" >
|
<property name="enabled" >
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="inputMask" >
|
|
||||||
<string>009.009.009.009; </string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="2" column="0" >
|
<item row="2" column="0" >
|
||||||
@ -281,12 +269,6 @@ Length (x4)</string>
|
|||||||
</item>
|
</item>
|
||||||
<item row="2" column="1" >
|
<item row="2" column="1" >
|
||||||
<widget class="QLineEdit" name="leIpDstAddr" >
|
<widget class="QLineEdit" name="leIpDstAddr" >
|
||||||
<property name="inputMask" >
|
|
||||||
<string>000.000.000.000; </string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
<property name="alignment" >
|
<property name="alignment" >
|
||||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
@ -331,12 +313,6 @@ Length (x4)</string>
|
|||||||
<property name="enabled" >
|
<property name="enabled" >
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="inputMask" >
|
|
||||||
<string>009.009.009.009; </string>
|
|
||||||
</property>
|
|
||||||
<property name="text" >
|
|
||||||
<string>...</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
@ -19,6 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "ip4config.h"
|
#include "ip4config.h"
|
||||||
#include "ip4.h"
|
#include "ip4.h"
|
||||||
|
#include "ipv4addressvalidator.h"
|
||||||
|
|
||||||
#include <QHostAddress>
|
#include <QHostAddress>
|
||||||
|
|
||||||
@ -30,6 +31,10 @@ Ip4ConfigForm::Ip4ConfigForm(QWidget *parent)
|
|||||||
leIpVersion->setValidator(new QIntValidator(0, 15, this));
|
leIpVersion->setValidator(new QIntValidator(0, 15, this));
|
||||||
leIpOptions->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"),
|
leIpOptions->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"),
|
||||||
this));
|
this));
|
||||||
|
leIpSrcAddr->setValidator(new IPv4AddressValidator(this));
|
||||||
|
leIpSrcAddrMask->setValidator(new IPv4AddressValidator(this));
|
||||||
|
leIpDstAddr->setValidator(new IPv4AddressValidator(this));
|
||||||
|
leIpDstAddrMask->setValidator(new IPv4AddressValidator(this));
|
||||||
|
|
||||||
connect(cmbIpSrcAddrMode, SIGNAL(currentIndexChanged(int)),
|
connect(cmbIpSrcAddrMode, SIGNAL(currentIndexChanged(int)),
|
||||||
this, SLOT(on_cmbIpSrcAddrMode_currentIndexChanged(int)));
|
this, SLOT(on_cmbIpSrcAddrMode_currentIndexChanged(int)));
|
||||||
|
@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "crc32c.h"
|
#include "crc32c.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QCoreApplication>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
|
||||||
@ -437,17 +437,19 @@ _exit:
|
|||||||
|
|
||||||
void NativeFileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
|
void NativeFileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
|
||||||
{
|
{
|
||||||
|
QCoreApplication *app = QCoreApplication::instance();
|
||||||
|
|
||||||
// Fill in the "native" file format version
|
// Fill in the "native" file format version
|
||||||
metaData.set_format_version_major(kFileFormatVersionMajor);
|
metaData.set_format_version_major(kFileFormatVersionMajor);
|
||||||
metaData.set_format_version_minor(kFileFormatVersionMinor);
|
metaData.set_format_version_minor(kFileFormatVersionMinor);
|
||||||
metaData.set_format_version_revision(kFileFormatVersionRevision);
|
metaData.set_format_version_revision(kFileFormatVersionRevision);
|
||||||
|
|
||||||
metaData.set_generator_name(
|
metaData.set_generator_name(
|
||||||
qApp->applicationName().toUtf8().constData());
|
app->applicationName().toUtf8().constData());
|
||||||
metaData.set_generator_version(
|
metaData.set_generator_version(
|
||||||
qApp->property("version").toString().toUtf8().constData());
|
app->property("version").toString().toUtf8().constData());
|
||||||
metaData.set_generator_revision(
|
metaData.set_generator_revision(
|
||||||
qApp->property("revision").toString().toUtf8().constData());
|
app->property("revision").toString().toUtf8().constData());
|
||||||
}
|
}
|
||||||
|
|
||||||
int NativeFileFormat::fileMetaSize(const quint8* file, int size)
|
int NativeFileFormat::fileMetaSize(const quint8* file, int size)
|
||||||
|
60
common/ostfile.pro
Normal file
60
common/ostfile.pro
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += qt staticlib
|
||||||
|
QT += network xml script
|
||||||
|
LIBS += \
|
||||||
|
-lprotobuf
|
||||||
|
|
||||||
|
PROTOS = \
|
||||||
|
fileformat.proto
|
||||||
|
|
||||||
|
HEADERS = \
|
||||||
|
ostprotolib.h \
|
||||||
|
nativefileformat.h \
|
||||||
|
ossnfileformat.h \
|
||||||
|
ostmfileformat.h \
|
||||||
|
pcapfileformat.h \
|
||||||
|
pdmlfileformat.h \
|
||||||
|
pythonfileformat.h \
|
||||||
|
pdmlprotocol.h \
|
||||||
|
pdmlprotocols.h \
|
||||||
|
pdmlreader.h \
|
||||||
|
sessionfileformat.h \
|
||||||
|
streamfileformat.h
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
ostprotolib.cpp \
|
||||||
|
nativefileformat.cpp \
|
||||||
|
ossnfileformat.cpp \
|
||||||
|
ostmfileformat.cpp \
|
||||||
|
pcapfileformat.cpp \
|
||||||
|
pdmlfileformat.cpp \
|
||||||
|
pythonfileformat.cpp \
|
||||||
|
pdmlprotocol.cpp \
|
||||||
|
pdmlprotocols.cpp \
|
||||||
|
pdmlreader.cpp \
|
||||||
|
sessionfileformat.cpp \
|
||||||
|
streamfileformat.cpp \
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
vlanpdml.cpp \
|
||||||
|
svlanpdml.cpp \
|
||||||
|
stppdml.cpp \
|
||||||
|
eth2pdml.cpp \
|
||||||
|
llcpdml.cpp \
|
||||||
|
arppdml.cpp \
|
||||||
|
ip4pdml.cpp \
|
||||||
|
ip6pdml.cpp \
|
||||||
|
grepdml.cpp \
|
||||||
|
icmppdml.cpp \
|
||||||
|
icmp6pdml.cpp \
|
||||||
|
igmppdml.cpp \
|
||||||
|
mldpdml.cpp \
|
||||||
|
tcppdml.cpp \
|
||||||
|
udppdml.cpp \
|
||||||
|
textprotopdml.cpp \
|
||||||
|
samplepdml.cpp
|
||||||
|
|
||||||
|
QMAKE_DISTCLEAN += object_script.*
|
||||||
|
|
||||||
|
include(../protobuf.pri)
|
||||||
|
include(../options.pri)
|
15
common/ostfilegui.pro
Normal file
15
common/ostfilegui.pro
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += qt staticlib
|
||||||
|
QT += widgets
|
||||||
|
|
||||||
|
FORMS = \
|
||||||
|
pcapfileimport.ui
|
||||||
|
|
||||||
|
HEADERS = \
|
||||||
|
fileformatoptions.h \
|
||||||
|
pcapoptionsdialog.h
|
||||||
|
|
||||||
|
SOURCES = \
|
||||||
|
fileformatoptions.cpp \
|
||||||
|
pcapoptionsdialog.cpp
|
||||||
|
|
@ -29,6 +29,7 @@ PROTOS += \
|
|||||||
ip4over6.proto \
|
ip4over6.proto \
|
||||||
ip4over4.proto \
|
ip4over4.proto \
|
||||||
ip6over6.proto \
|
ip6over6.proto \
|
||||||
|
gre.proto \
|
||||||
icmp.proto \
|
icmp.proto \
|
||||||
gmp.proto \
|
gmp.proto \
|
||||||
igmp.proto \
|
igmp.proto \
|
||||||
@ -69,6 +70,7 @@ HEADERS += \
|
|||||||
ip6over4.h \
|
ip6over4.h \
|
||||||
ip6over6.h \
|
ip6over6.h \
|
||||||
gmp.h \
|
gmp.h \
|
||||||
|
gre.h \
|
||||||
icmp.h \
|
icmp.h \
|
||||||
igmp.h \
|
igmp.h \
|
||||||
mld.h \
|
mld.h \
|
||||||
@ -103,6 +105,7 @@ SOURCES += \
|
|||||||
ip4.cpp \
|
ip4.cpp \
|
||||||
ip6.cpp \
|
ip6.cpp \
|
||||||
gmp.cpp \
|
gmp.cpp \
|
||||||
|
gre.cpp \
|
||||||
icmp.cpp \
|
icmp.cpp \
|
||||||
igmp.cpp \
|
igmp.cpp \
|
||||||
mld.cpp \
|
mld.cpp \
|
||||||
@ -110,6 +113,7 @@ SOURCES += \
|
|||||||
udp.cpp \
|
udp.cpp \
|
||||||
textproto.cpp \
|
textproto.cpp \
|
||||||
hexdump.cpp \
|
hexdump.cpp \
|
||||||
|
packet.cpp \
|
||||||
payload.cpp \
|
payload.cpp \
|
||||||
sample.cpp \
|
sample.cpp \
|
||||||
sign.cpp \
|
sign.cpp \
|
||||||
|
@ -2,11 +2,6 @@ TEMPLATE = lib
|
|||||||
CONFIG += qt staticlib
|
CONFIG += qt staticlib
|
||||||
QT += widgets network xml script
|
QT += widgets network xml script
|
||||||
INCLUDEPATH += "../extra/qhexedit2/src"
|
INCLUDEPATH += "../extra/qhexedit2/src"
|
||||||
LIBS += \
|
|
||||||
-lprotobuf
|
|
||||||
|
|
||||||
FORMS = \
|
|
||||||
pcapfileimport.ui \
|
|
||||||
|
|
||||||
FORMS += \
|
FORMS += \
|
||||||
mac.ui \
|
mac.ui \
|
||||||
@ -20,6 +15,7 @@ FORMS += \
|
|||||||
ip4.ui \
|
ip4.ui \
|
||||||
ip6.ui \
|
ip6.ui \
|
||||||
gmp.ui \
|
gmp.ui \
|
||||||
|
gre.ui \
|
||||||
icmp.ui \
|
icmp.ui \
|
||||||
tcp.ui \
|
tcp.ui \
|
||||||
udp.ui \
|
udp.ui \
|
||||||
@ -31,28 +27,10 @@ FORMS += \
|
|||||||
sign.ui \
|
sign.ui \
|
||||||
userscript.ui
|
userscript.ui
|
||||||
|
|
||||||
PROTOS = \
|
|
||||||
fileformat.proto
|
|
||||||
|
|
||||||
# TODO: Move fileformat related stuff into a different library - why?
|
|
||||||
HEADERS = \
|
HEADERS = \
|
||||||
ostprotolib.h \
|
|
||||||
ipv4addressdelegate.h \
|
ipv4addressdelegate.h \
|
||||||
ipv6addressdelegate.h \
|
ipv6addressdelegate.h \
|
||||||
nativefileformat.h \
|
spinboxdelegate.h \
|
||||||
ossnfileformat.h \
|
|
||||||
ostmfileformat.h \
|
|
||||||
pcapfileformat.h \
|
|
||||||
pdmlfileformat.h \
|
|
||||||
pythonfileformat.h \
|
|
||||||
pdmlprotocol.h \
|
|
||||||
pdmlprotocols.h \
|
|
||||||
pdmlreader.h \
|
|
||||||
sessionfileformat.h \
|
|
||||||
streamfileformat.h \
|
|
||||||
spinboxdelegate.h
|
|
||||||
|
|
||||||
HEADERS += \
|
|
||||||
tosdscp.h
|
tosdscp.h
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
@ -75,6 +53,7 @@ HEADERS += \
|
|||||||
ip6config.h \
|
ip6config.h \
|
||||||
ip4over4config.h \
|
ip4over4config.h \
|
||||||
gmpconfig.h \
|
gmpconfig.h \
|
||||||
|
greconfig.h \
|
||||||
icmpconfig.h \
|
icmpconfig.h \
|
||||||
igmpconfig.h \
|
igmpconfig.h \
|
||||||
mldconfig.h \
|
mldconfig.h \
|
||||||
@ -88,21 +67,7 @@ HEADERS += \
|
|||||||
userscriptconfig.h
|
userscriptconfig.h
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
ostprotolib.cpp \
|
spinboxdelegate.cpp \
|
||||||
nativefileformat.cpp \
|
|
||||||
ossnfileformat.cpp \
|
|
||||||
ostmfileformat.cpp \
|
|
||||||
pcapfileformat.cpp \
|
|
||||||
pdmlfileformat.cpp \
|
|
||||||
pythonfileformat.cpp \
|
|
||||||
pdmlprotocol.cpp \
|
|
||||||
pdmlprotocols.cpp \
|
|
||||||
pdmlreader.cpp \
|
|
||||||
sessionfileformat.cpp \
|
|
||||||
streamfileformat.cpp \
|
|
||||||
spinboxdelegate.cpp
|
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
tosdscp.cpp
|
tosdscp.cpp
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
@ -118,6 +83,7 @@ SOURCES += \
|
|||||||
ip4config.cpp \
|
ip4config.cpp \
|
||||||
ip6config.cpp \
|
ip6config.cpp \
|
||||||
gmpconfig.cpp \
|
gmpconfig.cpp \
|
||||||
|
greconfig.cpp \
|
||||||
icmpconfig.cpp \
|
icmpconfig.cpp \
|
||||||
igmpconfig.cpp \
|
igmpconfig.cpp \
|
||||||
mldconfig.cpp \
|
mldconfig.cpp \
|
||||||
@ -130,25 +96,6 @@ SOURCES += \
|
|||||||
signconfig.cpp \
|
signconfig.cpp \
|
||||||
userscriptconfig.cpp
|
userscriptconfig.cpp
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
vlanpdml.cpp \
|
|
||||||
svlanpdml.cpp \
|
|
||||||
stppdml.cpp \
|
|
||||||
eth2pdml.cpp \
|
|
||||||
llcpdml.cpp \
|
|
||||||
arppdml.cpp \
|
|
||||||
ip4pdml.cpp \
|
|
||||||
ip6pdml.cpp \
|
|
||||||
icmppdml.cpp \
|
|
||||||
icmp6pdml.cpp \
|
|
||||||
igmppdml.cpp \
|
|
||||||
mldpdml.cpp \
|
|
||||||
tcppdml.cpp \
|
|
||||||
udppdml.cpp \
|
|
||||||
textprotopdml.cpp \
|
|
||||||
samplepdml.cpp
|
|
||||||
|
|
||||||
QMAKE_DISTCLEAN += object_script.*
|
QMAKE_DISTCLEAN += object_script.*
|
||||||
|
|
||||||
include(../protobuf.pri)
|
|
||||||
include(../options.pri)
|
include(../options.pri)
|
||||||
|
117
common/packet.cpp
Normal file
117
common/packet.cpp
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2023 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "packet.h"
|
||||||
|
|
||||||
|
using namespace Packet;
|
||||||
|
|
||||||
|
quint16 Packet::l4ChecksumOffset(const uchar *pktData, int pktLen)
|
||||||
|
{
|
||||||
|
Parser parser(pktData, pktLen);
|
||||||
|
quint16 offset = kEthTypeOffset;
|
||||||
|
|
||||||
|
// Skip VLANs, if any
|
||||||
|
quint16 ethType = parser.field16(offset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
|
||||||
|
// TODO: support 802.3 frames
|
||||||
|
if (ethType <= 1500)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
while (kVlanEthTypes.contains(ethType)) {
|
||||||
|
offset += kVlanTagSize;
|
||||||
|
ethType = parser.field16(offset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
}
|
||||||
|
offset += kEthTypeSize;
|
||||||
|
|
||||||
|
// XXX: offset now points to Eth payload
|
||||||
|
|
||||||
|
// Skip MPLS tags, if any
|
||||||
|
if (ethType == kMplsEthType) {
|
||||||
|
while (1) {
|
||||||
|
quint32 mplsTag = parser.field32(offset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
offset += kMplsTagSize;
|
||||||
|
if (mplsTag & 0x100) { // BOS bit
|
||||||
|
quint32 nextWord = parser.field32(offset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
if (nextWord == 0) { // PW Control Word
|
||||||
|
offset += kMplsTagSize;
|
||||||
|
ethType = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
quint8 firstPayloadNibble = nextWord >> 28;
|
||||||
|
if (firstPayloadNibble == 0x4)
|
||||||
|
ethType = kIp4EthType;
|
||||||
|
else if (firstPayloadNibble == 0x6)
|
||||||
|
ethType = kIp6EthType;
|
||||||
|
else
|
||||||
|
ethType = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quint8 ipProto = 0;
|
||||||
|
if (ethType == kIp4EthType) {
|
||||||
|
ipProto = parser.field8(offset + kIp4ProtocolOffset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
|
||||||
|
quint8 ipHdrLen = parser.field8(offset) & 0x0F;
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
offset += 4*ipHdrLen;
|
||||||
|
} else if (ethType == kIp6EthType) {
|
||||||
|
ipProto = parser.field8(offset + kIp6NextHeaderOffset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
offset += kIp6HeaderSize;
|
||||||
|
|
||||||
|
// XXX: offset now points to IPv6 payload
|
||||||
|
|
||||||
|
// Skip IPv6 extension headers, if any
|
||||||
|
while (kIp6ExtensionHeaders.contains(ipProto)) {
|
||||||
|
ipProto = parser.field8(offset + kIp6ExtNextHeaderOffset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
|
||||||
|
quint16 extHdrLen = parser.field8(offset + kIp6ExtLengthOffset);
|
||||||
|
offset += 8 + 8*extHdrLen;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Non-IP
|
||||||
|
// TODO: support MPLS PW with Eth payload
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// XXX: offset now points to IP payload
|
||||||
|
|
||||||
|
if (ipProto == kIpProtoTcp) {
|
||||||
|
parser.field16(offset + kTcpChecksumOffset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
|
||||||
|
return offset + kTcpChecksumOffset;
|
||||||
|
} else if (ipProto == kIpProtoUdp) {
|
||||||
|
parser.field16(offset + kUdpChecksumOffset);
|
||||||
|
if (!parser.ok()) return 0;
|
||||||
|
|
||||||
|
return offset + kUdpChecksumOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
// No L4
|
||||||
|
return 0;
|
||||||
|
}
|
113
common/packet.h
Normal file
113
common/packet.h
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2023 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _PACKET_H
|
||||||
|
#define _PACKET_H
|
||||||
|
|
||||||
|
#include <QSet>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
namespace Packet {
|
||||||
|
|
||||||
|
class Parser {
|
||||||
|
public:
|
||||||
|
Parser(const uchar *data, int length)
|
||||||
|
: pktData_(data), pktLen_(length) {}
|
||||||
|
quint8 field8(int offset) {
|
||||||
|
if (offset >= pktLen_) {
|
||||||
|
ok_ = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ok_ = true;
|
||||||
|
return pktData_[offset];
|
||||||
|
}
|
||||||
|
quint16 field16(int offset) {
|
||||||
|
if (offset + 1 >= pktLen_) {
|
||||||
|
ok_ = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ok_ = true;
|
||||||
|
return pktData_[offset] << 8
|
||||||
|
| pktData_[offset+1];
|
||||||
|
}
|
||||||
|
quint32 field32(int offset) {
|
||||||
|
if (offset + 3 >= pktLen_) {
|
||||||
|
ok_ = false;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
ok_ = true;
|
||||||
|
return pktData_[offset] << 24
|
||||||
|
| pktData_[offset+1] << 16
|
||||||
|
| pktData_[offset+2] << 8
|
||||||
|
| pktData_[offset+3];
|
||||||
|
}
|
||||||
|
bool ok() {
|
||||||
|
return ok_;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const uchar *pktData_;
|
||||||
|
int pktLen_;
|
||||||
|
bool ok_{false};
|
||||||
|
};
|
||||||
|
|
||||||
|
quint16 l4ChecksumOffset(const uchar *pktData, int pktLen);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Constants
|
||||||
|
//
|
||||||
|
// Ethernet
|
||||||
|
const quint16 kEthTypeOffset = 12;
|
||||||
|
const quint16 kEthTypeSize = 2;
|
||||||
|
const quint16 kIp4EthType = 0x0800;
|
||||||
|
const quint16 kIp6EthType = 0x86dd;
|
||||||
|
const quint16 kMplsEthType = 0x8847;
|
||||||
|
const QSet<quint16> kVlanEthTypes = {0x8100, 0x9100, 0x88a8};
|
||||||
|
const uint kEthOverhead = 20;
|
||||||
|
|
||||||
|
// VLAN
|
||||||
|
const quint16 kVlanTagSize = 4;
|
||||||
|
|
||||||
|
// MPLS
|
||||||
|
const quint16 kMplsTagSize = 4;
|
||||||
|
|
||||||
|
// IPv4
|
||||||
|
const quint16 kIp4ProtocolOffset = 9;
|
||||||
|
|
||||||
|
// IPv6
|
||||||
|
const quint16 kIp6HeaderSize = 40;
|
||||||
|
const quint16 kIp6NextHeaderOffset = 6;
|
||||||
|
|
||||||
|
// IPv6 Extension Header
|
||||||
|
const quint16 kIp6ExtNextHeaderOffset = 0;
|
||||||
|
const quint16 kIp6ExtLengthOffset = 1;
|
||||||
|
|
||||||
|
// IPv4/IPv6 Proto/NextHeader values
|
||||||
|
const quint8 kIpProtoTcp = 6;
|
||||||
|
const quint8 kIpProtoUdp = 17;
|
||||||
|
|
||||||
|
const QSet<quint8> kIp6ExtensionHeaders = {0, 60, 43, 44, 51, 50, 60, 135}; // FIXME: use names
|
||||||
|
|
||||||
|
// TCP
|
||||||
|
const quint16 kTcpChecksumOffset = 16;
|
||||||
|
|
||||||
|
// UDP
|
||||||
|
const quint16 kUdpChecksumOffset = 6;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -33,6 +33,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
const quint32 kPcapFileMagic = 0xa1b2c3d4;
|
const quint32 kPcapFileMagic = 0xa1b2c3d4;
|
||||||
const quint32 kPcapFileMagicSwapped = 0xd4c3b2a1;
|
const quint32 kPcapFileMagicSwapped = 0xd4c3b2a1;
|
||||||
|
const quint32 kNanoSecondPcapFileMagic = 0xa1b23c4d;
|
||||||
|
const quint32 kNanoSecondPcapFileMagicSwapped = 0x4d3cb2a1;
|
||||||
const quint16 kPcapFileVersionMajor = 2;
|
const quint16 kPcapFileVersionMajor = 2;
|
||||||
const quint16 kPcapFileVersionMinor = 4;
|
const quint16 kPcapFileVersionMinor = 4;
|
||||||
const quint32 kMaxSnapLen = 65535;
|
const quint32 kMaxSnapLen = 65535;
|
||||||
@ -40,43 +42,9 @@ const quint32 kDltEthernet = 1;
|
|||||||
|
|
||||||
PcapFileFormat pcapFileFormat;
|
PcapFileFormat pcapFileFormat;
|
||||||
|
|
||||||
PcapImportOptionsDialog::PcapImportOptionsDialog(QVariantMap *options)
|
|
||||||
: QDialog(NULL)
|
|
||||||
{
|
|
||||||
setupUi(this);
|
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
|
||||||
options_ = options;
|
|
||||||
|
|
||||||
viaPdml->setChecked(options_->value("ViaPdml").toBool());
|
|
||||||
recalculateCksums->setChecked(
|
|
||||||
options_->value("RecalculateCksums").toBool());
|
|
||||||
doDiff->setChecked(options_->value("DoDiff").toBool());
|
|
||||||
|
|
||||||
// XXX: By default this is false - for pcap import tests to show
|
|
||||||
// minimal diffs. However, for the user, this should be enabled
|
|
||||||
// by default
|
|
||||||
recalculateCksums->setChecked(true);
|
|
||||||
|
|
||||||
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
|
||||||
}
|
|
||||||
|
|
||||||
PcapImportOptionsDialog::~PcapImportOptionsDialog()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void PcapImportOptionsDialog::accept()
|
|
||||||
{
|
|
||||||
options_->insert("ViaPdml", viaPdml->isChecked());
|
|
||||||
options_->insert("RecalculateCksums", recalculateCksums->isChecked());
|
|
||||||
options_->insert("DoDiff", doDiff->isChecked());
|
|
||||||
|
|
||||||
QDialog::accept();
|
|
||||||
}
|
|
||||||
|
|
||||||
PcapFileFormat::PcapFileFormat()
|
PcapFileFormat::PcapFileFormat()
|
||||||
{
|
{
|
||||||
importOptions_.insert("ViaPdml", true);
|
importOptions_.insert("ViaPdml", true);
|
||||||
importOptions_.insert("RecalculateCksums", false);
|
|
||||||
importOptions_.insert("DoDiff", true);
|
importOptions_.insert("DoDiff", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,11 +60,12 @@ bool PcapFileFormat::open(const QString fileName,
|
|||||||
QTemporaryFile file2;
|
QTemporaryFile file2;
|
||||||
quint32 magic;
|
quint32 magic;
|
||||||
uchar gzipMagic[2];
|
uchar gzipMagic[2];
|
||||||
|
bool nsecResolution = false;
|
||||||
int len;
|
int len;
|
||||||
PcapFileHeader fileHdr;
|
PcapFileHeader fileHdr;
|
||||||
PcapPacketHeader pktHdr;
|
PcapPacketHeader pktHdr;
|
||||||
OstProto::Stream *prevStream = NULL;
|
OstProto::Stream *prevStream = NULL;
|
||||||
uint lastUsec = 0;
|
quint64 lastXsec = 0;
|
||||||
int pktCount;
|
int pktCount;
|
||||||
qint64 byteCount = 0;
|
qint64 byteCount = 0;
|
||||||
qint64 byteTotal;
|
qint64 byteTotal;
|
||||||
@ -166,15 +135,22 @@ _retry:
|
|||||||
{
|
{
|
||||||
// Do nothing
|
// Do nothing
|
||||||
}
|
}
|
||||||
else if (magic == kPcapFileMagicSwapped)
|
else if (magic == kNanoSecondPcapFileMagic)
|
||||||
|
{
|
||||||
|
nsecResolution = true;
|
||||||
|
}
|
||||||
|
else if ((magic == kPcapFileMagicSwapped)
|
||||||
|
|| (magic == kNanoSecondPcapFileMagicSwapped))
|
||||||
{
|
{
|
||||||
// Toggle Byte order
|
// Toggle Byte order
|
||||||
if (fd_.byteOrder() == QDataStream::BigEndian)
|
if (fd_.byteOrder() == QDataStream::BigEndian)
|
||||||
fd_.setByteOrder(QDataStream::LittleEndian);
|
fd_.setByteOrder(QDataStream::LittleEndian);
|
||||||
else
|
else
|
||||||
fd_.setByteOrder(QDataStream::BigEndian);
|
fd_.setByteOrder(QDataStream::BigEndian);
|
||||||
|
|
||||||
|
nsecResolution = (magic == kNanoSecondPcapFileMagicSwapped);
|
||||||
}
|
}
|
||||||
else // Not a pcap file
|
else // Not a pcap file (could be pcapng or something else)
|
||||||
{
|
{
|
||||||
if (tryConvert)
|
if (tryConvert)
|
||||||
{
|
{
|
||||||
@ -226,6 +202,9 @@ _retry:
|
|||||||
|
|
||||||
pktBuf.resize(fileHdr.snapLen);
|
pktBuf.resize(fileHdr.snapLen);
|
||||||
|
|
||||||
|
// XXX: PDML also needs the PCAP file to cross check packet bytes
|
||||||
|
// with the PDML data, so we can't do PDML conversion any earlier
|
||||||
|
// than this
|
||||||
qDebug("pdml check");
|
qDebug("pdml check");
|
||||||
if (importOptions_.value("ViaPdml").toBool())
|
if (importOptions_.value("ViaPdml").toBool())
|
||||||
{
|
{
|
||||||
@ -265,6 +244,8 @@ _retry:
|
|||||||
|
|
||||||
emit status("Reading PDML packets...");
|
emit status("Reading PDML packets...");
|
||||||
emit target(100); // in percentage
|
emit target(100); // in percentage
|
||||||
|
|
||||||
|
// pdml reader needs pcap, so pass self
|
||||||
isOk = reader.read(&pdmlFile, this, &stop_);
|
isOk = reader.read(&pdmlFile, this, &stop_);
|
||||||
|
|
||||||
if (stop_)
|
if (stop_)
|
||||||
@ -450,7 +431,7 @@ _retry:
|
|||||||
diffFile.close();
|
diffFile.close();
|
||||||
if (diffFile.size())
|
if (diffFile.size())
|
||||||
{
|
{
|
||||||
error.append(tr("<p>There is a diff between the original and imported streams. See details to review the diff.</p><p>Why a diff? See <a href='%1'>possible reasons</a>.</p>\n\n\n\n").arg("https://jump.ostinato.org/pcapdiff"));
|
error.append(tr("<p>There is a diff between the original and imported streams. See details to review the diff.</p><p>💡 If you don't need to edit packets, you can retry the import and uncheck the Intelligent Import option.</p><p>Why a diff? See <a href='%1'>possible reasons</a>.</p>\n\n\n\n").arg("https://jump.ostinato.org/pcapdiff"));
|
||||||
diffFile.open();
|
diffFile.open();
|
||||||
diffFile.seek(0);
|
diffFile.seek(0);
|
||||||
error.append(QString(diffFile.readAll()));
|
error.append(QString(diffFile.readAll()));
|
||||||
@ -460,6 +441,7 @@ _retry:
|
|||||||
}
|
}
|
||||||
|
|
||||||
_non_pdml:
|
_non_pdml:
|
||||||
|
qDebug("pcap resolution: %s", nsecResolution ? "nsec" : "usec");
|
||||||
emit status("Reading Packets...");
|
emit status("Reading Packets...");
|
||||||
emit target(100); // in percentage
|
emit target(100); // in percentage
|
||||||
pktCount = 1;
|
pktCount = 1;
|
||||||
@ -487,20 +469,22 @@ _non_pdml:
|
|||||||
stream->mutable_control()->set_num_packets(1);
|
stream->mutable_control()->set_num_packets(1);
|
||||||
|
|
||||||
// setup packet rate to the timing in pcap (as close as possible)
|
// setup packet rate to the timing in pcap (as close as possible)
|
||||||
const double kUsecsInSec = 1e6;
|
// use quint64 rather than double to store micro/nano second as
|
||||||
uint usec = (pktHdr.tsSec*kUsecsInSec + pktHdr.tsUsec);
|
// it has a larger range (~580 years) and therefore better accuracy
|
||||||
uint delta = usec - lastUsec;
|
const quint64 kXsecsInSec = nsecResolution ? 1e9 : 1e6;
|
||||||
|
quint64 xsec = (pktHdr.tsSec*kXsecsInSec + pktHdr.tsUsec);
|
||||||
|
quint64 delta = xsec - lastXsec;
|
||||||
|
qDebug("pktCount = %d, delta = %llu", pktCount, delta);
|
||||||
|
|
||||||
if ((pktCount != 1) && delta)
|
if ((pktCount != 1) && delta)
|
||||||
stream->mutable_control()->set_packets_per_sec(kUsecsInSec/delta);
|
stream->mutable_control()->set_packets_per_sec(double(kXsecsInSec)/delta);
|
||||||
|
|
||||||
if (prevStream)
|
if (prevStream)
|
||||||
prevStream->mutable_control()->CopyFrom(stream->control());
|
prevStream->mutable_control()->CopyFrom(stream->control());
|
||||||
|
|
||||||
lastUsec = usec;
|
lastXsec = xsec;
|
||||||
prevStream = stream;
|
prevStream = stream;
|
||||||
pktCount++;
|
pktCount++;
|
||||||
qDebug("pktCount = %d", pktCount);
|
|
||||||
byteCount += pktHdr.inclLen + sizeof(pktHdr);
|
byteCount += pktHdr.inclLen + sizeof(pktHdr);
|
||||||
emit progress(int(byteCount*100/byteTotal)); // in percentage
|
emit progress(int(byteCount*100/byteTotal)); // in percentage
|
||||||
if (stop_)
|
if (stop_)
|
||||||
@ -576,7 +560,7 @@ bool PcapFileFormat::convertToStandardPcap(
|
|||||||
tshark.start(OstProtoLib::tsharkPath(),
|
tshark.start(OstProtoLib::tsharkPath(),
|
||||||
QStringList()
|
QStringList()
|
||||||
<< QString("-r%1").arg(fileName)
|
<< QString("-r%1").arg(fileName)
|
||||||
<< "-Fpcap"
|
<< "-Fnsecpcap"
|
||||||
<< QString("-w%1").arg(outputFileName));
|
<< QString("-w%1").arg(outputFileName));
|
||||||
if (!tshark.waitForStarted(-1))
|
if (!tshark.waitForStarted(-1))
|
||||||
{
|
{
|
||||||
@ -639,7 +623,7 @@ bool PcapFileFormat::save(const OstProto::StreamConfigList streams,
|
|||||||
|
|
||||||
fd_.setDevice(&file);
|
fd_.setDevice(&file);
|
||||||
|
|
||||||
fileHdr.magicNumber = kPcapFileMagic;
|
fileHdr.magicNumber = kNanoSecondPcapFileMagic;
|
||||||
fileHdr.versionMajor = kPcapFileVersionMajor;
|
fileHdr.versionMajor = kPcapFileVersionMajor;
|
||||||
fileHdr.versionMinor = kPcapFileVersionMinor;
|
fileHdr.versionMinor = kPcapFileVersionMinor;
|
||||||
fileHdr.thisZone = 0;
|
fileHdr.thisZone = 0;
|
||||||
@ -687,11 +671,16 @@ bool PcapFileFormat::save(const OstProto::StreamConfigList streams,
|
|||||||
fd_.writeRawData(pktBuf.data(), pktHdr.inclLen);
|
fd_.writeRawData(pktBuf.data(), pktHdr.inclLen);
|
||||||
|
|
||||||
if (s.packetRate())
|
if (s.packetRate())
|
||||||
pktHdr.tsUsec += quint32(1e6/s.packetRate());
|
{
|
||||||
if (pktHdr.tsUsec >= 1000000)
|
quint64 delta = quint64(1e9/s.packetRate());
|
||||||
|
pktHdr.tsSec += delta/quint32(1e9);
|
||||||
|
pktHdr.tsUsec += delta % quint32(1e9);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pktHdr.tsUsec >= quint32(1e9))
|
||||||
{
|
{
|
||||||
pktHdr.tsSec++;
|
pktHdr.tsSec++;
|
||||||
pktHdr.tsUsec -= 1000000;
|
pktHdr.tsUsec -= quint32(1e9);
|
||||||
}
|
}
|
||||||
|
|
||||||
emit progress(i);
|
emit progress(i);
|
||||||
@ -710,9 +699,9 @@ _exit:
|
|||||||
return isOk;
|
return isOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog* PcapFileFormat::openOptionsDialog()
|
QVariantMap* PcapFileFormat::options()
|
||||||
{
|
{
|
||||||
return new PcapImportOptionsDialog(&importOptions_);
|
return &importOptions_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PcapFileFormat::isMyFileFormat(const QString /*fileName*/)
|
bool PcapFileFormat::isMyFileFormat(const QString /*fileName*/)
|
||||||
|
@ -20,24 +20,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#define _PCAP_FILE_FORMAT_H
|
#define _PCAP_FILE_FORMAT_H
|
||||||
|
|
||||||
#include "streamfileformat.h"
|
#include "streamfileformat.h"
|
||||||
#include "ui_pcapfileimport.h"
|
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
class PcapImportOptionsDialog: public QDialog, public Ui::PcapFileImport
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
PcapImportOptionsDialog(QVariantMap *options);
|
|
||||||
~PcapImportOptionsDialog();
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void accept();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QVariantMap *options_;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PdmlReader;
|
class PdmlReader;
|
||||||
class PcapFileFormat : public StreamFileFormat
|
class PcapFileFormat : public StreamFileFormat
|
||||||
{
|
{
|
||||||
@ -52,7 +38,7 @@ public:
|
|||||||
bool save(const OstProto::StreamConfigList streams,
|
bool save(const OstProto::StreamConfigList streams,
|
||||||
const QString fileName, QString &error);
|
const QString fileName, QString &error);
|
||||||
|
|
||||||
virtual QDialog* openOptionsDialog();
|
virtual QVariantMap* options();
|
||||||
|
|
||||||
bool isMyFileFormat(const QString fileName);
|
bool isMyFileFormat(const QString fileName);
|
||||||
bool isMyFileType(const QString fileType);
|
bool isMyFileType(const QString fileType);
|
||||||
|
55
common/pcapoptionsdialog.cpp
Normal file
55
common/pcapoptionsdialog.cpp
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2011 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pcapoptionsdialog.h"
|
||||||
|
|
||||||
|
PcapImportOptionsDialog::PcapImportOptionsDialog(QVariantMap *options)
|
||||||
|
: QDialog(NULL)
|
||||||
|
{
|
||||||
|
Q_ASSERT(options != NULL);
|
||||||
|
|
||||||
|
setupUi(this);
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
options_ = options;
|
||||||
|
|
||||||
|
viaPdml->setChecked(options_->value("ViaPdml").toBool());
|
||||||
|
// XXX: By default this key is absent - so that pcap import tests
|
||||||
|
// evaluate to false and hence show minimal diffs.
|
||||||
|
// However, for the GUI user, this should be enabled by default.
|
||||||
|
recalculateCksums->setChecked(
|
||||||
|
options_->value("RecalculateCksums", QVariant(true))
|
||||||
|
.toBool());
|
||||||
|
doDiff->setChecked(options_->value("DoDiff").toBool());
|
||||||
|
|
||||||
|
connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
|
||||||
|
}
|
||||||
|
|
||||||
|
PcapImportOptionsDialog::~PcapImportOptionsDialog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void PcapImportOptionsDialog::accept()
|
||||||
|
{
|
||||||
|
options_->insert("ViaPdml", viaPdml->isChecked());
|
||||||
|
options_->insert("RecalculateCksums", recalculateCksums->isChecked());
|
||||||
|
options_->insert("DoDiff", doDiff->isChecked());
|
||||||
|
|
||||||
|
QDialog::accept();
|
||||||
|
}
|
||||||
|
|
39
common/pcapoptionsdialog.h
Normal file
39
common/pcapoptionsdialog.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2011 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
#ifndef _PCAP_OPTIONS_DIALOG_H
|
||||||
|
#define _PCAP_OPTIONS_DIALOG_H
|
||||||
|
|
||||||
|
#include "ui_pcapfileimport.h"
|
||||||
|
|
||||||
|
#include <QVariantMap>
|
||||||
|
|
||||||
|
class PcapImportOptionsDialog: public QDialog, public Ui::PcapFileImport
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PcapImportOptionsDialog(QVariantMap *options);
|
||||||
|
~PcapImportOptionsDialog();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void accept();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVariantMap *options_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -28,6 +28,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "arppdml.h"
|
#include "arppdml.h"
|
||||||
#include "eth2pdml.h"
|
#include "eth2pdml.h"
|
||||||
|
#include "grepdml.h"
|
||||||
#include "llcpdml.h"
|
#include "llcpdml.h"
|
||||||
#include "icmppdml.h"
|
#include "icmppdml.h"
|
||||||
#include "icmp6pdml.h"
|
#include "icmp6pdml.h"
|
||||||
@ -62,6 +63,7 @@ PdmlReader::PdmlReader(OstProto::StreamConfigList *streams,
|
|||||||
|
|
||||||
factory_.insert("arp", PdmlArpProtocol::createInstance);
|
factory_.insert("arp", PdmlArpProtocol::createInstance);
|
||||||
factory_.insert("eth", PdmlEthProtocol::createInstance);
|
factory_.insert("eth", PdmlEthProtocol::createInstance);
|
||||||
|
factory_.insert("gre", PdmlGreProtocol::createInstance);
|
||||||
factory_.insert("http", PdmlTextProtocol::createInstance);
|
factory_.insert("http", PdmlTextProtocol::createInstance);
|
||||||
factory_.insert("icmp", PdmlIcmpProtocol::createInstance);
|
factory_.insert("icmp", PdmlIcmpProtocol::createInstance);
|
||||||
factory_.insert("icmpv6", PdmlIcmp6Protocol::createInstance);
|
factory_.insert("icmpv6", PdmlIcmp6Protocol::createInstance);
|
||||||
|
@ -157,6 +157,7 @@ message Protocol {
|
|||||||
kIcmpFieldNumber = 402;
|
kIcmpFieldNumber = 402;
|
||||||
kIgmpFieldNumber = 403;
|
kIgmpFieldNumber = 403;
|
||||||
kMldFieldNumber = 404;
|
kMldFieldNumber = 404;
|
||||||
|
kGreFieldNumber = 405;
|
||||||
|
|
||||||
kTextProtocolFieldNumber = 500;
|
kTextProtocolFieldNumber = 500;
|
||||||
}
|
}
|
||||||
@ -215,6 +216,7 @@ message Port {
|
|||||||
|
|
||||||
optional double speed = 10; // in Mbps
|
optional double speed = 10; // in Mbps
|
||||||
optional uint32 mtu = 11;
|
optional uint32 mtu = 11;
|
||||||
|
optional string user_description = 12;
|
||||||
}
|
}
|
||||||
|
|
||||||
message PortConfigList {
|
message PortConfigList {
|
||||||
@ -289,6 +291,10 @@ message StreamStats {
|
|||||||
required PortId port_id = 1;
|
required PortId port_id = 1;
|
||||||
required StreamGuid stream_guid = 2;
|
required StreamGuid stream_guid = 2;
|
||||||
|
|
||||||
|
optional double tx_duration = 3; // in seconds
|
||||||
|
optional uint64 latency = 4; // in nanoseconds
|
||||||
|
optional uint64 jitter = 5; // in nanoseconds
|
||||||
|
|
||||||
optional uint64 rx_pkts = 11;
|
optional uint64 rx_pkts = 11;
|
||||||
optional uint64 rx_bytes = 12;
|
optional uint64 rx_bytes = 12;
|
||||||
optional uint64 tx_pkts = 13;
|
optional uint64 tx_pkts = 13;
|
||||||
|
@ -46,6 +46,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "ip6over6.h"
|
#include "ip6over6.h"
|
||||||
|
|
||||||
// L4 Protos
|
// L4 Protos
|
||||||
|
#include "gre.h"
|
||||||
#include "icmp.h"
|
#include "icmp.h"
|
||||||
#include "igmp.h"
|
#include "igmp.h"
|
||||||
#include "mld.h"
|
#include "mld.h"
|
||||||
@ -112,6 +113,8 @@ ProtocolManager::ProtocolManager()
|
|||||||
(void*) Ip6over6Protocol::createInstance);
|
(void*) Ip6over6Protocol::createInstance);
|
||||||
|
|
||||||
// Layer 4 Protocols
|
// Layer 4 Protocols
|
||||||
|
registerProtocol(OstProto::Protocol::kGreFieldNumber,
|
||||||
|
(void*) GreProtocol::createInstance);
|
||||||
registerProtocol(OstProto::Protocol::kIcmpFieldNumber,
|
registerProtocol(OstProto::Protocol::kIcmpFieldNumber,
|
||||||
(void*) IcmpProtocol::createInstance);
|
(void*) IcmpProtocol::createInstance);
|
||||||
registerProtocol(OstProto::Protocol::kIgmpFieldNumber,
|
registerProtocol(OstProto::Protocol::kIgmpFieldNumber,
|
||||||
|
@ -40,6 +40,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "ip6over4config.h"
|
#include "ip6over4config.h"
|
||||||
#include "ip6over6config.h"
|
#include "ip6over6config.h"
|
||||||
// L4 Protocol Widgets
|
// L4 Protocol Widgets
|
||||||
|
#include "greconfig.h"
|
||||||
#include "icmpconfig.h"
|
#include "icmpconfig.h"
|
||||||
#include "igmpconfig.h"
|
#include "igmpconfig.h"
|
||||||
#include "mldconfig.h"
|
#include "mldconfig.h"
|
||||||
@ -124,6 +125,9 @@ ProtocolWidgetFactory::ProtocolWidgetFactory()
|
|||||||
(void*) Ip6over6ConfigForm::createInstance);
|
(void*) Ip6over6ConfigForm::createInstance);
|
||||||
|
|
||||||
// Layer 4 Protocols
|
// Layer 4 Protocols
|
||||||
|
OstProtocolWidgetFactory->registerProtocolConfigWidget(
|
||||||
|
OstProto::Protocol::kGreFieldNumber,
|
||||||
|
(void*) GreConfigForm::createInstance);
|
||||||
OstProtocolWidgetFactory->registerProtocolConfigWidget(
|
OstProtocolWidgetFactory->registerProtocolConfigWidget(
|
||||||
OstProto::Protocol::kIcmpFieldNumber,
|
OstProto::Protocol::kIcmpFieldNumber,
|
||||||
(void*) IcmpConfigForm::createInstance);
|
(void*) IcmpConfigForm::createInstance);
|
||||||
|
@ -63,6 +63,8 @@ bool PythonFileFormat::save(const OstProto::StreamConfigList streams,
|
|||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
|
||||||
goto _open_fail;
|
goto _open_fail;
|
||||||
|
|
||||||
|
out.setCodec("UTF-8");
|
||||||
|
|
||||||
// import standard modules
|
// import standard modules
|
||||||
emit status("Writing imports ...");
|
emit status("Writing imports ...");
|
||||||
emit target(0);
|
emit target(0);
|
||||||
@ -450,9 +452,16 @@ void PythonFileFormat::writeFieldAssignment(
|
|||||||
std::string val = fieldDesc->is_repeated() ?
|
std::string val = fieldDesc->is_repeated() ?
|
||||||
refl->GetRepeatedStringReference(msg, fieldDesc, index, &val) :
|
refl->GetRepeatedStringReference(msg, fieldDesc, index, &val) :
|
||||||
refl->GetStringReference(msg, fieldDesc, &val);
|
refl->GetStringReference(msg, fieldDesc, &val);
|
||||||
QString escVal = escapeString(QString::fromStdString(val));
|
if (val == fieldDesc->default_value_string())
|
||||||
if (val != fieldDesc->default_value_string())
|
break;
|
||||||
out << fieldName << " = '" << escVal << "'\n";
|
if (fieldDesc->type() == FieldDescriptor::TYPE_BYTES) {
|
||||||
|
QString strVal = byteString(QByteArray(val.c_str(),
|
||||||
|
val.size()));
|
||||||
|
out << fieldName << " = b'" << strVal << "'\n";
|
||||||
|
} else {
|
||||||
|
QString strVal = QString::fromStdString(val);
|
||||||
|
out << fieldName << " = u'" << strVal << "'\n";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case FieldDescriptor::CPPTYPE_ENUM:
|
case FieldDescriptor::CPPTYPE_ENUM:
|
||||||
@ -533,16 +542,16 @@ QString PythonFileFormat::singularize(QString plural)
|
|||||||
return singular;
|
return singular;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString PythonFileFormat::escapeString(QString str)
|
QString PythonFileFormat::escapeString(QByteArray str)
|
||||||
{
|
{
|
||||||
QString escStr = "";
|
QString escStr = "";
|
||||||
for (int i=0; i < str.length(); i++) {
|
for (int i=0; i < str.length(); i++) {
|
||||||
uchar c = str[i].cell();
|
uchar c = uchar(str.at(i));
|
||||||
if ((c < 128) && isprint(c)) {
|
if ((c < 128) && isprint(c)) {
|
||||||
if (c == '\'')
|
if (c == '\'')
|
||||||
escStr.append("\\'");
|
escStr.append("\\'");
|
||||||
else
|
else
|
||||||
escStr.append(str[i]);
|
escStr.append(QChar(c));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
escStr.append(QString("\\x%1").arg(int(c), 2, 16, QChar('0')));
|
escStr.append(QString("\\x%1").arg(int(c), 2, 16, QChar('0')));
|
||||||
@ -550,6 +559,16 @@ QString PythonFileFormat::escapeString(QString str)
|
|||||||
return escStr;
|
return escStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PythonFileFormat::byteString(QByteArray str)
|
||||||
|
{
|
||||||
|
QString byteStr = "";
|
||||||
|
for (int i=0; i < str.length(); i++) {
|
||||||
|
uchar c = uchar(str.at(i));
|
||||||
|
byteStr.append(QString("\\x%1").arg(int(c), 2, 16, QChar('0')));
|
||||||
|
}
|
||||||
|
return byteStr;
|
||||||
|
}
|
||||||
|
|
||||||
bool PythonFileFormat::useDecimalBase(QString fieldName)
|
bool PythonFileFormat::useDecimalBase(QString fieldName)
|
||||||
{
|
{
|
||||||
// Heuristic - use Hex base for all except for the following
|
// Heuristic - use Hex base for all except for the following
|
||||||
|
@ -49,7 +49,8 @@ private:
|
|||||||
const google::protobuf::FieldDescriptor *fieldDesc,
|
const google::protobuf::FieldDescriptor *fieldDesc,
|
||||||
int index = -1);
|
int index = -1);
|
||||||
QString singularize(QString plural);
|
QString singularize(QString plural);
|
||||||
QString escapeString(QString str);
|
QString escapeString(QByteArray str);
|
||||||
|
QString byteString(QByteArray str);
|
||||||
bool useDecimalBase(QString fieldName);
|
bool useDecimalBase(QString fieldName);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,12 +32,7 @@ SessionFileFormat::~SessionFileFormat()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog* SessionFileFormat::openOptionsDialog()
|
QVariantMap* SessionFileFormat::options()
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialog* SessionFileFormat::saveOptionsDialog()
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -23,10 +23,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "fileformat.pb.h"
|
#include "fileformat.pb.h"
|
||||||
#include "protocol.pb.h"
|
#include "protocol.pb.h"
|
||||||
|
|
||||||
#include <QThread>
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QThread>
|
||||||
class QDialog;
|
#include <QVariantMap>
|
||||||
|
|
||||||
class SessionFileFormat : public QThread
|
class SessionFileFormat : public QThread
|
||||||
{
|
{
|
||||||
@ -42,8 +41,7 @@ public:
|
|||||||
virtual bool save(const OstProto::SessionContent &session,
|
virtual bool save(const OstProto::SessionContent &session,
|
||||||
const QString fileName, QString &error) = 0;
|
const QString fileName, QString &error) = 0;
|
||||||
|
|
||||||
virtual QDialog* openOptionsDialog();
|
virtual QVariantMap* options();
|
||||||
virtual QDialog* saveOptionsDialog();
|
|
||||||
|
|
||||||
void openAsync(const QString fileName,
|
void openAsync(const QString fileName,
|
||||||
OstProto::SessionContent &session, QString &error);
|
OstProto::SessionContent &session, QString &error);
|
||||||
|
@ -19,6 +19,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "sign.h"
|
#include "sign.h"
|
||||||
|
|
||||||
|
#include "../common/streambase.h"
|
||||||
|
|
||||||
SignProtocol::SignProtocol(StreamBase *stream, AbstractProtocol *parent)
|
SignProtocol::SignProtocol(StreamBase *stream, AbstractProtocol *parent)
|
||||||
: AbstractProtocol(stream, parent)
|
: AbstractProtocol(stream, parent)
|
||||||
{
|
{
|
||||||
@ -76,7 +78,9 @@ AbstractProtocol::FieldFlags SignProtocol::fieldFlags(int index) const
|
|||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case sign_magic:
|
case sign_magic:
|
||||||
|
case sign_tlv_tx_port:
|
||||||
case sign_tlv_guid:
|
case sign_tlv_guid:
|
||||||
|
case sign_tlv_ttag:
|
||||||
case sign_tlv_end:
|
case sign_tlv_end:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -116,6 +120,52 @@ QVariant SignProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case sign_tlv_ttag:
|
||||||
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("T-Tag");
|
||||||
|
case FieldValue:
|
||||||
|
return 0;
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("%1").arg(0);
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(2);
|
||||||
|
fv[0] = 0;
|
||||||
|
fv[1] = kTypeLenTtagPlaceholder;
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case sign_tlv_tx_port:
|
||||||
|
{
|
||||||
|
switch(attrib)
|
||||||
|
{
|
||||||
|
case FieldName:
|
||||||
|
return QString("TxPort");
|
||||||
|
case FieldValue:
|
||||||
|
return mpStream->portId();
|
||||||
|
case FieldTextValue:
|
||||||
|
return QString("%1").arg(mpStream->portId());
|
||||||
|
case FieldFrameValue:
|
||||||
|
{
|
||||||
|
QByteArray fv;
|
||||||
|
fv.resize(2);
|
||||||
|
fv[0] = mpStream->portId() & 0xFF;
|
||||||
|
fv[1] = kTypeLenTxPort;
|
||||||
|
return fv;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case sign_tlv_guid:
|
case sign_tlv_guid:
|
||||||
{
|
{
|
||||||
quint32 guid = data.stream_guid() & 0xFFFFFF;
|
quint32 guid = data.stream_guid() & 0xFFFFFF;
|
||||||
@ -217,3 +267,29 @@ bool SignProtocol::packetGuid(const uchar *pkt, int pktLen, uint *guid)
|
|||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SignProtocol::packetTtagId(const uchar *pkt, int pktLen, uint *ttagId, uint *guid)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
const uchar *p = pkt + pktLen - sizeof(kSignMagic);
|
||||||
|
quint32 magic = qFromBigEndian<quint32>(p);
|
||||||
|
if (magic != kSignMagic)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
*guid = kInvalidGuid;
|
||||||
|
p--;
|
||||||
|
while (*p != kTypeLenEnd) {
|
||||||
|
if (*p == kTypeLenTtag) {
|
||||||
|
*ttagId = *(p - 1);
|
||||||
|
ret = true;
|
||||||
|
} else if (*p == kTypeLenGuid) {
|
||||||
|
*guid = qFromBigEndian<quint32>(p - 3) >> 8;
|
||||||
|
} else if (*p == kTypeLenTxPort) {
|
||||||
|
#ifdef Q_OS_WIN32
|
||||||
|
*ttagId |= uint(*(p - 1)) << 8;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
p -= 1 + (*p >> 5); // move to next TLV
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
@ -23,6 +23,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "abstractprotocol.h"
|
#include "abstractprotocol.h"
|
||||||
#include "sign.pb.h"
|
#include "sign.pb.h"
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sign Protocol is expected at the end of the frame (just before the Eth FCS)
|
Sign Protocol is expected at the end of the frame (just before the Eth FCS)
|
||||||
---+--------+-------+
|
---+--------+-------+
|
||||||
@ -39,9 +41,19 @@ TLVs are encoded as
|
|||||||
Len does NOT include the one byte of TypeLen
|
Len does NOT include the one byte of TypeLen
|
||||||
Size of the value field varies between 0 to 7 bytes
|
Size of the value field varies between 0 to 7 bytes
|
||||||
|
|
||||||
Defined TLVs
|
Defined TLVs
|
||||||
Type = 0, Len = 0 (0x00): End of TLVs
|
Type = 0, Len = 0 (0x00): End of TLVs
|
||||||
Type = 1, Len = 3 (0x61): Stream GUID
|
Type = 1, Len = 3 (0x61): Stream GUID
|
||||||
|
Type = 2, Len = 1 (0x22): T-Tag Placeholder (0 value)
|
||||||
|
Type = 3, Len = 1 (0x23): T-Tag with actual value
|
||||||
|
Type = 4, Len = 1 (0x24): Tx Port Id
|
||||||
|
|
||||||
|
Order of TLVs from end of packet towards beginning [Offset, Size]
|
||||||
|
[ -4, 4 bytes] Magic
|
||||||
|
[ -6, 2 bytes] TTag (Placeholder or actual)
|
||||||
|
[-10, 4 bytes] Stream Guid
|
||||||
|
[-12, 2 bytes] Tx Port Id
|
||||||
|
[-13, 1 byte ] End
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class SignProtocol : public AbstractProtocol
|
class SignProtocol : public AbstractProtocol
|
||||||
@ -51,7 +63,9 @@ public:
|
|||||||
{
|
{
|
||||||
// Frame Fields
|
// Frame Fields
|
||||||
sign_tlv_end = 0,
|
sign_tlv_end = 0,
|
||||||
|
sign_tlv_tx_port,
|
||||||
sign_tlv_guid,
|
sign_tlv_guid,
|
||||||
|
sign_tlv_ttag,
|
||||||
sign_magic,
|
sign_magic,
|
||||||
|
|
||||||
// Meta Fields
|
// Meta Fields
|
||||||
@ -83,10 +97,19 @@ public:
|
|||||||
|
|
||||||
static quint32 magic();
|
static quint32 magic();
|
||||||
static bool packetGuid(const uchar *pkt, int pktLen, uint *guid);
|
static bool packetGuid(const uchar *pkt, int pktLen, uint *guid);
|
||||||
|
static bool packetTtagId(const uchar *pkt, int pktLen, uint *ttagId, uint *guid);
|
||||||
|
|
||||||
|
// XXX: Any change in kTypeLenXXX or magic value should also be done in
|
||||||
|
// TxThread/Ttag code as well where hardcoded values are used
|
||||||
|
static const quint32 kMaxGuid = 0x00ffffff;
|
||||||
|
static const quint32 kInvalidGuid = UINT_MAX;
|
||||||
|
static const quint8 kTypeLenTtagPlaceholder = 0x22;
|
||||||
|
static const quint8 kTypeLenTtag = 0x23;
|
||||||
private:
|
private:
|
||||||
static const quint32 kSignMagic = 0x1d10c0da; // coda! (unicode - 0x1d10c)
|
static const quint32 kSignMagic = 0x1d10c0da; // coda! (unicode - 0x1d10c)
|
||||||
static const quint8 kTypeLenEnd = 0x00;
|
static const quint8 kTypeLenEnd = 0x00;
|
||||||
static const quint8 kTypeLenGuid = 0x61;
|
static const quint8 kTypeLenGuid = 0x61;
|
||||||
|
static const quint8 kTypeLenTxPort = 0x24;
|
||||||
OstProto::Sign data;
|
OstProto::Sign data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -145,7 +145,7 @@ void StreamBase::setFrameProtocol(ProtocolList protocolList)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool StreamBase::hasProtocol(quint32 protocolNumber)
|
bool StreamBase::hasProtocol(quint32 protocolNumber) const
|
||||||
{
|
{
|
||||||
foreach(const AbstractProtocol *proto, *currentFrameProtocols)
|
foreach(const AbstractProtocol *proto, *currentFrameProtocols)
|
||||||
if (proto->protocolNumber() == protocolNumber)
|
if (proto->protocolNumber() == protocolNumber)
|
||||||
@ -681,14 +681,38 @@ quint64 StreamBase::neighborMacAddress(int frameIndex) const
|
|||||||
bool StreamBase::preflightCheck(QStringList &result) const
|
bool StreamBase::preflightCheck(QStringList &result) const
|
||||||
{
|
{
|
||||||
bool pass = true;
|
bool pass = true;
|
||||||
|
bool chkShort = true;
|
||||||
bool chkTrunc = true;
|
bool chkTrunc = true;
|
||||||
bool chkJumbo = true;
|
bool chkJumbo = true;
|
||||||
|
bool chkSignIcmp = true;
|
||||||
int count = isFrameSizeVariable() ? frameSizeVariableCount() : 1;
|
int count = isFrameSizeVariable() ? frameSizeVariableCount() : 1;
|
||||||
|
|
||||||
for (int i = 0; i < count; i++)
|
for (int i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
int pktLen = frameLen(i);
|
int pktLen = frameLen(i);
|
||||||
|
|
||||||
|
if (chkShort && hasProtocol(OstProto::Protocol::kSignFieldNumber)
|
||||||
|
&& (pktLen > (frameProtocolLength(i) + kFcsSize)))
|
||||||
|
{
|
||||||
|
result << QObject::tr("Stream statistics may not work since "
|
||||||
|
"frame content < 64 bytes and hence will get padded - "
|
||||||
|
"make sure special signature is at the end of the "
|
||||||
|
"frame and frame content ≥ 64 bytes");
|
||||||
|
chkShort = false;
|
||||||
|
pass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chkSignIcmp && hasProtocol(OstProto::Protocol::kSignFieldNumber)
|
||||||
|
&& hasProtocol(OstProto::Protocol::kIcmpFieldNumber))
|
||||||
|
{
|
||||||
|
result << QObject::tr("Stream statistics are not supported "
|
||||||
|
"for ICMP packets - please use a non-ICMP protocol or "
|
||||||
|
"remove special signature from ICMP streams");
|
||||||
|
chkSignIcmp = false;
|
||||||
|
pass = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (chkTrunc && (pktLen < (frameProtocolLength(i) + kFcsSize)))
|
if (chkTrunc && (pktLen < (frameProtocolLength(i) + kFcsSize)))
|
||||||
{
|
{
|
||||||
result << QObject::tr("One or more frames may be truncated - "
|
result << QObject::tr("One or more frames may be truncated - "
|
||||||
|
@ -42,7 +42,7 @@ public:
|
|||||||
void protoDataCopyFrom(const OstProto::Stream &stream);
|
void protoDataCopyFrom(const OstProto::Stream &stream);
|
||||||
void protoDataCopyInto(OstProto::Stream &stream) const;
|
void protoDataCopyInto(OstProto::Stream &stream) const;
|
||||||
|
|
||||||
bool hasProtocol(quint32 protocolNumber);
|
bool hasProtocol(quint32 protocolNumber) const;
|
||||||
ProtocolListIterator* createProtocolListIterator() const;
|
ProtocolListIterator* createProtocolListIterator() const;
|
||||||
|
|
||||||
//! \todo (LOW) should we have a copy constructor??
|
//! \todo (LOW) should we have a copy constructor??
|
||||||
@ -75,9 +75,8 @@ public:
|
|||||||
quint32 id() const;
|
quint32 id() const;
|
||||||
bool setId(quint32 id);
|
bool setId(quint32 id);
|
||||||
|
|
||||||
|
quint32 portId() { return portId_;}
|
||||||
#if 0 // FIXME(HI): needed?
|
#if 0 // FIXME(HI): needed?
|
||||||
quint32 portId()
|
|
||||||
{ return mCore->port_id();}
|
|
||||||
bool setPortId(quint32 id)
|
bool setPortId(quint32 id)
|
||||||
{ mCore->set_port_id(id); return true;}
|
{ mCore->set_port_id(id); return true;}
|
||||||
#endif
|
#endif
|
||||||
|
@ -35,12 +35,7 @@ StreamFileFormat::~StreamFileFormat()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog* StreamFileFormat::openOptionsDialog()
|
QVariantMap* StreamFileFormat::options()
|
||||||
{
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDialog* StreamFileFormat::saveOptionsDialog()
|
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,7 @@ public:
|
|||||||
virtual bool save(const OstProto::StreamConfigList streams,
|
virtual bool save(const OstProto::StreamConfigList streams,
|
||||||
const QString fileName, QString &error) = 0;
|
const QString fileName, QString &error) = 0;
|
||||||
|
|
||||||
virtual QDialog* openOptionsDialog();
|
virtual QVariantMap* options();
|
||||||
virtual QDialog* saveOptionsDialog();
|
|
||||||
|
|
||||||
void openAsync(const QString fileName,
|
void openAsync(const QString fileName,
|
||||||
OstProto::StreamConfigList &streams, QString &error);
|
OstProto::StreamConfigList &streams, QString &error);
|
||||||
|
57
common/uintedit.h
Normal file
57
common/uintedit.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
Copyright (C) 2022 Srivats P.
|
||||||
|
|
||||||
|
This file is part of "Ostinato"
|
||||||
|
|
||||||
|
This is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _UINT_EDIT_H
|
||||||
|
#define _UINT_EDIT_H
|
||||||
|
|
||||||
|
#include "ulonglongvalidator.h"
|
||||||
|
|
||||||
|
#include <QLineEdit>
|
||||||
|
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
class UIntEdit: public QLineEdit
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
UIntEdit(QWidget *parent = 0);
|
||||||
|
|
||||||
|
quint32 value();
|
||||||
|
void setValue(quint32 val);
|
||||||
|
};
|
||||||
|
|
||||||
|
// -------------------- //
|
||||||
|
|
||||||
|
inline UIntEdit::UIntEdit(QWidget *parent)
|
||||||
|
: QLineEdit(parent)
|
||||||
|
{
|
||||||
|
setValidator(new ULongLongValidator(0, UINT_MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline quint32 UIntEdit::value()
|
||||||
|
{
|
||||||
|
return text().toUInt(Q_NULLPTR, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void UIntEdit::setValue(quint32 val)
|
||||||
|
{
|
||||||
|
setText(QString::number(val));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -29,6 +29,11 @@ public:
|
|||||||
: QValidator(parent)
|
: QValidator(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
ULongLongValidator(qulonglong min, qulonglong max, QObject *parent = 0)
|
||||||
|
: QValidator(parent)
|
||||||
|
{
|
||||||
|
setRange(min, max);
|
||||||
|
}
|
||||||
~ULongLongValidator() {}
|
~ULongLongValidator() {}
|
||||||
|
|
||||||
void setRange(qulonglong min, qulonglong max)
|
void setRange(qulonglong min, qulonglong max)
|
||||||
|
@ -32,6 +32,9 @@ Updater::Updater()
|
|||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
// Tests!
|
// Tests!
|
||||||
|
Q_ASSERT(isVersionNewer("1.3.0", "1.2.0") == true);
|
||||||
|
Q_ASSERT(isVersionNewer("1.3.0", "1.1") == true);
|
||||||
|
Q_ASSERT(isVersionNewer("1.2.0", "1.1") == true);
|
||||||
Q_ASSERT(isVersionNewer("1.1", "1") == true);
|
Q_ASSERT(isVersionNewer("1.1", "1") == true);
|
||||||
Q_ASSERT(isVersionNewer("10.1", "2") == true);
|
Q_ASSERT(isVersionNewer("10.1", "2") == true);
|
||||||
Q_ASSERT(isVersionNewer("0.10", "0.2") == true);
|
Q_ASSERT(isVersionNewer("0.10", "0.2") == true);
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user