Refactored FileFormat Classes with an Abstract base class. Open/Save streams enhanced to support the new file formats - PCAP and PDML

This commit is contained in:
Srivats P. 2011-03-13 22:36:33 +05:30
parent ed03f06f44
commit 69d488d8a2
12 changed files with 284 additions and 40 deletions

View File

@ -19,9 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "port.h" #include "port.h"
#include "fileformat.h" #include "abstractfileformat.h"
#include "pcapfileformat.h"
#include "pdmlfileformat.h"
#include <QApplication> #include <QApplication>
#include <QVariant> #include <QVariant>
@ -228,10 +226,12 @@ void Port::updateStats(OstProto::PortStats *portStats)
bool Port::openStreams(QString fileName, bool append, QString &error) bool Port::openStreams(QString fileName, bool append, QString &error)
{ {
OstProto::StreamConfigList streams; OstProto::StreamConfigList streams;
AbstractFileFormat *fmt = AbstractFileFormat::fileFormatFromFile(fileName);
//if (!fileFormat.openStreams(fileName, streams, error)) if (fmt == NULL)
//if (!pdmlFileFormat.openStreams(fileName, streams, error)) goto _fail;
if (!pcapFileFormat.openStreams(fileName, streams, error))
if (!fmt->openStreams(fileName, streams, error))
goto _fail; goto _fail;
if (!append) if (!append)
@ -253,10 +253,14 @@ _fail:
return false; return false;
} }
bool Port::saveStreams(QString fileName, QString &error) bool Port::saveStreams(QString fileName, QString fileType, QString &error)
{ {
AbstractFileFormat *fmt = AbstractFileFormat::fileFormatFromType(fileType);
OstProto::StreamConfigList streams; OstProto::StreamConfigList streams;
if (fmt == NULL)
goto _fail;
streams.mutable_port_id()->set_id(0); streams.mutable_port_id()->set_id(0);
for (int i = 0; i < mStreams.size(); i++) for (int i = 0; i < mStreams.size(); i++)
{ {
@ -264,6 +268,9 @@ bool Port::saveStreams(QString fileName, QString &error)
mStreams[i]->protoDataCopyInto(*s); mStreams[i]->protoDataCopyInto(*s);
} }
//return fileFormat.saveStreams(streams, fileName, error); return fmt->saveStreams(streams, fileName, error);
return pcapFileFormat.saveStreams(streams, fileName, error);
_fail:
error = QString("Unsupported File Type - %1").arg(fileType);
return false;
} }

View File

@ -119,7 +119,7 @@ public:
void updateStats(OstProto::PortStats *portStats); void updateStats(OstProto::PortStats *portStats);
bool openStreams(QString fileName, bool append, QString &error); bool openStreams(QString fileName, bool append, QString &error);
bool saveStreams(QString fileName, QString &error); bool saveStreams(QString fileName, QString fileType, QString &error);
signals: signals:
void portDataChanged(int portGroupId, int portId); void portDataChanged(int portGroupId, int portId);

View File

