Compare commits

..

No commits in common. "master" and "find-replace" have entirely different histories.

140 changed files with 649 additions and 11652 deletions

1
.github/FUNDING.yml vendored
View File

@ -1 +0,0 @@
github: pstavirs

View File

@ -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.
If you build Ostinato from source and find it useful, please sponsor to keep the lights on and sustain the project.
[![](https://img.shields.io/static/v1?label=Sponsor&message=%E2%9D%A4&logo=GitHub&color=%23fe8e86&style=for-the-badge)](https://github.com/sponsors/pstavirs)
If you build Ostinato from source and find it useful, please donate to keep the lights on and sustain the project.
Read the Ostinato [origin story](https://ostinato.org/about).
[![Donate](https://ostinato.org/images/donate.png)](https://gum.co/ostdonate)
Srivats P<br/>
Author, Ostinato

View File

@ -94,7 +94,7 @@
<item>
<widget class="QLabel" name="CopyrightLabel" >
<property name="text" >
<string>Copyright (c) 2007-2023 Srivats P.</string>
<string>Copyright (c) 2007-2020 Srivats P.</string>
</property>
<property name="alignment" >
<set>Qt::AlignCenter</set>

View File

@ -209,7 +209,7 @@ void DeviceGroupDialog::updateTotalDeviceCount()
void DeviceGroupDialog::updateIp4Gateway()
{
quint32 net = ip4Address->value() & (~0UL << (32 - ip4PrefixLength->value()));
quint32 net = ip4Address->value() & (~0 << (32 - ip4PrefixLength->value()));
ip4Gateway->setValue(net | 0x01);
}

View File

@ -262,10 +262,8 @@ void DumpView::paintEvent(QPaintEvent* /*event*/)
// FIXME(LOW): unable to set the self widget's font in constructor
painter.setFont(QFont("Courier"));
// Qt automatically clears the background before we are called
// QWidget::paintEvent doc:
// When the paint event occurs, the update region has normally
// been erased, so you are painting on the widget's background.
// set a white background
painter.fillRect(rect(), QBrush(QColor(Qt::white)));
if (model())
{

View File

@ -31,13 +31,9 @@ class IconOnlyDelegate : public QStyledItemDelegate
{
QStyleOptionViewItem opt = option;
opt.decorationPosition = QStyleOptionViewItem::Top;
opt.features &= ~QStyleOptionViewItem::HasDisplay;
QStyledItemDelegate::paint(painter, opt, index);
}
QString displayText(const QVariant&, const QLocale&) const
{
return QString();
}
};
#endif

View File

@ -182,8 +182,6 @@ void LogsWindow::alert(State state)
// start - center of main window
QRect start;
QWidget *view = mainWindow;
if (!view)
return;
alert_->setParent(view);
alert_->raise();
start.setSize(QSize(256, 256).scaled(view->size()/2, Qt::KeepAspectRatio));

View File

@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "params.h"
#include "preferences.h"
#include "settings.h"
#include "thememanager.h"
#include <QApplication>
#include <QDateTime>
@ -85,8 +84,6 @@ int main(int argc, char* argv[])
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
ThemeManager::instance()->setTheme(appSettings->value(kThemeKey).toString());
qsrand(QDateTime::currentDateTime().toTime_t());
mainWindow = new MainWindow;

View File

@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#endif
#include "clipboardhelper.h"
#include "fileformatoptions.h"
#include "jumpurl.h"
#include "logsmodel.h"
#include "logswindow.h"
@ -86,14 +85,8 @@ MainWindow::MainWindow(QWidget *parent)
localServer_ = new QProcess(this);
connect(localServer_, SIGNAL(finished(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)),
SLOT(onLocalServerError(QProcess::ProcessError)));
#endif
localServer_->setProcessChannelMode(QProcess::ForwardedChannels);
localServer_->start(serverApp, QStringList());
QTimer::singleShot(5000, this, SLOT(stopLocalServerMonitor()));
@ -126,11 +119,8 @@ MainWindow::MainWindow(QWidget *parent)
setupUi(this);
menuFile->insertActions(menuFile->actions().at(3),
portsWindow->portActions());
menuFile->insertActions(menuFile->actions().at(3), portsWindow->actions());
menuEdit->addActions(clipboardHelper->actions());
menuStreams->addActions(portsWindow->streamActions());
menuDevices->addActions(portsWindow->deviceActions());
statsDock->setWidget(statsWindow);
addDockWidget(Qt::BottomDockWidgetArea, statsDock);
@ -175,7 +165,6 @@ MainWindow::MainWindow(QWidget *parent)
this, SLOT(onNewVersion(QString)));
updater->checkForNewVersion();
// TODO: If session file specified (and valid?), don't add local drone PG
// Add the "Local" Port Group
if (appParams.optLocalDrone()) {
PortGroup *pg = new PortGroup;
@ -420,13 +409,8 @@ void MainWindow::on_actionHelpAbout_triggered()
void MainWindow::stopLocalServerMonitor()
{
// 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)),
this, SLOT(onLocalServerError(QProcess::ProcessError)));
#endif
disconnect(localServer_, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(onLocalServerFinished(int, QProcess::ExitStatus)));
}
@ -467,8 +451,8 @@ void MainWindow::reportLocalServerError()
if (localServer_->exitCode() == STATUS_DLL_NOT_FOUND)
errorStr.append(tr("<p>This is most likely because Packet.dll "
"was not found - make sure you have "
"<a href='%1'>npcap installed and accessible</a>."
"</p>")
"<a href='%1'>WinPcap"
"</a> installed.</p>")
.arg(jumpUrl("winpcap")));
#endif
msgBox.setText(errorStr);
@ -548,7 +532,7 @@ bool MainWindow::openSession(QString fileName, QString &error)
goto _fail;
}
if ((optDialog = FileFormatOptions::openOptionsDialog(fmt)))
if ((optDialog = fmt->openOptionsDialog()))
{
int ret;
optDialog->setParent(this, Qt::Dialog);

View File

@ -25,33 +25,9 @@
<addaction name="actionOpenSession" />
<addaction name="actionSaveSession" />
<addaction name="separator" />
<addaction name="separator" />
<addaction name="actionPreferences" />
<addaction name="actionFileExit" />
</widget>
<widget class="QMenu" name="menuEdit" >
<property name="title" >
<string>&amp;Edit</string>
</property>
</widget>
<widget class="QMenu" name="menuView" >
<property name="title" >
<string>&amp;View</string>
</property>
<addaction name="actionViewShowMyReservedPortsOnly" />
<addaction name="actionViewRestoreDefaults" />
</widget>
<widget class="QMenu" name="menuStreams" >
<property name="title" >
<string>&amp;Streams</string>
</property>
<addaction name="actionTest" />
</widget>
<widget class="QMenu" name="menuDevices" >
<property name="title" >
<string>&amp;Devices</string>
</property>
</widget>
<widget class="QMenu" name="menuHelp" >
<property name="title" >
<string>&amp;Help</string>
@ -64,11 +40,21 @@
<addaction name="actionHelpAbout" />
<addaction name="actionAboutQt" />
</widget>
<widget class="QMenu" name="menuEdit" >
<property name="title" >
<string>&amp;Edit</string>
</property>
</widget>
<widget class="QMenu" name="menuView" >
<property name="title" >
<string>&amp;View</string>
</property>
<addaction name="actionViewShowMyReservedPortsOnly" />
<addaction name="actionViewRestoreDefaults" />
</widget>
<addaction name="menuFile" />
<addaction name="menuEdit" />
<addaction name="menuView" />
<addaction name="menuStreams" />
<addaction name="menuDevices" />
<addaction name="menuHelp" />
</widget>
<widget class="QStatusBar" name="statusbar" />

View File

@ -5,26 +5,31 @@ win32:RC_FILE = ostinato.rc
macx:ICON = icons/logo.icns
QT += widgets network script xml svg
INCLUDEPATH += "../rpc/" "../common/"
OBJDIR = .
win32 {
QMAKE_LFLAGS += -static
CONFIG(debug, debug|release) {
OBJDIR = debug
LIBS += -L"../common/debug" -lostprotogui -lostproto
LIBS += -L"../rpc/debug" -lpbrpc
POST_TARGETDEPS += \
"../common/debug/libostprotogui.a" \
"../common/debug/libostproto.a" \
"../rpc/debug/libpbrpc.a"
} else {
OBJDIR = release
LIBS += -L"../common/release" -lostprotogui -lostproto
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 += -L"../extra/qhexedit2/$(OBJECTS_DIR)/" -lqhexedit2
RESOURCES += ostinato.qrc
@ -123,23 +128,12 @@ SOURCES += \
streamstatsmodel.cpp \
streamstatswindow.cpp \
streamswidget.cpp \
thememanager.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.*
include(../install.pri)
include(../shared.pri)
include(../version.pri)
include(../options.pri)

View File

@ -45,11 +45,11 @@ int Params::parseCommandLine(int argc, char* argv[])
logsDisabled_ = false;
break;
case 'v':
printf("Ostinato %s rev %s\n", version, revision);
qDebug("Ostinato %s rev %s\n", version, revision);
exit(0);
case 'h':
default:
printf("usage: %s [-cdhv]\n", argv[0]);
qDebug("usage: %s [-cdhv]\n", argv[0]);
exit(1);
}
n++;

View File

@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "port.h"
#include "emulation.h"
#include "fileformatoptions.h"
#include "streamfileformat.h"
#include <QApplication>
@ -605,7 +604,7 @@ bool Port::openStreams(QString fileName, bool append, QString &error)
goto _fail;
}
if ((optDialog = FileFormatOptions::openOptionsDialog(fmt)))
if ((optDialog = fmt->openOptionsDialog()))
{
int ret;
optDialog->setParent(mainWindow, Qt::Dialog);

View File

@ -88,15 +88,8 @@ public:
{ return d.port_id().id(); }
const QString name() const
{ return QString().fromStdString(d.name()); }
const QString systemDescription() const
{ return QString().fromStdString(d.description()); }
const QString userDescription() const
{ return QString().fromStdString(d.user_description()); }
const QString description() const
{
return userDescription().isEmpty() ?
systemDescription() : userDescription();
}
{ return QString().fromStdString(d.description()); }
const QString notes() const
{ return QString().fromStdString(d.notes()); }
const QString userName() const

View File

@ -32,8 +32,6 @@ PortConfigDialog::PortConfigDialog(
setupUi(this);
description->setPlaceholderText(portConfig_.description().c_str());
description->setText(portConfig_.user_description().c_str());
switch(portConfig_.transmit_mode())
{
case OstProto::kSequentialTransmit:
@ -82,8 +80,6 @@ void PortConfigDialog::accept()
{
OstProto::Port pc;
pc.set_user_description(description->text().toStdString());
if (sequentialStreamsButton->isChecked())
pc.set_transmit_mode(OstProto::kSequentialTransmit);
else if (interleavedStreamsButton->isChecked())
@ -113,11 +109,6 @@ void PortConfigDialog::accept()
pc.set_is_tracking_stream_stats(streamStatsButton->isChecked());
// 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())
portConfig_.set_transmit_mode(pc.transmit_mode());
else

View File

@ -1,51 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<ui version="4.0" >
<class>PortConfigDialog</class>
<widget class="QDialog" name="PortConfigDialog">
<property name="geometry">
<widget class="QDialog" name="PortConfigDialog" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
<width>248</width>
<height>292</height>
<width>244</width>
<height>257</height>
</rect>
</property>
<property name="windowTitle">
<property name="windowTitle" >
<string>Port Config</string>
</property>
<layout class="QVBoxLayout">
<layout class="QVBoxLayout" >
<item>
<widget class="QLabel" name="label">
<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">
<widget class="QGroupBox" name="transmitModeBox" >
<property name="title" >
<string>Transmit Mode</string>
</property>
<layout class="QVBoxLayout">
<layout class="QVBoxLayout" >
<item>
<widget class="QRadioButton" name="sequentialStreamsButton">
<property name="text">
<widget class="QRadioButton" name="sequentialStreamsButton" >
<property name="text" >
<string>Sequential Streams</string>
</property>
<property name="checked">
<property name="checked" >
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QRadioButton" name="interleavedStreamsButton">
<property name="text">
<widget class="QRadioButton" name="interleavedStreamsButton" >
<property name="text" >
<string>Interleaved Streams</string>
</property>
</widget>
@ -54,21 +40,21 @@
</widget>
</item>
<item>
<widget class="QGroupBox" name="groupBox">
<property name="title">
<widget class="QGroupBox" name="groupBox" >
<property name="title" >
<string>Reservation</string>
</property>
<layout class="QVBoxLayout">
<layout class="QVBoxLayout" >
<item>
<widget class="QLabel" name="reservedBy">
<property name="text">
<widget class="QLabel" name="reservedBy" >
<property name="text" >
<string>Reserved by: </string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="reserveButton">
<property name="text">
<widget class="QCheckBox" name="reserveButton" >
<property name="text" >
<string>Reserve</string>
</property>
</widget>
@ -77,25 +63,25 @@
</widget>
</item>
<item>
<widget class="QCheckBox" name="exclusiveControlButton">
<property name="text">
<widget class="QCheckBox" name="exclusiveControlButton" >
<property name="text" >
<string>Exclusive Control</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="streamStatsButton">
<property name="text">
<widget class="QCheckBox" name="streamStatsButton" >
<property name="text" >
<string>Stream Statistics</string>
</property>
</widget>
</item>
<item>
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>226</width>
<height>71</height>
@ -104,25 +90,17 @@
</spacer>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>description</tabstop>
<tabstop>sequentialStreamsButton</tabstop>
<tabstop>interleavedStreamsButton</tabstop>
<tabstop>reserveButton</tabstop>
<tabstop>exclusiveControlButton</tabstop>
<tabstop>streamStatsButton</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
@ -131,11 +109,11 @@
<receiver>PortConfigDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<hint type="sourcelabel" >
<x>234</x>
<y>205</y>
</hint>
<hint type="destinationlabel">
<hint type="destinationlabel" >
<x>157</x>
<y>214</y>
</hint>
@ -147,11 +125,11 @@
<receiver>PortConfigDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<hint type="sourcelabel" >
<x>234</x>
<y>205</y>
</hint>
<hint type="destinationlabel">
<hint type="destinationlabel" >
<x>243</x>
<y>214</y>
</hint>

View File

@ -1111,11 +1111,8 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
// * modify (new) deviceGroups
// * add (new) stream ids
// * modify (new) streams
// * resolve neighbors
// * build packets
// XXX: This assumes getDeviceGroupIdList() was invoked before
// 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
PbRpcController *controller;
@ -1156,7 +1153,6 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
}
// add/modify deviceGroups
bool resolve = false;
if (newPortContent->device_groups_size())
{
OstProto::DeviceGroupIdList *deviceGroupIdList
@ -1188,7 +1184,6 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
deviceGroupConfigList, ack,
NewCallback(this, &PortGroup::processModifyDeviceGroupAck,
portIndex, controller));
resolve = true;
}
// add/modify streams
@ -1219,26 +1214,6 @@ void PortGroup::processStreamIdList(int portIndex, PbRpcController *controller)
serviceStub->modifyStream(controller, streamConfigList, ack,
NewCallback(this, &PortGroup::processModifyStreamAck,
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

View File

@ -68,7 +68,6 @@ bool PortGroupList::isPort(const QModelIndex& index)
PortGroup& PortGroupList::portGroup(const QModelIndex& index)
{
Q_ASSERT(index.isValid());
Q_ASSERT(mPortGroupListModel.isPortGroup(index));
return *(mPortGroups[index.row()]);
@ -76,8 +75,6 @@ PortGroup& PortGroupList::portGroup(const QModelIndex& index)
Port& PortGroupList::port(const QModelIndex& index)
{
Q_ASSERT(index.isValid());
Q_ASSERT(index.parent().isValid());
Q_ASSERT(mPortGroupListModel.isPort(index));
return (*mPortGroups.at(index.parent().row())->mPorts[index.row()]);
}
@ -100,9 +97,6 @@ void PortGroupList::addPortGroup(PortGroup &portGroup)
connect(&portGroup, SIGNAL(portListChanged(quint32)),
&mPortStatsModel, SLOT(when_portListChanged()));
connect(&portGroup, SIGNAL(portGroupDataChanged(int, int)),
&mPortStatsModel, SLOT(when_portGroupDataChanged(int, int)));
connect(&portGroup, SIGNAL(statsChanged(quint32)),
&mPortStatsModel, SLOT(when_portGroup_stats_update(quint32)));
@ -116,10 +110,8 @@ void PortGroupList::addPortGroup(PortGroup &portGroup)
void PortGroupList::removePortGroup(PortGroup &portGroup)
{
// Disconnect before removing from list
portGroup.disconnectFromHost();
mPortGroupListModel.portGroupAboutToBeRemoved(&portGroup);
PortGroup* pg = mPortGroups.takeAt(mPortGroups.indexOf(&portGroup));
qDebug("after takeAt()");
mPortGroupListModel.portGroupRemoved();
@ -136,12 +128,11 @@ void PortGroupList::removeAllPortGroups()
do {
PortGroup *pg = mPortGroups.at(0);
pg->disconnectFromHost();
mPortGroupListModel.portGroupAboutToBeRemoved(pg);
mPortGroups.removeFirst();
delete pg;
mPortGroupListModel.portGroupRemoved();
} while (!mPortGroups.isEmpty());
mPortGroupListModel.portGroupRemoved();
mPortGroupListModel.when_portListChanged();
mPortStatsModel.when_portListChanged();

View File

@ -49,8 +49,7 @@ QList<uint> PortStatsFilterDialog::getItemList(bool* ok,
{
QStandardItem *item;
item = new QStandardItem(model->headerData(i, orientation)
.toString().replace('\n', ' '));
item = new QStandardItem(model->headerData(i, orientation).toString());
item->setData(i, kLogicalIndex);
item->setData(initial.indexOf(i), kVisualIndex);
item->setFlags(Qt::ItemIsSelectable

View File

@ -20,9 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "portstatsmodel.h"
#include "portgrouplist.h"
#include <QApplication>
#include <QPainter>
#include <QPalette>
#include <QPixmapCache>
#include <QTimer>
@ -137,10 +135,7 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
// States
case e_COMBO_STATE:
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" : "");
return QVariant();
// Statistics
case e_STAT_FRAMES_RCVD:
@ -161,13 +156,11 @@ QVariant PortStatsModel::data(const QModelIndex &index, int role) const
case e_STAT_BYTES_SENT:
return QString("%L1").arg(quint64(stats.tx_bytes()));
#if 0
case e_STAT_BYTE_SEND_RATE:
return QString("%L1").arg(quint64(stats.tx_bps()));
case e_STAT_BYTE_RECV_RATE:
return QString("%L1").arg(quint64(stats.rx_bps()));
#endif
case e_STAT_BIT_SEND_RATE:
return QString("%L1").arg(quint64(
@ -277,14 +270,6 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
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)
return QVariant();
@ -295,23 +280,16 @@ QVariant PortStatsModel::headerData(int section, Qt::Orientation orientation, in
if (numPorts.isEmpty() || section >= numPorts.last())
return QVariant();
getDomainIndexes(index(0, section), portGroupIdx, portIdx);
PortGroup *portGroup = pgl->mPortGroups.at(portGroupIdx);
Port *port = portGroup->mPorts.at(portIdx);
portName = QString("Port %1-%2")
.arg(portGroup->id())
.arg(port->id());
.arg(pgl->mPortGroups.at(portGroupIdx)->id())
.arg(pgl->mPortGroups.at(portGroupIdx)->mPorts.at(portIdx)->id());
if (portGroupIdx < (uint) pgl->mPortGroups.size()
&& portIdx < (uint) portGroup->mPorts.size())
&& portIdx < (uint) pgl->mPortGroups.at(portGroupIdx)->mPorts.size())
{
if (!port->notes().isEmpty())
if (!pgl->mPortGroups.at(portGroupIdx)->mPorts[portIdx]->notes()
.isEmpty())
portName += " *";
portName += "\n";
portName += port->userDescription().isEmpty() ?
port->userAlias() : port->userDescription();
}
return portName;
}
@ -385,16 +363,6 @@ void PortStatsModel::when_portListChanged()
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
#if 0
void PortStatsModel::on_portStatsUpdate(int port, void* /*stats*/)

View File

@ -26,8 +26,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
class QTimer;
typedef enum {
// Info
e_INFO_START = 0,
e_INFO_USER = e_INFO_START,
e_INFO_END = e_INFO_USER,
// State
e_STATE_START = 0,
e_STATE_START,
e_COMBO_STATE = e_STATE_START,
@ -36,16 +43,14 @@ typedef enum {
// Statistics
e_STATISTICS_START,
e_STAT_FRAMES_SENT = e_STATISTICS_START,
e_STAT_FRAMES_RCVD,
e_STAT_BYTES_SENT,
e_STAT_BYTES_RCVD,
e_STAT_FRAMES_RCVD = e_STATISTICS_START,
e_STAT_FRAMES_SENT,
e_STAT_FRAME_SEND_RATE,
e_STAT_FRAME_RECV_RATE,
#if 0
e_STAT_BYTES_RCVD,
e_STAT_BYTES_SENT,
e_STAT_BYTE_SEND_RATE,
e_STAT_BYTE_RECV_RATE,
#endif
e_STAT_BIT_SEND_RATE,
e_STAT_BIT_RECV_RATE,
#if 0
@ -64,34 +69,24 @@ typedef enum {
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
} PortStat;
static const QStringList PortStatName = (QStringList()
static QStringList PortStatName = (QStringList()
<< "User"
<< "Status"
<< "Sent Frames"
<< "Received Frames"
<< "Sent Bytes"
<< "Received Bytes"
<< "Send Frame Rate (fps)"
<< "Receive Frame Rate (fps)"
#if 0
<< "Send Byte Rate (Bps)"
<< "Receive Byte Rate (Bps)"
#endif
<< "Send Bit Rate (bps)"
<< "Receive Bit Rate (bps)"
<< "Frames Received"
<< "Frames Sent"
<< "Frame Send Rate (fps)"
<< "Frame Receive Rate (fps)"
<< "Bytes Received"
<< "Bytes Sent"
<< "Byte Send Rate (Bps)"
<< "Byte Receive Rate (Bps)"
<< "Bit Send Rate (bps)"
<< "Bit Receive Rate (bps)"
#if 0
<< "Frames Received (NIC)"
<< "Frames Sent (NIC)"
@ -103,8 +98,6 @@ static const QStringList PortStatName = (QStringList()
<< "Receive Errors"
<< "Receive Fifo Errors"
<< "Receive Frame Errors"
<< "User"
);
static QStringList LinkStateName = (QStringList()
@ -143,7 +136,6 @@ class PortStatsModel : public QAbstractTableModel
public slots:
void when_portListChanged();
//void on_portStatsUpdate(int port, void*stats);
void when_portGroupDataChanged(int portGroupId, int portId);
void when_portGroup_stats_update(quint32 portGroupId);
private slots:

View File

@ -26,8 +26,8 @@ class PortStatsProxyModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
PortStatsProxyModel(int userRow, QObject *parent = 0)
: QSortFilterProxyModel(parent), userRow_(userRow)
PortStatsProxyModel(QObject *parent = 0)
: QSortFilterProxyModel(parent)
{
setFilterRegExp(QRegExp(".*"));
}
@ -36,7 +36,7 @@ protected:
bool filterAcceptsColumn(int sourceColumn,
const QModelIndex &sourceParent) const
{
QModelIndex index = sourceModel()->index(userRow_, sourceColumn,sourceParent);
QModelIndex index = sourceModel()->index(0, sourceColumn, sourceParent);
QString user = sourceModel()->data(index).toString();
return filterRegExp().exactMatch(user) ? true : false;
@ -44,10 +44,9 @@ protected:
bool filterAcceptsRow(int sourceRow,
const QModelIndex &/*sourceParent*/) const
{
return sourceRow == userRow_ ? false : true;
// Hide row 0 - username (needed only by this filter class)
return (sourceRow > 0) ? true : false;
}
private:
int userRow_;
};
#endif

View File

@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "portstatsfilterdialog.h"
#include "portstatsmodel.h"
#include "portstatsproxymodel.h"
#include "rowborderdelegate.h"
#include "streamstatsmodel.h"
#include "streamstatswindow.h"
#include "settings.h"
@ -43,8 +42,7 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
this->pgl = pgl;
model = pgl->getPortStatsModel();
// Hide 'user' row
proxyStatsModel = new PortStatsProxyModel(e_INFO_USER, this);
proxyStatsModel = new PortStatsProxyModel(this);
if (proxyStatsModel) {
proxyStatsModel->setSourceModel(model);
tvPortStats->setModel(proxyStatsModel);
@ -57,17 +55,6 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
tvPortStats->verticalHeader()->setDefaultSectionSize(
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);
#if 0
// XXX: Ideally we should use this, but it doesn't work because in
@ -81,7 +68,9 @@ PortStatsWindow::PortStatsWindow(PortGroupList *pgl, QWidget *parent)
statusDelegate);
#else
// ... so we use this hard-coded hack
tvPortStats->setItemDelegateForRow(e_COMBO_STATE, statusDelegate);
tvPortStats->setItemDelegateForRow(
proxyStatsModel ? e_COMBO_STATE-1 : e_COMBO_STATE,
statusDelegate);
#endif
connect(tvPortStats->selectionModel(),

View File

@ -165,7 +165,7 @@
<string>Stop Capture</string>
</property>
<property name="statusTip">
<string>End capture on selected port(s)</string>
<string>End capture on selecteed port(s)</string>
</property>
<property name="text">
<string>Stop</string>

View File

@ -97,19 +97,14 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
connect(plm->getPortModel(), SIGNAL(modelReset()),
SLOT(when_portModel_reset()));
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(),
connect( tvPortList->selectionModel(),
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
this, SLOT(when_portView_currentChanged(const QModelIndex&,
const QModelIndex&)));
connect(this,
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
portWidget,
SLOT(setCurrentPortIndex(const QModelIndex&, const QModelIndex&)));
portWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
connect(this,
SIGNAL(currentPortChanged(const QModelIndex&, const QModelIndex&)),
streamsWidget, SLOT(setCurrentPortIndex(const QModelIndex&)));
@ -238,21 +233,6 @@ bool PortsWindow::saveSession(
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()
{
tvPortList->selectionModel()->clearCurrentIndex();
@ -602,11 +582,9 @@ void PortsWindow::on_actionExclusive_Control_triggered(bool checked)
}
}
void PortsWindow::when_actionPort_Configuration_triggered(
const QModelIndex &portIndex)
void PortsWindow::on_actionPort_Configuration_triggered()
{
QModelIndex current = portIndex.isValid() ?
portIndex : tvPortList->selectionModel()->currentIndex();
QModelIndex current = tvPortList->selectionModel()->currentIndex();
if (proxyPortModel)
current = proxyPortModel->mapToSource(current);
@ -621,8 +599,6 @@ void PortsWindow::when_actionPort_Configuration_triggered(
// TODO: extend Port::protoDataCopyInto() to accept an optional param
// which says copy only modifiable fields
//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_is_tracking_stream_stats(port.trackStreamStats());
config.set_is_exclusive_control(port.hasExclusiveControl());

View File

@ -50,10 +50,6 @@ public:
QString &error,
QProgressDialog *progress = NULL);
QList<QAction*> portActions();
QList<QAction*> streamActions();
QList<QAction*> deviceActions();
signals:
void currentPortChanged(const QModelIndex &current,
const QModelIndex &previous);
@ -80,8 +76,7 @@ private slots:
void on_actionDisconnect_Port_Group_triggered();
void on_actionExclusive_Control_triggered(bool checked);
void when_actionPort_Configuration_triggered(
const QModelIndex &portIndex = QModelIndex());
void on_actionPort_Configuration_triggered();
private:
PortGroupList *plm;

View File

@ -39,7 +39,7 @@
<widget class="QStackedWidget" name="swDetail">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>1</horstretch>
<horstretch>2</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>

View File

@ -48,34 +48,30 @@ PortWidget::~PortWidget()
{
}
void PortWidget::setCurrentPortIndex(const QModelIndex &currentIndex,
const QModelIndex &previousIndex)
void PortWidget::setCurrentPortIndex(const QModelIndex &portIndex)
{
if (!plm)
return;
qDebug("In %s", __PRETTY_FUNCTION__);
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel
if (!plm->isPort(portIndex))
return;
// XXX: We assume indices corresponds to sourceModel, not proxyModel
// - caller/sender should ensure this
qDebug("In %s", __FUNCTION__);
// Disconnect previous port
if (plm->isPort(previousIndex))
disconnect(&(plm->port(previousIndex)),
if (plm->isPort(currentPortIndex_))
disconnect(&(plm->port(currentPortIndex_)),
SIGNAL(portRateChanged(int, int)),
this, SLOT(updatePortRates()));
if (!plm->isPort(currentIndex)) {
currentPortIndex_ = QModelIndex(); // set to invalid
return;
}
currentPortIndex_ = currentIndex;
currentPortIndex_ = portIndex;
// Connect current port
connect(&(plm->port(currentPortIndex_)),
SIGNAL(portRateChanged(int, int)),
this, SLOT(updatePortRates()));
if (plm->isPort(currentPortIndex_))
connect(&(plm->port(currentPortIndex_)),
SIGNAL(portRateChanged(int, int)),
this, SLOT(updatePortRates()));
double speed = plm->port(currentPortIndex_).speed();
portSpeed->setText(QString("Max %L1 Mbps").arg(speed));

View File

@ -37,8 +37,7 @@ public:
void setPortGroupList(PortGroupList *portGroups);
public slots:
void setCurrentPortIndex(const QModelIndex &currentIndex,
const QModelIndex &previousIndex);
void setCurrentPortIndex(const QModelIndex &portIndex);
private slots:

View File

@ -21,7 +21,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "../common/ostprotolib.h"
#include "settings.h"
#include "thememanager.h"
#include <QFileDialog>
#include <QtGlobal>
@ -41,7 +40,6 @@ Preferences::Preferences()
setupUi(this);
// Program paths
wiresharkPathEdit->setText(appSettings->value(kWiresharkPathKey,
kWiresharkPathDefaultValue).toString());
tsharkPathEdit->setText(appSettings->value(kTsharkPathKey,
@ -53,10 +51,6 @@ Preferences::Preferences()
awkPathEdit->setText(appSettings->value(kAwkPathKey,
kAwkPathDefaultValue).toString());
// Theme
theme->addItems(ThemeManager::instance()->themeList());
theme->setCurrentText(appSettings->value(kThemeKey).toString());
// TODO(only if required): kUserKey
}
@ -84,7 +78,6 @@ void Preferences::initDefaults()
void Preferences::accept()
{
// Program paths
appSettings->setValue(kWiresharkPathKey, wiresharkPathEdit->text());
appSettings->setValue(kTsharkPathKey, tsharkPathEdit->text());
appSettings->setValue(kGzipPathKey, gzipPathEdit->text());
@ -97,9 +90,6 @@ void Preferences::accept()
appSettings->value(kDiffPathKey, kDiffPathDefaultValue).toString(),
appSettings->value(kAwkPathKey, kAwkPathDefaultValue).toString());
// Theme
ThemeManager::instance()->setTheme(theme->currentText());
QDialog::accept();
}

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<ui version="4.0" >
<class>Preferences</class>
<widget class="QDialog" name="Preferences">
<property name="geometry">
<widget class="QDialog" name="Preferences" >
<property name="geometry" >
<rect>
<x>0</x>
<y>0</y>
@ -10,149 +9,148 @@
<height>220</height>
</rect>
</property>
<property name="windowTitle">
<property name="windowTitle" >
<string>Preferences</string>
</property>
<property name="windowIcon">
<iconset resource="ostinato.qrc">
<normaloff>:/icons/preferences.png</normaloff>:/icons/preferences.png</iconset>
<property name="windowIcon" >
<iconset resource="ostinato.qrc" >:/icons/preferences.png</iconset>
</property>
<layout class="QVBoxLayout">
<layout class="QVBoxLayout" >
<item>
<widget class="QFrame" name="frame">
<property name="frameShape">
<widget class="QFrame" name="frame" >
<property name="frameShape" >
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<property name="frameShadow" >
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout">
<item row="0" column="0">
<widget class="QLabel" name="label">
<property name="text">
<layout class="QGridLayout" >
<item row="0" column="0" >
<widget class="QLabel" name="label" >
<property name="text" >
<string>'wireshark' Path</string>
</property>
<property name="buddy">
<property name="buddy" >
<cstring>wiresharkPathEdit</cstring>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="wiresharkPathEdit">
<property name="enabled">
<item row="0" column="1" >
<widget class="QLineEdit" name="wiresharkPathEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="2">
<widget class="QToolButton" name="wiresharkPathButton">
<property name="text">
<item row="0" column="2" >
<widget class="QToolButton" name="wiresharkPathButton" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<item row="1" column="0" >
<widget class="QLabel" name="label_2" >
<property name="text" >
<string>'tshark' Path</string>
</property>
<property name="buddy">
<property name="buddy" >
<cstring>tsharkPathEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="tsharkPathEdit">
<property name="enabled">
<item row="1" column="1" >
<widget class="QLineEdit" name="tsharkPathEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QToolButton" name="tsharkPathButton">
<property name="text">
<item row="1" column="2" >
<widget class="QToolButton" name="tsharkPathButton" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QLabel" name="label_5">
<property name="text">
<item row="2" column="0" >
<widget class="QLabel" name="label_5" >
<property name="text" >
<string>'gzip' Path</string>
</property>
<property name="buddy">
<property name="buddy" >
<cstring>diffPathEdit</cstring>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="gzipPathEdit">
<property name="enabled">
<item row="2" column="1" >
<widget class="QLineEdit" name="gzipPathEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QToolButton" name="gzipPathButton">
<property name="text">
<item row="2" column="2" >
<widget class="QToolButton" name="gzipPathButton" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<item row="3" column="0" >
<widget class="QLabel" name="label_3" >
<property name="text" >
<string>'diff' Path</string>
</property>
<property name="buddy">
<property name="buddy" >
<cstring>diffPathEdit</cstring>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="diffPathEdit">
<property name="enabled">
<item row="3" column="1" >
<widget class="QLineEdit" name="diffPathEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="2">
<widget class="QToolButton" name="diffPathButton">
<property name="text">
<item row="3" column="2" >
<widget class="QToolButton" name="diffPathButton" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_4">
<property name="text">
<item row="4" column="0" >
<widget class="QLabel" name="label_4" >
<property name="text" >
<string>'awk' Path</string>
</property>
<property name="buddy">
<property name="buddy" >
<cstring>awkPathEdit</cstring>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLineEdit" name="awkPathEdit">
<property name="enabled">
<item row="4" column="1" >
<widget class="QLineEdit" name="awkPathEdit" >
<property name="enabled" >
<bool>true</bool>
</property>
</widget>
</item>
<item row="4" column="2">
<widget class="QToolButton" name="awkPathButton">
<property name="text">
<item row="4" column="2" >
<widget class="QToolButton" name="awkPathButton" >
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="5" column="1" >
<spacer>
<property name="orientation">
<property name="orientation" >
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<property name="sizeHint" >
<size>
<width>21</width>
<height>61</height>
@ -164,26 +162,12 @@
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<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">
<widget class="QDialogButtonBox" name="buttonBox" >
<property name="orientation" >
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
<property name="standardButtons" >
<set>QDialogButtonBox::Cancel|QDialogButtonBox::NoButton|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
@ -203,7 +187,7 @@
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
<include location="ostinato.qrc"/>
<include location="ostinato.qrc" />
</resources>
<connections>
<connection>
@ -212,11 +196,11 @@
<receiver>Preferences</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<hint type="sourcelabel" >
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<hint type="destinationlabel" >
<x>157</x>
<y>274</y>
</hint>
@ -228,11 +212,11 @@
<receiver>Preferences</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<hint type="sourcelabel" >
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<hint type="destinationlabel" >
<x>286</x>
<y>274</y>
</hint>

View File

@ -1,50 +0,0 @@
/*
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

View File

@ -74,8 +74,6 @@ const QString kAwkPathDefaultValue("/usr/bin/awk");
const QString kAwkPathDefaultValue("/usr/bin/awk");
#endif
const QString kThemeKey("Theme");
const QString kUserKey("User");
extern QString kUserDefaultValue;

View File

@ -675,19 +675,6 @@ QLineEdit:enabled[inputMask = &quot;HH HH HH HH HH HH; &quot;] { background-colo
</layout>
</widget>
</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>
</widget>
<widget class="QWidget" name="page_2">

View File

@ -361,13 +361,15 @@ void StreamModel::setCurrentPortIndex(const QModelIndex &current)
else
{
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)
{
disconnect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));
}
quint16 pg = current.internalId() >> 16;
// TODO: make mCurrentPort a smart weak pointer
mCurrentPort = pgl->mPortGroups[pgl->indexOfPortGroup(pg)]->mPorts[current.row()];
connect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));

View File

@ -20,12 +20,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "streamstatsmodel.h"
#include "protocol.pb.h"
#include "xqlocale.h"
#include <QApplication>
#include <QBrush>
#include <QFont>
#include <QPalette>
// XXX: Keep the enum in sync with it's string
enum {
@ -46,26 +42,12 @@ enum {
kAggrTxPkts,
kAggrRxPkts,
kAggrPktLoss,
kTxDuration,
kAvgTxFrameRate,
kAvgRxFrameRate,
kAvgTxBitRate,
kAvgRxBitRate,
kAvgLatency,
kAvgJitter,
kMaxAggrStreamStats
};
static QStringList aggrStatTitles = QStringList()
<< "Total\nTx Pkts"
<< "Total\nRx Pkts"
<< "Total\nPkt Loss"
<< "Duration\n(secs)"
<< "Avg\nTx PktRate"
<< "Avg\nRx PktRate"
<< "Avg\nTx BitRate"
<< "Avg\nRx BitRate"
<< "Avg\nLatency"
<< "Avg\nJitter";
<< "Total\nPkt Loss";
static const uint kAggrGuid = 0xffffffff;
@ -121,35 +103,20 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
return Qt::AlignRight;
int portColumn = index.column() - kMaxAggrStreamStats;
// Stylesheets typically don't use or set palette colors, so if
// using one, don't use palette colors
if ((role == Qt::BackgroundRole) && qApp->styleSheet().isEmpty()) {
QPalette palette = QApplication::palette();
if (index.row() == (guidList_.size() - 1)) // Aggregate Row
return palette.dark();
if (portColumn < 0) // Aggregate Column
return palette.alternateBase();
if ((portColumn/kMaxStreamStats) & 1) // Color alternate Ports
return palette.alternateBase();
if (role == Qt::BackgroundRole) {
if (portColumn < 0)
return QBrush(QColor("lavender")); // Aggregate Column
if (index.row() == (guidList_.size() - 1))
return QBrush(QColor("burlywood")); // Aggregate Row
else if ((portColumn/kMaxStreamStats) & 1)
return QBrush(QColor("beige")); // Color alternate Ports
}
Guid guid = guidList_.at(index.row());
if ((role == Qt::ForegroundRole && qApp->styleSheet().isEmpty())) {
QPalette palette = QApplication::palette();
if (role == Qt::ForegroundRole) {
if ((index.column() == kAggrPktLoss)
&& aggrGuidStats_.value(guid).pktLoss)
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;
}
return QBrush(QColor("firebrick"));
}
if (role != Qt::DisplayRole)
@ -164,42 +131,6 @@ QVariant StreamStatsModel::data(const QModelIndex &index, int role) const
return QString("%L1").arg(aggrGuidStats_.value(guid).txPkts);
case kAggrPktLoss:
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:
break;
};
@ -274,8 +205,6 @@ void StreamStatsModel::appendStreamStatsList(
ss.txPkts = s.tx_pkts();
ss.rxBytes = s.rx_bytes();
ss.txBytes = s.tx_bytes();
ss.rxLatency = s.latency();
ss.rxJitter = s.jitter();
aggrPort.rxPkts += ss.rxPkts;
aggrPort.txPkts += ss.txPkts;
@ -285,28 +214,10 @@ void StreamStatsModel::appendStreamStatsList(
aggrGuid.rxPkts += ss.rxPkts;
aggrGuid.txPkts += ss.txPkts;
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.txPkts += ss.txPkts;
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))
portList_.append(pgp);
@ -317,8 +228,6 @@ void StreamStatsModel::appendStreamStatsList(
if (guidList_.size() && !guidList_.contains(kAggrGuid))
guidList_.append(kAggrGuid);
std::sort(guidList_.begin(), guidList_.end());
#if QT_VERSION >= 0x040600
endResetModel();
#else

View File

@ -57,19 +57,11 @@ private:
quint64 txPkts;
quint64 rxBytes;
quint64 txBytes;
quint64 rxLatency;
quint64 rxJitter;
};
struct AggrGuidStats {
quint64 rxPkts;
quint64 txPkts;
quint64 rxBytes;
quint64 txBytes;
qint64 pktLoss;
double txDuration;
quint64 latencySum;
quint64 jitterSum;
uint latencyCount;
};
QList<Guid> guidList_;
QList<PortGroupPort> portList_;

View File

@ -31,7 +31,7 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
: QWidget(parent)
{
setupUi(this);
streamStats->addAction(actionShowDetails);
streamStats->addAction(actionShowByteCounters);
if (id)
setWindowTitle(windowTitle() + QString("(%1)").arg(id));
@ -39,17 +39,13 @@ StreamStatsWindow::StreamStatsWindow(QAbstractItemModel *model, QWidget *parent)
count++;
filterModel_ = new StreamStatsFilterModel(this);
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*"));
filterModel_->setSourceModel(model);
streamStats->setModel(filterModel_);
streamStats->verticalHeader()->setHighlightSections(false);
streamStats->verticalHeader()->setDefaultSectionSize(
streamStats->verticalHeader()->minimumSectionSize());
// Fit all columns in window whenever data changes
connect(model, &QAbstractItemModel::modelReset,
[=]() { streamStats->resizeColumnsToContents(); });
}
StreamStatsWindow::~StreamStatsWindow()
@ -60,12 +56,10 @@ StreamStatsWindow::~StreamStatsWindow()
id = 0;
}
void StreamStatsWindow::on_actionShowDetails_triggered(bool checked)
void StreamStatsWindow::on_actionShowByteCounters_triggered(bool checked)
{
if (checked)
filterModel_->setFilterRegExp(QRegExp(".*"));
else
filterModel_->setFilterRegExp(QRegExp(kDefaultFilter_));
streamStats->resizeColumnsToContents();
filterModel_->setFilterRegExp(QRegExp(".*Pkt.*"));
}

View File

@ -33,10 +33,9 @@ public:
~StreamStatsWindow();
private slots:
void on_actionShowDetails_triggered(bool checked);
void on_actionShowByteCounters_triggered(bool checked);
private:
QString kDefaultFilter_{"^(?!Port).*"};
QSortFilterProxyModel *filterModel_;
};

View File

@ -19,9 +19,6 @@
<property name="contextMenuPolicy">
<enum>Qt::ActionsContextMenu</enum>
</property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="whatsThis">
<string>Oops! We don't seem to have any stream statistics for the requested port(s)
@ -30,12 +27,12 @@ Wait a little bit to see if they appear, otherwise verify your stream stats conf
</widget>
</item>
</layout>
<action name="actionShowDetails">
<action name="actionShowByteCounters">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string>Show Details</string>
<string>Show Byte Counters</string>
</property>
</action>
</widget>

View File

@ -126,8 +126,6 @@ void StreamsWidget::on_tvStreamList_activated(const QModelIndex & index)
qDebug("stream list activated\n");
Q_ASSERT(plm->isPort(currentPortIndex_));
Port &curPort = plm->port(currentPortIndex_);
QList<Stream*> streams;
@ -145,10 +143,11 @@ void StreamsWidget::setCurrentPortIndex(const QModelIndex &portIndex)
if (!plm)
return;
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel;
// caller should ensure this
// XXX: We assume portIndex corresponds to sourceModel, not proxyModel
if (!plm->isPort(portIndex))
return;
qDebug("In %s", __PRETTY_FUNCTION__);
qDebug("In %s", __FUNCTION__);
currentPortIndex_ = portIndex;
plm->getStreamModel()->setCurrentPortIndex(portIndex);
@ -224,8 +223,6 @@ void StreamsWidget::on_actionNew_Stream_triggered()
count = selectionModel->selection().at(0).height();
}
Q_ASSERT(plm->isPort(currentPortIndex_));
Port &curPort = plm->port(currentPortIndex_);
QList<Stream*> streams;
@ -246,8 +243,6 @@ void StreamsWidget::on_actionEdit_Stream_triggered()
if (!streamModel->hasSelection())
return;
Q_ASSERT(plm->isPort(currentPortIndex_));
Port &curPort = plm->port(currentPortIndex_);
QList<Stream*> streams;
@ -267,8 +262,6 @@ void StreamsWidget::on_actionDuplicate_Stream_triggered()
qDebug("Duplicate Stream Action");
Q_ASSERT(plm->isPort(currentPortIndex_));
if (model->hasSelection())
{
bool isOk;
@ -311,8 +304,6 @@ void StreamsWidget::on_actionFind_Replace_triggered()
{
qDebug("Find & Replace Action");
Q_ASSERT(plm->isPort(currentPortIndex_));
QItemSelectionModel* selectionModel = tvStreamList->selectionModel();
FindReplaceDialog::Action action;

View File

@ -1,130 +0,0 @@
/*
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_;
}

View File

@ -1,42 +0,0 @@
/*
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

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -376,9 +376,6 @@ void VariableFieldsWidget::loadProtocolFields(
int byteOfs = bitOfs >> 3;
uint bitSize = protocol->fieldData(i, AbstractProtocol::FieldBitSize)
.toInt();
if (bitSize == 0)
continue;
vm["offset"] = byteOfs;
if (bitSize <= 8) {
vm["type"] = int(OstProto::VariableField::kCounter8);

View File

@ -85,49 +85,20 @@ public:
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 text;
if (bps >= 1e9)
return QObject::tr("%L1 Gbps").arg(bps/1e9, 0, 'f', 3);
return QObject::tr("%L1 Gbps").arg(bps/1e9, 0, 'f', 4);
if (bps >= 1e6)
return QObject::tr("%L1 Mbps").arg(bps/1e6, 0, 'f', 3);
return QObject::tr("%L1 Mbps").arg(bps/1e6, 0, 'f', 4);
if (bps >= 1e3)
return QObject::tr("%L1 Kbps").arg(bps/1e3, 0, 'f', 3);
return QObject::tr("%L1 Kbps").arg(bps/1e3, 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);
return QObject::tr("%L1 bps").arg(bps, 0, 'f', 4);
}
};

View File

@ -169,8 +169,7 @@ private:
for (int i = start; i < end; i++)
if (indexes.contains(model()->index(indexes.first().row(), i)))
text.append(model()->headerData(i, Qt::Horizontal)
.toString().replace('\n', ' ')
+"\t");;
.toString()+"\t");;
text.append("\n");
}

View File

@ -62,14 +62,12 @@ void ArpProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
QString ArpProtocol::name() const
{
return isRarp() ?
QString("Reverse Address Resolution Protocol") :
QString("Address Resolution Protocol");
return QString("Address Resolution Protocol");
}
QString ArpProtocol::shortName() const
{
return isRarp() ? QString("RARP") : QString("ARP");
return QString("ARP");
}
/*!
@ -98,7 +96,7 @@ quint32 ArpProtocol::protocolId(ProtocolIdType type) const
{
switch(type)
{
case ProtocolIdEth: return isRarp() ? 0x8035 : 0x0806;
case ProtocolIdEth: return 0x0806;
default:break;
}
@ -810,11 +808,3 @@ int ArpProtocol::protocolFrameVariableCount() const
return count;
}
bool ArpProtocol::isRarp() const
{
if ((data.op_code() == 3)
|| (data.op_code() ==4))
return true;
return false;
}

View File

@ -96,8 +96,6 @@ public:
virtual int protocolFrameVariableCount() const;
private:
bool isRarp() const;
OstProto::Arp data;
};

View File

@ -30,8 +30,6 @@ ArpConfigForm::ArpConfigForm(QWidget *parent)
opCodeCombo->setValidator(new QIntValidator(0, 0xFFFF, this));
opCodeCombo->addItem(1, "ARP Request");
opCodeCombo->addItem(2, "ARP Reply");
opCodeCombo->addItem(3, "Reverse ARP Request");
opCodeCombo->addItem(4, "Reverse ARP Reply");
connect(senderHwAddrMode, SIGNAL(currentIndexChanged(int)),
SLOT(on_senderHwAddrMode_currentIndexChanged(int)));

View File

@ -25,6 +25,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
template <int protoNumber, class ProtoA, class ProtoB>
class ComboProtocol : public AbstractProtocol
{
protected:
ProtoA *protoA;
ProtoB *protoB;
public:
ComboProtocol(StreamBase *stream, AbstractProtocol *parent = 0)
: AbstractProtocol(stream, parent)
@ -36,12 +40,6 @@ public:
qDebug("%s: protoNumber = %d, %p <--> %p", __FUNCTION__,
protoNumber, protoA, protoB);
if (protoA->protocolNumber() == protoB->protocolNumber())
fieldPrefix = OuterInnerPrefix;
else if (similarProto())
fieldPrefix = ProtoNamePrefix;
}
virtual ~ComboProtocol()
@ -127,29 +125,11 @@ public:
int streamIndex = 0) const
{
int cnt = protoA->fieldCount();
QVariant value = index < cnt ?
protoA->fieldData(index, attrib, streamIndex) :
protoB->fieldData(index - cnt, attrib, streamIndex);
if (attrib == FieldName) {
switch (fieldPrefix) {
case OuterInnerPrefix:
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;
if (index < cnt)
return protoA->fieldData(index, attrib, streamIndex);
else
return protoB->fieldData(index - cnt, attrib, streamIndex);
}
virtual bool setFieldData(int index, const QVariant &value,
FieldAttrib attrib = FieldValue)
@ -206,32 +186,6 @@ public:
CksumType cksumType = CksumIp) const;
#endif
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

View File

@ -1,29 +0,0 @@
/*
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

View File

@ -1,47 +0,0 @@
/*
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;
}

View File

@ -1,41 +0,0 @@
/*
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

View File

@ -27,7 +27,6 @@ struct FrameValueAttrib
enum ErrorFlag {
UnresolvedSrcMacError = 0x1,
UnresolvedDstMacError = 0x2,
OutOfMemoryError = 0x4,
};
Q_DECLARE_FLAGS(ErrorFlags, ErrorFlag);
ErrorFlags errorFlags{0};

View File

@ -1,471 +0,0 @@
/*
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;
}

View File

@ -1,97 +0,0 @@
/*
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

View File

@ -1,39 +0,0 @@
/*
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;
}

View File

@ -1,193 +0,0 @@
<?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>&lt;auto&gt;</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>

View File

@ -1,118 +0,0 @@
/*
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
}

View File

@ -1,44 +0,0 @@
/*
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

View File

@ -1,69 +0,0 @@
/*
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);
}
}

View File

@ -1,45 +0,0 @@
/*
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

View File

@ -214,6 +214,12 @@ Length (x4)</string>
</item>
<item row="1" column="1" >
<widget class="QLineEdit" name="leIpSrcAddr" >
<property name="inputMask" >
<string>009.009.009.009; </string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@ -258,6 +264,12 @@ Length (x4)</string>
<property name="enabled" >
<bool>false</bool>
</property>
<property name="inputMask" >
<string>009.009.009.009; </string>
</property>
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
<item row="2" column="0" >
@ -269,6 +281,12 @@ Length (x4)</string>
</item>
<item row="2" column="1" >
<widget class="QLineEdit" name="leIpDstAddr" >
<property name="inputMask" >
<string>000.000.000.000; </string>
</property>
<property name="text" >
<string>...</string>
</property>
<property name="alignment" >
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
@ -313,6 +331,12 @@ Length (x4)</string>
<property name="enabled" >
<bool>false</bool>
</property>
<property name="inputMask" >
<string>009.009.009.009; </string>
</property>
<property name="text" >
<string>...</string>
</property>
</widget>
</item>
</layout>

View File

@ -19,7 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "ip4config.h"
#include "ip4.h"
#include "ipv4addressvalidator.h"
#include <QHostAddress>
@ -31,10 +30,6 @@ Ip4ConfigForm::Ip4ConfigForm(QWidget *parent)
leIpVersion->setValidator(new QIntValidator(0, 15, this));
leIpOptions->setValidator(new QRegExpValidator(QRegExp("[0-9a-fA-F]*"),
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)),
this, SLOT(on_cmbIpSrcAddrMode_currentIndexChanged(int)));

View File

@ -21,7 +21,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "crc32c.h"
#include <QCoreApplication>
#include <QApplication>
#include <QFile>
#include <QVariant>
@ -437,19 +437,17 @@ _exit:
void NativeFileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
{
QCoreApplication *app = QCoreApplication::instance();
// Fill in the "native" file format version
metaData.set_format_version_major(kFileFormatVersionMajor);
metaData.set_format_version_minor(kFileFormatVersionMinor);
metaData.set_format_version_revision(kFileFormatVersionRevision);
metaData.set_generator_name(
app->applicationName().toUtf8().constData());
qApp->applicationName().toUtf8().constData());
metaData.set_generator_version(
app->property("version").toString().toUtf8().constData());
qApp->property("version").toString().toUtf8().constData());
metaData.set_generator_revision(
app->property("revision").toString().toUtf8().constData());
qApp->property("revision").toString().toUtf8().constData());
}
int NativeFileFormat::fileMetaSize(const quint8* file, int size)

View File

@ -1,60 +0,0 @@
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)

View File

@ -1,15 +0,0 @@
TEMPLATE = lib
CONFIG += qt staticlib
QT += widgets
FORMS = \
pcapfileimport.ui
HEADERS = \
fileformatoptions.h \
pcapoptionsdialog.h
SOURCES = \
fileformatoptions.cpp \
pcapoptionsdialog.cpp

View File

@ -29,7 +29,6 @@ PROTOS += \
ip4over6.proto \
ip4over4.proto \
ip6over6.proto \
gre.proto \
icmp.proto \
gmp.proto \
igmp.proto \
@ -70,7 +69,6 @@ HEADERS += \
ip6over4.h \
ip6over6.h \
gmp.h \
gre.h \
icmp.h \
igmp.h \
mld.h \
@ -105,7 +103,6 @@ SOURCES += \
ip4.cpp \
ip6.cpp \
gmp.cpp \
gre.cpp \
icmp.cpp \
igmp.cpp \
mld.cpp \
@ -113,7 +110,6 @@ SOURCES += \
udp.cpp \
textproto.cpp \
hexdump.cpp \
packet.cpp \
payload.cpp \
sample.cpp \
sign.cpp \

View File

@ -2,6 +2,11 @@ TEMPLATE = lib
CONFIG += qt staticlib
QT += widgets network xml script
INCLUDEPATH += "../extra/qhexedit2/src"
LIBS += \
-lprotobuf
FORMS = \
pcapfileimport.ui \
FORMS += \
mac.ui \
@ -15,7 +20,6 @@ FORMS += \
ip4.ui \
ip6.ui \
gmp.ui \
gre.ui \
icmp.ui \
tcp.ui \
udp.ui \
@ -27,10 +31,28 @@ FORMS += \
sign.ui \
userscript.ui
PROTOS = \
fileformat.proto
# TODO: Move fileformat related stuff into a different library - why?
HEADERS = \
ostprotolib.h \
ipv4addressdelegate.h \
ipv6addressdelegate.h \
spinboxdelegate.h \
nativefileformat.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
HEADERS += \
@ -53,7 +75,6 @@ HEADERS += \
ip6config.h \
ip4over4config.h \
gmpconfig.h \
greconfig.h \
icmpconfig.h \
igmpconfig.h \
mldconfig.h \
@ -67,7 +88,21 @@ HEADERS += \
userscriptconfig.h
SOURCES += \
spinboxdelegate.cpp \
ostprotolib.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
SOURCES += \
@ -83,7 +118,6 @@ SOURCES += \
ip4config.cpp \
ip6config.cpp \
gmpconfig.cpp \
greconfig.cpp \
icmpconfig.cpp \
igmpconfig.cpp \
mldconfig.cpp \
@ -96,6 +130,25 @@ SOURCES += \
signconfig.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.*
include(../protobuf.pri)
include(../options.pri)

View File

@ -1,117 +0,0 @@
/*
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;
}

View File

@ -1,113 +0,0 @@
/*
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

View File

@ -33,8 +33,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
const quint32 kPcapFileMagic = 0xa1b2c3d4;
const quint32 kPcapFileMagicSwapped = 0xd4c3b2a1;
const quint32 kNanoSecondPcapFileMagic = 0xa1b23c4d;
const quint32 kNanoSecondPcapFileMagicSwapped = 0x4d3cb2a1;
const quint16 kPcapFileVersionMajor = 2;
const quint16 kPcapFileVersionMinor = 4;
const quint32 kMaxSnapLen = 65535;
@ -42,9 +40,43 @@ const quint32 kDltEthernet = 1;
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()
{
importOptions_.insert("ViaPdml", true);
importOptions_.insert("RecalculateCksums", false);
importOptions_.insert("DoDiff", true);
}
@ -60,12 +92,11 @@ bool PcapFileFormat::open(const QString fileName,
QTemporaryFile file2;
quint32 magic;
uchar gzipMagic[2];
bool nsecResolution = false;
int len;
PcapFileHeader fileHdr;
PcapPacketHeader pktHdr;
OstProto::Stream *prevStream = NULL;
quint64 lastXsec = 0;
uint lastUsec = 0;
int pktCount;
qint64 byteCount = 0;
qint64 byteTotal;
@ -135,22 +166,15 @@ _retry:
{
// Do nothing
}
else if (magic == kNanoSecondPcapFileMagic)
{
nsecResolution = true;
}
else if ((magic == kPcapFileMagicSwapped)
|| (magic == kNanoSecondPcapFileMagicSwapped))
else if (magic == kPcapFileMagicSwapped)
{
// Toggle Byte order
if (fd_.byteOrder() == QDataStream::BigEndian)
fd_.setByteOrder(QDataStream::LittleEndian);
else
fd_.setByteOrder(QDataStream::BigEndian);
nsecResolution = (magic == kNanoSecondPcapFileMagicSwapped);
}
else // Not a pcap file (could be pcapng or something else)
else // Not a pcap file
{
if (tryConvert)
{
@ -202,9 +226,6 @@ _retry:
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");
if (importOptions_.value("ViaPdml").toBool())
{
@ -244,8 +265,6 @@ _retry:
emit status("Reading PDML packets...");
emit target(100); // in percentage
// pdml reader needs pcap, so pass self
isOk = reader.read(&pdmlFile, this, &stop_);
if (stop_)
@ -431,7 +450,7 @@ _retry:
diffFile.close();
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>&#x1F4A1; 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"));
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"));
diffFile.open();
diffFile.seek(0);
error.append(QString(diffFile.readAll()));
@ -441,7 +460,6 @@ _retry:
}
_non_pdml:
qDebug("pcap resolution: %s", nsecResolution ? "nsec" : "usec");
emit status("Reading Packets...");
emit target(100); // in percentage
pktCount = 1;
@ -469,22 +487,20 @@ _non_pdml:
stream->mutable_control()->set_num_packets(1);
// setup packet rate to the timing in pcap (as close as possible)
// use quint64 rather than double to store micro/nano second as
// it has a larger range (~580 years) and therefore better accuracy
const quint64 kXsecsInSec = nsecResolution ? 1e9 : 1e6;
quint64 xsec = (pktHdr.tsSec*kXsecsInSec + pktHdr.tsUsec);
quint64 delta = xsec - lastXsec;
qDebug("pktCount = %d, delta = %llu", pktCount, delta);
const double kUsecsInSec = 1e6;
uint usec = (pktHdr.tsSec*kUsecsInSec + pktHdr.tsUsec);
uint delta = usec - lastUsec;
if ((pktCount != 1) && delta)
stream->mutable_control()->set_packets_per_sec(double(kXsecsInSec)/delta);
stream->mutable_control()->set_packets_per_sec(kUsecsInSec/delta);
if (prevStream)
prevStream->mutable_control()->CopyFrom(stream->control());
lastXsec = xsec;
lastUsec = usec;
prevStream = stream;
pktCount++;
qDebug("pktCount = %d", pktCount);
byteCount += pktHdr.inclLen + sizeof(pktHdr);
emit progress(int(byteCount*100/byteTotal)); // in percentage
if (stop_)
@ -560,7 +576,7 @@ bool PcapFileFormat::convertToStandardPcap(
tshark.start(OstProtoLib::tsharkPath(),
QStringList()
<< QString("-r%1").arg(fileName)
<< "-Fnsecpcap"
<< "-Fpcap"
<< QString("-w%1").arg(outputFileName));
if (!tshark.waitForStarted(-1))
{
@ -623,7 +639,7 @@ bool PcapFileFormat::save(const OstProto::StreamConfigList streams,
fd_.setDevice(&file);
fileHdr.magicNumber = kNanoSecondPcapFileMagic;
fileHdr.magicNumber = kPcapFileMagic;
fileHdr.versionMajor = kPcapFileVersionMajor;
fileHdr.versionMinor = kPcapFileVersionMinor;
fileHdr.thisZone = 0;
@ -671,16 +687,11 @@ bool PcapFileFormat::save(const OstProto::StreamConfigList streams,
fd_.writeRawData(pktBuf.data(), pktHdr.inclLen);
if (s.packetRate())
{
quint64 delta = quint64(1e9/s.packetRate());
pktHdr.tsSec += delta/quint32(1e9);
pktHdr.tsUsec += delta % quint32(1e9);
}
if (pktHdr.tsUsec >= quint32(1e9))
pktHdr.tsUsec += quint32(1e6/s.packetRate());
if (pktHdr.tsUsec >= 1000000)
{
pktHdr.tsSec++;
pktHdr.tsUsec -= quint32(1e9);
pktHdr.tsUsec -= 1000000;
}
emit progress(i);
@ -699,9 +710,9 @@ _exit:
return isOk;
}
QVariantMap* PcapFileFormat::options()
QDialog* PcapFileFormat::openOptionsDialog()
{
return &importOptions_;
return new PcapImportOptionsDialog(&importOptions_);
}
bool PcapFileFormat::isMyFileFormat(const QString /*fileName*/)

View File

@ -20,10 +20,24 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#define _PCAP_FILE_FORMAT_H
#include "streamfileformat.h"
#include "ui_pcapfileimport.h"
#include <QDataStream>
#include <QVariantMap>
class PcapImportOptionsDialog: public QDialog, public Ui::PcapFileImport
{
public:
PcapImportOptionsDialog(QVariantMap *options);
~PcapImportOptionsDialog();
private slots:
void accept();
private:
QVariantMap *options_;
};
class PdmlReader;
class PcapFileFormat : public StreamFileFormat
{
@ -38,7 +52,7 @@ public:
bool save(const OstProto::StreamConfigList streams,
const QString fileName, QString &error);
virtual QVariantMap* options();
virtual QDialog* openOptionsDialog();
bool isMyFileFormat(const QString fileName);
bool isMyFileType(const QString fileType);

View File

@ -1,55 +0,0 @@
/*
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();
}

View File

@ -1,39 +0,0 @@
/*
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

View File

@ -28,7 +28,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "arppdml.h"
#include "eth2pdml.h"
#include "grepdml.h"
#include "llcpdml.h"
#include "icmppdml.h"
#include "icmp6pdml.h"
@ -63,7 +62,6 @@ PdmlReader::PdmlReader(OstProto::StreamConfigList *streams,
factory_.insert("arp", PdmlArpProtocol::createInstance);
factory_.insert("eth", PdmlEthProtocol::createInstance);
factory_.insert("gre", PdmlGreProtocol::createInstance);
factory_.insert("http", PdmlTextProtocol::createInstance);
factory_.insert("icmp", PdmlIcmpProtocol::createInstance);
factory_.insert("icmpv6", PdmlIcmp6Protocol::createInstance);

View File

@ -157,7 +157,6 @@ message Protocol {
kIcmpFieldNumber = 402;
kIgmpFieldNumber = 403;
kMldFieldNumber = 404;
kGreFieldNumber = 405;
kTextProtocolFieldNumber = 500;
}
@ -216,7 +215,6 @@ message Port {
optional double speed = 10; // in Mbps
optional uint32 mtu = 11;
optional string user_description = 12;
}
message PortConfigList {
@ -291,10 +289,6 @@ message StreamStats {
required PortId port_id = 1;
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_bytes = 12;
optional uint64 tx_pkts = 13;

View File

@ -46,7 +46,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "ip6over6.h"
// L4 Protos
#include "gre.h"
#include "icmp.h"
#include "igmp.h"
#include "mld.h"
@ -113,8 +112,6 @@ ProtocolManager::ProtocolManager()
(void*) Ip6over6Protocol::createInstance);
// Layer 4 Protocols
registerProtocol(OstProto::Protocol::kGreFieldNumber,
(void*) GreProtocol::createInstance);
registerProtocol(OstProto::Protocol::kIcmpFieldNumber,
(void*) IcmpProtocol::createInstance);
registerProtocol(OstProto::Protocol::kIgmpFieldNumber,

View File

@ -40,7 +40,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "ip6over4config.h"
#include "ip6over6config.h"
// L4 Protocol Widgets
#include "greconfig.h"
#include "icmpconfig.h"
#include "igmpconfig.h"
#include "mldconfig.h"
@ -125,9 +124,6 @@ ProtocolWidgetFactory::ProtocolWidgetFactory()
(void*) Ip6over6ConfigForm::createInstance);
// Layer 4 Protocols
OstProtocolWidgetFactory->registerProtocolConfigWidget(
OstProto::Protocol::kGreFieldNumber,
(void*) GreConfigForm::createInstance);
OstProtocolWidgetFactory->registerProtocolConfigWidget(
OstProto::Protocol::kIcmpFieldNumber,
(void*) IcmpConfigForm::createInstance);

View File

@ -63,8 +63,6 @@ bool PythonFileFormat::save(const OstProto::StreamConfigList streams,
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
goto _open_fail;
out.setCodec("UTF-8");
// import standard modules
emit status("Writing imports ...");
emit target(0);
@ -452,16 +450,9 @@ void PythonFileFormat::writeFieldAssignment(
std::string val = fieldDesc->is_repeated() ?
refl->GetRepeatedStringReference(msg, fieldDesc, index, &val) :
refl->GetStringReference(msg, fieldDesc, &val);
if (val == fieldDesc->default_value_string())
break;
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";
}
QString escVal = escapeString(QString::fromStdString(val));
if (val != fieldDesc->default_value_string())
out << fieldName << " = '" << escVal << "'\n";
break;
}
case FieldDescriptor::CPPTYPE_ENUM:
@ -542,16 +533,16 @@ QString PythonFileFormat::singularize(QString plural)
return singular;
}
QString PythonFileFormat::escapeString(QByteArray str)
QString PythonFileFormat::escapeString(QString str)
{
QString escStr = "";
for (int i=0; i < str.length(); i++) {
uchar c = uchar(str.at(i));
uchar c = str[i].cell();
if ((c < 128) && isprint(c)) {
if (c == '\'')
escStr.append("\\'");
else
escStr.append(QChar(c));
escStr.append(str[i]);
}
else
escStr.append(QString("\\x%1").arg(int(c), 2, 16, QChar('0')));
@ -559,16 +550,6 @@ QString PythonFileFormat::escapeString(QByteArray str)
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)
{
// Heuristic - use Hex base for all except for the following

View File

@ -49,8 +49,7 @@ private:
const google::protobuf::FieldDescriptor *fieldDesc,
int index = -1);
QString singularize(QString plural);
QString escapeString(QByteArray str);
QString byteString(QByteArray str);
QString escapeString(QString str);
bool useDecimalBase(QString fieldName);
};

View File

@ -32,7 +32,12 @@ SessionFileFormat::~SessionFileFormat()
{
}
QVariantMap* SessionFileFormat::options()
QDialog* SessionFileFormat::openOptionsDialog()
{
return NULL;
}
QDialog* SessionFileFormat::saveOptionsDialog()
{
return NULL;
}

View File

@ -23,9 +23,10 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "fileformat.pb.h"
#include "protocol.pb.h"
#include <QString>
#include <QThread>
#include <QVariantMap>
#include <QString>
class QDialog;
class SessionFileFormat : public QThread
{
@ -41,7 +42,8 @@ public:
virtual bool save(const OstProto::SessionContent &session,
const QString fileName, QString &error) = 0;
virtual QVariantMap* options();
virtual QDialog* openOptionsDialog();
virtual QDialog* saveOptionsDialog();
void openAsync(const QString fileName,
OstProto::SessionContent &session, QString &error);

View File

@ -19,8 +19,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "sign.h"
#include "../common/streambase.h"
SignProtocol::SignProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent)
{
@ -78,9 +76,7 @@ AbstractProtocol::FieldFlags SignProtocol::fieldFlags(int index) const
switch (index)
{
case sign_magic:
case sign_tlv_tx_port:
case sign_tlv_guid:
case sign_tlv_ttag:
case sign_tlv_end:
break;
@ -120,52 +116,6 @@ QVariant SignProtocol::fieldData(int index, FieldAttrib attrib,
}
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:
{
quint32 guid = data.stream_guid() & 0xFFFFFF;
@ -267,29 +217,3 @@ bool SignProtocol::packetGuid(const uchar *pkt, int pktLen, uint *guid)
}
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;
}

View File

@ -23,8 +23,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "abstractprotocol.h"
#include "sign.pb.h"
#include <limits.h>
/*
Sign Protocol is expected at the end of the frame (just before the Eth FCS)
---+--------+-------+
@ -41,19 +39,9 @@ TLVs are encoded as
Len does NOT include the one byte of TypeLen
Size of the value field varies between 0 to 7 bytes
Defined TLVs
Defined TLVs
Type = 0, Len = 0 (0x00): End of TLVs
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
@ -63,9 +51,7 @@ public:
{
// Frame Fields
sign_tlv_end = 0,
sign_tlv_tx_port,
sign_tlv_guid,
sign_tlv_ttag,
sign_magic,
// Meta Fields
@ -97,19 +83,10 @@ public:
static quint32 magic();
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:
static const quint32 kSignMagic = 0x1d10c0da; // coda! (unicode - 0x1d10c)
static const quint8 kTypeLenEnd = 0x00;
static const quint8 kTypeLenGuid = 0x61;
static const quint8 kTypeLenTxPort = 0x24;
OstProto::Sign data;
};

View File

@ -145,7 +145,7 @@ void StreamBase::setFrameProtocol(ProtocolList protocolList)
}
#endif
bool StreamBase::hasProtocol(quint32 protocolNumber) const
bool StreamBase::hasProtocol(quint32 protocolNumber)
{
foreach(const AbstractProtocol *proto, *currentFrameProtocols)
if (proto->protocolNumber() == protocolNumber)
@ -681,38 +681,14 @@ quint64 StreamBase::neighborMacAddress(int frameIndex) const
bool StreamBase::preflightCheck(QStringList &result) const
{
bool pass = true;
bool chkShort = true;
bool chkTrunc = true;
bool chkJumbo = true;
bool chkSignIcmp = true;
int count = isFrameSizeVariable() ? frameSizeVariableCount() : 1;
for (int i = 0; i < count; 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 &lt; 64 bytes and hence will get padded - "
"make sure special signature is at the end of the "
"frame and frame content &ge; 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)))
{
result << QObject::tr("One or more frames may be truncated - "

View File

@ -42,7 +42,7 @@ public:
void protoDataCopyFrom(const OstProto::Stream &stream);
void protoDataCopyInto(OstProto::Stream &stream) const;
bool hasProtocol(quint32 protocolNumber) const;
bool hasProtocol(quint32 protocolNumber);
ProtocolListIterator* createProtocolListIterator() const;
//! \todo (LOW) should we have a copy constructor??
@ -75,8 +75,9 @@ public:
quint32 id() const;
bool setId(quint32 id);
quint32 portId() { return portId_;}
#if 0 // FIXME(HI): needed?
quint32 portId()
{ return mCore->port_id();}
bool setPortId(quint32 id)
{ mCore->set_port_id(id); return true;}
#endif

View File

@ -35,7 +35,12 @@ StreamFileFormat::~StreamFileFormat()
{
}
QVariantMap* StreamFileFormat::options()
QDialog* StreamFileFormat::openOptionsDialog()
{
return NULL;
}
QDialog* StreamFileFormat::saveOptionsDialog()
{
return NULL;
}

View File

@ -41,7 +41,8 @@ public:
virtual bool save(const OstProto::StreamConfigList streams,
const QString fileName, QString &error) = 0;
virtual QVariantMap* options();
virtual QDialog* openOptionsDialog();
virtual QDialog* saveOptionsDialog();
void openAsync(const QString fileName,
OstProto::StreamConfigList &streams, QString &error);

View File

@ -1,57 +0,0 @@
/*
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

View File

@ -29,11 +29,6 @@ public:
: QValidator(parent)
{
}
ULongLongValidator(qulonglong min, qulonglong max, QObject *parent = 0)
: QValidator(parent)
{
setRange(min, max);
}
~ULongLongValidator() {}
void setRange(qulonglong min, qulonglong max)

View File

@ -32,9 +32,6 @@ Updater::Updater()
#if 1
// 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("10.1", "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