ostinato/common/sample.cpp

518 lines
14 KiB
C++
Raw Normal View History

/*
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 <qendian.h>
#include "sample.h"
SampleConfigForm::SampleConfigForm(QWidget *parent)
: QWidget(parent)
{
setupUi(this);
}
SampleProtocol::SampleProtocol(StreamBase *stream, AbstractProtocol *parent)
: AbstractProtocol(stream, parent)
{
configForm = NULL;
}
SampleProtocol::~SampleProtocol()
{
delete configForm;
}
Protocol Framework related -------------------------- - AbstractProtocol Constructor and Factory function now take an optional (default NULL) "parent" abstract protocol in addition to the stream; this "parent" protocol is non-NULL for protocols which are aggregated in a ComboProtocol - All subclasses of AbstractProtocol modified as per the above interface change - ProtocolManager also modifed as per the above interface change - new data members in AbstractProtocol - prev, next; the AbstractProtocol implementation now uses these members to traverse protocols on the list instead of ProtocolListIterator; this change required for ComboProtocol - ProtocolListIterator updates these new members - prev/next on insert/remove/replace - ComboProtocol and ProtocolListIterator classes made friends of AbstractProtocol - ComboProtocol implemented as a template class (completed) - Dot2LLc implemented as a combo of Dot3Raw and LLC - Dot2Snap implemented as a combo of Dot2Llc and SNAP - VlanStack implemented as a combo of VLAN + VLAN - ProtocolManager now uses the ProtocolId enums rather than hardcoded values Stream Config Dialog -------------------- - "None" radio button added to all protocol levels - Protocol Level 1 added with 'mac' as the only valid protocol in the "simple" mode widget - With Dot2Llc, Dot2Snap and VlanStack implemented as "combo" protocols, the protocol choice radiobuttons in the "simple" mode are now 1:1 with a protocol; this has the following implications/advantages: - Updates of the "simple" mode widget from/to stream's protocolList is simpler; this code has now been rewritten to take advantage of 1:1 - This paves the way for exporting tunneled protocols 4over4, 4over6, 6over4 etc. in the "simple" mode - This should also (hopefully) require less changes when adding a new protocol; more work needs to be done to reach this goal Fixes ----- - Dot3Protocol now derives "length" correctly for VLAN tagged packets - StreamBase now uses the ProtocolListIterator to append the default protocols in a stream instead of directly manipulating ProtocolList; also in protoDataCopyFrom() Others (Client/Server) ---------------------- - Port Packet Capture implemented; "view capture" is pending (hack put in place now for testing)
2009-10-14 10:16:56 -05:00
AbstractProtocol* SampleProtocol::createInstance(StreamBase *stream,
AbstractProtocol *parent)
{
return new SampleProtocol(stream, parent);
}
Major rewrite of the protocol framework - changes not yet complete Common ------ - Change in OstProto - Individual protocols are now extensions of (new) message 'Protocol' instead of 'Stream' - Stream now contains a repeated Protocol which also determines the ordered set of currently selected protocols; StreamCore.frame_proto which was doing this earlier has been removed - Change in AbstractProtocol Interface - Parent changed to StreamBase - Corresponding change in constructor and factory func - createInstance() - new method protocolNumber() - returns unique id for each protocol - protoDataCopyInto/From() now copies into OstProto::Protocol instead of OstProto::Stream - Change in all subclasses of AbstractProtocol to match new interface - For all protocols, configFrom is no longer static, but each protocol has its own configForm - configForm creation is lazy - configForm is still a child of the protocol i.e. it will be destroyed alongwith the protocol - TODO: convert configWidget() to a pure factory function i.e. the protocol does not own the configForm - this requires us to pass the widget into load/storeConfigWidget() methods - ProtocolCollection class removed alongwith its .h and .cpp - ProtocolList class redefined to serve the purpose of ProtocolCollection - New class ProtocolListIterator defined to iterate ProtocolList - AbstractProtocol methods now use the ProtocolListIterator - Factory function createProtocol() added to ProtocolManager - OstProto::StreamCore accessor functions moved from Stream to StreamBase Server ------ - MyService uses the newly moved accessors to StreamBase for OstProto::StreamCore members - StreamInfo now uses the protocols to create the packet Client ------ - StreamConfigDialog now uses ProtocolListIterator - So does PacketModel
2009-08-02 09:52:34 -05:00
quint32 SampleProtocol::protocolNumber() const
{
return OstProto::Protocol::kSampleFieldNumber;
}
Major rewrite of the protocol framework - changes not yet complete Common ------ - Change in OstProto - Individual protocols are now extensions of (new) message 'Protocol' instead of 'Stream' - Stream now contains a repeated Protocol which also determines the ordered set of currently selected protocols; StreamCore.frame_proto which was doing this earlier has been removed - Change in AbstractProtocol Interface - Parent changed to StreamBase - Corresponding change in constructor and factory func - createInstance() - new method protocolNumber() - returns unique id for each protocol - protoDataCopyInto/From() now copies into OstProto::Protocol instead of OstProto::Stream - Change in all subclasses of AbstractProtocol to match new interface - For all protocols, configFrom is no longer static, but each protocol has its own configForm - configForm creation is lazy - configForm is still a child of the protocol i.e. it will be destroyed alongwith the protocol - TODO: convert configWidget() to a pure factory function i.e. the protocol does not own the configForm - this requires us to pass the widget into load/storeConfigWidget() methods - ProtocolCollection class removed alongwith its .h and .cpp - ProtocolList class redefined to serve the purpose of ProtocolCollection - New class ProtocolListIterator defined to iterate ProtocolList - AbstractProtocol methods now use the ProtocolListIterator - Factory function createProtocol() added to ProtocolManager - OstProto::StreamCore accessor functions moved from Stream to StreamBase Server ------ - MyService uses the newly moved accessors to StreamBase for OstProto::StreamCore members - StreamInfo now uses the protocols to create the packet Client ------ - StreamConfigDialog now uses ProtocolListIterator - So does PacketModel
2009-08-02 09:52:34 -05:00
void SampleProtocol::protoDataCopyInto(OstProto::Protocol &protocol) const
{
protocol.MutableExtension(OstProto::sample)->CopyFrom(data);
protocol.mutable_protocol_id()->set_id(protocolNumber());
Major rewrite of the protocol framework - changes not yet complete Common ------ - Change in OstProto - Individual protocols are now extensions of (new) message 'Protocol' instead of 'Stream' - Stream now contains a repeated Protocol which also determines the ordered set of currently selected protocols; StreamCore.frame_proto which was doing this earlier has been removed - Change in AbstractProtocol Interface - Parent changed to StreamBase - Corresponding change in constructor and factory func - createInstance() - new method protocolNumber() - returns unique id for each protocol - protoDataCopyInto/From() now copies into OstProto::Protocol instead of OstProto::Stream - Change in all subclasses of AbstractProtocol to match new interface - For all protocols, configFrom is no longer static, but each protocol has its own configForm - configForm creation is lazy - configForm is still a child of the protocol i.e. it will be destroyed alongwith the protocol - TODO: convert configWidget() to a pure factory function i.e. the protocol does not own the configForm - this requires us to pass the widget into load/storeConfigWidget() methods - ProtocolCollection class removed alongwith its .h and .cpp - ProtocolList class redefined to serve the purpose of ProtocolCollection - New class ProtocolListIterator defined to iterate ProtocolList - AbstractProtocol methods now use the ProtocolListIterator - Factory function createProtocol() added to ProtocolManager - OstProto::StreamCore accessor functions moved from Stream to StreamBase Server ------ - MyService uses the newly moved accessors to StreamBase for OstProto::StreamCore members - StreamInfo now uses the protocols to create the packet Client ------ - StreamConfigDialog now uses ProtocolListIterator - So does PacketModel
2009-08-02 09:52:34 -05:00
}
void SampleProtocol::protoDataCopyFrom(const OstProto::Protocol &protocol)
{
if (protocol.protocol_id().id() == protocolNumber() &&
protocol.HasExtension(OstProto::sample))
data.MergeFrom(protocol.GetExtension(OstProto::sample));
}
QString SampleProtocol::name() const
{
return QString("Sample Protocol");
}
QString SampleProtocol::shortName() const
{
return QString("SAMPLE");
}
/*!
TODO Return the ProtocolIdType for your protocol \n
If your protocol doesn't have a protocolId field, you don't need to
reimplement this method - the base class implementation will do the
right thing
*/
AbstractProtocol::ProtocolIdType SampleProtocol::protocolIdType() const
{
return ProtocolIdIp;
}
/*!
TODO Return the protocolId for your protoocol based on the 'type' requested \n
If not all types are valid for your protocol, handle the valid type(s)
and for the remaining fallback to the base class implementation; if your
protocol doesn't have a protocolId at all, you don't need to reimplement
this method - the base class will do the right thing
*/
quint32 SampleProtocol::protocolId(ProtocolIdType type) const
{
switch(type)
{
case ProtocolIdIp: return 1234;
default:break;
}
return AbstractProtocol::protocolId(type);
}
int SampleProtocol::fieldCount() const
{
return sample_fieldCount;
}
/*!
TODO Edit this function to return the appropriate flags for each field \n
See AbstractProtocol::FieldFlags for more info
*/
AbstractProtocol::FieldFlags SampleProtocol::fieldFlags(int index) const
{
AbstractProtocol::FieldFlags flags;
flags = AbstractProtocol::fieldFlags(index);
switch (index)
{
case sample_a:
case sample_b:
case sample_payloadLength:
break;
case sample_checksum:
flags |= FieldIsCksum;
break;
case sample_x:
case sample_y:
break;
case sample_is_override_checksum:
flags |= FieldIsMeta;
break;
default:
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
index);
break;
}
return flags;
}
/*!
TODO: Edit this function to return the data for each field
See AbstractProtocol::fieldData() for more info
*/
QVariant SampleProtocol::fieldData(int index, FieldAttrib attrib,
int streamIndex) const
{
switch (index)
{
case sample_a:
{
int a = data.ab() >> 13;
switch(attrib)
{
case FieldName:
return QString("A");
case FieldValue:
return a;
case FieldTextValue:
return QString("%1").arg(a);
case FieldFrameValue:
return QByteArray(1, (char) a);
case FieldBitSize:
return 3;
default:
break;
}
break;
}
case sample_b:
{
int b = data.ab() & 0x1FFF;
switch(attrib)
{
case FieldName:
return QString("B");
case FieldValue:
return b;
case FieldTextValue:
return QString("%1").arg(b, 4, BASE_HEX, QChar('0'));
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
qToBigEndian((quint16) b, (uchar*) fv.data());
return fv;
}
case FieldBitSize:
return 13;
default:
break;
}
break;
}
case sample_payloadLength:
{
switch(attrib)
{
case FieldName:
return QString("Payload Length");
case FieldValue:
return protocolFramePayloadSize(streamIndex);
case FieldFrameValue:
{
QByteArray fv;
int totlen;
totlen = protocolFramePayloadSize(streamIndex);
fv.resize(2);
qToBigEndian((quint16) totlen, (uchar*) fv.data());
return fv;
}
case FieldTextValue:
return QString("%1").arg(
protocolFramePayloadSize(streamIndex));
case FieldBitSize:
return 16;
default:
break;
}
break;
}
case sample_checksum:
{
quint16 cksum;
switch(attrib)
{
case FieldValue:
case FieldFrameValue:
case FieldTextValue:
if (data.is_override_checksum())
cksum = data.checksum();
else
cksum = protocolFrameCksum(streamIndex, CksumIp);
break;
default:
cksum = 0; // avoid the 'maybe used unitialized' warning
break;
}
switch(attrib)
{
case FieldName:
return QString("Checksum");
case FieldValue:
return cksum;
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
qToBigEndian(cksum, (uchar*) fv.data());
return fv;
}
case FieldTextValue:
return QString("0x%1").arg(
cksum, 4, BASE_HEX, QChar('0'));;
case FieldBitSize:
return 16;
default:
break;
}
break;
}
case sample_x:
{
switch(attrib)
{
case FieldName:
return QString("X");
case FieldValue:
return data.x();
case FieldTextValue:
// Use the following line for display in decimal
return QString("%1").arg(data.x());
// Use the following line for display in hexa-decimal
//return QString("%1").arg(data.x(), 8, BASE_HEX, QChar('0'));
case FieldFrameValue:
{
QByteArray fv;
fv.resize(4);
qToBigEndian((quint32) data.x(), (uchar*) fv.data());
return fv;
}
default:
break;
}
break;
}
case sample_y:
{
switch(attrib)
{
case FieldName:
return QString("Y");
case FieldValue:
return data.y();
case FieldTextValue:
// Use the following line for display in decimal
//return QString("%1").arg(data.y());
// Use the following line for display in hexa-decimal
return QString("%1").arg(data.y(), 4, BASE_HEX, QChar('0'));
case FieldFrameValue:
{
QByteArray fv;
fv.resize(2);
qToBigEndian((quint16) data.y(), (uchar*) fv.data());
return fv;
}
default:
break;
}
break;
}
// Meta fields
case sample_is_override_checksum:
{
switch(attrib)
{
case FieldValue:
return data.is_override_checksum();
default:
break;
}
break;
}
default:
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
index);
break;
}
return AbstractProtocol::fieldData(index, attrib, streamIndex);
}
/*!
TODO: Edit this function to set the data for each field
See AbstractProtocol::setFieldData() for more info
*/
bool SampleProtocol::setFieldData(int index, const QVariant &value,
FieldAttrib attrib)
{
bool isOk = false;
if (attrib != FieldValue)
goto _exit;
switch (index)
{
case sample_a:
{
uint a = value.toUInt(&isOk);
if (isOk)
data.set_ab((data.ab() & 0xe000) | (a << 13));
break;
}
case sample_b:
{
uint b = value.toUInt(&isOk);
if (isOk)
data.set_ab((data.ab() & 0x1FFF) | b);
break;
}
case sample_payloadLength:
{
uint len = value.toUInt(&isOk);
if (isOk)
data.set_payload_length(len);
break;
}
case sample_checksum:
{
uint csum = value.toUInt(&isOk);
if (isOk)
data.set_checksum(csum);
break;
}
case sample_x:
{
uint x = value.toUInt(&isOk);
if (isOk)
data.set_x(x);
break;
}
case sample_y:
{
uint y = value.toUInt(&isOk);
if (isOk)
data.set_y(y);
break;
}
case sample_is_override_checksum:
{
bool ovr = value.toBool();
data.set_is_override_checksum(ovr);
isOk = true;
break;
}
default:
qFatal("%s: unimplemented case %d in switch", __PRETTY_FUNCTION__,
index);
break;
}
_exit:
return isOk;
}
/*!
TODO: Return the protocol frame size in bytes\n
If your protocol has a fixed size - you don't need to reimplement this; the
base class implementation is good enough
*/
int SampleProtocol::protocolFrameSize(int streamIndex) const
{
return AbstractProtocol::protocolFrameSize(streamIndex);
}
/*!
TODO: If your protocol has any variable fields, return true \n
Otherwise you don't need to reimplement this method - the base class always
returns false
*/
bool SampleProtocol::isProtocolFrameValueVariable() const
{
return false;
}
/*!
TODO: If your protocol frame size can vary across pkts of the same stream,
return true \n
Otherwise you don't need to reimplement this method - the base class always
returns false
*/
bool SampleProtocol::isProtocolFrameSizeVariable() const
{
return false;
}
QWidget* SampleProtocol::configWidget()
{
if (configForm == NULL)
{
configForm = new SampleConfigForm;
loadConfigWidget();
}
Major rewrite of the protocol framework - changes not yet complete Common ------ - Change in OstProto - Individual protocols are now extensions of (new) message 'Protocol' instead of 'Stream' - Stream now contains a repeated Protocol which also determines the ordered set of currently selected protocols; StreamCore.frame_proto which was doing this earlier has been removed - Change in AbstractProtocol Interface - Parent changed to StreamBase - Corresponding change in constructor and factory func - createInstance() - new method protocolNumber() - returns unique id for each protocol - protoDataCopyInto/From() now copies into OstProto::Protocol instead of OstProto::Stream - Change in all subclasses of AbstractProtocol to match new interface - For all protocols, configFrom is no longer static, but each protocol has its own configForm - configForm creation is lazy - configForm is still a child of the protocol i.e. it will be destroyed alongwith the protocol - TODO: convert configWidget() to a pure factory function i.e. the protocol does not own the configForm - this requires us to pass the widget into load/storeConfigWidget() methods - ProtocolCollection class removed alongwith its .h and .cpp - ProtocolList class redefined to serve the purpose of ProtocolCollection - New class ProtocolListIterator defined to iterate ProtocolList - AbstractProtocol methods now use the ProtocolListIterator - Factory function createProtocol() added to ProtocolManager - OstProto::StreamCore accessor functions moved from Stream to StreamBase Server ------ - MyService uses the newly moved accessors to StreamBase for OstProto::StreamCore members - StreamInfo now uses the protocols to create the packet Client ------ - StreamConfigDialog now uses ProtocolListIterator - So does PacketModel
2009-08-02 09:52:34 -05:00
return configForm;
}
/*!
TODO: Edit this function to load each field's data into the config Widget
See AbstractProtocol::loadConfigWidget() for more info
*/
void SampleProtocol::loadConfigWidget()
{
configWidget();
configForm->sampleA->setText(fieldData(sample_a, FieldValue).toString());
configForm->sampleB->setText(fieldData(sample_b, FieldValue).toString());
configForm->samplePayloadLength->setText(
fieldData(sample_payloadLength, FieldValue).toString());
configForm->isChecksumOverride->setChecked(
fieldData(sample_is_override_checksum, FieldValue).toBool());
configForm->sampleChecksum->setText(uintToHexStr(
fieldData(sample_checksum, FieldValue).toUInt(), 2));
configForm->sampleX->setText(fieldData(sample_x, FieldValue).toString());
configForm->sampleY->setText(fieldData(sample_y, FieldValue).toString());
}
/*!
TODO: Edit this function to store each field's data from the config Widget
See AbstractProtocol::storeConfigWidget() for more info
*/
void SampleProtocol::storeConfigWidget()
{
bool isOk;
Major rewrite of the protocol framework - changes not yet complete Common ------ - Change in OstProto - Individual protocols are now extensions of (new) message 'Protocol' instead of 'Stream' - Stream now contains a repeated Protocol which also determines the ordered set of currently selected protocols; StreamCore.frame_proto which was doing this earlier has been removed - Change in AbstractProtocol Interface - Parent changed to StreamBase - Corresponding change in constructor and factory func - createInstance() - new method protocolNumber() - returns unique id for each protocol - protoDataCopyInto/From() now copies into OstProto::Protocol instead of OstProto::Stream - Change in all subclasses of AbstractProtocol to match new interface - For all protocols, configFrom is no longer static, but each protocol has its own configForm - configForm creation is lazy - configForm is still a child of the protocol i.e. it will be destroyed alongwith the protocol - TODO: convert configWidget() to a pure factory function i.e. the protocol does not own the configForm - this requires us to pass the widget into load/storeConfigWidget() methods - ProtocolCollection class removed alongwith its .h and .cpp - ProtocolList class redefined to serve the purpose of ProtocolCollection - New class ProtocolListIterator defined to iterate ProtocolList - AbstractProtocol methods now use the ProtocolListIterator - Factory function createProtocol() added to ProtocolManager - OstProto::StreamCore accessor functions moved from Stream to StreamBase Server ------ - MyService uses the newly moved accessors to StreamBase for OstProto::StreamCore members - StreamInfo now uses the protocols to create the packet Client ------ - StreamConfigDialog now uses ProtocolListIterator - So does PacketModel
2009-08-02 09:52:34 -05:00
configWidget();
setFieldData(sample_a, configForm->sampleA->text());
setFieldData(sample_b, configForm->sampleB->text());
setFieldData(sample_payloadLength, configForm->samplePayloadLength->text());
setFieldData(sample_is_override_checksum,
configForm->isChecksumOverride->isChecked());
setFieldData(sample_checksum, configForm->sampleChecksum->text().toUInt(&isOk, BASE_HEX));
setFieldData(sample_x, configForm->sampleX->text());
setFieldData(sample_y, configForm->sampleY->text());
}