@ -19,13 +19,14 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include "portswindow.h" #include "portswindow.h"
#include "abstractfileformat.h"
#include "streamconfigdialog.h"
#include "streamlistdelegate.h"
#include <QInputDialog> #include <QInputDialog>
#include <QItemSelectionModel> #include <QItemSelectionModel>
#include <QMessageBox> #include <QMessageBox>
#include "streamconfigdialog.h"
#include "streamlistdelegate.h"
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent) PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
: QWidget(parent) : QWidget(parent)
{ {
@ -497,17 +498,44 @@ void PortsWindow::on_actionSave_Streams_triggered()
QModelIndex current = tvPortList->selectionModel()->currentIndex(); QModelIndex current = tvPortList->selectionModel()->currentIndex();
QString fileName; QString fileName;
QStringList fileTypes = AbstractFileFormat::supportedFileTypes();
QString fileType;
QString errorStr; QString errorStr;
QFileDialog::Options options;
// On Mac OS with Native Dialog, getSaveFileName() ignores fileType
// which we need.
#ifdef Q_OS_MAC
options |= QFileDialog::DontUseNativeDialog;
#endif
if (fileTypes.size())
fileType = fileTypes.at(0);
Q_ASSERT(plm->isPort(current)); Q_ASSERT(plm->isPort(current));
fileName = QFileDialog::getSaveFileName(this, tr("Save Streams")); _retry:
fileName = QFileDialog::getSaveFileName(this, tr("Save Streams"),
fileName, fileTypes.join(";;"), &fileType, options);
if (fileName.isEmpty()) if (fileName.isEmpty())
goto _exit; goto _exit;
fileType = fileType.remove(QRegExp("\\(.*\\)")).trimmed();
if (!fileType.startsWith("Ostinato"))
{
if (QMessageBox::warning(this, tr("Ostinato"),
QString("You have chosen to save in %1 format. All stream "
"attributes may not be saved in this format.\n\n"
"It is recommended to save in native Ostinato format.\n\n"
"Continue to save in %2 format?").arg(fileType).arg(fileType),
QMessageBox::Yes|QMessageBox::No,
QMessageBox::No) != QMessageBox::Yes)
goto _retry;
}
// TODO: all or selected? // TODO: all or selected?
if (!plm->port(current).saveStreams(fileName, errorStr)) if (!plm->port(current).saveStreams(fileName, fileType, errorStr))
QMessageBox::critical(this, qApp->applicationName(), errorStr); QMessageBox::critical(this, qApp->applicationName(), errorStr);
else if (!errorStr.isEmpty()) else if (!errorStr.isEmpty())
QMessageBox::warning(this, qApp->applicationName(), errorStr); QMessageBox::warning(this, qApp->applicationName(), errorStr);

View File

@ -0,0 +1,73 @@
/*
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 "abstractfileformat.h"
#include "fileformat.h"
#include "pcapfileformat.h"
#include "pdmlfileformat.h"
#include <QStringList>
AbstractFileFormat::AbstractFileFormat()
{
}
AbstractFileFormat::~AbstractFileFormat()
{
}
QStringList AbstractFileFormat::supportedFileTypes()
{
return QStringList()
<< "Ostinato (*)"
<< "PCAP (*)"
<< "PDML (*.pdml)";
}
AbstractFileFormat* AbstractFileFormat::fileFormatFromFile(
const QString fileName)
{
if (fileFormat.isMyFileFormat(fileName))
return &fileFormat;
if (pdmlFileFormat.isMyFileFormat(fileName))
return &pdmlFileFormat;
if (pcapFileFormat.isMyFileFormat(fileName))
return &pcapFileFormat;
return NULL;
}
AbstractFileFormat* AbstractFileFormat::fileFormatFromType(
const QString fileType)
{
if (fileFormat.isMyFileType(fileType))
return &fileFormat;
if (pdmlFileFormat.isMyFileType(fileType))
return &pdmlFileFormat;
if (pcapFileFormat.isMyFileType(fileType))
return &pcapFileFormat;
return NULL;
}

View File

@ -0,0 +1,52 @@
/*
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 _ABSTRACT_FILE_FORMAT_H
#define _ABSTRACT_FILE_FORMAT_H
#include "protocol.pb.h"
#include <QObject>
#include <QString>
class AbstractFileFormat : public QObject
{
Q_OBJECT
public:
AbstractFileFormat();
virtual ~AbstractFileFormat();
virtual bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error) = 0;
virtual bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error) = 0;
static AbstractFileFormat* fileFormatFromFile(const QString fileName);
static AbstractFileFormat* fileFormatFromType(const QString fileType);
static QStringList supportedFileTypes();
#if 0
bool isMyFileFormat(const QString fileName) = 0;
bool isMyFileType(const QString fileType) = 0;
#endif
};
#endif

View File

@ -394,6 +394,38 @@ _fail:
return false; return false;
} }
bool FileFormat::isMyFileFormat(const QString fileName)
{
bool ret = false;
QFile file(fileName);
QByteArray buf;
OstProto::FileMagic magic;
if (!file.open(QIODevice::ReadOnly))
goto _exit;
buf = file.peek(kFileMagicOffset + kFileMagicSize);
if (!magic.ParseFromArray((void*)(buf.constData() + kFileMagicOffset),
kFileMagicSize))
goto _close_exit;
if (magic.value() == kFileMagicValue)
ret = true;
_close_exit:
file.close();
_exit:
return ret;
}
bool FileFormat::isMyFileType(const QString fileType)
{
if (fileType.startsWith("Ostinato"))
return true;
else
return false;
}
void FileFormat::initFileMetaData(OstProto::FileMetaData &metaData) void FileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
{ {
// Fill in the "native" file format version // Fill in the "native" file format version

View File

@ -19,24 +19,27 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#ifndef _FILE_FORMAT_H #ifndef _FILE_FORMAT_H
#define _FILE_FORMAT_H #define _FILE_FORMAT_H
#include "abstractfileformat.h"
#include "fileformat.pb.h" #include "fileformat.pb.h"
#include <QString> class FileFormat : public AbstractFileFormat
#include <QObject>
class FileFormat : public QObject
{ {
Q_OBJECT
public: public:
FileFormat(); FileFormat();
~FileFormat(); ~FileFormat();
bool openStreams(const QString fileName, virtual bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error); OstProto::StreamConfigList &streams, QString &error);
bool saveStreams(const OstProto::StreamConfigList streams, virtual bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error); const QString fileName, QString &error);
bool isMyFileFormat(const QString fileName);
bool isMyFileType(const QString fileType);
private: private:
void initFileMetaData(OstProto::FileMetaData &metaData);
static const int kFileMagicSize = 12; static const int kFileMagicSize = 12;
static const int kFileChecksumSize = 5; static const int kFileChecksumSize = 5;
static const int kFileMinSize = kFileMagicSize + kFileChecksumSize; static const int kFileMinSize = kFileMagicSize + kFileChecksumSize;
@ -50,8 +53,6 @@ private:
static const uint kFileFormatVersionMajor = 0; static const uint kFileFormatVersionMajor = 0;
static const uint kFileFormatVersionMinor = 1; static const uint kFileFormatVersionMinor = 1;
static const uint kFileFormatVersionRevision = 3; static const uint kFileFormatVersionRevision = 3;
void initFileMetaData(OstProto::FileMetaData &metaData);
}; };
extern FileFormat fileFormat; extern FileFormat fileFormat;

View File

@ -57,6 +57,7 @@ PROTOS += \
HEADERS += \ HEADERS += \
abstractprotocol.h \ abstractprotocol.h \
comboprotocol.h \ comboprotocol.h \
abstractfileformat.h \
fileformat.h \ fileformat.h \
pcapfileformat.h \ pcapfileformat.h \
pdmlfileformat.h \ pdmlfileformat.h \
@ -98,6 +99,7 @@ HEADERS += \
SOURCES += \ SOURCES += \
abstractprotocol.cpp \ abstractprotocol.cpp \
crc32c.cpp \ crc32c.cpp \
abstractfileformat.cpp \
fileformat.cpp \ fileformat.cpp \
pcapfileformat.cpp \ pcapfileformat.cpp \
pdmlfileformat.cpp \ pdmlfileformat.cpp \

View File

@ -25,6 +25,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#include <QDataStream> #include <QDataStream>
#include <QFile> #include <QFile>
#include <QFileInfo>
#include <QProcess> #include <QProcess>
#include <QTemporaryFile> #include <QTemporaryFile>
#include <QtGlobal> #include <QtGlobal>
@ -243,7 +244,7 @@ _non_pdml:
_err_unsupported_encap: _err_unsupported_encap:
error = QString(tr("%1 has non-ethernet encapsulation (%2) which is " error = QString(tr("%1 has non-ethernet encapsulation (%2) which is "
"not supported - Sorry!")) "not supported - Sorry!"))
.arg(fileName).arg(fileHdr.network); .arg(QFileInfo(fileName).fileName()).arg(fileHdr.network);
goto _exit; goto _exit;
#endif #endif
@ -391,3 +392,16 @@ _exit:
return isOk; return isOk;
} }
bool PcapFileFormat::isMyFileFormat(const QString fileName)
{
// TODO
return true;
}
bool PcapFileFormat::isMyFileType(const QString fileType)
{
if (fileType.startsWith("PCAP"))
return true;
else
return false;
}

View File

@ -19,16 +19,13 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#ifndef _PCAP_FILE_FORMAT_H #ifndef _PCAP_FILE_FORMAT_H
#define _PCAP_FILE_FORMAT_H #define _PCAP_FILE_FORMAT_H
#include "protocol.pb.h" #include "abstractfileformat.h"
#include <QDataStream> #include <QDataStream>
#include <QObject>
class PdmlReader; class PdmlReader;
class PcapFileFormat : public QObject class PcapFileFormat : public AbstractFileFormat
{ {
Q_OBJECT
friend class PdmlReader; friend class PdmlReader;
public: public:
@ -40,6 +37,9 @@ public:
bool saveStreams(const OstProto::StreamConfigList streams, bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error); const QString fileName, QString &error);
bool isMyFileFormat(const QString fileName);
bool isMyFileType(const QString fileType);
private: private:
typedef struct { typedef struct {
quint32 magicNumber; /* magic number */ quint32 magicNumber; /* magic number */

View File

@ -92,6 +92,43 @@ _exit:
bool PdmlFileFormat::saveStreams(const OstProto::StreamConfigList streams, bool PdmlFileFormat::saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error) const QString fileName, QString &error)
{ {
error = "Save to PDML format is not supported";
return false; return false;
} }
bool PdmlFileFormat::isMyFileFormat(const QString fileName)
{
bool ret = false;
QFile file(fileName);
QByteArray buf;
QXmlStreamReader xml;
if (!file.open(QIODevice::ReadOnly))
goto _exit;
xml.setDevice(&file);
xml.readNext();
if (xml.hasError() || !xml.isStartDocument())
goto _close_exit;
xml.readNext();
if (!xml.hasError() && xml.isStartElement() && (xml.name() == "pdml"))
ret = true;
else
ret = false;
_close_exit:
xml.clear();
file.close();
_exit:
return ret;
}
bool PdmlFileFormat::isMyFileType(const QString fileType)
{
if (fileType.startsWith("PDML"))
return true;
else
return false;
}

View File

@ -19,24 +19,22 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
#ifndef _PDML_FILE_FORMAT_H #ifndef _PDML_FILE_FORMAT_H
#define _PDML_FILE_FORMAT_H #define _PDML_FILE_FORMAT_H
#include "protocol.pb.h" #include "abstractfileformat.h"
#include <QObject> class PdmlFileFormat : public AbstractFileFormat
class PdmlParser;
class PdmlFileFormat : public QObject
{ {
Q_OBJECT
public: public:
PdmlFileFormat(); PdmlFileFormat();
~PdmlFileFormat(); ~PdmlFileFormat();
bool openStreams(const QString fileName, virtual bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error); OstProto::StreamConfigList &streams, QString &error);
bool saveStreams(const OstProto::StreamConfigList streams, virtual bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error); const QString fileName, QString &error);
bool isMyFileFormat(const QString fileName);
bool isMyFileType(const QString fileType);
}; };
extern PdmlFileFormat pdmlFileFormat; extern PdmlFileFormat pdmlFileFormat;