diff --git a/client/port.cpp b/client/port.cpp
index 90992ab..3130432 100644
--- a/client/port.cpp
+++ b/client/port.cpp
@@ -22,10 +22,14 @@ along with this program. If not, see
#include "abstractfileformat.h"
#include
+#include
+#include
#include
#include
#include
+extern QMainWindow *mainWindow;
+
uint Port::mAllocStreamId = 0;
uint Port::newStreamId()
@@ -225,52 +229,137 @@ void Port::updateStats(OstProto::PortStats *portStats)
bool Port::openStreams(QString fileName, bool append, QString &error)
{
+ bool ret = false;
+ QProgressDialog progress("Opening Streams", "Cancel", 0, 0, mainWindow);
OstProto::StreamConfigList streams;
AbstractFileFormat *fmt = AbstractFileFormat::fileFormatFromFile(fileName);
if (fmt == NULL)
goto _fail;
- if (!fmt->openStreams(fileName, streams, error))
+ progress.setAutoReset(false);
+ progress.setAutoClose(false);
+ progress.setMinimumDuration(0);
+ progress.show();
+
+ mainWindow->setDisabled(true);
+ progress.setEnabled(true); // to override the mainWindow disable
+
+ connect(fmt, SIGNAL(status(QString)),&progress,SLOT(setLabelText(QString)));
+ connect(fmt, SIGNAL(target(int)), &progress, SLOT(setMaximum(int)));
+ connect(fmt, SIGNAL(progress(int)), &progress, SLOT(setValue(int)));
+ connect(&progress, SIGNAL(canceled()), fmt, SLOT(cancel()));
+
+ fmt->openStreamsOffline(fileName, streams, error);
+ qDebug("after open offline");
+
+ while (!fmt->isFinished())
+ qApp->processEvents();
+ qDebug("wait over for offline operation");
+
+ if (!fmt->result())
goto _fail;
+
+ // process any remaining events posted from the thread
+ for (int i = 0; i < 10; i++)
+ qApp->processEvents();
if (!append)
{
- while (numStreams())
+ int n = numStreams();
+
+ progress.setLabelText("Deleting existing streams...");
+ progress.setRange(0, n);
+ for (int i = 0; i < n; i++)
+ {
+ if (progress.wasCanceled())
+ goto _user_cancel;
deleteStreamAt(0);
+ progress.setValue(i);
+ if (i % 32 == 0)
+ qApp->processEvents();
+ }
}
+ progress.setLabelText("Constructing new streams...");
+ progress.setRange(0, streams.stream_size());
for (int i = 0; i < streams.stream_size(); i++)
{
+ if (progress.wasCanceled())
+ goto _user_cancel;
newStreamAt(mStreams.size(), &streams.stream(i));
+ progress.setValue(i);
+ if (i % 32 == 0)
+ qApp->processEvents();
}
+_user_cancel:
emit streamListChanged(mPortGroupId, mPortId);
-
- return true;
+ ret = true;
_fail:
- return false;
+ progress.close();
+ mainWindow->setEnabled(true);
+ return ret;
}
bool Port::saveStreams(QString fileName, QString fileType, QString &error)
{
+ bool ret = false;
+ QProgressDialog progress("Saving Streams", "Cancel", 0, 0, mainWindow);
AbstractFileFormat *fmt = AbstractFileFormat::fileFormatFromType(fileType);
OstProto::StreamConfigList streams;
if (fmt == NULL)
goto _fail;
+ progress.setAutoReset(false);
+ progress.setAutoClose(false);
+ progress.setMinimumDuration(0);
+ progress.show();
+
+ mainWindow->setDisabled(true);
+ progress.setEnabled(true); // to override the mainWindow disable
+
+ connect(fmt, SIGNAL(status(QString)),&progress,SLOT(setLabelText(QString)));
+ connect(fmt, SIGNAL(target(int)), &progress, SLOT(setMaximum(int)));
+ connect(fmt, SIGNAL(progress(int)), &progress, SLOT(setValue(int)));
+ connect(&progress, SIGNAL(canceled()), fmt, SLOT(cancel()));
+
+ progress.setLabelText("Preparing Streams...");
+ progress.setRange(0, mStreams.size());
streams.mutable_port_id()->set_id(0);
for (int i = 0; i < mStreams.size(); i++)
{
OstProto::Stream *s = streams.add_stream();
mStreams[i]->protoDataCopyInto(*s);
+
+ if (progress.wasCanceled())
+ goto _user_cancel;
+ progress.setValue(i);
+ if (i % 32 == 0)
+ qApp->processEvents();
}
- return fmt->saveStreams(streams, fileName, error);
+ fmt->saveStreamsOffline(streams, fileName, error);
+ qDebug("after save offline");
+
+ while (!fmt->isFinished())
+ qApp->processEvents();
+ qDebug("wait over for offline operation");
+
+ ret = fmt->result();
+ goto _exit;
+
+_user_cancel:
+ goto _exit;
_fail:
error = QString("Unsupported File Type - %1").arg(fileType);
- return false;
+ goto _exit;
+
+_exit:
+ progress.close();
+ mainWindow->setEnabled(true);
+ return ret;
}
diff --git a/client/portswindow.cpp b/client/portswindow.cpp
index 86bcf71..a2cf238 100644
--- a/client/portswindow.cpp
+++ b/client/portswindow.cpp
@@ -458,14 +458,15 @@ void PortsWindow::on_actionOpen_Streams_triggered()
Q_ASSERT(plm->isPort(current));
- fileName = QFileDialog::getOpenFileName(this, tr("Open Streams"));
+ fileName = QFileDialog::getOpenFileName(this, tr("Open Streams"), "D:/srivatsp/projects/ostinato/testfiles/pcaps");
if (fileName.isEmpty())
goto _exit;
if (tvStreamList->model()->rowCount())
{
QMessageBox msgBox(QMessageBox::Question, qApp->applicationName(),
- tr("Append to existing streams? Or overwrite?"));
+ tr("Append to existing streams? Or overwrite?"),
+ QMessageBox::NoButton, this);
QPushButton *appendBtn = msgBox.addButton(tr("Append"),
QMessageBox::ActionRole);
QPushButton *overwriteBtn = msgBox.addButton(tr("Overwrite"),
diff --git a/common/abstractfileformat.cpp b/common/abstractfileformat.cpp
index cb3fa43..f748447 100644
--- a/common/abstractfileformat.cpp
+++ b/common/abstractfileformat.cpp
@@ -27,6 +27,7 @@ along with this program. If not, see
AbstractFileFormat::AbstractFileFormat()
{
+ stop_ = false;
}
AbstractFileFormat::~AbstractFileFormat()
@@ -40,10 +41,40 @@ QStringList AbstractFileFormat::supportedFileTypes()
<< "PCAP (*)"
<< "PDML (*.pdml)";
}
+
+void AbstractFileFormat::openStreamsOffline(const QString fileName,
+ OstProto::StreamConfigList &streams, QString &error)
+{
+ fileName_ = fileName;
+ openStreams_ = &streams;
+ error_ = &error;
+ op_ = kOpen;
+ stop_ = false;
+
+ start();
+}
+
+void AbstractFileFormat::saveStreamsOffline(
+ const OstProto::StreamConfigList streams,
+ const QString fileName, QString &error)
+{
+ saveStreams_ = streams;
+ fileName_ = fileName;
+ error_ = &error;
+ op_ = kSave;
+ stop_ = false;
+
+ start();
+}
+
+bool AbstractFileFormat::result()
+{
+ return result_;
+}
+
AbstractFileFormat* AbstractFileFormat::fileFormatFromFile(
const QString fileName)
{
-
if (fileFormat.isMyFileFormat(fileName))
return &fileFormat;
@@ -71,3 +102,16 @@ AbstractFileFormat* AbstractFileFormat::fileFormatFromType(
return NULL;
}
+
+void AbstractFileFormat::cancel()
+{
+ stop_ = true;
+}
+
+void AbstractFileFormat::run()
+{
+ if (op_ == kOpen)
+ result_ = openStreams(fileName_, *openStreams_, *error_);
+ else if (op_ == kSave)
+ result_ = saveStreams(saveStreams_, fileName_, *error_);
+}
diff --git a/common/abstractfileformat.h b/common/abstractfileformat.h
index 7a648ee..031e4e1 100644
--- a/common/abstractfileformat.h
+++ b/common/abstractfileformat.h
@@ -22,12 +22,12 @@ along with this program. If not, see
#include "protocol.pb.h"
-#include
+#include
#include
-class AbstractFileFormat : public QObject
+class AbstractFileFormat : public QThread
{
- Q_OBJECT
+ Q_OBJECT
public:
AbstractFileFormat();
virtual ~AbstractFileFormat();
@@ -37,6 +37,13 @@ public:
virtual bool saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error) = 0;
+ void openStreamsOffline(const QString fileName,
+ OstProto::StreamConfigList &streams, QString &error);
+ void saveStreamsOffline(const OstProto::StreamConfigList streams,
+ const QString fileName, QString &error);
+
+ bool result();
+
static AbstractFileFormat* fileFormatFromFile(const QString fileName);
static AbstractFileFormat* fileFormatFromType(const QString fileType);
@@ -46,6 +53,33 @@ public:
bool isMyFileFormat(const QString fileName) = 0;
bool isMyFileType(const QString fileType) = 0;
#endif
+
+signals:
+ void status(QString text);
+ void target(int value);
+ void progress(int value);
+
+public slots:
+ void cancel();
+
+protected:
+ void run();
+
+ bool stop_;
+
+private:
+ enum kOp
+ {
+ kOpen,
+ kSave
+ };
+ QString fileName_;
+ OstProto::StreamConfigList *openStreams_;
+ OstProto::StreamConfigList saveStreams_;
+ QString *error_;
+ kOp op_;
+ bool result_;
+
};
#endif
diff --git a/common/fileformat.cpp b/common/fileformat.cpp
index 7ddc65b..aada8b1 100644
--- a/common/fileformat.cpp
+++ b/common/fileformat.cpp
@@ -322,6 +322,8 @@ bool FileFormat::saveStreams(const OstProto::StreamConfigList streams,
goto _zero_cksum_serialize_fail;
}
+ emit status("Calculating checksum...");
+
// Calculate and write checksum
calcCksum = checksumCrc32C((quint8*)buf.constData(), buf.size());
cksum.set_value(calcCksum);
@@ -335,6 +337,7 @@ bool FileFormat::saveStreams(const OstProto::StreamConfigList streams,
qDebug("Writing %d bytes", buf.size());
//qDebug("%s", QString(buf.toHex()).toAscii().constData());
+ emit status("Writing to disk...");
if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
goto _open_fail;
diff --git a/common/pcapfileformat.cpp b/common/pcapfileformat.cpp
index a893565..04ace99 100644
--- a/common/pcapfileformat.cpp
+++ b/common/pcapfileformat.cpp
@@ -64,7 +64,7 @@ PcapFileFormat::~PcapFileFormat()
bool PcapFileFormat::openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error)
{
- bool viaPdml = true; // TODO: shd be a param to function
+ bool viaPdml = false; // TODO: shd be a param to function
bool isOk = false;
QFile file(fileName);
@@ -77,6 +77,8 @@ bool PcapFileFormat::openStreams(const QString fileName,
OstProto::Stream *prevStream = NULL;
uint lastUsec = 0;
int pktCount;
+ qint64 byteCount = 0;
+ qint64 byteTotal;
QByteArray pktBuf;
if (!file.open(QIODevice::ReadOnly))
@@ -90,6 +92,9 @@ bool PcapFileFormat::openStreams(const QString fileName,
{
QProcess gzip;
+ emit status("Decompressing...");
+ emit target(0);
+
if (!file2.open())
{
error.append("Unable to open temporary file to uncompress .gz\n");
@@ -126,6 +131,11 @@ bool PcapFileFormat::openStreams(const QString fileName,
fd_.setDevice(&file);
}
+ byteTotal = fd_.device()->size() - sizeof(fileHdr);
+
+ emit status("Reading File Header...");
+ emit target(0);
+
fd_ >> magic;
qDebug("magic = %08x", magic);
@@ -173,6 +183,8 @@ bool PcapFileFormat::openStreams(const QString fileName,
}
qDebug("generating PDML %s", pdmlFile.fileName().toAscii().constData());
+ emit status("Generating PDML...");
+ emit target(0);
tshark.setStandardOutputFile(pdmlFile.fileName());
// FIXME: hardcoded prog name
@@ -193,12 +205,18 @@ bool PcapFileFormat::openStreams(const QString fileName,
goto _non_pdml;
}
- isOk = reader.read(&pdmlFile, this); // TODO: pass error string?
+ connect(&reader, SIGNAL(progress(int)), this, SIGNAL(progress(int)));
+
+ emit status("Reading PDML packets...");
+ emit target(100); // in percentage
+ isOk = reader.read(&pdmlFile, this, &stop_); // TODO: pass error string?
goto _exit;
}
_non_pdml:
+ emit status("Reading Packets...");
+ emit target(100); // in percentage
pktCount = 1;
while (!fd_.atEnd())
{
@@ -235,11 +253,20 @@ _non_pdml:
lastUsec = usec;
prevStream = stream;
pktCount++;
+ qDebug("pktCount = %d", pktCount);
+ byteCount += pktHdr.inclLen + sizeof(pktHdr);
+ emit progress(int(byteCount*100/byteTotal)); // in percentage
+ if (stop_)
+ goto _user_cancel;
}
isOk = true;
goto _exit;
+_user_cancel:
+ isOk = true;
+ goto _exit;
+
#if 1
_err_unsupported_encap:
error = QString(tr("%1 has non-ethernet encapsulation (%2) which is "
@@ -344,6 +371,9 @@ bool PcapFileFormat::saveStreams(const OstProto::StreamConfigList streams,
pktBuf.resize(kMaxSnapLen);
+ emit status("Writing Packets...");
+ emit target(streams.stream_size());
+
pktHdr.tsSec = 0;
pktHdr.tsUsec = 0;
for (int i = 0; i < streams.stream_size(); i++)
@@ -377,6 +407,8 @@ bool PcapFileFormat::saveStreams(const OstProto::StreamConfigList streams,
pktHdr.tsSec++;
pktHdr.tsUsec -= 1000000;
}
+
+ emit progress(i);
}
file.close();
diff --git a/common/pdml_p.cpp b/common/pdml_p.cpp
index ae1c7ce..3dac8e0 100644
--- a/common/pdml_p.cpp
+++ b/common/pdml_p.cpp
@@ -115,6 +115,8 @@ PdmlReader::PdmlReader(OstProto::StreamConfigList *streams)
currentStream_ = NULL;
prevStream_ = NULL;
+ stop_ = NULL;
+
factory_.insert("hexdump", PdmlUnknownProtocol::createInstance);
factory_.insert("geninfo", PdmlGenInfoProtocol::createInstance);
factory_.insert("frame", PdmlFrameProtocol::createInstance);
@@ -128,12 +130,13 @@ PdmlReader::~PdmlReader()
{
}
-bool PdmlReader::read(QIODevice *device, PcapFileFormat *pcap)
+bool PdmlReader::read(QIODevice *device, PcapFileFormat *pcap, bool *stop)
{
setDevice(device);
pcap_ = pcap;
packetCount_ = 0;
+ stop_ = stop;
while (!atEnd())
{
readNext();
@@ -146,7 +149,7 @@ bool PdmlReader::read(QIODevice *device, PcapFileFormat *pcap)
}
}
- if (error())
+ if (error() && (errorString() != "USER-CANCEL"))
{
qDebug("Line %lld", lineNumber());
qDebug("Col %lld", columnNumber());
@@ -325,8 +328,11 @@ void PdmlReader::readPacket()
}
packetCount_++;
+ emit progress(int(characterOffset()*100/device()->size()));
if (prevStream_)
prevStream_->mutable_control()->CopyFrom(currentStream_->control());
+ if (stop_ && *stop_)
+ raiseError("USER-CANCEL");
}
void PdmlReader::readProto()
diff --git a/common/pdml_p.h b/common/pdml_p.h
index 42ea327..af7c4f6 100644
--- a/common/pdml_p.h
+++ b/common/pdml_p.h
@@ -62,14 +62,18 @@ protected:
class PdmlUnknownProtocol;
class PcapFileFormat;
-class PdmlReader : public QXmlStreamReader
+class PdmlReader : public QObject, public QXmlStreamReader
{
+ Q_OBJECT
friend class PdmlUnknownProtocol;
public:
PdmlReader(OstProto::StreamConfigList *streams);
~PdmlReader();
- bool read(QIODevice *device, PcapFileFormat *pcap = NULL);
+ bool read(QIODevice *device, PcapFileFormat *pcap = NULL,
+ bool *stop = NULL);
+signals:
+ void progress(int value);
private:
PdmlDefaultProtocol* allocPdmlProtocol(QString protoName);
@@ -103,6 +107,7 @@ private:
OstProto::Stream *currentStream_;
QByteArray pktBuf_;
+ bool *stop_;
};
class PdmlUnknownProtocol : public PdmlDefaultProtocol
diff --git a/common/pdmlfileformat.cpp b/common/pdmlfileformat.cpp
index 0c51652..1e2c4c8 100644
--- a/common/pdmlfileformat.cpp
+++ b/common/pdmlfileformat.cpp
@@ -30,39 +30,6 @@ PdmlFileFormat::~PdmlFileFormat()
{
}
-#if 0
-bool PdmlFileFormat::openStreams(const QString fileName,
- OstProto::StreamConfigList &streams, QString &error)
-{
- bool isOk;
- QFile file(fileName);
- PdmlParser *pdml;
- QXmlSimpleReader *xmlReader;
- QXmlInputSource *xmlSource;
-
- if (!file.open(QIODevice::ReadOnly))
- goto _open_fail;
-
- pdml = new PdmlParser(&streams);
- xmlSource = new QXmlInputSource(&file);
- xmlReader = new QXmlSimpleReader;
- xmlReader->setContentHandler(pdml);
- xmlReader->setErrorHandler(pdml);
- isOk = xmlReader->parse(xmlSource, false); // non-incremental parse
-
- goto _exit;
-
-_open_fail:
- isOk = false;
-
-_exit:
- delete xmlReader;
- delete xmlSource;
- delete pdml;
-
- return isOk;
-}
-#else
bool PdmlFileFormat::openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error)
{
@@ -73,6 +40,10 @@ bool PdmlFileFormat::openStreams(const QString fileName,
if (!file.open(QIODevice::ReadOnly))
goto _open_fail;
+ connect(reader, SIGNAL(progress(int)), this, SIGNAL(progress(int)));
+ emit status("Reading PDML packets...");
+ emit target(100); // in percentage
+
// TODO: fill in error string
isOk = reader->read(&file);
@@ -87,7 +58,6 @@ _exit:
return isOk;
}
-#endif
bool PdmlFileFormat::saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error)