diff --git a/common/fileformat.cpp b/common/fileformat.cpp
index 4edd980..2ccf270 100644
--- a/common/fileformat.cpp
+++ b/common/fileformat.cpp
@@ -19,160 +19,23 @@ along with this program. If not, see
#include "fileformat.h"
-#include "crc32c.h"
-
-#include
-#include
-#include
-
-#include
-
-const std::string FileFormat::kFileMagicValue = "\xa7\xb7OSTINATO";
-
FileFormat fileFormat;
-const int kBaseHex = 16;
-
FileFormat::FileFormat()
+ : AbstractFileFormat(), NativeFileFormat()
{
- /*
- * We don't have any "real" work to do here in the constructor.
- * What we do is run some "assert" tests so that these get caught
- * at init itself instead of while saving/restoring when a user
- * might lose some data!
- */
- OstProto::FileMagic magic;
- OstProto::FileChecksum cksum;
-
- magic.set_value(kFileMagicValue);
- cksum.set_value(quint32(0));
-
- // TODO: convert Q_ASSERT to something that will run in RELEASE mode also
- Q_ASSERT(magic.IsInitialized());
- Q_ASSERT(cksum.IsInitialized());
- Q_ASSERT(magic.ByteSize() == kFileMagicSize);
- Q_ASSERT(cksum.ByteSize() == kFileChecksumSize);
-}
-
-FileFormat::~FileFormat()
-{
+ // Do Nothing!
}
bool FileFormat::openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error)
{
- QFile file(fileName);
- QByteArray buf;
- int size, contentOffset, contentSize;
- quint32 calcCksum;
- OstProto::FileMagic magic;
OstProto::FileMeta meta;
OstProto::FileContent content;
- OstProto::FileChecksum cksum, zeroCksum;
-
- if (!file.open(QIODevice::ReadOnly))
- goto _open_fail;
-
- if (file.size() < kFileMagicSize)
- goto _magic_missing;
-
- if (file.size() < kFileMinSize)
- goto _checksum_missing;
-
- buf.resize(file.size());
- size = file.read(buf.data(), buf.size());
- if (size < 0)
- goto _read_fail;
-
- Q_ASSERT(file.atEnd());
- file.close();
-
- qDebug("%s: file.size() = %lld", __FUNCTION__, file.size());
- qDebug("%s: size = %d", __FUNCTION__, size);
-
- //qDebug("Read %d bytes", buf.size());
- //qDebug("%s", QString(buf.toHex()).toAscii().constData());
-
- // Parse and verify magic
- if (!magic.ParseFromArray(
- (void*)(buf.constData() + kFileMagicOffset),
- kFileMagicSize))
- {
- goto _magic_parse_fail;
- }
- if (magic.value() != kFileMagicValue)
- goto _magic_match_fail;
-
- // Parse and verify checksum
- if (!cksum.ParseFromArray(
- (void*)(buf.constData() + size - kFileChecksumSize),
- kFileChecksumSize))
- {
- goto _cksum_parse_fail;
- }
-
- zeroCksum.set_value(0);
- if (!zeroCksum.SerializeToArray(
- (void*) (buf.data() + size - kFileChecksumSize),
- kFileChecksumSize))
- {
- goto _zero_cksum_serialize_fail;
- }
+ bool ret = NativeFileFormat::open(fileName, meta, content, error);
- calcCksum = checksumCrc32C((quint8*) buf.constData(), size);
-
- qDebug("checksum \nExpected:%x Actual:%x",
- calcCksum, cksum.value());
-
- if (cksum.value() != calcCksum)
- goto _cksum_verify_fail;
-
- // Parse the metadata first before we parse the full contents
- if (!meta.ParseFromArray(
- (void*)(buf.constData() + kFileMetaDataOffset),
- size - kFileMetaDataOffset))
- {
- goto _metadata_parse_fail;
- }
-
- qDebug("%s: File MetaData (INFORMATION) - \n%s", __FUNCTION__,
- QString().fromStdString(meta.DebugString()).toAscii().constData());
-
- // MetaData Validation(s)
- if (meta.data().file_type() != OstProto::kStreamsFileType)
- goto _unexpected_file_type;
-
- if (meta.data().format_version_major() != kFileFormatVersionMajor)
- goto _incompatible_file_version;
-
- if (meta.data().format_version_minor() > kFileFormatVersionMinor)
- goto _incompatible_file_version;
-
- if (meta.data().format_version_minor() < kFileFormatVersionMinor)
- {
- // TODO: need to modify 'buf' such that we can parse successfully
- // assuming the native minor version
- }
-
- if (meta.data().format_version_revision() > kFileFormatVersionRevision)
- {
- error = QString(tr("%1 was created using a newer version of Ostinato."
- " New features/protocols will not be available.")).arg(fileName);
- }
-
- Q_ASSERT(meta.data().format_version_major() == kFileFormatVersionMajor);
-
- // ByteSize() does not include the Tag/Key, so we add 2 for that
- contentOffset = kFileMetaDataOffset + meta.data().ByteSize() + 2;
- contentSize = size - contentOffset - kFileChecksumSize;
-
- // Parse full contents
- if (!content.ParseFromArray(
- (void*)(buf.constData() + contentOffset),
- contentSize))
- {
- goto _content_parse_fail;
- }
+ if (!ret)
+ goto _fail;
if (!content.matter().has_streams())
goto _missing_streams;
@@ -186,75 +49,6 @@ bool FileFormat::openStreams(const QString fileName,
_missing_streams:
error = QString(tr("%1 does not contain any streams")).arg(fileName);
goto _fail;
-_content_parse_fail:
- error = QString(tr("Failed parsing %1 contents")).arg(fileName);
- qDebug("Error: %s", QString().fromStdString(
- content.matter().InitializationErrorString())
- .toAscii().constData());
- qDebug("Debug: %s", QString().fromStdString(
- content.matter().DebugString()).toAscii().constData());
- goto _fail;
-_incompatible_file_version:
- error = QString(tr("%1 is in an incompatible format version - %2.%3.%4"
- " (Native version is %5.%6.%7)"))
- .arg(fileName)
- .arg(meta.data().format_version_major())
- .arg(meta.data().format_version_minor())
- .arg(meta.data().format_version_revision())
- .arg(kFileFormatVersionMajor)
- .arg(kFileFormatVersionMinor)
- .arg(kFileFormatVersionRevision);
- goto _fail;
-_unexpected_file_type:
- error = QString(tr("%1 is not a streams file")).arg(fileName);
- goto _fail;
-_metadata_parse_fail:
- error = QString(tr("Failed parsing %1 meta data")).arg(fileName);
- qDebug("Error: %s", QString().fromStdString(
- meta.data().InitializationErrorString())
- .toAscii().constData());
- goto _fail;
-_cksum_verify_fail:
- error = QString(tr("%1 checksum validation failed!\nExpected:%2 Actual:%3"))
- .arg(fileName)
- .arg(calcCksum, 0, kBaseHex)
- .arg(cksum.value(), 0, kBaseHex);
- goto _fail;
-_zero_cksum_serialize_fail:
- error = QString(tr("Internal Error: Zero Checksum Serialize failed!\n"
- "Error: %1\nDebug: %2"))
- .arg(QString().fromStdString(
- cksum.InitializationErrorString()))
- .arg(QString().fromStdString(cksum.DebugString()));
- goto _fail;
-_cksum_parse_fail:
- error = QString(tr("Failed parsing %1 checksum")).arg(fileName);
- qDebug("Error: %s", QString().fromStdString(
- cksum.InitializationErrorString())
- .toAscii().constData());
- goto _fail;
-_magic_match_fail:
- error = QString(tr("%1 is not an Ostinato file")).arg(fileName);
- goto _fail;
-_magic_parse_fail:
- error = QString(tr("%1 does not look like an Ostinato file")).arg(fileName);
- qDebug("Error: %s", QString().fromStdString(
- magic.InitializationErrorString())
- .toAscii().constData());
- goto _fail;
-_read_fail:
- error = QString(tr("Error reading from %1")).arg(fileName);
- goto _fail;
-_checksum_missing:
- error = QString(tr("%1 is too small (missing checksum)")).arg(fileName);
- goto _fail;
-_magic_missing:
- error = QString(tr("%1 is too small (missing magic value)"))
- .arg(fileName);
- goto _fail;
-_open_fail:
- error = QString(tr("Error opening %1")).arg(fileName);
- goto _fail;
_fail:
qDebug("%s", error.toAscii().constData());
return false;
@@ -263,25 +57,7 @@ _fail:
bool FileFormat::saveStreams(const OstProto::StreamConfigList streams,
const QString fileName, QString &error)
{
- OstProto::FileMagic magic;
- OstProto::FileMeta meta;
OstProto::FileContent content;
- OstProto::FileChecksum cksum;
- QFile file(fileName);
- int metaSize, contentSize;
- int contentOffset, cksumOffset;
- QByteArray buf;
- quint32 calcCksum;
-
- magic.set_value(kFileMagicValue);
- Q_ASSERT(magic.IsInitialized());
-
- cksum.set_value(0);
- Q_ASSERT(cksum.IsInitialized());
-
- initFileMetaData(*(meta.mutable_data()));
- meta.mutable_data()->set_file_type(OstProto::kStreamsFileType);
- Q_ASSERT(meta.IsInitialized());
if (!streams.IsInitialized())
goto _stream_not_init;
@@ -289,104 +65,9 @@ bool FileFormat::saveStreams(const OstProto::StreamConfigList streams,
content.mutable_matter()->mutable_streams()->CopyFrom(streams);
Q_ASSERT(content.IsInitialized());
- metaSize = meta.ByteSize();
- contentSize = content.ByteSize();
- contentOffset = kFileMetaDataOffset + metaSize;
- cksumOffset = contentOffset + contentSize;
+ return NativeFileFormat::save(OstProto::kStreamsFileType, content,
+ fileName, error);
- Q_ASSERT(magic.ByteSize() == kFileMagicSize);
- Q_ASSERT(cksum.ByteSize() == kFileChecksumSize);
- buf.resize(kFileMagicSize + metaSize + contentSize + kFileChecksumSize);
-
- // Serialize everything
- if (!magic.SerializeToArray((void*) (buf.data() + kFileMagicOffset),
- kFileMagicSize))
- {
- goto _magic_serialize_fail;
- }
-
- if (!meta.SerializeToArray((void*) (buf.data() + kFileMetaDataOffset),
- metaSize))
- {
- goto _meta_serialize_fail;
- }
-
- if (!content.SerializeToArray((void*) (buf.data() + contentOffset),
- contentSize))
- {
- goto _content_serialize_fail;
- }
-
- if (!cksum.SerializeToArray((void*) (buf.data() + cksumOffset),
- kFileChecksumSize))
- {
- goto _zero_cksum_serialize_fail;
- }
-
- emit status("Calculating checksum...");
-
- // Calculate and write checksum
- calcCksum = checksumCrc32C((quint8*)buf.constData(), buf.size());
- cksum.set_value(calcCksum);
- if (!cksum.SerializeToArray(
- (void*) (buf.data() + cksumOffset),
- kFileChecksumSize))
- {
- goto _cksum_serialize_fail;
- }
-
- 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;
-
- if (file.write(buf) < 0)
- goto _write_fail;
-
- file.close();
-
- return true;
-
-_write_fail:
- error = QString(tr("Error writing to %1")).arg(fileName);
- goto _fail;
-_open_fail:
- error = QString(tr("Error opening %1 (Error Code = %2)"))
- .arg(fileName)
- .arg(file.error());
- goto _fail;
-_cksum_serialize_fail:
- error = QString(tr("Internal Error: Checksum Serialize failed\n%1\n%2"))
- .arg(QString().fromStdString(
- cksum.InitializationErrorString()))
- .arg(QString().fromStdString(cksum.DebugString()));
- goto _fail;
-_zero_cksum_serialize_fail:
- error = QString(tr("Internal Eror: Zero Checksum Serialize failed\n%1\n%2"))
- .arg(QString().fromStdString(
- cksum.InitializationErrorString()))
- .arg(QString().fromStdString(cksum.DebugString()));
- goto _fail;
-_content_serialize_fail:
- error = QString(tr("Internal Error: Content Serialize failed\n%1\n%2"))
- .arg(QString().fromStdString(
- content.InitializationErrorString()))
- .arg(QString().fromStdString(content.DebugString()));
- goto _fail;
-_meta_serialize_fail:
- error = QString(tr("Internal Error: Meta Data Serialize failed\n%1\n%2"))
- .arg(QString().fromStdString(
- meta.InitializationErrorString()))
- .arg(QString().fromStdString(meta.DebugString()));
- goto _fail;
-_magic_serialize_fail:
- error = QString(tr("Internal Error: Magic Serialize failed\n%1\n%2"))
- .arg(QString().fromStdString(
- magic.InitializationErrorString()))
- .arg(QString().fromStdString(magic.DebugString()));
- goto _fail;
_stream_not_init:
error = QString(tr("Internal Error: Streams not initialized\n%1\n%2"))
.arg(QString().fromStdString(
@@ -400,26 +81,7 @@ _fail:
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;
+ return isNativeFileFormat(fileName, OstProto::kStreamsFileType);
}
bool FileFormat::isMyFileType(const QString fileType)
@@ -430,54 +92,3 @@ bool FileFormat::isMyFileType(const QString fileType)
return false;
}
-void FileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
-{
- // 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(
- qApp->applicationName().toUtf8().constData());
- metaData.set_generator_version(
- qApp->property("version").toString().toUtf8().constData());
- metaData.set_generator_revision(
- qApp->property("revision").toString().toUtf8().constData());
-}
-
-#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
-/*! Fixup content to what is expected in the native version */
-void FileFormat::postParseFixup(OstProto::FileMetaData metaData,
- OstProto::FileContent &content)
-{
- Q_ASSERT(metaData.format_version_major() == kFileFormatVersionMajor);
-
- // Do fixups from oldest to newest versions
- switch (metaData.format_version_minor())
- {
- case 1:
- {
- int n = content.matter().streams().stream_size();
- for (int i = 0; i < n; i++)
- {
- OstProto::StreamControl *sctl =
- content.mutable_matter()->mutable_streams()->mutable_stream(i)->mutable_control();
- sctl->set_packets_per_sec(sctl->obsolete_packets_per_sec());
- sctl->set_bursts_per_sec(sctl->obsolete_bursts_per_sec());
- }
-
- // fall-through to next higher version until native version
- }
- case kFileFormatVersionMinor: // native version
- break;
-
- case 0:
- default:
- qWarning("%s: minor version %u unhandled", __FUNCTION__,
- metaData.format_version_minor());
- Q_ASSERT_X(false, "postParseFixup", "unhandled minor version");
- }
-
-}
-#pragma GCC diagnostic warning "-Wdeprecated-declarations"
-
diff --git a/common/fileformat.h b/common/fileformat.h
index f2c5b32..95eb310 100644
--- a/common/fileformat.h
+++ b/common/fileformat.h
@@ -20,14 +20,14 @@ along with this program. If not, see
#define _FILE_FORMAT_H
#include "abstractfileformat.h"
+#include "nativefileformat.h"
#include "fileformat.pb.h"
-class FileFormat : public AbstractFileFormat
+class FileFormat : public AbstractFileFormat, public NativeFileFormat
{
public:
FileFormat();
- ~FileFormat();
virtual bool openStreams(const QString fileName,
OstProto::StreamConfigList &streams, QString &error);
@@ -36,25 +36,6 @@ public:
bool isMyFileFormat(const QString fileName);
bool isMyFileType(const QString fileType);
-
-private:
- void initFileMetaData(OstProto::FileMetaData &metaData);
- void postParseFixup(OstProto::FileMetaData metaData,
- OstProto::FileContent &content);
-
- static const int kFileMagicSize = 12;
- static const int kFileChecksumSize = 5;
- static const int kFileMinSize = kFileMagicSize + kFileChecksumSize;
-
- static const int kFileMagicOffset = 0;
- static const int kFileMetaDataOffset = kFileMagicSize;
-
- static const std::string kFileMagicValue;
-
- // Native file format version
- static const uint kFileFormatVersionMajor = 0;
- static const uint kFileFormatVersionMinor = 2;
- static const uint kFileFormatVersionRevision = 4;
};
extern FileFormat fileFormat;
diff --git a/common/nativefileformat.cpp b/common/nativefileformat.cpp
new file mode 100644
index 0000000..83e13ba
--- /dev/null
+++ b/common/nativefileformat.cpp
@@ -0,0 +1,470 @@
+/*
+Copyright (C) 2010, 2016 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
+*/
+
+#include "nativefileformat.h"
+
+#include "crc32c.h"
+
+#include
+#include
+#include
+
+#define tr(str) QObject::tr(str)
+
+const std::string NativeFileFormat::kFileMagicValue = "\xa7\xb7OSTINATO";
+
+static const int kBaseHex = 16;
+
+NativeFileFormat::NativeFileFormat()
+{
+ /*
+ * We don't have any "real" work to do here in the constructor.
+ * What we do is run some "assert" tests so that these get caught
+ * at init itself instead of while saving/restoring when a user
+ * might lose some data!
+ */
+ OstProto::FileMagic magic;
+ OstProto::FileChecksum cksum;
+
+ magic.set_value(kFileMagicValue);
+ cksum.set_value(quint32(0));
+
+ // TODO: convert Q_ASSERT to something that will run in RELEASE mode also
+ Q_ASSERT(magic.IsInitialized());
+ Q_ASSERT(cksum.IsInitialized());
+ Q_ASSERT(magic.ByteSize() == kFileMagicSize);
+ Q_ASSERT(cksum.ByteSize() == kFileChecksumSize);
+}
+
+bool NativeFileFormat::open(
+ const QString fileName,
+ OstProto::FileMeta &meta,
+ OstProto::FileContent &content,
+ QString &error)
+{
+ QFile file(fileName);
+ QByteArray buf;
+ int size, contentOffset, contentSize;
+ quint32 calcCksum;
+ OstProto::FileMagic magic;
+ OstProto::FileChecksum cksum, zeroCksum;
+
+ if (!file.open(QIODevice::ReadOnly))
+ goto _open_fail;
+
+ if (file.size() < kFileMagicSize)
+ goto _magic_missing;
+
+ if (file.size() < kFileMinSize)
+ goto _checksum_missing;
+
+ buf.resize(file.size());
+ size = file.read(buf.data(), buf.size());
+ if (size < 0)
+ goto _read_fail;
+
+ Q_ASSERT(file.atEnd());
+ file.close();
+
+ qDebug("%s: file.size() = %lld", __FUNCTION__, file.size());
+ qDebug("%s: size = %d", __FUNCTION__, size);
+
+ //qDebug("Read %d bytes", buf.size());
+ //qDebug("%s", QString(buf.toHex()).toAscii().constData());
+
+ // Parse and verify magic
+ if (!magic.ParseFromArray(
+ (void*)(buf.constData() + kFileMagicOffset),
+ kFileMagicSize))
+ {
+ goto _magic_parse_fail;
+ }
+ if (magic.value() != kFileMagicValue)
+ goto _magic_match_fail;
+
+ // Parse and verify checksum
+ if (!cksum.ParseFromArray(
+ (void*)(buf.constData() + size - kFileChecksumSize),
+ kFileChecksumSize))
+ {
+ goto _cksum_parse_fail;
+ }
+
+ zeroCksum.set_value(0);
+ if (!zeroCksum.SerializeToArray(
+ (void*) (buf.data() + size - kFileChecksumSize),
+ kFileChecksumSize))
+ {
+ goto _zero_cksum_serialize_fail;
+ }
+
+ calcCksum = checksumCrc32C((quint8*) buf.constData(), size);
+
+ qDebug("checksum \nExpected:%x Actual:%x",
+ calcCksum, cksum.value());
+
+ if (cksum.value() != calcCksum)
+ goto _cksum_verify_fail;
+
+ // Parse the metadata first before we parse the full contents
+ // FIXME: metadata size is not known beforehand, so we end up
+ // parsing till EOF
+ if (!meta.ParseFromArray(
+ (void*)(buf.constData() + kFileMetaDataOffset),
+ size - kFileMetaDataOffset))
+ {
+ goto _metadata_parse_fail;
+ }
+
+ qDebug("%s: File MetaData (INFORMATION) - \n%s", __FUNCTION__,
+ QString().fromStdString(meta.DebugString()).toAscii().constData());
+ qDebug("%s: END MetaData", __FUNCTION__);
+
+ // MetaData Validation(s)
+ if (meta.data().file_type() != OstProto::kStreamsFileType)
+ goto _unexpected_file_type;
+
+ if (meta.data().format_version_major() != kFileFormatVersionMajor)
+ goto _incompatible_file_version;
+
+ if (meta.data().format_version_minor() > kFileFormatVersionMinor)
+ goto _incompatible_file_version;
+
+ if (meta.data().format_version_minor() < kFileFormatVersionMinor)
+ {
+ // TODO: need to modify 'buf' such that we can parse successfully
+ // assuming the native minor version
+ }
+
+ if (meta.data().format_version_revision() > kFileFormatVersionRevision)
+ {
+ error = QString(tr("%1 was created using a newer version of Ostinato."
+ " New features/protocols will not be available.")).arg(fileName);
+ }
+
+ Q_ASSERT(meta.data().format_version_major() == kFileFormatVersionMajor);
+
+ // ByteSize() does not include the Tag/Key, so we add 2 for that
+ contentOffset = kFileMetaDataOffset + meta.data().ByteSize() + 2;
+ contentSize = size - contentOffset - kFileChecksumSize;
+ qDebug("%s: content offset/size = %d/%d", __FUNCTION__,
+ contentOffset, contentSize);
+
+ // Parse full contents
+ if (!content.ParseFromArray(
+ (void*)(buf.constData() + contentOffset),
+ contentSize))
+ {
+ goto _content_parse_fail;
+ }
+
+ return true;
+
+_content_parse_fail:
+ error = QString(tr("Failed parsing %1 contents")).arg(fileName);
+ qDebug("Error: %s", QString().fromStdString(
+ content.InitializationErrorString())
+ .toAscii().constData());
+ qDebug("Debug: %s", QString().fromStdString(
+ content.DebugString()).toAscii().constData());
+ goto _fail;
+_incompatible_file_version:
+ error = QString(tr("%1 is in an incompatible format version - %2.%3.%4"
+ " (Native version is %5.%6.%7)"))
+ .arg(fileName)
+ .arg(meta.data().format_version_major())
+ .arg(meta.data().format_version_minor())
+ .arg(meta.data().format_version_revision())
+ .arg(kFileFormatVersionMajor)
+ .arg(kFileFormatVersionMinor)
+ .arg(kFileFormatVersionRevision);
+ goto _fail;
+_unexpected_file_type:
+ error = QString(tr("%1 is not a streams file")).arg(fileName);
+ goto _fail;
+_metadata_parse_fail:
+ error = QString(tr("Failed parsing %1 meta data")).arg(fileName);
+ qDebug("Error: %s", QString().fromStdString(
+ meta.data().InitializationErrorString())
+ .toAscii().constData());
+ goto _fail;
+_cksum_verify_fail:
+ error = QString(tr("%1 checksum validation failed!\nExpected:%2 Actual:%3"))
+ .arg(fileName)
+ .arg(calcCksum, 0, kBaseHex)
+ .arg(cksum.value(), 0, kBaseHex);
+ goto _fail;
+_zero_cksum_serialize_fail:
+ error = QString(tr("Internal Error: Zero Checksum Serialize failed!\n"
+ "Error: %1\nDebug: %2"))
+ .arg(QString().fromStdString(
+ cksum.InitializationErrorString()))
+ .arg(QString().fromStdString(cksum.DebugString()));
+ goto _fail;
+_cksum_parse_fail:
+ error = QString(tr("Failed parsing %1 checksum")).arg(fileName);
+ qDebug("Error: %s", QString().fromStdString(
+ cksum.InitializationErrorString())
+ .toAscii().constData());
+ goto _fail;
+_magic_match_fail:
+ error = QString(tr("%1 is not an Ostinato file")).arg(fileName);
+ goto _fail;
+_magic_parse_fail:
+ error = QString(tr("%1 does not look like an Ostinato file")).arg(fileName);
+ qDebug("Error: %s", QString().fromStdString(
+ magic.InitializationErrorString())
+ .toAscii().constData());
+ goto _fail;
+_read_fail:
+ error = QString(tr("Error reading from %1")).arg(fileName);
+ goto _fail;
+_checksum_missing:
+ error = QString(tr("%1 is too small (missing checksum)")).arg(fileName);
+ goto _fail;
+_magic_missing:
+ error = QString(tr("%1 is too small (missing magic value)"))
+ .arg(fileName);
+ goto _fail;
+_open_fail:
+ error = QString(tr("Error opening %1")).arg(fileName);
+ goto _fail;
+_fail:
+ qDebug("%s", error.toAscii().constData());
+ return false;
+}
+
+bool NativeFileFormat::save(
+ OstProto::FileType fileType,
+ const OstProto::FileContent &content,
+ const QString fileName,
+ QString &error)
+{
+ OstProto::FileMagic magic;
+ OstProto::FileMeta meta;
+ OstProto::FileChecksum cksum;
+ QFile file(fileName);
+ int metaSize, contentSize;
+ int contentOffset, cksumOffset;
+ QByteArray buf;
+ quint32 calcCksum;
+
+ magic.set_value(kFileMagicValue);
+ Q_ASSERT(magic.IsInitialized());
+
+ cksum.set_value(0);
+ Q_ASSERT(cksum.IsInitialized());
+
+ initFileMetaData(*(meta.mutable_data()));
+ meta.mutable_data()->set_file_type(fileType);
+ Q_ASSERT(meta.IsInitialized());
+
+ if (!content.IsInitialized())
+ goto _content_not_init;
+
+ Q_ASSERT(content.IsInitialized());
+
+ metaSize = meta.ByteSize();
+ contentSize = content.ByteSize();
+ contentOffset = kFileMetaDataOffset + metaSize;
+ cksumOffset = contentOffset + contentSize;
+
+ Q_ASSERT(magic.ByteSize() == kFileMagicSize);
+ Q_ASSERT(cksum.ByteSize() == kFileChecksumSize);
+ buf.resize(kFileMagicSize + metaSize + contentSize + kFileChecksumSize);
+
+ // Serialize everything
+ if (!magic.SerializeToArray((void*) (buf.data() + kFileMagicOffset),
+ kFileMagicSize))
+ {
+ goto _magic_serialize_fail;
+ }
+
+ if (!meta.SerializeToArray((void*) (buf.data() + kFileMetaDataOffset),
+ metaSize))
+ {
+ goto _meta_serialize_fail;
+ }
+
+ if (!content.SerializeToArray((void*) (buf.data() + contentOffset),
+ contentSize))
+ {
+ goto _content_serialize_fail;
+ }
+
+ if (!cksum.SerializeToArray((void*) (buf.data() + cksumOffset),
+ kFileChecksumSize))
+ {
+ goto _zero_cksum_serialize_fail;
+ }
+
+ // TODO: emit status("Calculating checksum...");
+
+ // Calculate and write checksum
+ calcCksum = checksumCrc32C((quint8*)buf.constData(), buf.size());
+ cksum.set_value(calcCksum);
+ if (!cksum.SerializeToArray(
+ (void*) (buf.data() + cksumOffset),
+ kFileChecksumSize))
+ {
+ goto _cksum_serialize_fail;
+ }
+
+ qDebug("Writing %d bytes", buf.size());
+ //qDebug("%s", QString(buf.toHex()).toAscii().constData());
+
+ // TODO: emit status("Writing to disk...");
+ if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate))
+ goto _open_fail;
+
+ if (file.write(buf) < 0)
+ goto _write_fail;
+
+ file.close();
+
+ return true;
+
+_write_fail:
+ error = QString(tr("Error writing to %1")).arg(fileName);
+ goto _fail;
+_open_fail:
+ error = QString(tr("Error opening %1 (Error Code = %2)"))
+ .arg(fileName)
+ .arg(file.error());
+ goto _fail;
+_cksum_serialize_fail:
+ error = QString(tr("Internal Error: Checksum Serialize failed\n%1\n%2"))
+ .arg(QString().fromStdString(
+ cksum.InitializationErrorString()))
+ .arg(QString().fromStdString(cksum.DebugString()));
+ goto _fail;
+_zero_cksum_serialize_fail:
+ error = QString(tr("Internal Eror: Zero Checksum Serialize failed\n%1\n%2"))
+ .arg(QString().fromStdString(
+ cksum.InitializationErrorString()))
+ .arg(QString().fromStdString(cksum.DebugString()));
+ goto _fail;
+_content_serialize_fail:
+ error = QString(tr("Internal Error: Content Serialize failed\n%1\n%2"))
+ .arg(QString().fromStdString(
+ content.InitializationErrorString()))
+ .arg(QString().fromStdString(content.DebugString()));
+ goto _fail;
+_meta_serialize_fail:
+ error = QString(tr("Internal Error: Meta Data Serialize failed\n%1\n%2"))
+ .arg(QString().fromStdString(
+ meta.InitializationErrorString()))
+ .arg(QString().fromStdString(meta.DebugString()));
+ goto _fail;
+_magic_serialize_fail:
+ error = QString(tr("Internal Error: Magic Serialize failed\n%1\n%2"))
+ .arg(QString().fromStdString(
+ magic.InitializationErrorString()))
+ .arg(QString().fromStdString(magic.DebugString()));
+ goto _fail;
+_content_not_init:
+ error = QString(tr("Internal Error: Content not initialized\n%1\n%2"))
+ .arg(QString().fromStdString(
+ content.InitializationErrorString()))
+ .arg(QString().fromStdString(content.DebugString()));
+ goto _fail;
+_fail:
+ qDebug("%s", error.toAscii().constData());
+ return false;
+}
+
+bool NativeFileFormat::isNativeFileFormat(
+ const QString fileName,
+ OstProto::FileType fileType)
+{
+ 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;
+
+ // TODO: check fileType
+
+_close_exit:
+ file.close();
+_exit:
+ return ret;
+}
+
+void NativeFileFormat::initFileMetaData(OstProto::FileMetaData &metaData)
+{
+ // 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(
+ qApp->applicationName().toUtf8().constData());
+ metaData.set_generator_version(
+ qApp->property("version").toString().toUtf8().constData());
+ metaData.set_generator_revision(
+ qApp->property("revision").toString().toUtf8().constData());
+}
+
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+/*! Fixup content to what is expected in the native version */
+void NativeFileFormat::postParseFixup(OstProto::FileMetaData metaData,
+ OstProto::FileContent &content)
+{
+ Q_ASSERT(metaData.format_version_major() == kFileFormatVersionMajor);
+
+ // Do fixups from oldest to newest versions
+ switch (metaData.format_version_minor())
+ {
+ case 1:
+ {
+ int n = content.matter().streams().stream_size();
+ for (int i = 0; i < n; i++)
+ {
+ OstProto::StreamControl *sctl =
+ content.mutable_matter()->mutable_streams()->mutable_stream(i)->mutable_control();
+ sctl->set_packets_per_sec(sctl->obsolete_packets_per_sec());
+ sctl->set_bursts_per_sec(sctl->obsolete_bursts_per_sec());
+ }
+
+ // fall-through to next higher version until native version
+ }
+ case kFileFormatVersionMinor: // native version
+ break;
+
+ case 0:
+ default:
+ qWarning("%s: minor version %u unhandled", __FUNCTION__,
+ metaData.format_version_minor());
+ Q_ASSERT_X(false, "postParseFixup", "unhandled minor version");
+ }
+
+}
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+
diff --git a/common/nativefileformat.h b/common/nativefileformat.h
new file mode 100644
index 0000000..fb49fc8
--- /dev/null
+++ b/common/nativefileformat.h
@@ -0,0 +1,75 @@
+/*
+Copyright (C) 2010, 2016 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
+*/
+#ifndef _NATIVE_FILE_FORMAT_H
+#define _NATIVE_FILE_FORMAT_H
+
+/*
+ * This file contains helper functions for the native file format
+ * defined in fileformat.proto
+ *
+ * The actual file format classes - (Ostm)FileFormat and OssnFileFormat
+ * use multiple inheritance from the abstract interface class and this
+ * helper class
+ *
+ * The primary reason for the existence of this class is to have a common
+ * code for dealing with native file formats
+ */
+
+#include "fileformat.pb.h"
+
+#include
+
+class NativeFileFormat
+{
+public:
+ NativeFileFormat();
+
+ bool open(const QString fileName,
+ OstProto::FileMeta &meta,
+ OstProto::FileContent &content,
+ QString &error);
+ bool save(OstProto::FileType fileType,
+ const OstProto::FileContent &content,
+ const QString fileName,
+ QString &error);
+
+ bool isNativeFileFormat(const QString fileName,
+ OstProto::FileType fileType);
+ void postParseFixup(OstProto::FileMetaData metaData,
+ OstProto::FileContent &content);
+
+private:
+ void initFileMetaData(OstProto::FileMetaData &metaData);
+
+ static const int kFileMagicSize = 12;
+ static const int kFileChecksumSize = 5;
+ static const int kFileMinSize = kFileMagicSize + kFileChecksumSize;
+
+ static const int kFileMagicOffset = 0;
+ static const int kFileMetaDataOffset = kFileMagicSize;
+
+ static const std::string kFileMagicValue;
+
+ // Native file format version
+ static const uint kFileFormatVersionMajor = 0;
+ static const uint kFileFormatVersionMinor = 2;
+ static const uint kFileFormatVersionRevision = 4;
+};
+
+#endif
diff --git a/common/ossnfileformat.cpp b/common/ossnfileformat.cpp
new file mode 100644
index 0000000..ed6ebc2
--- /dev/null
+++ b/common/ossnfileformat.cpp
@@ -0,0 +1,46 @@
+/*
+Copyright (C) 2016 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
+*/
+
+#include "ossnfileformat.h"
+
+bool OssnFileFormat::open(const QString fileName,
+ OstProto::SessionContent &session, QString &error)
+{
+ // TODO
+ return false;
+}
+
+bool OssnFileFormat::save(const OstProto::SessionContent &session,
+ const QString fileName, QString &error)
+{
+ // TODO
+ return false;
+}
+
+bool OssnFileFormat::isMyFileFormat(const QString fileName)
+{
+ // TODO
+ return true;
+}
+
+bool OssnFileFormat::isMyFileType(const QString fileType)
+{
+ // TODO
+ return true;
+}
diff --git a/common/ossnfileformat.h b/common/ossnfileformat.h
new file mode 100644
index 0000000..73eb5a8
--- /dev/null
+++ b/common/ossnfileformat.h
@@ -0,0 +1,40 @@
+/*
+Copyright (C) 2016 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
+*/
+
+#ifndef _OSSN_FILE_FORMAT_H
+#define _OSSN_FILE_FORMAT_H
+
+#include "sessionfileformat.h"
+
+class OssnFileFormat : public SessionFileFormat
+{
+public:
+ virtual bool open(const QString fileName,
+ OstProto::SessionContent &session, QString &error);
+ virtual bool save(const OstProto::SessionContent &session,
+ const QString fileName, QString &error);
+
+ virtual bool isMyFileFormat(const QString fileName);
+ virtual bool isMyFileType(const QString fileType);
+};
+
+extern OssnFileFormat ossnFileFormat;
+
+#endif
+
diff --git a/common/ostprotogui.pro b/common/ostprotogui.pro
index b39526e..44f1061 100644
--- a/common/ostprotogui.pro
+++ b/common/ostprotogui.pro
@@ -39,12 +39,15 @@ HEADERS = \
fileformat.h \
ipv4addressdelegate.h \
ipv6addressdelegate.h \
+ nativefileformat.h \
+ ossnfileformat.h \
pcapfileformat.h \
pdmlfileformat.h \
pythonfileformat.h \
pdmlprotocol.h \
pdmlprotocols.h \
pdmlreader.h \
+ sessionfileformat.h \
spinboxdelegate.h
HEADERS += \
@@ -82,12 +85,15 @@ SOURCES += \
ostprotolib.cpp \
abstractfileformat.cpp \
fileformat.cpp \
+ nativefileformat.cpp \
+ ossnfileformat.cpp \
pcapfileformat.cpp \
pdmlfileformat.cpp \
pythonfileformat.cpp \
pdmlprotocol.cpp \
pdmlprotocols.cpp \
pdmlreader.cpp \
+ sessionfileformat.cpp \
spinboxdelegate.cpp
SOURCES += \
diff --git a/common/sessionfileformat.cpp b/common/sessionfileformat.cpp
new file mode 100644
index 0000000..644b956
--- /dev/null
+++ b/common/sessionfileformat.cpp
@@ -0,0 +1,111 @@
+/*
+Copyright (C) 2016 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
+*/
+
+#include "sessionfileformat.h"
+
+#include "ossnfileformat.h"
+
+#include
+
+SessionFileFormat::SessionFileFormat()
+{
+ stop_ = false;
+}
+
+SessionFileFormat::~SessionFileFormat()
+{
+}
+
+QDialog* SessionFileFormat::openOptionsDialog()
+{
+ return NULL;
+}
+
+QDialog* SessionFileFormat::saveOptionsDialog()
+{
+ return NULL;
+}
+
+QStringList SessionFileFormat::supportedFileTypes()
+{
+ return QStringList()
+ << "Ostinato Session (*.ossn)";
+}
+
+void SessionFileFormat::openOffline(const QString fileName,
+ OstProto::SessionContent &session, QString &error)
+{
+ fileName_ = fileName;
+ openSession_ = &session;
+ error_ = &error;
+ op_ = kOpen;
+ stop_ = false;
+
+ start();
+}
+
+void SessionFileFormat::saveOffline(
+ const OstProto::SessionContent &session,
+ const QString fileName, QString &error)
+{
+ saveSession_ = &session;
+ fileName_ = fileName;
+ error_ = &error;
+ op_ = kSave;
+ stop_ = false;
+
+ start();
+}
+
+bool SessionFileFormat::result()
+{
+ return result_;
+}
+
+SessionFileFormat* SessionFileFormat::fileFormatFromFile(
+ const QString fileName)
+{
+ if (ossnFileFormat.isMyFileFormat(fileName))
+ return &ossnFileFormat;
+
+ return NULL;
+}
+
+SessionFileFormat* SessionFileFormat::fileFormatFromType(
+ const QString fileType)
+{
+
+ if (ossnFileFormat.isMyFileType(fileType))
+ return &ossnFileFormat;
+
+ return NULL;
+}
+
+void SessionFileFormat::cancel()
+{
+ stop_ = true;
+}
+
+void SessionFileFormat::run()
+{
+ if (op_ == kOpen)
+ result_ = open(fileName_, *openSession_, *error_);
+ else if (op_ == kSave)
+ result_ = save(*saveSession_, fileName_, *error_);
+}
diff --git a/common/sessionfileformat.h b/common/sessionfileformat.h
new file mode 100644
index 0000000..0146324
--- /dev/null
+++ b/common/sessionfileformat.h
@@ -0,0 +1,90 @@
+/*
+Copyright (C) 2016 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
+*/
+
+#ifndef _SESSION_FILE_FORMAT_H
+#define _SESSION_FILE_FORMAT_H
+
+#include "fileformat.pb.h"
+#include "protocol.pb.h"
+
+#include
+#include
+
+class QDialog;
+
+class SessionFileFormat : public QThread
+{
+ Q_OBJECT
+public:
+ SessionFileFormat();
+ virtual ~SessionFileFormat();
+
+ virtual bool open(const QString fileName,
+ OstProto::SessionContent &session, QString &error) = 0;
+ virtual bool save(const OstProto::SessionContent &session,
+ const QString fileName, QString &error) = 0;
+
+ virtual QDialog* openOptionsDialog();
+ virtual QDialog* saveOptionsDialog();
+
+ void openOffline(const QString fileName,
+ OstProto::SessionContent &session, QString &error);
+ void saveOffline(const OstProto::SessionContent &session,
+ const QString fileName, QString &error);
+
+ bool result();
+
+ static QStringList supportedFileTypes();
+
+ static SessionFileFormat* fileFormatFromFile(const QString fileName);
+ static SessionFileFormat* fileFormatFromType(const QString fileType);
+
+ virtual bool isMyFileFormat(const QString fileName) = 0;
+ virtual bool isMyFileType(const QString fileType) = 0;
+
+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::SessionContent *openSession_;
+ const OstProto::SessionContent *saveSession_;
+ QString *error_;
+ kOp op_;
+ bool result_;
+
+};
+
+#endif
+