Implement find-replace logic for fields <= 64 bits
This commit is contained in:
parent
e19083ed3f
commit
b60aad45d1
@ -19,7 +19,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
|
|
||||||
#include "findreplace.h"
|
#include "findreplace.h"
|
||||||
|
|
||||||
|
#include "../common/abstractprotocol.h"
|
||||||
#include "../common/protocolmanager.h"
|
#include "../common/protocolmanager.h"
|
||||||
|
#include "stream.h"
|
||||||
|
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
extern ProtocolManager *OstProtocolManager;
|
extern ProtocolManager *OstProtocolManager;
|
||||||
|
|
||||||
@ -32,23 +36,86 @@ FindReplaceDialog::FindReplaceDialog(Action *action, QWidget *parent)
|
|||||||
useFindMask->setChecked(false);
|
useFindMask->setChecked(false);
|
||||||
useReplaceMask->setChecked(false);
|
useReplaceMask->setChecked(false);
|
||||||
|
|
||||||
protocol->addItems(OstProtocolManager->protocolDatabase());
|
// TODO: remove combo protocols, sample, userscript
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
QStringList protocolList = OstProtocolManager->protocolDatabase();
|
||||||
protocol->setPlaceholderText(tr("Select"));
|
protocolList.sort();
|
||||||
#endif
|
protocol->addItems(protocolList);
|
||||||
protocol->setCurrentIndex(-1);
|
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
|
||||||
field->setPlaceholderText(tr("Select"));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Enable this setting if we have streams selected on input
|
// Enable this setting if we have streams selected on input
|
||||||
selectedStreamsOnly->setEnabled(action->selectedStreamsOnly);
|
selectedStreamsOnly->setEnabled(action->selectedStreamsOnly);
|
||||||
|
|
||||||
// Reset for user input
|
// Reset for user input
|
||||||
action->selectedStreamsOnly = false;
|
action->selectedStreamsOnly = false;
|
||||||
|
|
||||||
|
buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Replace All"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindReplaceDialog::on_protocol_currentIndexChanged(const QString &/*name*/)
|
void FindReplaceDialog::on_protocol_currentIndexChanged(const QString &name)
|
||||||
{
|
{
|
||||||
|
field->clear();
|
||||||
|
fieldAttrib_.clear();
|
||||||
|
|
||||||
|
Stream stream;
|
||||||
|
AbstractProtocol *protocol = OstProtocolManager->createProtocol(
|
||||||
|
name, &stream);
|
||||||
|
int count = protocol->fieldCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
// XXX: It might be useful to support meta fields too, later!
|
||||||
|
if (!protocol->fieldFlags(i).testFlag(AbstractProtocol::FrameField))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int bitSize = protocol->fieldData(i, AbstractProtocol::FieldBitSize)
|
||||||
|
.toInt();
|
||||||
|
if (bitSize <= 0) // skip optional fields
|
||||||
|
continue;
|
||||||
|
|
||||||
|
FieldAttrib fieldAttrib;
|
||||||
|
fieldAttrib.index = i; // fieldIndex
|
||||||
|
fieldAttrib.bitSize = bitSize;
|
||||||
|
fieldAttrib.max = (1 << bitSize) - 1; // min is always 0
|
||||||
|
|
||||||
|
// field and fieldAttrib_ have same count and order of fields
|
||||||
|
fieldAttrib_.append(fieldAttrib);
|
||||||
|
field->addItem(protocol->fieldData(i, AbstractProtocol::FieldName)
|
||||||
|
.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
protocolId_ = protocol->protocolNumber();
|
||||||
|
delete protocol;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FindReplaceDialog::on_buttonBox_accepted()
|
||||||
|
{
|
||||||
|
FieldAttrib fieldAttrib = fieldAttrib_.at(field->currentIndex());
|
||||||
|
action_->protocolNumber = protocolId_;
|
||||||
|
action_->fieldIndex = fieldAttrib.index;
|
||||||
|
action_->fieldBitSize = fieldAttrib.bitSize;
|
||||||
|
|
||||||
|
// XXX: All find/replace value/mask QVariants are set to
|
||||||
|
// 64-bit decimal number encoded as string
|
||||||
|
// - The action user is expected to convert to appropriate type
|
||||||
|
// (fieldBitSize is included as a hint)
|
||||||
|
// - QVariant can only do decimal conversions (not hex)
|
||||||
|
|
||||||
|
if (matchAny->isChecked()) {
|
||||||
|
action_->findMask.setValue(QString("0"));
|
||||||
|
action_->findValue.setValue(QString("0"));
|
||||||
|
} else {
|
||||||
|
action_->findMask.setValue(QString::number(
|
||||||
|
useFindMask->isChecked() ?
|
||||||
|
findMask->text().toULongLong(nullptr, BASE_HEX) :
|
||||||
|
quint64(~0)));
|
||||||
|
action_->findValue.setValue(QString::number(
|
||||||
|
findValue->text().toULongLong(nullptr, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
action_->replaceMask.setValue(QString::number(
|
||||||
|
useReplaceMask->isChecked() ?
|
||||||
|
replaceMask->text().toULongLong(nullptr, BASE_HEX) :
|
||||||
|
quint64(~0)));
|
||||||
|
action_->replaceValue.setValue(QString::number(
|
||||||
|
replaceValue->text().toULongLong(nullptr, 0)));
|
||||||
|
|
||||||
|
action_->selectedStreamsOnly = selectedStreamsOnly->isChecked();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -32,15 +32,21 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void on_protocol_currentIndexChanged(const QString &name);
|
void on_protocol_currentIndexChanged(const QString &name);
|
||||||
|
void on_buttonBox_accepted();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct FieldAttrib;
|
||||||
|
|
||||||
|
quint32 protocolId_{0};
|
||||||
Action *action_{nullptr};
|
Action *action_{nullptr};
|
||||||
|
QList<FieldAttrib> fieldAttrib_;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct FindReplaceDialog::Action
|
struct FindReplaceDialog::Action
|
||||||
{
|
{
|
||||||
quint32 protocolNumber;
|
quint32 protocolNumber;
|
||||||
quint32 fieldIndex;
|
quint32 fieldIndex;
|
||||||
|
int fieldBitSize;
|
||||||
QVariant findValue;
|
QVariant findValue;
|
||||||
QVariant findMask;
|
QVariant findMask;
|
||||||
QVariant replaceValue;
|
QVariant replaceValue;
|
||||||
@ -49,5 +55,11 @@ struct FindReplaceDialog::Action
|
|||||||
bool selectedStreamsOnly; // in-out param
|
bool selectedStreamsOnly; // in-out param
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FindReplaceDialog::FieldAttrib
|
||||||
|
{
|
||||||
|
quint32 index;
|
||||||
|
int bitSize;
|
||||||
|
quint64 max;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -314,33 +314,41 @@ void StreamsWidget::on_actionFind_Replace_triggered()
|
|||||||
if (findReplace.exec() == QDialog::Accepted) {
|
if (findReplace.exec() == QDialog::Accepted) {
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
Port &port = plm->port(currentPortIndex_);
|
Port &port = plm->port(currentPortIndex_);
|
||||||
|
// TODO: progress bar
|
||||||
if (action.selectedStreamsOnly) {
|
if (action.selectedStreamsOnly) {
|
||||||
foreach(QModelIndex index, selectionModel->selectedRows()) {
|
foreach(QModelIndex index, selectionModel->selectedRows()) {
|
||||||
Stream *stream = port.mutableStreamByIndex(index.row(), false);
|
Stream *stream = port.mutableStreamByIndex(index.row(), false);
|
||||||
if (stream->findReplace(action.protocolNumber,
|
if (stream->protocolFieldReplace(action.protocolNumber,
|
||||||
action.fieldIndex,
|
action.fieldIndex,
|
||||||
action.findValue,
|
action.fieldBitSize,
|
||||||
action.findMask,
|
action.findValue,
|
||||||
action.replaceValue,
|
action.findMask,
|
||||||
action.replaceMask))
|
action.replaceValue,
|
||||||
|
action.replaceMask))
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
int count = tvStreamList->model()->rowCount();
|
int count = tvStreamList->model()->rowCount();
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
Stream *stream = port.mutableStreamByIndex(i, false);
|
Stream *stream = port.mutableStreamByIndex(i, false);
|
||||||
if (stream->findReplace(action.protocolNumber,
|
if (stream->protocolFieldReplace(action.protocolNumber,
|
||||||
action.fieldIndex,
|
action.fieldIndex,
|
||||||
action.findValue,
|
action.fieldBitSize,
|
||||||
action.findMask,
|
action.findValue,
|
||||||
action.replaceValue,
|
action.findMask,
|
||||||
action.replaceMask))
|
action.replaceValue,
|
||||||
|
action.replaceMask))
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (changed)
|
if (changed)
|
||||||
port.setLocalConfigChanged(true);
|
port.setLocalConfigChanged(true);
|
||||||
|
|
||||||
|
// TODO: count # of fields and # of streams changed
|
||||||
|
QMessageBox::information(this, tr("Find & Replace"),
|
||||||
|
tr("%1 streams changed").arg(changed));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,6 +270,7 @@ QVariant MacProtocol::fieldData(int index, FieldAttrib attrib,
|
|||||||
bool MacProtocol::setFieldData(int index, const QVariant &value,
|
bool MacProtocol::setFieldData(int index, const QVariant &value,
|
||||||
FieldAttrib attrib)
|
FieldAttrib attrib)
|
||||||
{
|
{
|
||||||
|
// FIXME: make sure isOk is set correctly for all fields and protocols
|
||||||
bool isOk = false;
|
bool isOk = false;
|
||||||
|
|
||||||
if (attrib != FieldValue)
|
if (attrib != FieldValue)
|
||||||
|
@ -236,3 +236,33 @@ QStringList ProtocolManager::protocolDatabase()
|
|||||||
{
|
{
|
||||||
return numberToNameMap.values();
|
return numberToNameMap.values();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
void ProtocolManager::showFieldAttribs()
|
||||||
|
{
|
||||||
|
QStringList protocolList = protocolDatabase();
|
||||||
|
Stream stream;
|
||||||
|
foreach(QString name, protocolList) {
|
||||||
|
if (name.contains("/")) // assume combo
|
||||||
|
continue;
|
||||||
|
AbstractProtocol *protocol = OstProtocolManager->createProtocol(name, &stream);
|
||||||
|
int count = protocol->fieldCount();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (!protocol->fieldFlags(i).testFlag(AbstractProtocol::FrameField))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
uint bitSize = protocol->fieldData(i, AbstractProtocol::FieldBitSize)
|
||||||
|
.toInt();
|
||||||
|
qDebug("$$$$, %s, %d, %s, %u, %x, %llu",
|
||||||
|
qPrintable(name),
|
||||||
|
i,
|
||||||
|
qPrintable(protocol->fieldData(i, AbstractProtocol::FieldName).toString()),
|
||||||
|
bitSize,
|
||||||
|
0, // min
|
||||||
|
(1 << bitSize) - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
delete protocol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
@ -24,6 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
|||||||
#include "protocollistiterator.h"
|
#include "protocollistiterator.h"
|
||||||
#include "protocolmanager.h"
|
#include "protocolmanager.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
extern ProtocolManager *OstProtocolManager;
|
extern ProtocolManager *OstProtocolManager;
|
||||||
extern quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex);
|
extern quint64 getDeviceMacAddress(int portId, int streamId, int frameIndex);
|
||||||
extern quint64 getNeighborMacAddress(int portId, int streamId, int frameIndex);
|
extern quint64 getNeighborMacAddress(int portId, int streamId, int frameIndex);
|
||||||
@ -598,12 +600,56 @@ int StreamBase::frameValue(uchar *buf, int bufMaxSize, int frameIndex,
|
|||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StreamBase::findReplace(quint32 /*protocolNumber*/, int /*fieldIndex*/,
|
template <typename T>
|
||||||
QVariant /*findValue*/, QVariant /*findMask*/,
|
int StreamBase::findReplace(quint32 protocolNumber, int fieldIndex,
|
||||||
QVariant /*replaceValue*/, QVariant /*replaceMask*/)
|
QVariant findValue, QVariant findMask,
|
||||||
|
QVariant replaceValue, QVariant replaceMask)
|
||||||
{
|
{
|
||||||
// TODO
|
int replaceCount = 0;
|
||||||
return false;
|
ProtocolListIterator *iter = createProtocolListIterator();
|
||||||
|
|
||||||
|
// FIXME: Because protocol list iterator is unaware of combo protocols
|
||||||
|
// search for ip4.src will NOT succeed in a combo protocol containing ip4
|
||||||
|
while (iter->hasNext()) {
|
||||||
|
AbstractProtocol *proto = iter->next();
|
||||||
|
if (proto->protocolNumber() != protocolNumber)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
T fieldValue = proto->fieldData(fieldIndex,
|
||||||
|
AbstractProtocol::FieldValue).value<T>();
|
||||||
|
qDebug() << "findReplace:"
|
||||||
|
<< "field" << fieldValue
|
||||||
|
<< "findMask" << hex << findMask.value<T>() << dec
|
||||||
|
<< "findValue" << findValue.value<T>();
|
||||||
|
if ((fieldValue & findMask.value<T>()) == findValue.value<T>()) {
|
||||||
|
T newValue = (fieldValue & ~replaceMask.value<T>())
|
||||||
|
| (replaceValue.value<T>() & replaceMask.value<T>());
|
||||||
|
qDebug() << "findReplace:"
|
||||||
|
<< "replaceMask" << hex << replaceMask.value<T>() << dec
|
||||||
|
<< "replaceValue" << replaceValue.value<T>()
|
||||||
|
<< "newValue" << newValue;
|
||||||
|
if (proto->setFieldData(fieldIndex, newValue))
|
||||||
|
replaceCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete iter;
|
||||||
|
|
||||||
|
return replaceCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
int StreamBase::protocolFieldReplace(quint32 protocolNumber,
|
||||||
|
int fieldIndex, int fieldBitSize,
|
||||||
|
QVariant findValue, QVariant findMask,
|
||||||
|
QVariant replaceValue, QVariant replaceMask)
|
||||||
|
{
|
||||||
|
if (fieldBitSize <= 64)
|
||||||
|
return findReplace<qulonglong>(protocolNumber, fieldIndex,
|
||||||
|
findValue, findMask, replaceValue, replaceMask);
|
||||||
|
|
||||||
|
// TODO: > 64 (e.g. IPv6 128 bit)
|
||||||
|
|
||||||
|
qWarning("Unknown find/replace type %d", findValue.type());
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
quint64 StreamBase::deviceMacAddress(int frameIndex) const
|
quint64 StreamBase::deviceMacAddress(int frameIndex) const
|
||||||
|
@ -142,9 +142,10 @@ public:
|
|||||||
int frameValue(uchar *buf, int bufMaxSize, int frameIndex,
|
int frameValue(uchar *buf, int bufMaxSize, int frameIndex,
|
||||||
FrameValueAttrib *attrib = nullptr) const;
|
FrameValueAttrib *attrib = nullptr) const;
|
||||||
|
|
||||||
bool findReplace(quint32 protocolNumber, int fieldIndex,
|
int protocolFieldReplace(quint32 protocolNumber,
|
||||||
QVariant findValue, QVariant findMask,
|
int fieldIndex, int fieldBitSize,
|
||||||
QVariant replaceValue, QVariant replaceMask);
|
QVariant findValue, QVariant findMask,
|
||||||
|
QVariant replaceValue, QVariant replaceMask);
|
||||||
|
|
||||||
quint64 deviceMacAddress(int frameIndex) const;
|
quint64 deviceMacAddress(int frameIndex) const;
|
||||||
quint64 neighborMacAddress(int frameIndex) const;
|
quint64 neighborMacAddress(int frameIndex) const;
|
||||||
@ -154,6 +155,10 @@ public:
|
|||||||
static bool StreamLessThan(StreamBase* stream1, StreamBase* stream2);
|
static bool StreamLessThan(StreamBase* stream1, StreamBase* stream2);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
template <typename T>
|
||||||
|
int findReplace(quint32 protocolNumber, int fieldIndex,
|
||||||
|
QVariant findValue, QVariant findMask,
|
||||||
|
QVariant replaceValue, QVariant replaceMask);
|
||||||
int portId_;
|
int portId_;
|
||||||
|
|
||||||
OstProto::StreamId *mStreamId;
|
OstProto::StreamId *mStreamId;
|
||||||
|
Loading…
Reference in New Issue
Block a user