Added streams save/restore; Ostinato file format specified; Protocol Field Numbering scheme changed - existing protocol field numbers changed accordingly
This commit is contained in:
parent
2e6503faad
commit
c2fac2db70
@ -24,6 +24,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#include <QFile>
|
||||
#include <QSettings>
|
||||
|
||||
extern const char* version;
|
||||
extern const char* revision;
|
||||
extern ProtocolManager *OstProtocolManager;
|
||||
|
||||
QSettings *appSettings;
|
||||
@ -34,6 +36,11 @@ int main(int argc, char* argv[])
|
||||
QApplication app(argc, argv);
|
||||
int exitCode;
|
||||
|
||||
app.setApplicationName("Ostinato");
|
||||
app.setOrganizationName("Ostinato");
|
||||
app.setProperty("version", version);
|
||||
app.setProperty("revision", revision);
|
||||
|
||||
OstProtocolManager = new ProtocolManager();
|
||||
|
||||
/* (Portable Mode) If we have a .ini file in the same directory as the
|
||||
@ -44,7 +51,7 @@ int main(int argc, char* argv[])
|
||||
if (QFile::exists(portableIni))
|
||||
appSettings = new QSettings(portableIni, QSettings::IniFormat);
|
||||
else
|
||||
appSettings = new QSettings("Ostinato", "Ostinato");
|
||||
appSettings = new QSettings();
|
||||
|
||||
mainWindow = new MainWindow;
|
||||
mainWindow->show();
|
||||
|
@ -17,12 +17,14 @@ 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 <vector>
|
||||
|
||||
#include <google/protobuf/descriptor.h>
|
||||
|
||||
#include "port.h"
|
||||
#include "pbhelper.h"
|
||||
|
||||
#include "fileformat.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QVariant>
|
||||
#include <google/protobuf/descriptor.h>
|
||||
#include <vector>
|
||||
|
||||
uint Port::mAllocStreamId = 0;
|
||||
|
||||
@ -218,3 +220,43 @@ void Port::updateStats(OstProto::PortStats *portStats)
|
||||
}
|
||||
}
|
||||
|
||||
bool Port::openStreams(QString fileName, bool append, QString &error)
|
||||
{
|
||||
OstProto::StreamConfigList streams;
|
||||
|
||||
if (!fileFormat.openStreams(fileName, streams, error))
|
||||
goto _fail;
|
||||
|
||||
if (!append)
|
||||
{
|
||||
while (numStreams())
|
||||
deleteStreamAt(0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < streams.stream_size(); i++)
|
||||
{
|
||||
newStreamAt(mStreams.size());
|
||||
streamByIndex(mStreams.size()-1)->protoDataCopyFrom(streams.stream(i));
|
||||
}
|
||||
|
||||
emit streamListChanged(mPortGroupId, mPortId);
|
||||
|
||||
return true;
|
||||
|
||||
_fail:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Port::saveStreams(QString fileName, QString &error)
|
||||
{
|
||||
OstProto::StreamConfigList streams;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
return fileFormat.saveStreams(streams, fileName, error);
|
||||
}
|
||||
|
@ -114,13 +114,16 @@ public:
|
||||
void getModifiedStreamsSinceLastSync(
|
||||
OstProto::StreamConfigList &streamConfigList);
|
||||
|
||||
|
||||
void when_syncComplete();
|
||||
|
||||
void updateStats(OstProto::PortStats *portStats);
|
||||
|
||||
bool openStreams(QString fileName, bool append, QString &error);
|
||||
bool saveStreams(QString fileName, QString &error);
|
||||
|
||||
signals:
|
||||
void portDataChanged(int portGroupId, int portId);
|
||||
void streamListChanged(int portGroupId, int portId);
|
||||
|
||||
};
|
||||
|
||||
|
@ -29,6 +29,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
{
|
||||
QAction *sep;
|
||||
|
||||
delegate = new StreamListDelegate;
|
||||
//slm = new StreamListModel();
|
||||
//plm = new PortGroupList();
|
||||
@ -43,7 +45,7 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
tvStreamList->verticalHeader()->setDefaultSectionSize(
|
||||
tvStreamList->verticalHeader()->minimumSectionSize());
|
||||
|
||||
// Populate Context Menu Actions
|
||||
// Populate PortList Context Menu Actions
|
||||
tvPortList->addAction(actionNew_Port_Group);
|
||||
tvPortList->addAction(actionDelete_Port_Group);
|
||||
tvPortList->addAction(actionConnect_Port_Group);
|
||||
@ -51,12 +53,21 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
|
||||
tvPortList->addAction(actionExclusive_Control);
|
||||
|
||||
// Populate StramList Context Menu Actions
|
||||
tvStreamList->addAction(actionNew_Stream);
|
||||
tvStreamList->addAction(actionEdit_Stream);
|
||||
tvStreamList->addAction(actionDelete_Stream);
|
||||
|
||||
sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
tvStreamList->addAction(sep);
|
||||
|
||||
tvStreamList->addAction(actionOpen_Streams);
|
||||
tvStreamList->addAction(actionSave_Streams);
|
||||
|
||||
// PortList and StreamList actions combined make this window's actions
|
||||
addActions(tvPortList->actions());
|
||||
QAction *sep = new QAction(this);
|
||||
sep = new QAction(this);
|
||||
sep->setSeparator(true);
|
||||
addAction(sep);
|
||||
addActions(tvStreamList->actions());
|
||||
@ -77,26 +88,24 @@ PortsWindow::PortsWindow(PortGroupList *pgl, QWidget *parent)
|
||||
this, SLOT(when_portView_currentChanged(const QModelIndex&,
|
||||
const QModelIndex&)));
|
||||
|
||||
connect( tvStreamList->selectionModel(),
|
||||
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
|
||||
this, SLOT(when_streamView_currentChanged(const QModelIndex&,
|
||||
const QModelIndex&)));
|
||||
connect( tvStreamList->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
this, SLOT(when_streamView_selectionChanged()));
|
||||
connect(plm->getStreamModel(), SIGNAL(rowsInserted(QModelIndex, int, int)),
|
||||
SLOT(updateStreamViewActions()));
|
||||
connect(plm->getStreamModel(), SIGNAL(rowsRemoved(QModelIndex, int, int)),
|
||||
SLOT(updateStreamViewActions()));
|
||||
|
||||
#if 0
|
||||
connect( tvPortList->selectionModel(),
|
||||
connect(tvStreamList->selectionModel(),
|
||||
SIGNAL(currentChanged(const QModelIndex&, const QModelIndex&)),
|
||||
plm->getStreamModel(), SLOT(setCurrentPortIndex(const QModelIndex&)));
|
||||
#endif
|
||||
SLOT(updateStreamViewActions()));
|
||||
connect(tvStreamList->selectionModel(),
|
||||
SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection&)),
|
||||
SLOT(updateStreamViewActions()));
|
||||
|
||||
tvStreamList->resizeColumnToContents(StreamModel::StreamIcon);
|
||||
tvStreamList->resizeColumnToContents(StreamModel::StreamStatus);
|
||||
|
||||
// Initially we don't have any ports/streams - so send signal triggers
|
||||
when_portView_currentChanged(QModelIndex(), QModelIndex());
|
||||
when_streamView_currentChanged(QModelIndex(), QModelIndex());
|
||||
updateStreamViewActions();
|
||||
|
||||
//! \todo Hide the Aggregate Box till we add support
|
||||
frAggregate->setHidden(true);
|
||||
@ -148,19 +157,6 @@ void PortsWindow::when_portView_currentChanged(const QModelIndex& current,
|
||||
}
|
||||
}
|
||||
|
||||
void PortsWindow::when_streamView_currentChanged(const QModelIndex& /*current*/,
|
||||
const QModelIndex& /*previous*/)
|
||||
{
|
||||
qDebug("stream view current changed");
|
||||
updateStreamViewActions();
|
||||
}
|
||||
|
||||
void PortsWindow::when_streamView_selectionChanged()
|
||||
{
|
||||
qDebug("stream view selection changed");
|
||||
updateStreamViewActions();
|
||||
}
|
||||
|
||||
void PortsWindow::when_portModel_dataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight)
|
||||
{
|
||||
@ -182,16 +178,6 @@ void PortsWindow::when_portModel_reset()
|
||||
when_portView_currentChanged(QModelIndex(), tvPortList->currentIndex());
|
||||
}
|
||||
|
||||
#if 0
|
||||
void PortsWindow::updateStreamViewActions(const QModelIndex& current)
|
||||
{
|
||||
if (current.isValid())
|
||||
actionDelete_Stream->setEnabled(true);
|
||||
else
|
||||
actionDelete_Stream->setDisabled(true);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PortsWindow::updateStreamViewActions()
|
||||
{
|
||||
// For some reason hasSelection() returns true even if selection size is 0
|
||||
@ -233,6 +219,9 @@ void PortsWindow::updateStreamViewActions()
|
||||
actionEdit_Stream->setDisabled(true);
|
||||
actionDelete_Stream->setDisabled(true);
|
||||
}
|
||||
actionOpen_Streams->setEnabled(plm->isPort(
|
||||
tvPortList->selectionModel()->currentIndex()));
|
||||
actionSave_Streams->setEnabled(tvStreamList->model()->rowCount() > 0);
|
||||
}
|
||||
|
||||
void PortsWindow::updatePortViewActions(const QModelIndex& current)
|
||||
@ -406,26 +395,6 @@ void PortsWindow::on_actionExclusive_Control_triggered(bool checked)
|
||||
plm->portGroup(current.parent()).modifyPort(current.row(), checked);
|
||||
}
|
||||
|
||||
#if 0
|
||||
void PortsWindow::on_actionNew_Stream_triggered()
|
||||
{
|
||||
qDebug("New Stream Action");
|
||||
|
||||
int row = 0;
|
||||
|
||||
if (tvStreamList->currentIndex().isValid())
|
||||
row = tvStreamList->currentIndex().row();
|
||||
plm->getStreamModel()->insertRows(row, 1);
|
||||
}
|
||||
|
||||
void PortsWindow::on_actionDelete_Stream_triggered()
|
||||
{
|
||||
qDebug("Delete Stream Action");
|
||||
if (tvStreamList->currentIndex().isValid())
|
||||
plm->getStreamModel()->removeRows(tvStreamList->currentIndex().row(), 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void PortsWindow::on_actionNew_Stream_triggered()
|
||||
{
|
||||
qDebug("New Stream Action");
|
||||
@ -477,4 +446,73 @@ void PortsWindow::on_actionDelete_Stream_triggered()
|
||||
qDebug("No selection");
|
||||
}
|
||||
|
||||
void PortsWindow::on_actionOpen_Streams_triggered()
|
||||
{
|
||||
qDebug("Open Streams Action");
|
||||
|
||||
QModelIndex current = tvPortList->selectionModel()->currentIndex();
|
||||
QString fileName;
|
||||
QString errorStr;
|
||||
bool append = true;
|
||||
|
||||
Q_ASSERT(plm->isPort(current));
|
||||
|
||||
fileName = QFileDialog::getOpenFileName(this, tr("Open Streams"));
|
||||
if (fileName.isEmpty())
|
||||
goto _exit;
|
||||
|
||||
if (tvStreamList->model()->rowCount())
|
||||
{
|
||||
QMessageBox msgBox(QMessageBox::Question, qApp->applicationName(),
|
||||
tr("Append to existing streams? Or overwrite?"));
|
||||
QPushButton *appendBtn = msgBox.addButton(tr("Append"),
|
||||
QMessageBox::ActionRole);
|
||||
QPushButton *overwriteBtn = msgBox.addButton(tr("Overwrite"),
|
||||
QMessageBox::ActionRole);
|
||||
QPushButton *cancelBtn = msgBox.addButton(QMessageBox::Cancel);
|
||||
|
||||
msgBox.exec();
|
||||
|
||||
if (msgBox.clickedButton() == cancelBtn)
|
||||
goto _exit;
|
||||
else if (msgBox.clickedButton() == appendBtn)
|
||||
append = true;
|
||||
else if (msgBox.clickedButton() == overwriteBtn)
|
||||
append = false;
|
||||
else
|
||||
Q_ASSERT(false);
|
||||
}
|
||||
|
||||
if (!plm->port(current).openStreams(fileName, append, errorStr))
|
||||
QMessageBox::critical(this, qApp->applicationName(), errorStr);
|
||||
else if (!errorStr.isEmpty())
|
||||
QMessageBox::warning(this, qApp->applicationName(), errorStr);
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void PortsWindow::on_actionSave_Streams_triggered()
|
||||
{
|
||||
qDebug("Save Streams Action");
|
||||
|
||||
QModelIndex current = tvPortList->selectionModel()->currentIndex();
|
||||
QString fileName;
|
||||
QString errorStr;
|
||||
|
||||
Q_ASSERT(plm->isPort(current));
|
||||
|
||||
fileName = QFileDialog::getSaveFileName(this, tr("Save Streams"));
|
||||
if (fileName.isEmpty())
|
||||
goto _exit;
|
||||
|
||||
// TODO: all or selected?
|
||||
|
||||
if (!plm->port(current).saveStreams(fileName, errorStr))
|
||||
QMessageBox::critical(this, qApp->applicationName(), errorStr);
|
||||
else if (!errorStr.isEmpty())
|
||||
QMessageBox::warning(this, qApp->applicationName(), errorStr);
|
||||
_exit:
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
@ -48,17 +48,13 @@ private:
|
||||
QString lastNewPortGroup;
|
||||
QAbstractItemDelegate *delegate;
|
||||
|
||||
private slots:
|
||||
void updatePortViewActions(const QModelIndex& current);
|
||||
//void updateStreamViewActions(const QModelIndex& current);
|
||||
void updateStreamViewActions();
|
||||
|
||||
private slots:
|
||||
void on_tvStreamList_activated(const QModelIndex & index);
|
||||
void when_portView_currentChanged(const QModelIndex& current,
|
||||
const QModelIndex& previous);
|
||||
void when_streamView_currentChanged(const QModelIndex& current,
|
||||
const QModelIndex& previous);
|
||||
void when_streamView_selectionChanged();
|
||||
void when_portModel_dataChanged(const QModelIndex& topLeft,
|
||||
const QModelIndex& bottomRight);
|
||||
void when_portModel_reset();
|
||||
@ -75,6 +71,9 @@ private slots:
|
||||
void on_actionNew_Stream_triggered();
|
||||
void on_actionEdit_Stream_triggered();
|
||||
void on_actionDelete_Stream_triggered();
|
||||
|
||||
void on_actionOpen_Streams_triggered();
|
||||
void on_actionSave_Streams_triggered();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -230,6 +230,16 @@
|
||||
<string>Exclusive Port Control (EXPERIMENTAL)</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionOpen_Streams" >
|
||||
<property name="text" >
|
||||
<string>Open Streams ...</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave_Streams" >
|
||||
<property name="text" >
|
||||
<string>Save Streams ...</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="ostinato.qrc" />
|
||||
|
@ -254,8 +254,30 @@ void StreamModel::setCurrentPortIndex(const QModelIndex ¤t)
|
||||
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;
|
||||
mCurrentPort = pgl->mPortGroups[pgl->indexOfPortGroup(pg)]->mPorts[current.row()];
|
||||
connect(mCurrentPort, SIGNAL(streamListChanged(int, int)),
|
||||
this, SLOT(when_mCurrentPort_streamListChanged(int, int)));
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
void StreamModel::when_mCurrentPort_streamListChanged(int portGroupId,
|
||||
int portId)
|
||||
{
|
||||
qDebug("In %s", __FUNCTION__);
|
||||
if (mCurrentPort)
|
||||
{
|
||||
if ((quint32(portGroupId) == mCurrentPort->portGroupId())
|
||||
&& (quint32(portId) == mCurrentPort->id()))
|
||||
reset();
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,8 @@ class StreamModel : public QAbstractTableModel
|
||||
public slots:
|
||||
void setCurrentPortIndex(const QModelIndex ¤t);
|
||||
|
||||
private slots:
|
||||
void when_mCurrentPort_streamListChanged(int portGroupId, int portId);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -63,5 +63,5 @@ message Arp {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Arp arp = 130;
|
||||
optional Arp arp = 300;
|
||||
}
|
||||
|
134
common/crc32c.cpp
Normal file
134
common/crc32c.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
Copyright (C) 2010 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/>
|
||||
*/
|
||||
|
||||
/*******************************************************************
|
||||
** IMPORTANT NOTE:
|
||||
** This code is from RFC 4960 Stream Control Transmission Protocol
|
||||
** It has been modified suitably while keeping the algorithm intact.
|
||||
********************************************************************/
|
||||
|
||||
#include "crc32c.h"
|
||||
|
||||
#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
|
||||
|
||||
quint32 crc_c[256] =
|
||||
{
|
||||
0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L,
|
||||
0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL,
|
||||
0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL,
|
||||
0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L,
|
||||
0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL,
|
||||
0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L,
|
||||
0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L,
|
||||
0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL,
|
||||
0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL,
|
||||
0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L,
|
||||
0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L,
|
||||
0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL,
|
||||
0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L,
|
||||
0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL,
|
||||
0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL,
|
||||
0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L,
|
||||
0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L,
|
||||
0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L,
|
||||
0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L,
|
||||
0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L,
|
||||
0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L,
|
||||
0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L,
|
||||
0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L,
|
||||
0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L,
|
||||
0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L,
|
||||
0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L,
|
||||
0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L,
|
||||
0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L,
|
||||
0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L,
|
||||
0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L,
|
||||
0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L,
|
||||
0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L,
|
||||
0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL,
|
||||
0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L,
|
||||
0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L,
|
||||
0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL,
|
||||
0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L,
|
||||
0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL,
|
||||
0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL,
|
||||
0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L,
|
||||
0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L,
|
||||
0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL,
|
||||
0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL,
|
||||
0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L,
|
||||
0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL,
|
||||
0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L,
|
||||
0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L,
|
||||
0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL,
|
||||
0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L,
|
||||
0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL,
|
||||
0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL,
|
||||
0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L,
|
||||
0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL,
|
||||
0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L,
|
||||
0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L,
|
||||
0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL,
|
||||
0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL,
|
||||
0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L,
|
||||
0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L,
|
||||
0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL,
|
||||
0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L,
|
||||
0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL,
|
||||
0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL,
|
||||
0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L,
|
||||
};
|
||||
|
||||
quint32 checksumCrc32C(quint8 *buffer, uint length)
|
||||
{
|
||||
uint i;
|
||||
quint32 crc32 = ~0L;
|
||||
quint32 result;
|
||||
quint8 byte0,byte1,byte2,byte3;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
CRC32C(crc32, buffer[i]);
|
||||
}
|
||||
|
||||
result = ~crc32;
|
||||
|
||||
/* result now holds the negated polynomial remainder;
|
||||
* since the table and algorithm is "reflected" [williams95].
|
||||
* That is, result has the same value as if we mapped the message
|
||||
* to a polynomial, computed the host-bit-order polynomial
|
||||
* remainder, performed final negation, then did an end-for-end
|
||||
* bit-reversal.
|
||||
* Note that a 32-bit bit-reversal is identical to four inplace
|
||||
* 8-bit reversals followed by an end-for-end byteswap.
|
||||
* In other words, the bytes of each bit are in the right order,
|
||||
* but the bytes have been byteswapped. So we now do an explicit
|
||||
* byteswap. On a little-endian machine, this byteswap and
|
||||
* the final ntohl cancel out and could be elided.
|
||||
*/
|
||||
|
||||
byte0 = result & 0xff;
|
||||
byte1 = (result>>8) & 0xff;
|
||||
byte2 = (result>>16) & 0xff;
|
||||
byte3 = (result>>24) & 0xff;
|
||||
crc32 = ((byte0 << 24) |
|
||||
(byte1 << 16) |
|
||||
(byte2 << 8) |
|
||||
byte3);
|
||||
return ( crc32 );
|
||||
}
|
23
common/crc32c.h
Normal file
23
common/crc32c.h
Normal file
@ -0,0 +1,23 @@
|
||||
/*
|
||||
Copyright (C) 2010 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 <QtGlobal>
|
||||
|
||||
quint32 checksumCrc32C(quint8 *buffer, uint length);
|
||||
|
@ -29,5 +29,5 @@ message Dot2Llc {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Dot2Llc dot2Llc = 127;
|
||||
optional Dot2Llc dot2Llc = 206;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message Dot2Snap {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Dot2Snap dot2Snap = 128;
|
||||
optional Dot2Snap dot2Snap = 207;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message Dot3 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Dot3 dot3 = 122;
|
||||
optional Dot3 dot3 = 201;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message Eth2 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Eth2 eth2 = 121;
|
||||
optional Eth2 eth2 = 200;
|
||||
}
|
||||
|
411
common/fileformat.cpp
Normal file
411
common/fileformat.cpp
Normal file
@ -0,0 +1,411 @@
|
||||
/*
|
||||
Copyright (C) 2010 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 "fileformat.h"
|
||||
|
||||
#include "crc32c.h"
|
||||
|
||||
#include <QApplication>
|
||||
#include <QFile>
|
||||
#include <QVariant>
|
||||
|
||||
#include <string>
|
||||
|
||||
const std::string FileFormat::kFileMagicValue = "\xa7\xb7OSTINATO";
|
||||
|
||||
FileFormat fileFormat;
|
||||
|
||||
const int kBaseHex = 16;
|
||||
|
||||
FileFormat::FileFormat()
|
||||
{
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
Q_ASSERT(meta.data().format_version_minor() == kFileFormatVersionMinor);
|
||||
|
||||
// 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 (!content.matter().has_streams())
|
||||
goto _missing_streams;
|
||||
|
||||
streams.CopyFrom(content.matter().streams());
|
||||
|
||||
return true;
|
||||
|
||||
_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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
content.mutable_matter()->mutable_streams()->CopyFrom(streams);
|
||||
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;
|
||||
}
|
||||
|
||||
// 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());
|
||||
|
||||
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(
|
||||
streams.InitializationErrorString()))
|
||||
.arg(QString().fromStdString(streams.DebugString()));
|
||||
goto _fail;
|
||||
_fail:
|
||||
qDebug("%s", error.toAscii().constData());
|
||||
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());
|
||||
}
|
||||
|
59
common/fileformat.h
Normal file
59
common/fileformat.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
Copyright (C) 2010 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_H
|
||||
#define _FILE_FORMAT_H
|
||||
|
||||
#include "fileformat.pb.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QObject>
|
||||
|
||||
class FileFormat : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
FileFormat();
|
||||
~FileFormat();
|
||||
|
||||
bool openStreams(const QString fileName,
|
||||
OstProto::StreamConfigList &streams, QString &error);
|
||||
bool saveStreams(const OstProto::StreamConfigList streams,
|
||||
const QString fileName, QString &error);
|
||||
|
||||
private:
|
||||
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 = 1;
|
||||
static const uint kFileFormatVersionRevision = 0;
|
||||
|
||||
void initFileMetaData(OstProto::FileMetaData &metaData);
|
||||
};
|
||||
|
||||
extern FileFormat fileFormat;
|
||||
|
||||
#endif
|
98
common/fileformat.proto
Normal file
98
common/fileformat.proto
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
Copyright (C) 2010 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;
|
||||
|
||||
enum FileType {
|
||||
kReservedFileType = 0;
|
||||
kStreamsFileType = 1;
|
||||
}
|
||||
|
||||
message FileMetaData {
|
||||
required FileType file_type = 1;
|
||||
required uint32 format_version_major = 2;
|
||||
required uint32 format_version_minor = 3;
|
||||
required uint32 format_version_revision = 4;
|
||||
required string generator_name = 5;
|
||||
required string generator_version = 6;
|
||||
required string generator_revision = 7;
|
||||
}
|
||||
|
||||
message FileContentMatter {
|
||||
optional StreamConfigList streams = 1;
|
||||
}
|
||||
|
||||
/*
|
||||
An Ostinato file is the binary encoding of the File message below
|
||||
STRICTLY in increasing order of field number for the top level fields
|
||||
|
||||
We do not use field number '1' for magic value because its encoded key
|
||||
is '0a' (LF or \n) which occurs commonly in text files. Checksum should
|
||||
be the last field, so top level field numbers greater than 15 are not
|
||||
permitted. We use 15 as the checksum field number because it is the
|
||||
largest field number that can fit in a 1-byte tag
|
||||
|
||||
The magic value is of a fixed length so that meta data has a fixed offset
|
||||
from the start in the encoded message.
|
||||
|
||||
Checksum is fixed length so that it is at a fixed negative offset from
|
||||
the end in the encoded message.
|
||||
|
||||
Because the protobuf serialization API does not _guarantee_
|
||||
strict ordering, so we define wrapper messages for each top level field
|
||||
and serialize the individual wrapper messages. The field numbers MUST
|
||||
be the same in 'File' and the wrapper messages
|
||||
*/
|
||||
message File {
|
||||
// FieldNumber 1 is reserved and MUST not be used!
|
||||
required bytes magic_value = 2;
|
||||
required FileMetaData meta_data = 3;
|
||||
optional FileContent content_matter = 9;
|
||||
required fixed32 checksum_value = 15;
|
||||
}
|
||||
|
||||
/*
|
||||
The magic value is 10 bytes - "\xa7\xb7OSTINATO"
|
||||
The 1st-2nd byte has the MSB set to avoid mixup with text files
|
||||
The 3rd-10th byte spell OSTINATO (duh!)
|
||||
|
||||
Encoded Size : Key(1) + Length(1) + Value(10) = 12 bytes
|
||||
Encoded Value: 120aa7b7 4f535449 4e41544f
|
||||
*/
|
||||
message FileMagic {
|
||||
required bytes value = 2;
|
||||
}
|
||||
|
||||
message FileMeta {
|
||||
required FileMetaData data = 3;
|
||||
}
|
||||
|
||||
message FileContent {
|
||||
optional FileContentMatter matter = 9;
|
||||
}
|
||||
|
||||
/*
|
||||
Encoded Size : Key(1) + Value(4) = 5 bytes
|
||||
Encoded Value: 7d xxXXxxXX
|
||||
*/
|
||||
message FileChecksum {
|
||||
required fixed32 value = 15; // should always be a fixed 32-bit size
|
||||
}
|
@ -40,5 +40,5 @@ message Icmp {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Icmp icmp = 142;
|
||||
optional Icmp icmp = 402;
|
||||
}
|
||||
|
@ -61,5 +61,5 @@ message Ip4 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Ip4 ip4 = 131;
|
||||
optional Ip4 ip4 = 301;
|
||||
}
|
||||
|
@ -33,5 +33,5 @@ extend Ip4over4 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Ip4over4 ip4over4 = 135;
|
||||
optional Ip4over4 ip4over4 = 305;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message Ip4over6 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Ip4over6 ip4over6 = 134;
|
||||
optional Ip4over6 ip4over6 = 304;
|
||||
}
|
||||
|
@ -57,5 +57,5 @@ message Ip6 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Ip6 ip6 = 132;
|
||||
optional Ip6 ip6 = 302;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message Ip6over4 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Ip6over4 ip6over4 = 133;
|
||||
optional Ip6over4 ip6over4 = 303;
|
||||
}
|
||||
|
@ -33,5 +33,5 @@ extend Ip6over6 {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Ip6over6 ip6over6 = 136;
|
||||
optional Ip6over6 ip6over6 = 306;
|
||||
}
|
||||
|
@ -28,5 +28,5 @@ message Llc {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Llc llc = 123;
|
||||
optional Llc llc = 202;
|
||||
}
|
||||
|
@ -44,5 +44,5 @@ message Mac {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Mac mac = 51;
|
||||
optional Mac mac = 100;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ FORMS += \
|
||||
sample.ui
|
||||
PROTOS += \
|
||||
protocol.proto \
|
||||
fileformat.proto \
|
||||
mac.proto \
|
||||
payload.proto \
|
||||
eth2.proto \
|
||||
@ -45,10 +46,11 @@ PROTOS += \
|
||||
udp.proto \
|
||||
textproto.proto \
|
||||
userscript.proto \
|
||||
sample.proto
|
||||
sample.proto
|
||||
HEADERS += \
|
||||
abstractprotocol.h \
|
||||
comboprotocol.h \
|
||||
fileformat.h \
|
||||
protocolmanager.h \
|
||||
protocollist.h \
|
||||
protocollistiterator.h \
|
||||
@ -79,6 +81,8 @@ HEADERS += \
|
||||
sample.h
|
||||
SOURCES += \
|
||||
abstractprotocol.cpp \
|
||||
crc32c.cpp \
|
||||
fileformat.cpp \
|
||||
protocolmanager.cpp \
|
||||
protocollist.cpp \
|
||||
protocollistiterator.cpp \
|
||||
@ -101,19 +105,6 @@ SOURCES += \
|
||||
userscript.cpp \
|
||||
sample.cpp
|
||||
|
||||
protobuf_decl.name = protobuf header
|
||||
protobuf_decl.input = PROTOS
|
||||
protobuf_decl.output = ${QMAKE_FILE_BASE}.pb.h
|
||||
protobuf_decl.commands = protoc --cpp_out="." ${QMAKE_FILE_NAME}
|
||||
protobuf_decl.variable_out = GENERATED_FILES
|
||||
QMAKE_EXTRA_COMPILERS += protobuf_decl
|
||||
|
||||
protobuf_impl.name = protobuf implementation
|
||||
protobuf_impl.input = PROTOS
|
||||
protobuf_impl.output = ${QMAKE_FILE_BASE}.pb.cc
|
||||
protobuf_impl.depends = ${QMAKE_FILE_BASE}.pb.h
|
||||
protobuf_impl.commands = $$escape_expand(\n)
|
||||
protobuf_impl.variable_out = GENERATED_SOURCES
|
||||
QMAKE_EXTRA_COMPILERS += protobuf_impl
|
||||
|
||||
QMAKE_DISTCLEAN += object_script.*
|
||||
|
||||
include(../protobuf.pri)
|
||||
|
@ -37,5 +37,5 @@ message Payload {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Payload payload = 52;
|
||||
optional Payload payload = 101;
|
||||
}
|
||||
|
@ -78,41 +78,41 @@ message Protocol {
|
||||
|
||||
required ProtocolId protocol_id = 1;
|
||||
|
||||
extensions 51 to 100; // Reserved for Ostinato Use
|
||||
extensions 101 to 200; // Available for use by protocols
|
||||
extensions 100 to 199; // Reserved for Ostinato Use
|
||||
extensions 200 to 500; // Available for use by protocols
|
||||
|
||||
enum k {
|
||||
kMacFieldNumber = 51;
|
||||
kPayloadFieldNumber = 52;
|
||||
kSampleFieldNumber = 53;
|
||||
kUserScriptFieldNumber = 54;
|
||||
kMacFieldNumber = 100;
|
||||
kPayloadFieldNumber = 101;
|
||||
kSampleFieldNumber = 102;
|
||||
kUserScriptFieldNumber = 103;
|
||||
|
||||
kEth2FieldNumber = 121;
|
||||
kDot3FieldNumber = 122;
|
||||
kLlcFieldNumber = 123;
|
||||
kSnapFieldNumber = 124;
|
||||
kEth2FieldNumber = 200;
|
||||
kDot3FieldNumber = 201;
|
||||
kLlcFieldNumber = 202;
|
||||
kSnapFieldNumber = 203;
|
||||
|
||||
kSvlanFieldNumber = 125;
|
||||
kVlanFieldNumber = 126;
|
||||
kSvlanFieldNumber = 204;
|
||||
kVlanFieldNumber = 205;
|
||||
|
||||
kDot2LlcFieldNumber = 127;
|
||||
kDot2SnapFieldNumber = 128;
|
||||
kVlanStackFieldNumber = 129;
|
||||
kDot2LlcFieldNumber = 206;
|
||||
kDot2SnapFieldNumber = 207;
|
||||
kVlanStackFieldNumber = 208;
|
||||
|
||||
kArpFieldNumber = 130;
|
||||
kIp4FieldNumber = 131;
|
||||
kIp6FieldNumber = 132;
|
||||
kIp6over4FieldNumber = 133;
|
||||
kIp4over6FieldNumber = 134;
|
||||
kIp4over4FieldNumber = 135;
|
||||
kIp6over6FieldNumber = 136;
|
||||
kArpFieldNumber = 300;
|
||||
kIp4FieldNumber = 301;
|
||||
kIp6FieldNumber = 302;
|
||||
kIp6over4FieldNumber = 303;
|
||||
kIp4over6FieldNumber = 304;
|
||||
kIp4over4FieldNumber = 305;
|
||||
kIp6over6FieldNumber = 306;
|
||||
|
||||
kTcpFieldNumber = 140;
|
||||
kUdpFieldNumber = 141;
|
||||
kIcmpFieldNumber = 142;
|
||||
kIgmpFieldNumber = 143;
|
||||
kTcpFieldNumber = 400;
|
||||
kUdpFieldNumber = 401;
|
||||
kIcmpFieldNumber = 402;
|
||||
kIgmpFieldNumber = 403;
|
||||
|
||||
kTextProtocolFieldNumber = 150;
|
||||
kTextProtocolFieldNumber = 500;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,5 +34,5 @@ message Sample {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Sample sample = 53;
|
||||
optional Sample sample = 102;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message Snap {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Snap snap = 124;
|
||||
optional Snap snap = 203;
|
||||
}
|
||||
|
@ -23,5 +23,5 @@ import "vlan.proto";
|
||||
package OstProto;
|
||||
|
||||
extend Protocol {
|
||||
optional Vlan svlan = 125;
|
||||
optional Vlan svlan = 204;
|
||||
}
|
||||
|
@ -42,6 +42,6 @@ message Tcp {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Tcp tcp = 140;
|
||||
optional Tcp tcp = 400;
|
||||
}
|
||||
|
||||
|
@ -33,5 +33,5 @@ message TextProtocol {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional TextProtocol textProtocol = 150;
|
||||
optional TextProtocol textProtocol = 500;
|
||||
}
|
||||
|
@ -35,5 +35,5 @@ message Udp {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Udp udp = 141;
|
||||
optional Udp udp = 401;
|
||||
}
|
||||
|
@ -29,5 +29,5 @@ message UserScript {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional UserScript userScript = 54;
|
||||
optional UserScript userScript = 103;
|
||||
}
|
||||
|
@ -30,5 +30,5 @@ message Vlan {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional Vlan vlan = 126;
|
||||
optional Vlan vlan = 205;
|
||||
}
|
||||
|
@ -27,5 +27,5 @@ message VlanStack {
|
||||
}
|
||||
|
||||
extend Protocol {
|
||||
optional VlanStack vlanStack = 129;
|
||||
optional VlanStack vlanStack = 208;
|
||||
}
|
||||
|
33
protobuf.pri
Normal file
33
protobuf.pri
Normal file
@ -0,0 +1,33 @@
|
||||
#
|
||||
# Qt qmake integration with Google Protocol Buffers compiler protoc
|
||||
#
|
||||
# To compile protocol buffers with qt qmake, specify PROTOS variable and
|
||||
# include this file
|
||||
#
|
||||
# Example:
|
||||
# PROTOS = a.proto b.proto
|
||||
# include(protobuf.pri)
|
||||
#
|
||||
# By default protoc looks for .proto files (including the imported ones) in
|
||||
# the current directory where protoc is run. If you need to include additional
|
||||
# paths specify the PROTOPATH variable
|
||||
#
|
||||
|
||||
PROTOPATH += .
|
||||
PROTOPATHS =
|
||||
for(p, PROTOPATH):PROTOPATHS += --proto_path=$${p}
|
||||
|
||||
protobuf_decl.name = protobuf header
|
||||
protobuf_decl.input = PROTOS
|
||||
protobuf_decl.output = ${QMAKE_FILE_BASE}.pb.h
|
||||
protobuf_decl.commands = protoc --cpp_out="." $${PROTOPATHS} ${QMAKE_FILE_NAME}
|
||||
protobuf_decl.variable_out = GENERATED_FILES
|
||||
QMAKE_EXTRA_COMPILERS += protobuf_decl
|
||||
|
||||
protobuf_impl.name = protobuf implementation
|
||||
protobuf_impl.input = PROTOS
|
||||
protobuf_impl.output = ${QMAKE_FILE_BASE}.pb.cc
|
||||
protobuf_impl.depends = ${QMAKE_FILE_BASE}.pb.h
|
||||
protobuf_impl.commands = $$escape_expand(\n)
|
||||
protobuf_impl.variable_out = GENERATED_SOURCES
|
||||
QMAKE_EXTRA_COMPILERS += protobuf_impl
|
Loading…
Reference in New Issue
Block a user